setTimeout(function() { window.location.reload(true) }, 1000)'); } if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) { date_default_timezone_set(@date_default_timezone_get()); } if ('cli' === PHP_SAPI || !isset($_SERVER['REQUEST_URI'])) { if (isset($_SERVER['argv'][1]) && 'test' === $_SERVER['argv'][1]) { die(json_encode(['version' => PHP_VERSION, 'version_id' => PHP_VERSION_ID, 'sapi' => PHP_SAPI])); } Phar::mapPhar('contao-manager.phar'); require 'phar://contao-manager.phar/api/console'; } else { function rewrites() { // The function argument is unreliable across servers, Nginx for example is always empty list(,$url) = explode(basename(__FILE__), $_SERVER['REQUEST_URI'], 2); if (strpos($url, '..')) { return false; } if ('' === $url) { header('Location: /'.basename(__FILE__).'/'); exit; } if (0 === strpos($url, '/api/')) { return '/dist/api.php'.$url; } if (!empty($url) && is_file('phar://'.__FILE__.'/dist'.$url)) { return '/dist'.$url; } return '/dist/index.html'; } Phar::webPhar( null, 'index.html', null, array( 'log' => 'text/plain', 'txt' => 'text/plain', 'php' => Phar::PHP, // parse as PHP 'css' => 'text/css', 'gif' => 'image/gif', 'html' => 'text/html', 'ico' => 'image/x-ico', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'js' => 'application/x-javascript', 'png' => 'image/png', 'svg' => 'image/svg+xml', 'json' => 'application/json' ), 'rewrites' ); } __HALT_COMPILER(); ?> .box/bin/check-requirements.php-g^ʨ.box/.requirements.php8-g8>WS5.box/vendor/autoload.php-gs,.box/vendor/composer/autoload_namespaces.php-gt!פ.box/vendor/composer/LICENSE.-g. $.box/vendor/composer/ClassLoader.php>-g>5Ky&.box/vendor/composer/autoload_psr4.php6-g60Ӥ*.box/vendor/composer/autoload_classmap.php, -g, ӽǤ(.box/vendor/composer/autoload_static.phpK-gK?&.box/vendor/composer/autoload_real.php-gyi\..box/vendor/composer/semver/src/Comparator.phpu-gu 74*.box/vendor/composer/semver/src/Semver.php-gׯ1.box/vendor/composer/semver/src/VersionParser.php9-g9Wz B.box/vendor/composer/semver/src/Constraint/ConstraintInterface.php-gwQ>.box/vendor/composer/semver/src/Constraint/MultiConstraint.php~-g~5[e9.box/vendor/composer/semver/src/Constraint/Constraint.php'&-g'&`.box/src/Terminal.php -g %V.box/src/IO.php -g [l%!.box/src/IsExtensionFulfilled.phpv-gv'0Ҥ.box/src/Checker.php-g)W>".box/src/IsPhpVersionFulfilled.php-g!83".box/src/RequirementCollection.php-gWb?.box/src/Printer.php -g )8AV.box/src/IsFulfilled.phpv-gv%*H.box/src/Requirement.phpm-gmBLICENSE-gpdist/index.htmlH'-gH'~dist/api.php---gL|Rdist/css/531.fa97fb72.css>-g>:edist/css/612.3a60e65a.css-gi_Ӥdist/css/212.44f2aba0.cssO-gOodist/css/496.10f7bb83.cssb-gbb#dist/css/chunk-vendors.852f1008.css:p-g:pdist/css/82.e18cb2b2.css-g26&dist/css/479.5c4f2539.cssf-gf)\dist/css/app.ca33bfae.cssx-gxQfdist/css/139.11002f25.css-g+dist/css/306.25211792.cssl-glAdist/js/120.ad9ecc53.jsp-gpdist/js/523.14592c65.js-g3dist/js/606.c408386b.jsJ-gJ!dist/js/chunk-vendors.1dc47d2a.jsgy-ggydist/js/669.deb99932.jsz-gzYHdist/js/60.15d99754.jsI"-gI"H[dist/js/518.16da88f4.jsk-gkBZf dist/js/554.6793dc25.js-gCdist/js/706.fa5ca273.jsP-gPtdist/js/953.cfd6dc8d.js.-g. dist/js/715.39edc453.jsz-gzˤdist/js/139.a9db33f9.jsY--gY-X:dist/js/958.7fdd57a1.jsS-gSCIsƤdist/js/367.b1973e97.jss-gsh dist/js/542.a77d6afc.js -g dist/js/180.25fde044.js-godist/js/874.cb764366.js -g h[dist/js/app.450ee362.js-gN/dist/js/851.800f4cc3.jsڥ-gڥ3pdist/js/44.aa3a6943.js-g$,Ȝdist/js/638.9d60aca3.jsŢ-gŢ+Fdist/js/52.53a6eeda.js-gyWdist/js/520.015d305f.jsU-gU){3dist/js/560.bf496880.js-gߌ/dist/js/82.4d867f71.js -g P<Τdist/js/500.d95d38df.jsuM-guMdist/js/28.ceef267d.jsw-gwIg0dist/js/219.c00b841d.js -g C Fdist/js/721.92ab0b05.js-gƿdist/js/581.34ad7ec7.js-g4dist/js/612.ba8a2b90.js-gYdist/js/716.a21c458e.jsA-gACddist/js/194.1e21e427.js-gИUdist/js/479.98674663.js-gfJdist/js/540.9222434f.js--g-TzŤdist/js/643.f898abfb.jsy-gy -dist/js/551.3fd69aa4.jsm-gmdist/js/477.b60ba150.jsO-gOeJdist/js/557.9a8ca5d7.js-g=]ɤdist/js/140.9f138779.js= -g= 3Ndist/js/531.d9917883.js-guߤdist/js/710.aa0213da.js|-g|gǘkdist/js/164.1bf38df2.js-g2}Adist/js/486.dbfe136b.js-g!dist/js/553.9a474b92.jsԙ-gԙdJdist/js/306.7db13eb6.jsu -gu pƤdist/js/769.46cebc27.js-g 9dist/js/212.82f9b333.jsQ-gQC!dist/img/button-show.2336e1d9.svgS-gSUdist/img/warning.9a7cd776.svg-gfhdist/img/logo.d9707286.svg-g;w dist/img/button-add.759df12e.svg-gO dist/img/favers.056e2836.svgH-gHy,ͤ#dist/img/server-config.1a2d0888.svgg-ggRN%dist/img/button-database.5282fc7e.svg-gP"dist/img/symfony-logo.5c162c73.svg -g Os@!dist/img/button-link.dd42e161.svg-g֖>(dist/img/button-maintenance.93830369.svgE-gEO$dist/img/create-project.b22522ee.svg-gʅ)dist/img/button-incompatible.3eb2b686.svg-g/$#dist/img/document-root.0e6dd2e4.svg-gD'dist/img/search-by-algolia.72f0ac9a.svg-gdist/img/boot.92149bf5.svg-gSo#dist/img/button-search.44ce1d4b.svgL-gLwdist/img/oauth.1243e742.svg.-g.@ dist/img/private.a1c65662.svg-g_50w%dist/img/button-download.e1ba6f25.svg1-g1O#dist/img/person.00d78897.svg-gw*)dist/img/widget-checkbox--on.8b830157.svg-g#;!dist/img/button-lock.98988f08.svgc-gc5=6z"dist/img/button-check.7a3b5ada.svg-g]Rdist/img/user.129e863d.svg-gcǤdist/img/offline.0c23d1ce.svg-gУ-(dist/img/symfony-logo--dark.ea265042.svg -g 溤#dist/img/private--dark.41b90022.svg-gb&dist/img/button-cloud-off.dd8ba18e.svg-gܡ<"dist/img/button-power.298a8072.svg6-g6Kb%dist/img/downloads--dark.034bf7a3.svg--g- Ǥ"dist/img/button-trash.855f57fa.svgt-gt2} dist/img/link-blank.eb57b3fa.svg-gf^&dist/img/button-clipboard.9ef63d39.svgJ-gJv,N'dist/img/widget-radio--off.4e93f443.svg-gdist/img/task.e9e5333f.svg{-g{Jl#dist/img/button-update.ad79c617.svg\-g\Įdist/img/hint.ba2ac97e.svg!-g!!dist/img/button-hide.d23f6533.svg-gm3(dist/img/database.7f0a8c49.svg-g< dist/img/updated.3b47bebb.svgH-gHʦ$dist/img/language--dark.a24e849e.svgx-gxG7?!dist/img/button-save.3b5224de.svg -g $dist/img/button-details.161475b3.svg-g&dist/img/lock.3c42a55f.svgf-gfgGdist/img/downloads.c1db2a9e.svg0-g0¤"dist/img/color_scheme.d527d153.svg-gtdist/img/recovery.70ee118a.svg-gOTM`#dist/img/button-upload.ca8e9cfc.svg3-g30U!dist/img/button-edit.40a4be06.svg-g!.&dist/img/link-blank--dark.07eeaee6.svg-gB|dist/img/funding.cf78a0a0.svgJ-gJ`1_#dist/img/button-unlock.51b76e07.svgi-gi dist/img/php-logo.7376e212.svg -g k9q#dist/img/updated--dark.c21fdd5b.svgE-gEEy"dist/img/button-cloud.bc42f267.svg-gI["dist/img/favers--dark.4765f7d4.svgE-gE!dist/img/button-more.e3eb2622.svg-gvdist/img/language.582b2920.svg{-g{tW&dist/img/widget-radio--on.181461b6.svg:-g:j M$dist/img/button-console.05dcdfc4.svg-g>y(dist/img/color_scheme--dark.ef0f0aed.svg:-g:<!dist/img/button-gear.a2dc1f09.svg-g0dist/img/sad.c7de6e95.svg5-g5h dist/img/button-run.b6310c5a.svg-gdist/img/close.8b27dbcb.svg-ge"dist/img/link-funding.b25cd92d.svg-gPԤ*dist/img/widget-checkbox--off.73856538.svg-g~(dist/icons/task-active/favicon-16x16.png3-g3K"dist/icons/task-active/favicon.ico:-g:8(dist/icons/task-active/favicon-32x32.pngF-gF)fx'dist/icons/task-error/favicon-16x16.png;-g;!dist/icons/task-error/favicon.ico:-g:u'dist/icons/task-error/favicon-32x32.pngB-gB)dist/icons/task-success/favicon-16x16.pngU-gU{ؤ#dist/icons/task-success/favicon.ico:-g:TIm)dist/icons/task-success/favicon-32x32.pngq-gq?. dist/api.php-gC¾dist/assets/favicon-16x16.png-g dist/assets/mstile-310x310.png%-g%xH&dist/assets/android-chrome-384x384.png%-g%1| &3dist/assets/apple-touch-startup-image-1125x2436.png-g52dist/assets/apple-touch-startup-image-1792x828.png-g8Q2dist/assets/apple-touch-startup-image-1334x750.png}y-g}yԴdist/assets/mstile-144x144.png -g 3dist/assets/apple-touch-startup-image-1290x2796.pngu-gu^vdist/assets/favicon.ico-g}*~(dist/assets/apple-touch-icon-120x120.png -g 3dist/assets/apple-touch-startup-image-2732x2048.png-g.uE&dist/assets/android-chrome-192x192.png3-g3'\ dist/assets/apple-touch-icon.png-g:53dist/assets/apple-touch-startup-image-1242x2688.png&-g&:Pg&dist/assets/android-chrome-256x256.pngh-ghj't3dist/assets/apple-touch-startup-image-2436x1125.png-g5xdist/assets/mstile-70x70.png-geݺ=2dist/assets/apple-touch-startup-image-640x1136.pngP-gPn3dist/assets/apple-touch-startup-image-1170x2532.png@-g@ ˨*dist/assets/apple-touch-icon-1024x1024.pngr|-gr|T(dist/assets/apple-touch-icon-152x152.png -g o3dist/assets/apple-touch-startup-image-1620x2160.pngb-gbRE3dist/assets/apple-touch-startup-image-1668x2388.png-gI2dist/assets/apple-touch-startup-image-828x1792.pngv-gv>H3dist/assets/apple-touch-startup-image-2048x1536.pngn-gnxEy(dist/assets/apple-touch-icon-180x180.png-g:5(dist/assets/yandex-browser-manifest.json-gp#Ȥ3dist/assets/apple-touch-startup-image-1640x2160.pngv-gvŤBapi/Resources/cache/Symfony/Config/Framework/RateLimiterConfig.php -g Uapi/Resources/cache/Symfony/Config/Framework/RateLimiter/LimiterConfig/RateConfig.phpm-gm$SJapi/Resources/cache/Symfony/Config/Framework/RateLimiter/LimiterConfig.php-g9§Aapi/Resources/cache/Symfony/Config/Framework/Cache/PoolConfig.php-g-.-Aapi/Resources/cache/Symfony/Config/Framework/SerializerConfig.php-g 2*Eapi/Resources/cache/Symfony/Config/Framework/CsrfProtectionConfig.php7-g7g =api/Resources/cache/Symfony/Config/Framework/AssetsConfig.php+-g+(Napi/Resources/cache/Symfony/Config/Framework/Notifier/AdminRecipientConfig.phpZ-gZ¾@api/Resources/cache/Symfony/Config/Framework/MessengerConfig.phpe*-ge*]>api/Resources/cache/Symfony/Config/Framework/WebhookConfig.php -g &J=api/Resources/cache/Symfony/Config/Framework/RouterConfig.php-g^Aapi/Resources/cache/Symfony/Config/Framework/TranslatorConfig.php"-g"f@api/Resources/cache/Symfony/Config/Framework/WorkflowsConfig.php -g Japi/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig.php~+-g~+7[api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/AuditTrailConfig.phpN-gNVN]api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/MarkingStoreConfig.php -g h4[api/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/TransitionConfig.php]-g]Eg:Vapi/Resources/cache/Symfony/Config/Framework/Workflows/WorkflowsConfig/PlaceConfig.php-gi::api/Resources/cache/Symfony/Config/Framework/EsiConfig.php--g-5>api/Resources/cache/Symfony/Config/Framework/WebLinkConfig.php1-g1Fapi/Resources/cache/Symfony/Config/Framework/Mailer/EnvelopeConfig.php-gRDapi/Resources/cache/Symfony/Config/Framework/Mailer/HeaderConfig.php,-g,lu:api/Resources/cache/Symfony/Config/Framework/SsiConfig.php--g-( Tapi/Resources/cache/Symfony/Config/Framework/Translator/PseudoLocalizationConfig.php-g|ЊJapi/Resources/cache/Symfony/Config/Framework/Translator/ProviderConfig.php -g ܤ?api/Resources/cache/Symfony/Config/Framework/ProfilerConfig.php-gpé@api/Resources/cache/Symfony/Config/Framework/SemaphoreConfig.php-gR8>api/Resources/cache/Symfony/Config/Framework/SecretsConfig.php-g|1Eapi/Resources/cache/Symfony/Config/Framework/PropertyAccessConfig.php-gS(Japi/Resources/cache/Symfony/Config/Framework/Messenger/TransportConfig.php-g ]api/Resources/cache/Symfony/Config/Framework/Messenger/Serializer/SymfonySerializerConfig.php-g+]Kapi/Resources/cache/Symfony/Config/Framework/Messenger/SerializerConfig.php -g Ot^api/Resources/cache/Symfony/Config/Framework/Messenger/TransportConfig/RetryStrategyConfig.php?-g?[THapi/Resources/cache/Symfony/Config/Framework/Messenger/RoutingConfig.php]-g]zTUapi/Resources/cache/Symfony/Config/Framework/Messenger/BusConfig/MiddlewareConfig.php-gi\api/Resources/cache/Symfony/Config/Framework/Messenger/BusConfig/DefaultMiddlewareConfig.php -g ԤDapi/Resources/cache/Symfony/Config/Framework/Messenger/BusConfig.php-gCapi/Resources/cache/Symfony/Config/Framework/PropertyInfoConfig.php5-g5=api/Resources/cache/Symfony/Config/Framework/MailerConfig.php2-g2:api/Resources/cache/Symfony/Config/Framework/UidConfig.php-gեBapi/Resources/cache/Symfony/Config/Framework/RemoteeventConfig.php5-g5`Bapi/Resources/cache/Symfony/Config/Framework/AssetMapperConfig.phpY(-gY(PmDapi/Resources/cache/Symfony/Config/Framework/HtmlSanitizerConfig.php* -g* ?@api/Resources/cache/Symfony/Config/Framework/ExceptionConfig.phpO-gO>api/Resources/cache/Symfony/Config/Framework/SessionConfig.php`2-g`2Napi/Resources/cache/Symfony/Config/Framework/HtmlSanitizer/SanitizerConfig.php9-g9,Aapi/Resources/cache/Symfony/Config/Framework/HttpClientConfig.phpm-gm@api/Resources/cache/Symfony/Config/Framework/PhpErrorsConfig.php-g.m?api/Resources/cache/Symfony/Config/Framework/NotifierConfig.phpS-gS6 S2>api/Resources/cache/Symfony/Config/Framework/RequestConfig.phpg-ggΪBapi/Resources/cache/Symfony/Config/Framework/AnnotationsConfig.php -g c:ĤEapi/Resources/cache/Symfony/Config/Framework/Assets/PackageConfig.php!-g!`Xapi/Resources/cache/Symfony/Config/Framework/Validation/NotCompromisedPasswordConfig.php9-g9r9`Iapi/Resources/cache/Symfony/Config/Framework/Validation/MappingConfig.phpF-gFҺMapi/Resources/cache/Symfony/Config/Framework/Validation/AutoMappingConfig.phpn-gn};api/Resources/cache/Symfony/Config/Framework/LockConfig.php-g$@api/Resources/cache/Symfony/Config/Framework/SchedulerConfig.php3-g3;api/Resources/cache/Symfony/Config/Framework/FormConfig.php -g ܥ;Papi/Resources/cache/Symfony/Config/Security/ProviderConfig/Memory/UserConfig.php-gKIapi/Resources/cache/Symfony/Config/Security/ProviderConfig/LdapConfig.php-gOKKapi/Resources/cache/Symfony/Config/Security/ProviderConfig/MemoryConfig.phpO-gO>]Japi/Resources/cache/Symfony/Config/Security/ProviderConfig/ChainConfig.php-gy4Dapi/Resources/cache/Symfony/Config/Security/PasswordHasherConfig.php-gj{쾤>api/Resources/cache/Symfony/Config/Security/ProviderConfig.php-g73>api/Resources/cache/Symfony/Config/Security/FirewallConfig.php&n-g&n Papi/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessTokenConfig.php-g?3Oapi/Resources/cache/Symfony/Config/Security/FirewallConfig/RememberMeConfig.php1-g1ڊNapi/Resources/cache/Symfony/Config/Security/FirewallConfig/FormLoginConfig.phpA-gAnjRapi/Resources/cache/Symfony/Config/Security/FirewallConfig/JsonLoginLdapConfig.php,*-g,*ExNapi/Resources/cache/Symfony/Config/Security/FirewallConfig/HttpBasicConfig.php-gj]api/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessToken/TokenHandlerConfig.php-gJjapi/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessToken/TokenHandler/OidcUserInfoConfig.php -g bapi/Resources/cache/Symfony/Config/Security/FirewallConfig/AccessToken/TokenHandler/OidcConfig.php-g.}eNapi/Resources/cache/Symfony/Config/Security/FirewallConfig/JsonLoginConfig.php-g\Xapi/Resources/cache/Symfony/Config/Security/FirewallConfig/Logout/DeleteCookieConfig.php-g8xOapi/Resources/cache/Symfony/Config/Security/FirewallConfig/SwitchUserConfig.php -g j aTapi/Resources/cache/Symfony/Config/Security/FirewallConfig/LoginThrottlingConfig.php -g >Napi/Resources/cache/Symfony/Config/Security/FirewallConfig/LoginLinkConfig.php3-g3~1fapi/Resources/cache/Symfony/Config/Security/FirewallConfig/RememberMe/TokenProvider/DoctrineConfig.php-g=]api/Resources/cache/Symfony/Config/Security/FirewallConfig/RememberMe/TokenProviderConfig.php -g Rapi/Resources/cache/Symfony/Config/Security/FirewallConfig/FormLoginLdapConfig.phpNN-gNNjNRapi/Resources/cache/Symfony/Config/Security/FirewallConfig/HttpBasicLdapConfig.php-gBIapi/Resources/cache/Symfony/Config/Security/FirewallConfig/X509Config.php -g IOapi/Resources/cache/Symfony/Config/Security/FirewallConfig/RemoteUserConfig.php-gU8Kapi/Resources/cache/Symfony/Config/Security/FirewallConfig/LogoutConfig.php#-g#Kapi/Resources/cache/Symfony/Config/Security/AccessDecisionManagerConfig.php-gO^Capi/Resources/cache/Symfony/Config/Security/AccessControlConfig.php-gXAL5api/Resources/cache/Symfony/Config/SecurityConfig.php 1-g 1Y~4api/Resources/cache/Symfony/Config/MonologConfig.php-gFF<api/Resources/cache/Symfony/Config/Monolog/HandlerConfig.php*-g*ՌVapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ProcessPsr3MessagesConfig.php -g ULapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/PublisherConfig.php" -g" -Hapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/RedisConfig.php-gעPapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ElasticsearchConfig.php-g!aQapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/EmailPrototypeConfig.phpZ-gZq:_Hapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/MongoConfig.php-g=oRapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/VerbosityLevelsConfig.php-g=1ޤIapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/PredisConfig.php:-g:f ɤSapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ExcludedHttpCodeConfig.php~-g~4:TKapi/Resources/cache/Symfony/Config/Monolog/HandlerConfig/ChannelsConfig.php-gу6api/Resources/cache/Symfony/Config/FrameworkConfig.php'-g'oATapi/Resources/cache/ContainerHxlxvCx/getSecurity_Firewall_Map_Context_ApiService.php^ -g^ dhWapi/Resources/cache/ContainerHxlxvCx/getContainer_GetRoutingConditionServiceService.php-gcFapi/Resources/cache/ContainerHxlxvCx/getComposerController2Service.php-g|uNapi/Resources/cache/ContainerHxlxvCx/getSecurity_UserCheckerLocatorService.php-g`פNapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_SecretsListService.php-g 0Papi/Resources/cache/ContainerHxlxvCx/getConsole_Command_SecretsRemoveService.php-g*VCapi/Resources/cache/ContainerHxlxvCx/getGraphicsLibCheckService.php-gy|Capi/Resources/cache/ContainerHxlxvCx/getPhpCliControllerService.php-g~_gYapi/Resources/cache/ContainerHxlxvCx/getSecurity_Authenticator_ManagersLocatorService.php-g2$"~Dapi/Resources/cache/ContainerHxlxvCx/getTaskDeleteCommandService.php-gȳ?`api/Resources/cache/ContainerHxlxvCx/get_Console_Command_SecretsEncryptFromLocal_LazyService.php~-g~vGGapi/Resources/cache/ContainerHxlxvCx/getConstraintControllerService.php-gb=Vapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_BackedEnumResolverService.php-gٹ}ߤ4api/Resources/cache/ContainerHxlxvCx/removed-ids.php-g~ 'Gapi/Resources/cache/ContainerHxlxvCx/getProcessRunnerCommandService.php/-g/Capi/Resources/cache/ContainerHxlxvCx/getJwtAuthenticatorService.php-gzq`Capi/Resources/cache/ContainerHxlxvCx/getContaoControllerService.php?-g?n 0Eapi/Resources/cache/ContainerHxlxvCx/getSecurity_AccessMapService.php*-g*@`JHapi/Resources/cache/ContainerHxlxvCx/getIntegrityCheckFactoryService.php?-g?3-Qapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_ContainerDebugService.php)-g)FQWapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_ContainerDebug_LazyService.php(-g(F.Hapi/Resources/cache/ContainerHxlxvCx/getWebauthnAuthenticatorService.php -g )qFapi/Resources/cache/ContainerHxlxvCx/getJwtCookieControllerService.php:-g:(Eapi/Resources/cache/ContainerHxlxvCx/getRouter_CacheWarmerService.phpu-guMäDapi/Resources/cache/ContainerHxlxvCx/getBackupRestoreTaskService.phpL-gL$AHapi/Resources/cache/ContainerHxlxvCx/getConsole_CommandLoaderService.phpN'-gN'׺<api/Resources/cache/ContainerHxlxvCx/getCache_AppService.phpb-gbFʤMapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_SecretsSetService.php-g0Tapi/Resources/cache/ContainerHxlxvCx/getSecurity_Command_UserPasswordHashService.php-gÆHapi/Resources/cache/ContainerHxlxvCx/getConsoleProcessFactoryService.phpd-gdW8\api/Resources/cache/ContainerHxlxvCx/get_Console_Command_ConfigDumpReference_LazyService.php^-g^F8Capi/Resources/cache/ContainerHxlxvCx/getCache_AppClearerService.php-gNAapi/Resources/cache/ContainerHxlxvCx/getUserControllerService.php-gNapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_RouterDebugService.php-g9Qapi/Resources/cache/ContainerHxlxvCx/Contao_ManagerApi_ApiKernelProdContainer.php-gWapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_CachePoolPrune_LazyService.php-gDapi/Resources/cache/ContainerHxlxvCx/getTaskUpdateCommandService.php-gSSAapi/Resources/cache/ContainerHxlxvCx/getTaskControllerService.php-gƵfLapi/Resources/cache/ContainerHxlxvCx/getMaintenanceModeControllerService.php-gAapi/Resources/cache/ContainerHxlxvCx/getFileControllerService.php-g)Japi/Resources/cache/ContainerHxlxvCx/get_ServiceLocator_Y_Xs7MwService.phpT-gT0Aapi/Resources/cache/ContainerHxlxvCx/getRouting_LoaderService.phpN -gN +#>api/Resources/cache/ContainerHxlxvCx/getEnvironmentService.php-gOޤTapi/Resources/cache/ContainerHxlxvCx/getSecurity_Listener_UserChecker_ApiService.php-g L[Capi/Resources/cache/ContainerHxlxvCx/getServicesResetterService.php~-g~eapi/Resources/cache/ContainerHxlxvCx/getCache_SecurityIsGrantedAttributeExpressionLanguageService.php-g'gDapi/Resources/cache/ContainerHxlxvCx/getOpcacheControllerService.php-gPapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_AssetsInstallService.php-g1xӤQapi/Resources/cache/ContainerHxlxvCx/getSerializer_Mapping_CacheWarmerService.php-gѯEapi/Resources/cache/ContainerHxlxvCx/getLoginAuthenticatorService.php-gS/ۤOapi/Resources/cache/ContainerHxlxvCx/getSecurity_EventDispatcher_ApiService.php&-g&t+?api/Resources/cache/ContainerHxlxvCx/getCache_SystemService.php-glAapi/Resources/cache/ContainerHxlxvCx/getMonolog_LoggerService.php-ghFdXapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_CachePoolDelete_LazyService.php+-g+"d )Japi/Resources/cache/ContainerHxlxvCx/getMonolog_Logger_SecurityService.php-gnzؤ@api/Resources/cache/ContainerHxlxvCx/getUpdateCommandService.php-g&jФQapi/Resources/cache/ContainerHxlxvCx/getDebug_ErrorHandlerConfiguratorService.php\-g\DIapi/Resources/cache/ContainerHxlxvCx/getTaskDeleteCommand_LazyService.php-gfUapi/Resources/cache/ContainerHxlxvCx/getSecurity_Access_AuthenticatedVoterService.phpL-gL B?api/Resources/cache/ContainerHxlxvCx/getProcessCheckService.php -g ;82Dapi/Resources/cache/ContainerHxlxvCx/getSessionControllerService.php-g(uVapi/Resources/cache/ContainerHxlxvCx/getSecurity_Listener_PasswordMigratingService.php$-g$TAapi/Resources/cache/ContainerHxlxvCx/getSelfUpdateTaskService.php*-g*VXapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_SerializerDebug_LazyService.php-g¤Fapi/Resources/cache/ContainerHxlxvCx/getCache_GlobalClearerService.phpn-gn3>api/Resources/cache/ContainerHxlxvCx/getTaskManagerService.php -g oHapi/Resources/cache/ContainerHxlxvCx/getConsole_ErrorListenerService.php-g-Kapi/Resources/cache/ContainerHxlxvCx/getUploadPackagesControllerService.php-gwu<api/Resources/cache/ContainerHxlxvCx/getContaoApiService.php^-g^.*Capi/Resources/cache/ContainerHxlxvCx/getMemoryLimitCheckService.php-g"Wapi/Resources/cache/ContainerHxlxvCx/get_Security_Command_DebugFirewall_LazyService.php+-g+qVBapi/Resources/cache/ContainerHxlxvCx/getSysTempDirCheckService.php-g<Vapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_SecretsRemove_LazyService.php-gwl_api/Resources/cache/ContainerHxlxvCx/getArgumentResolver_QueryParameterValueResolverService.php-g?سIapi/Resources/cache/ContainerHxlxvCx/getTaskUpdateCommand_LazyService.php-g*FqCapi/Resources/cache/ContainerHxlxvCx/getConfigControllerService.php-g=api/Resources/cache/ContainerHxlxvCx/getSelfUpdateService.php-g%CCapi/Resources/cache/ContainerHxlxvCx/getTaskAbortCommandService.php-g$@api/Resources/cache/ContainerHxlxvCx/getCloudResolverService.php-g\;^api/Resources/cache/ContainerHxlxvCx/get_Console_Command_SecretsDecryptToLocal_LazyService.php|-g|r6Fapi/Resources/cache/ContainerHxlxvCx/getAccessKeyControllerService.php:-g:11Sapi/Resources/cache/ContainerHxlxvCx/getPropertyInfo_SerializerExtractorService.php$-g$3-8?api/Resources/cache/ContainerHxlxvCx/getUserProviderService.php-g Capi/Resources/cache/ContainerHxlxvCx/getPhpWebControllerService.phpJ-gJӤDapi/Resources/cache/ContainerHxlxvCx/getAboutCommand_LazyService.php-gmPapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_ContainerLintService.php<-g<- Napi/Resources/cache/ContainerHxlxvCx/get_Console_Command_About_LazyService.php-gXțTapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_RouterMatch_LazyService.php-g4=api/Resources/cache/ContainerHxlxvCx/getTranslatorService.php-g$@Gapi/Resources/cache/ContainerHxlxvCx/getSelfUpdateControllerService.php-gKapi/Resources/cache/ContainerHxlxvCx/getSecurity_ChannelListenerService.php-gLLapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_VariadicService.php-gvR*Dapi/Resources/cache/ContainerHxlxvCx/getManagerControllerService.php7-g7gKvCapi/Resources/cache/ContainerHxlxvCx/getBackupControllerService.php-gށxBapi/Resources/cache/ContainerHxlxvCx/getSecurity_HelperService.php;-g;"ᖤQapi/Resources/cache/ContainerHxlxvCx/getSecurity_Listener_UserProviderService.php-g$ؤQapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_YamlLint_LazyService.php-gvʖ@api/Resources/cache/ContainerHxlxvCx/getSecrets_VaultService.phpE-gEN摤Vapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_ConfigDumpReferenceService.phpN-gNr8Napi/Resources/cache/ContainerHxlxvCx/getConsole_Command_CacheWarmupService.phpS-gSOk3Uapi/Resources/cache/ContainerHxlxvCx/getSecurity_Access_RoleHierarchyVoterService.php*-g* ?Tapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_RequestAttributeService.php-go%Capi/Resources/cache/ContainerHxlxvCx/getBackupCreateTaskService.phpG-gGPs-RLapi/Resources/cache/ContainerHxlxvCx/getProcessRunnerCommand_LazyService.php-gڒ$Rapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_CachePoolDeleteService.phpt-gtcBapi/Resources/cache/ContainerHxlxvCx/getCloudControllerService.phpm-gmh.Ф<api/Resources/cache/ContainerHxlxvCx/getSetupTaskService.phpX-gX>?qSapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_SecretsSet_LazyService.php-gAEapi/Resources/cache/ContainerHxlxvCx/getTemplateControllerService.php-gsZapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_CachePoolInvalidateTagsService.php-g 1w]api/Resources/cache/ContainerHxlxvCx/get_Console_Command_EventDispatcherDebug_LazyService.phpg-gg wVapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_CachePoolList_LazyService.php-gԢWapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_EventDispatcherDebugService.php-gE;Kapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_ServiceService.php-gU댋`api/Resources/cache/ContainerHxlxvCx/get_Console_Command_CachePoolInvalidateTags_LazyService.php-g{ʳTapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_CacheWarmup_LazyService.php-gFapi/Resources/cache/ContainerHxlxvCx/getCache_SystemClearerService.php-gS\Japi/Resources/cache/ContainerHxlxvCx/get_ServiceLocator_BvkMlPlService.phpP-gP Gapi/Resources/cache/ContainerHxlxvCx/getMonolog_Logger_TasksService.php-gۤFapi/Resources/cache/ContainerHxlxvCx/getAdminUserControllerService.phpB-gBJHapi/Resources/cache/ContainerHxlxvCx/getIntegrityCheckCommandService.php-gPVapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_AssetsInstall_LazyService.php)-g)ۊ[api/Resources/cache/ContainerHxlxvCx/getSecurity_Firewall_EventDispatcherLocatorService.php-g%BۤRapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_SerializerDebugService.php-gRGEapi/Resources/cache/ContainerHxlxvCx/getPhpExtensionsCheckService.php(-g(\ jdKapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_DefaultService.php-gn8Aapi/Resources/cache/ContainerHxlxvCx/getAuthControllerService.php-gtLapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_DatetimeService.php-g:sGapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_UidService.php-gLapi/Resources/cache/ContainerHxlxvCx/getInstallToolLockControllerService.php-gLtEapi/Resources/cache/ContainerHxlxvCx/getUpdateCommand_LazyService.php-gfkEapi/Resources/cache/ContainerHxlxvCx/getComposerControllerService.php>-g>Kapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_SessionService.php-gx>api/Resources/cache/ContainerHxlxvCx/getCacheWarmerService.php-g:eEapi/Resources/cache/ContainerHxlxvCx/getRedirectControllerService.php-gCI1@api/Resources/cache/ContainerHxlxvCx/getUploadsConfigService.php-g烛Napi/Resources/cache/ContainerHxlxvCx/getDatabaseMigrationControllerService.php=-g=]Kapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_YamlLintService.php -g `g"Gapi/Resources/cache/ContainerHxlxvCx/getConfigBuilder_WarmerService.php-g4!Lapi/Resources/cache/ContainerHxlxvCx/getPasswordlessAuthenticatorService.php-g4Aapi/Resources/cache/ContainerHxlxvCx/getClearCacheTaskService.phpE-gEF9Hapi/Resources/cache/ContainerHxlxvCx/getRootPackageControllerService.phpQ-gQ^Eapi/Resources/cache/ContainerHxlxvCx/getCache_App_TaggableService.php-g(4k@api/Resources/cache/ContainerHxlxvCx/getContaoConsoleService.php -g @api/Resources/cache/ContainerHxlxvCx/getManagerConfigService.php-gTnMapi/Resources/cache/ContainerHxlxvCx/getSecurity_UserValueResolverService.php-g@wѤXapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_DebugAutowiring_LazyService.php8-g8!qQapi/Resources/cache/ContainerHxlxvCx/getSecurity_Command_DebugFirewallService.php-g V߂bapi/Resources/cache/ContainerHxlxvCx/getSecurity_Listener_CheckAuthenticatorCredentialsService.phpH-gHڄWapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_CachePoolClear_LazyService.php-gUMapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_CacheClearService.php-g(񯨤Dapi/Resources/cache/ContainerHxlxvCx/getPhpinfoControllerService.php-gkPapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_CachePoolListService.php-g֨Uapi/Resources/cache/ContainerHxlxvCx/getSecurity_Authenticator_Manager_ApiService.php-g?Eapi/Resources/cache/ContainerHxlxvCx/getAllowUrlFopenCheckService.php(-g(KQ@Capi/Resources/cache/ContainerHxlxvCx/getRebuildCacheTaskService.phpp-gpp}Vapi/Resources/cache/ContainerHxlxvCx/getSecurity_Firewall_Authenticator_ApiService.php-grФ[api/Resources/cache/ContainerHxlxvCx/get_Console_Command_SecretsGenerateKey_LazyService.phpE-gEF0Tapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_RouterDebug_LazyService.php -g d)ܒQapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_CachePoolClearService.php_-g_@api/Resources/cache/ContainerHxlxvCx/getLogControllerService.php*-g*]%Lapi/Resources/cache/ContainerHxlxvCx/getContainer_EnvVarProcessorService.php,-g,[Uapi/Resources/cache/ContainerHxlxvCx/getSecurity_Listener_Api_UserProviderService.php!-g!Og>api/Resources/cache/ContainerHxlxvCx/getInstallTaskService.php#-g#HӤTapi/Resources/cache/ContainerHxlxvCx/getContainer_EnvVarProcessorsLocatorService.php -g Dapi/Resources/cache/ContainerHxlxvCx/getExceptionListenerService.php-g Te?api/Resources/cache/ContainerHxlxvCx/getSymlinkCheckService.phpJ-gJ:api/Resources/cache/ContainerHxlxvCx/getRequestService.php-g?m?api/Resources/cache/ContainerHxlxvCx/getSessionCheckService.php -g `Lapi/Resources/cache/ContainerHxlxvCx/getMissingPackagesControllerService.phpe-gevUapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_SecretsGenerateKeyService.php8-g8'=api/Resources/cache/ContainerHxlxvCx/getUpdateTaskService.php-gWqTapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_SecretsList_LazyService.php-gvAapi/Resources/cache/ContainerHxlxvCx/getComposerConfigService.php -g wGZapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_SecretsEncryptFromLocalService.php`-g`ADJapi/Resources/cache/ContainerHxlxvCx/getSecurity_AccessListenerService.php-g5-Qapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_CachePoolPruneService.php-g3#Zapi/Resources/cache/ContainerHxlxvCx/get_Security_Command_UserPasswordHash_LazyService.php6-g6ۤNapi/Resources/cache/ContainerHxlxvCx/getSecurity_RouteLoader_LogoutService.php-gs Tapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_ConfigDebug_LazyService.php-ggEapi/Resources/cache/ContainerHxlxvCx/getDatabaseControllerService.php-gNXapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_SecretsDecryptToLocalService.phpd-gdJapi/Resources/cache/ContainerHxlxvCx/getLocalPackagesControllerService.php[-g[/ -?api/Resources/cache/ContainerHxlxvCx/getAboutCommandService.php-g>{$Hapi/Resources/cache/ContainerHxlxvCx/getTaskAbortCommand_LazyService.php-g|Vapi/Resources/cache/ContainerHxlxvCx/getSecurity_SecurityTokenValueResolverService.php@-g@hEapi/Resources/cache/ContainerHxlxvCx/getTokenAuthenticatorService.php-gUt+Rapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_DebugAutowiringService.php-gN&=api/Resources/cache/ContainerHxlxvCx/getServerInfoService.php-g9Napi/Resources/cache/ContainerHxlxvCx/getConsole_Command_RouterMatchService.php-gmMapi/Resources/cache/ContainerHxlxvCx/getIntegrityCheckCommand_LazyService.php-gHKJapi/Resources/cache/ContainerHxlxvCx/get_ServiceLocator_AH5O6SdService.phph-gh Bapi/Resources/cache/ContainerHxlxvCx/getErrorControllerService.php-guZJapi/Resources/cache/ContainerHxlxvCx/get_ServiceLocator_EZsc_DOService.phpb-gbHWSapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_CacheClear_LazyService.php-g Kapi/Resources/cache/ContainerHxlxvCx/getArgumentResolver_RequestService.php-gOxPapi/Resources/cache/ContainerHxlxvCx/RequestPayloadValueResolverGhost8d82153.phpp-gp0ϤHapi/Resources/cache/ContainerHxlxvCx/getConsole_Command_AboutService.php-gǤCapi/Resources/cache/ContainerHxlxvCx/getDumpAutoloadTaskService.phpO-gO Vapi/Resources/cache/ContainerHxlxvCx/get_Console_Command_ContainerLint_LazyService.php8-g8 Napi/Resources/cache/ContainerHxlxvCx/getConsole_Command_ConfigDebugService.php-gY:y#api/Resources/cache/annotations.map-gr'"api/Resources/config/services.yaml -g ?ʊ$api/Resources/config/config_dev.yaml-g%api/Resources/config/config_prod.yaml-gH  api/Resources/config/config.yaml*-g*"Hapi/Resources/i18n/cs.ymll-glzapi/Resources/i18n/br.yml-gapi/Resources/i18n/es.yml-gk3?api/Resources/i18n/pt.yml-g򍤤api/Resources/i18n/de.yml-g|Eapi/Resources/i18n/it.yml-gk6api/Resources/i18n/pl.yml-gOyapi/Resources/i18n/fa.yml; -g; 1,api/Resources/i18n/sv.yml-g9詤api/Resources/i18n/en.yml!-g!sapi/Resources/i18n/ja.ymlX-gXdapi/Resources/i18n/ru.ymlh-gh Vapi/Resources/i18n/sr.yml-g"\api/Resources/i18n/fr.yml-g0api/Resources/i18n/lv.ymlx-gxMapi/Resources/i18n/tr.yml8-g8Eyapi/Resources/i18n/nl.yml-gUapi/Resources/i18n/zh.yml -g ;Ϥapi/ApiApplication.php -g -r#api/Tests/Composer/CloudJobTest.php-g!L'api/Tests/Controller/LogPatternTest.php0-g0Ly!api/Controller/FileController.phpU-gU_ќ!api/Controller/UserController.php=-g=  api/Controller/LogController.php-g'%(api/Controller/Config/AuthController.php-g 2api/Controller/Config/AbstractConfigController.php-g*api/Controller/Contao/BackupController.php,-g,>]63api/Controller/Contao/MaintenanceModeController.php-g$iW-api/Controller/Contao/JwtCookieController.php -g bˤapi/ApiKernel.php=&-g=&\api/System/ServerInfo.php-gR api/System/Request.php-g#Eapi/System/SelfUpdate.phpD-gDqׂapi/Task/TaskStatus.php-gS!~'&api/Task/Composer/DumpAutoloadTask.php-gWj$api/Task/Composer/ClearCacheTask.php-g#api/Task/Manager/SelfUpdateTask.php-g @?&api/Task/AbstractTask.php -g ΪGapi/Task/Packages/SetupTask.php -g 3P api/Task/Packages/UpdateTask.php1(-g1(B!api/Task/Packages/InstallTask.php -g }Kݤ*api/Task/Packages/AbstractPackagesTask.phpY-gY$api/Task/Contao/BackupCreateTask.php-gE%api/Task/Contao/BackupRestoreTask.php-gUF$api/Task/Contao/RebuildCacheTask.php -g lKapi/Task/TaskManager.php-g)FŤapi/Task/TaskInterface.php-g1mapi/Task/TaskConfig.php -g /ʤ%api/Command/IntegrityCheckCommand.php -g api/Command/UpdateCommand.php-g% api/Command/TaskAbortCommand.phpJ-gJ{P峤!api/Command/TaskUpdateCommand.phpz-gzk$api/Command/ProcessRunnerCommand.phpy-gy`݃yapi/Command/AboutCommand.phpY-gYɜ!api/Command/TaskDeleteCommand.phpa-ga Wapi/I18n/Translator.php -g q %api/Exception/ApiProblemException.php5-g5W{(api/Exception/ProcessOutputException.php-go&api/Exception/InvalidTotpException.php-gʤ&api/Exception/InvalidJsonException.php -g 8Y"api/Exception/RequestException.php-gŰ)api/IntegrityCheck/AllowUrlFopenCheck.php%-g%z2Ť'api/IntegrityCheck/GraphicsLibCheck.php-gkp¤api/IntegrityCheck/ZipCheck.php-gk"&api/IntegrityCheck/SysTempDirCheck.php-g)Z.api/IntegrityCheck/IntegrityCheckInterface.php~-g~#api/IntegrityCheck/ProcessCheck.php-g\.sg#api/IntegrityCheck/SymlinkCheck.php-g,#api/IntegrityCheck/SessionCheck.php-g˭K'api/IntegrityCheck/MemoryLimitCheck.phpK-gK^)api/IntegrityCheck/PhpExtensionsCheck.php-g :-api/IntegrityCheck/AbstractIntegrityCheck.php-g,api/IntegrityCheck/IntegrityCheckFactory.php-gR,api/Process/ContaoApi.phpF-gFB!api/Process/ProcessController.php-g٧e%api/Process/Forker/AbstractForker.php -g ȮH&api/Process/Forker/ForkerInterface.phpn-gn|5oq#api/Process/Forker/DisownForker.php-gw4h"api/Process/Forker/NohupForker.php-gZA)api/Process/Forker/WindowsStartForker.php-ga\"#api/Process/Forker/InlineForker.php-gѶ#api/Process/Utf8Process.php-gxapi/Process/ProcessRunner.php-g|Eapi/Process/AbstractProcess.php-g6?=api/Process/ContaoConsole.php -g v)1#api/Process/PhpExecutableFinder.php-gr%api/Process/ConsoleProcessFactory.php-g5  api/console8 -g8 i.$api/EventListener/LocaleListener.php-g.ʴ,'api/EventListener/ExceptionListener.php~ -g~ &api/EventListener/SecurityListener.php-gO'api/EventListener/CheckTotpListener.php-g5%T)api/EventListener/JsonRequestListener.phpM-gMä downgrade.php0-g08-ˤ$vendor/seld/phar-utils/composer.lock/-g/cւ(vendor/seld/phar-utils/LICENSE"-g"?e vendor/seld/phar-utils/README.mde-ge:N$vendor/seld/phar-utils/composer.json;-g;=%vendor/seld/phar-utils/src/Linter.php -g #: )vendor/seld/phar-utils/src/Timestamps.phpk-gkFvendor/seld/jsonlint/LICENSE"-g"asy!vendor/seld/jsonlint/bin/jsonlint -g !vendor/seld/jsonlint/CHANGELOG.md -g ݣʤvendor/seld/jsonlint/README.md -g f"vendor/seld/jsonlint/composer.jsonU-gUTR@vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php-gArQ;vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php-gm2;0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php"-g"; 4vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php*-g*5vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php,_-g,_v"vendor/seld/signal-handler/LICENSE"-g"?e(vendor/seld/signal-handler/composer.json-gc0vendor/seld/signal-handler/src/SignalHandler.phpO-gO,Cvendor/autoload.php-gZǤ$vendor/phpstan/phpdoc-parser/LICENSEQ-gQw&vendor/phpstan/phpdoc-parser/README.md-g0h)vendor/phpstan/phpdoc-parser/UPGRADING.md#-g#&~g*vendor/phpstan/phpdoc-parser/composer.json-gR 0vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php-g&eo5vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php-g 3vendor/phpstan/phpdoc-parser/src/Printer/Differ.phpj-gjyT4vendor/phpstan/phpdoc-parser/src/Printer/Printer.phpG-gG|"&v;vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php -g 2Ф8vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.phpޭ-gޭa;vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php!-g!HH;vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php\ -g\ k'#6vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php_-g_YeG9vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php8)-g8)\j1vendor/phpstan/phpdoc-parser/src/ParserConfig.php`-g`KäVvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php-g;Avendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php-g0Dvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php-gBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php:-g: fBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php-g}Uvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php-gOS^Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php-gckJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php-g-Mvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php-gZ3Fvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php-g^Ĥ>vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php-gh%:vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.phpI)-gI)Lvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php--g-=HCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php-g~TEvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.phpc-gcBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php-g^T@vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php-gZ!KKvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php4-g4ܤIvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php-g=Kvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php-g;kMvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php-gj$ѤJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php-gKFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php-g(ҤCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php-g^ߤ?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.phpL-gLKHx=vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php-gɿDvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php%-g%Ivendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php-gm#wHvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php-g{֤Kvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php-gjWDvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php -g 7b![vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php-g'D?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php-g)5QCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php-gݤAvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.phpU-gU~,Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php-g7ǤCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php-gL~Fvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php-gK]CJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php-g>Avendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php-g"iTEvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.phpF-gFY7@vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php-gFvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php -g &mDvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php5-g5#6Gvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php-g80Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php7-g7c󷯤Ivendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php-gۋDvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php5-g5"Nvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.phpt-gt<Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php-gGʤ4vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php -g һcCvendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php -g 2vendor/phpstan/phpdoc-parser/src/Ast/Attribute.phpp-gpB-vendor/phpstan/phpdoc-parser/src/Ast/Node.php-gI ;vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php-g'¤Bvendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php -g m@vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php-gz21@vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php-go=;vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php-gV0 Gvendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php-g>vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.phpz-gzz"6vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php-g9Avendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php-g[Z:vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php'-g'|=vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.phpR-gR7Nf=vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.phpg-ggLBvendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php-g4Avendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php-gRפHvendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php-gtMvendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php-g+ $>vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php-gqo<vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php-g\鿤=vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php.-g. 3;vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.phpi-giz#vendor/lcobucci/clock/renovate.json-g]G(#vendor/lcobucci/clock/composer.json,-g,;#vendor/lcobucci/clock/src/Clock.php-g* )vendor/lcobucci/clock/src/FrozenClock.php*-g*8o)vendor/lcobucci/clock/src/SystemClock.php-gvendor/bin/yaml-lint -g 8vendor/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStep.php-gujv>vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckCounter.php-gʤ@vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckTopOrigin.php-g"=vendor/web-auth/webauthn-lib/src/CeremonyStep/CheckOrigin.php -g ŤAvendor/web-auth/webauthn-lib/src/CeremonyStep/CheckExtensions.phpt-gt=Hvendor/web-auth/webauthn-lib/src/CeremonyStep/CheckMetadataStatement.php -g `Lvendor/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php-g^frBvendor/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php -g yP7vendor/web-auth/webauthn-lib/src/CertificateToolbox.php-gµVvendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.php-g;k[vendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php}-g}%}hbvendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php-g`iRvendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php-gH'Uvendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php-gRTvendor/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php-gDAcvendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php-g QTivendor/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php-gD+evendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php66-g66v\vendor/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.phpZ-gZTZvendor/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.phpR-gR9Yvendor/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.phpz-gz| Uvendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php-g0HäQvendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php-ga[vendor/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php+-g+ɯKvendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php-g_f_vendor/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.phpM"-gM"O~O\vendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php-goXvendor/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php=-g=$3YNvendor/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php-g*>vendor/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php-gx&Bvendor/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php-gAݤ>vendor/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php-gjhդHvendor/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php-gKvendor/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php-gɗCڤQvendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php-gWEvendor/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.phph-gh <vendor/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php`-g`_nW0vendor/web-auth/webauthn-lib/src/Util/Base64.phps-gsݤ;vendor/web-auth/webauthn-lib/src/AttestedCredentialData.php -g sr/vendor/web-auth/webauthn-lib/src/Credential.php-ghNvendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.phpd2-gd2sBvendor/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php -g #8rBvendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php -g 9\o@vendor/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.phpX-gX{BEvendor/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php-gJ?vendor/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php-g^96vendor/web-auth/webauthn-lib/src/AuthenticatorData.phpo -go WoLvendor/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php-g ?Ҥ:vendor/web-auth/webauthn-lib/src/AuthenticatorResponse.php-gJLvendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php0-g0D ߤCvendor/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php=-g=ȪWvendor/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php-g{ϤTvendor/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php-g2ƤFvendor/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php.-g.Dg<vendor/web-auth/webauthn-lib/src/AuthenticatorDataLoader.php-gLڤHvendor/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php -g z>vendor/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php-g@bBvendor/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php-g,q8vendor/web-auth/webauthn-lib/src/TrustPath/TrustPath.php-g"ߣ=vendor/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php-gb_Cvendor/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php-gA#>vendor/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php-g Lvendor/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.phpA-gAУSvendor/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php-g[6Xvendor/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php-g=mDvendor/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.phpw-gwQvendor/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.phpC-gCe0@Ovendor/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php0 -g0 ҨKvendor/web-auth/webauthn-lib/src/MetadataService/Statement/StatusReport.php7-g7P [vendor/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php!-g! +9Vvendor/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php+-g+cZvendor/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricAccuracyDescriptor.php -g nX}}Fvendor/web-auth/webauthn-lib/src/MetadataService/Statement/Version.phpV -gV Nvendor/web-auth/webauthn-lib/src/MetadataService/Statement/RgbPaletteEntry.php\ -g\ PnuMvendor/web-auth/webauthn-lib/src/MetadataService/Statement/RogueListEntry.php-gx"#bvendor/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php-g꠼@vendor/web-auth/webauthn-lib/src/MetadataService/ValueFilter.phpo-gojPOϤavendor/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php-gЋz dvendor/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php -g yxavendor/web-auth/webauthn-lib/src/MetadataService/Service/FidoAllianceCompliantMetadataService.php'-g'+X5դPvendor/web-auth/webauthn-lib/src/MetadataService/Service/JsonMetadataService.php -g KRvendor/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php-g:)ĤUvendor/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php-g7[vendor/web-auth/webauthn-lib/src/MetadataService/Service/DistantResourceMetadataService.php-gfBPvendor/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php-g4 nLvendor/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php-gYvendor/web-auth/webauthn-lib/src/MetadataService/Service/LocalResourceMetadataService.php -g iTvendor/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php -g Zvendor/web-auth/webauthn-lib/src/MetadataService/Service/FolderResourceMetadataService.php -g -NZTvendor/web-auth/webauthn-lib/src/MetadataService/Service/InMemoryMetadataService.phpA-gATZvendor/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php-gz]Wvendor/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php-gY1صZvendor/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php-gg/Svendor/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.phpq-gqh`vendor/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php-gm%Zvendor/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php-g/`vendor/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php-g/VYvendor/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php-gc Xvendor/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php-g]ཤavendor/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php-g[Lvendor/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.phpU-gUxHvendor/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.phpA-gAo[vendor/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php-g-g> Jvendor/web-auth/webauthn-lib/src/Exception/ExpiredCertificateException.php-gpJvendor/web-auth/webauthn-lib/src/Exception/UnsupportedFeatureException.php5-g5GCvendor/web-auth/webauthn-lib/src/Exception/CertificateException.phpO-gOZlPvendor/web-auth/webauthn-lib/src/Exception/MissingMetadataStatementException.php;-g;)<ԤJvendor/web-auth/webauthn-lib/src/Exception/RevokedCertificateException.php-gcOLvendor/web-auth/webauthn-lib/src/Exception/AttestationStatementException.php-gnPvendor/web-auth/webauthn-lib/src/Exception/MetadataStatementLoadingException.phpz-gz$BC?vendor/web-auth/webauthn-lib/src/Exception/CounterException.phpL-gLIvendor/web-auth/webauthn-lib/src/Exception/MetadataStatementException.php-gngHvendor/web-auth/webauthn-lib/src/Exception/CertificateChainException.php-g[4ۤSvendor/web-auth/webauthn-lib/src/Exception/AttestationStatementLoadingException.php-gCvendor/web-auth/webauthn-lib/src/Exception/InvalidDataException.php-gޘ+Qvendor/web-auth/webauthn-lib/src/Exception/CertificateRevocationListException.php-gq9Ivendor/web-auth/webauthn-lib/src/Exception/InvalidUserHandleException.phpe-ge|1vendor/web-auth/webauthn-lib/src/U2FPublicKey.php-gT<vendor/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php-g':cvendor/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php7-g7\Z8vendor/web-auth/webauthn-lib/src/Event/WebauthnEvent.phpg-gg>GBvendor/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php-gobavendor/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php -g ^vendor/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationFailedEvent.php -g o~֤Kvendor/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.phpX-gX/Kvendor/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.phpX-gXpNvendor/web-auth/webauthn-lib/src/Event/CertificateChainValidationSucceeded.php[-g[(ɤAvendor/web-auth/webauthn-lib/src/Event/MetadataStatementFound.php-g >vendor/web-auth/webauthn-lib/src/Event/NullEventDispatcher.php8-g8}o`vendor/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php-gvendor/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php"-g"IkGvendor/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.phpo)-go)í8vendor/web-auth/webauthn-lib/src/CollectedClientData.phpr-gr+Ĥ vendor/web-auth/cose-lib/LICENSE,-g,C"vendor/web-auth/cose-lib/README.md-gŬ&vendor/web-auth/cose-lib/composer.json-gB:+j$vendor/web-auth/cose-lib/SECURITY.md-gY{%vendor/web-auth/cose-lib/src/Hash.php-g8pȤ(vendor/web-auth/cose-lib/src/Key/Key.php -g o+vendor/web-auth/cose-lib/src/Key/RsaKey.php -g ZΤ1vendor/web-auth/cose-lib/src/Key/SymmetricKey.php-gf+vendor/web-auth/cose-lib/src/Key/Ec2Key.php-gʤ+vendor/web-auth/cose-lib/src/Key/OkpKey.php -g ?9vendor/web-auth/cose-lib/src/Algorithm/ManagerFactory.php-gE@vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php-gU0@vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php-gAf@vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php-g"8Fvendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php-g3yAvendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php-g8@vendor/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php-gˤ<vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php-g]2<vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php-g#2>vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php-g f¤>vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php-g掤>vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php-g {>vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php-g>vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php-g*(z?vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php\-g\i">vendor/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php-gkJ@vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed512.php-gƩK@vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php-g~e0@vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed256.php-gXyBvendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php@-g@ >vendor/web-auth/cose-lib/src/Algorithm/Signature/Signature.phpV-gV;4vendor/web-auth/cose-lib/src/Algorithm/Algorithm.php-g= h4vendor/web-auth/cose-lib/src/Algorithm/Mac/HS512.php-g4X e3vendor/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php-gJd2vendor/web-auth/cose-lib/src/Algorithm/Mac/Mac.phpJ-gJl'4vendor/web-auth/cose-lib/src/Algorithm/Mac/HS384.php-g5YF?vendor/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php-gy4vendor/web-auth/cose-lib/src/Algorithm/Mac/HS256.php-g2vendor/web-auth/cose-lib/src/Algorithm/Manager.php-g,+vendor/web-auth/cose-lib/src/BigInteger.php-gYy+vendor/web-auth/cose-lib/src/Algorithms.phpX-gXS@'vendor/composer/autoload_namespaces.php-g/t&vendor/composer/xdebug-handler/LICENSE)-g)#;^+vendor/composer/xdebug-handler/CHANGELOG.md-g!YsK(vendor/composer/xdebug-handler/README.md4-g4S%,vendor/composer/xdebug-handler/composer.jsony-gy-0vendor/composer/xdebug-handler/src/PhpConfig.php-g]-vendor/composer/xdebug-handler/src/Status.phpz-gz"4vendor/composer/xdebug-handler/src/XdebugHandler.phpKV-gKVEb.vendor/composer/xdebug-handler/src/Process.phpH -gH G+vendor/composer/class-map-generator/LICENSE-gDӤ-vendor/composer/class-map-generator/README.mdN-gNK(1vendor/composer/class-map-generator/composer.json-g|(~=vendor/composer/class-map-generator/src/ClassMapGenerator.phpk6-gk62Bgn:vendor/composer/class-map-generator/src/PhpFileCleaner.php?-g?s4vendor/composer/class-map-generator/src/FileList.phpc-gcr59vendor/composer/class-map-generator/src/PhpFileParser.php-g8C4vendor/composer/class-map-generator/src/ClassMap.php-gvendor/composer/LICENSE.-g. vendor/composer/ClassLoader.php?-g?2@u+vendor/composer/composer/phpstan/rules.neon-g~d1vendor/composer/composer/res/composer-schema.json-g|Ȥ6vendor/composer/composer/res/composer-lock-schema.json -g rf<vendor/composer/composer/res/composer-repository-schema.json -g 븂&vendor/composer/composer/composer.lockK-gK k vendor/composer/composer/LICENSE,-g,Vg%vendor/composer/composer/bin/composer -g -0~$vendor/composer/composer/bin/compile-g\0&vendor/composer/composer/composer.json-gSv'Svendor/composer/composer/src/Composer/PHPStan/RuleReasonDataReturnTypeExtension.php -g Kvendor/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.phpL"-gL"W1vendor/composer/composer/src/Composer/Factory.php-gz0Hvendor/composer/composer/src/Composer/Repository/RepositoryInterface.php-gйRvendor/composer/composer/src/Composer/Repository/InstalledFilesystemRepository.php-gJ=Fvendor/composer/composer/src/Composer/Repository/PackageRepository.phpl-gl+Z%Hvendor/composer/composer/src/Composer/Repository/LockArrayRepository.php-gȤGvendor/composer/composer/src/Composer/Repository/PlatformRepository.php-g,+Fvendor/composer/composer/src/Composer/Repository/RepositoryFactory.php$ -g$ 8lQvendor/composer/composer/src/Composer/Repository/InstalledRepositoryInterface.php-g+Pvendor/composer/composer/src/Composer/Repository/WritableRepositoryInterface.php@-g@ekDvendor/composer/composer/src/Composer/Repository/RepositoryUtils.php -g Pvendor/composer/composer/src/Composer/Repository/RepositorySecurityException.php-gl ФHvendor/composer/composer/src/Composer/Repository/CompositeRepository.php-g$ )Dvendor/composer/composer/src/Composer/Repository/ArrayRepository.phpw(-gw(x)Lvendor/composer/composer/src/Composer/Repository/WritableArrayRepository.php -g X Bvendor/composer/composer/src/Composer/Repository/VcsRepository.phpR-gRBqGvendor/composer/composer/src/Composer/Repository/ComposerRepository.php1-g1h)Cvendor/composer/composer/src/Composer/Repository/PearRepository.php`-g`Bvendor/composer/composer/src/Composer/Repository/RepositorySet.phpA-gA_OGvendor/composer/composer/src/Composer/Repository/ArtifactRepository.php-geJvendor/composer/composer/src/Composer/Repository/RootPackageRepository.php:-g:V>Fvendor/composer/composer/src/Composer/Repository/RepositoryManager.php-gnHEvendor/composer/composer/src/Composer/Repository/Vcs/GitHubDriver.phpZ-gZUsBvendor/composer/composer/src/Composer/Repository/Vcs/VcsDriver.php-grOBvendor/composer/composer/src/Composer/Repository/Vcs/SvnDriver.php3-g3ʍEAvendor/composer/composer/src/Composer/Repository/Vcs/HgDriver.php6-g6 Gvendor/composer/composer/src/Composer/Repository/Vcs/PerforceDriver.php-g%6ɤKvendor/composer/composer/src/Composer/Repository/Vcs/GitBitbucketDriver.php8-g8MnBvendor/composer/composer/src/Composer/Repository/Vcs/GitDriver.php!-g!ZfEvendor/composer/composer/src/Composer/Repository/Vcs/GitLabDriver.php4R-g4R\6LKvendor/composer/composer/src/Composer/Repository/Vcs/VcsDriverInterface.php -g O 4ۤEvendor/composer/composer/src/Composer/Repository/Vcs/FossilDriver.php\-g\b:Cvendor/composer/composer/src/Composer/Repository/PathRepository.phpK"-gK"-ƤJvendor/composer/composer/src/Composer/Repository/VersionCacheInterface.phpd-gd~Kvendor/composer/composer/src/Composer/Repository/CanonicalPackagesTrait.php-g=Evendor/composer/composer/src/Composer/Repository/FilterRepository.php-gXHvendor/composer/composer/src/Composer/Repository/InstalledRepository.phpI3-gI3̤Nvendor/composer/composer/src/Composer/Repository/AdvisoryProviderInterface.php-gXD@Ivendor/composer/composer/src/Composer/Repository/FilesystemRepository.php??-g?? WMvendor/composer/composer/src/Composer/Repository/InstalledArrayRepository.php-gf~Tvendor/composer/composer/src/Composer/Repository/ConfigurableRepositoryInterface.php-gF*'Ovendor/composer/composer/src/Composer/Repository/InvalidRepositoryException.php-gf=<vendor/composer/composer/src/Composer/Util/PackageSorter.phpN-gN8 >vendor/composer/composer/src/Composer/Util/ConfigValidator.php[$-g[$zf2vendor/composer/composer/src/Composer/Util/Git.phpqi-gqi2vendor/composer/composer/src/Composer/Util/Svn.php&-g&sH=vendor/composer/composer/src/Composer/Util/NoProxyPattern.php)-g)x=vendor/composer/composer/src/Composer/Util/ComposerMirror.phpW -gW ~w:vendor/composer/composer/src/Composer/Util/PackageInfo.phpA-gA#R9vendor/composer/composer/src/Composer/Util/AuthHelper.php8-g82vendor/composer/composer/src/Composer/Util/Zip.phpR -gR Aä7vendor/composer/composer/src/Composer/Util/Silencer.php/-g/<9vendor/composer/composer/src/Composer/Util/Filesystem.phpd{-gd{d}`2vendor/composer/composer/src/Composer/Util/Tar.php-g Ǥ5vendor/composer/composer/src/Composer/Util/GitHub.php!-g!j\ v5vendor/composer/composer/src/Composer/Util/GitLab.php/-g/|!8vendor/composer/composer/src/Composer/Util/Bitbucket.php9&-g9& ǽ =vendor/composer/composer/src/Composer/Util/HttpDownloader.php)H-g)Hs%G8vendor/composer/composer/src/Composer/Util/IniHelper.phpm-gm7r7vendor/composer/composer/src/Composer/Util/Platform.php,*-g,*LCvendor/composer/composer/src/Composer/Util/StreamContextFactory.php"-g"?x8vendor/composer/composer/src/Composer/Util/TlsHelper.php-g5FϤ2vendor/composer/composer/src/Composer/Util/Url.php-gʉ٤7vendor/composer/composer/src/Composer/Util/Perforce.php2L-g2L Ǥ@vendor/composer/composer/src/Composer/Util/Http/ProxyManager.php-gewY<vendor/composer/composer/src/Composer/Util/Http/Response.phpa -ga ^@vendor/composer/composer/src/Composer/Util/Http/RequestProxy.php-gMgBvendor/composer/composer/src/Composer/Util/Http/CurlDownloader.phpy-gy'B@vendor/composer/composer/src/Composer/Util/Http/CurlResponse.php-g1'ɤ=vendor/composer/composer/src/Composer/Util/Http/ProxyItem.php-g=eY?vendor/composer/composer/src/Composer/Util/MetadataMinifier.php-g#`>vendor/composer/composer/src/Composer/Util/ProcessExecutor.phpE-gE5U1vendor/composer/composer/src/Composer/Util/Hg.php-gQ5?vendor/composer/composer/src/Composer/Util/RemoteFilesystem.php?l-g?lq';vendor/composer/composer/src/Composer/Util/ErrorHandler.php, -g, JC9vendor/composer/composer/src/Composer/Util/SyncHelper.php -g ެpQ3vendor/composer/composer/src/Composer/Util/Loop.php2-g2Avendor/composer/composer/src/Composer/Config/JsonConfigSource.phpv)-gv)Fvendor/composer/composer/src/Composer/Config/ConfigSourceInterface.phpf-gf(פ=vendor/composer/composer/src/Composer/SelfUpdate/Versions.php-g.]!9vendor/composer/composer/src/Composer/SelfUpdate/Keys.php-g-*/vendor/composer/composer/src/Composer/Cache.php+-g+@U?vendor/composer/composer/src/Composer/EventDispatcher/Event.php-g~kRvendor/composer/composer/src/Composer/EventDispatcher/ScriptExecutionException.php-g;;Ivendor/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php-g_JRvendor/composer/composer/src/Composer/EventDispatcher/EventSubscriberInterface.phpu-guh_}9vendor/composer/composer/src/Composer/PartialComposer.php' -g' c:vendor/composer/composer/src/Composer/Platform/Runtime.php -g :K(?vendor/composer/composer/src/Composer/Platform/HhvmDetector.php-gH껥:vendor/composer/composer/src/Composer/Platform/Version.php -g \ 5vendor/composer/composer/src/Composer/IO/BufferIO.php -g '˄6vendor/composer/composer/src/Composer/IO/ConsoleIO.phpK)-gK)51 3vendor/composer/composer/src/Composer/IO/BaseIO.phpX#-gX#3vendor/composer/composer/src/Composer/IO/NullIO.php -g {8vendor/composer/composer/src/Composer/IO/IOInterface.phpZ -gZ =vendor/composer/composer/src/Composer/Plugin/PluginEvents.phpe-ge1+ˤCvendor/composer/composer/src/Composer/Plugin/PreCommandRunEvent.php2-g2:q@Kvendor/composer/composer/src/Composer/Plugin/Capability/CommandProvider.php-gd,Fvendor/composer/composer/src/Composer/Plugin/Capability/Capability.php-gL kGvendor/composer/composer/src/Composer/Plugin/PluginBlockedException.php-gNu=vendor/composer/composer/src/Composer/Plugin/CommandEvent.phpy-gy/@vendor/composer/composer/src/Composer/Plugin/PluginInterface.php?-g?#?">vendor/composer/composer/src/Composer/Plugin/PluginManager.phpP-gP.rEvendor/composer/composer/src/Composer/Plugin/PreFileDownloadEvent.php9-g9Fvendor/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php -g 8vendor/composer/composer/src/Composer/Plugin/Capable.php-guCvendor/composer/composer/src/Composer/Plugin/PrePoolCreateEvent.php-gHBvendor/composer/composer/src/Composer/Downloader/RarDownloader.php -g "ĤRvendor/composer/composer/src/Composer/Downloader/VcsCapableDownloaderInterface.phpC-gCHBvendor/composer/composer/src/Composer/Downloader/VcsDownloader.php4-g4\4=Hvendor/composer/composer/src/Composer/Downloader/FilesystemException.php-gJDvendor/composer/composer/src/Composer/Downloader/DownloadManager.phpR<-gR<HBvendor/composer/composer/src/Composer/Downloader/TarDownloader.php-gK7JEvendor/composer/composer/src/Composer/Downloader/FossilDownloader.php-gWΤQvendor/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php-g`ܤHvendor/composer/composer/src/Composer/Downloader/DownloaderInterface.php-gxAvendor/composer/composer/src/Composer/Downloader/XzDownloader.phpQ-gQaYŤAvendor/composer/composer/src/Composer/Downloader/HgDownloader.php-gpBvendor/composer/composer/src/Composer/Downloader/SvnDownloader.php"-g"rvCvendor/composer/composer/src/Composer/Downloader/FileDownloader.phpCS-gCSRJvendor/composer/composer/src/Composer/Downloader/ChangeReportInterface.php'-g'}s$Gvendor/composer/composer/src/Composer/Downloader/TransportException.php-gʤFvendor/composer/composer/src/Composer/Downloader/ArchiveDownloader.php!-g!{ZLvendor/composer/composer/src/Composer/Downloader/DvcsDownloaderInterface.php6-g61N}Cvendor/composer/composer/src/Composer/Downloader/PharDownloader.php-g/&֤Cvendor/composer/composer/src/Composer/Downloader/PathDownloader.php6-g6,_Gvendor/composer/composer/src/Composer/Downloader/PerforceDownloader.php -g R.Bvendor/composer/composer/src/Composer/Downloader/GitDownloader.phpa-ga5ȤBvendor/composer/composer/src/Composer/Downloader/ZipDownloader.phpL9-gL90Cvendor/composer/composer/src/Composer/Downloader/GzipDownloader.php-gS0vendor/composer/composer/src/Composer/Config.phpCa-gCa~s6vendor/composer/composer/src/Composer/Script/Event.php -g D]=vendor/composer/composer/src/Composer/Script/ScriptEvents.php-gKGꮤMvendor/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php -g `a2vendor/composer/composer/src/Composer/Composer.php-g()ۤFvendor/composer/composer/src/Composer/Json/JsonValidationException.phpl-glexˤ<vendor/composer/composer/src/Composer/Json/JsonFormatter.phpe-ge7vendor/composer/composer/src/Composer/Json/JsonFile.php3-g3N>vendor/composer/composer/src/Composer/Json/JsonManipulator.phpbS-gbSٺ;vendor/composer/composer/src/Composer/InstalledVersions.phpIB-gIB "Wvendor/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.phpz-gz=~ibvendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.phpx-gxnҤYvendor/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php-g}|(̤Vvendor/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.phpw -gw c;Vvendor/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php-gIwYvendor/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.phpb-gb&Yldvendor/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php~-g~Hvendor/composer/composer/src/Composer/DependencyResolver/Transaction.php8-g8|ԤLvendor/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php-gQvendor/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php(-g(tʺKvendor/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.phpA-gA>Hvendor/composer/composer/src/Composer/DependencyResolver/GenericRule.php-g>>MVLvendor/composer/composer/src/Composer/DependencyResolver/LockTransaction.php-ghCvendor/composer/composer/src/Composer/DependencyResolver/Solver.phph-ghsAvendor/composer/composer/src/Composer/DependencyResolver/Rule.phpN-gNd ۤJvendor/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php -g dײTvendor/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php-g18MOvendor/composer/composer/src/Composer/DependencyResolver/SolverBugException.php-g/dJvendor/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php(-g( 8Jvendor/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php -g 'Dvendor/composer/composer/src/Composer/DependencyResolver/RuleSet.phpX-gXqAvendor/composer/composer/src/Composer/DependencyResolver/Pool.php -g ?6lJNvendor/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.phpq -gq S8eDvendor/composer/composer/src/Composer/DependencyResolver/Request.php!-g!1Jvendor/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.phpM-gM zAMvendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php6-g6wFvendor/composer/composer/src/Composer/DependencyResolver/Decisions.php-gQHvendor/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php-g dA"Dvendor/composer/composer/src/Composer/DependencyResolver/Problem.phpG-gG"1 Lvendor/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.phpC -gC rKvendor/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php-g]Dvendor/composer/composer/src/Composer/Autoload/AutoloadGenerator.phpM-gMpN>vendor/composer/composer/src/Composer/Autoload/ClassLoader.phpg>-gg>vDvendor/composer/composer/src/Composer/Autoload/ClassMapGenerator.php-gI%c Avendor/composer/composer/src/Composer/Command/SuggestsCommand.php;-g;:&|?vendor/composer/composer/src/Composer/Command/SearchCommand.php-gk^=vendor/composer/composer/src/Composer/Command/BumpCommand.php&-g&r@vendor/composer/composer/src/Composer/Command/ArchiveCommand.php*!-g*!sM>vendor/composer/composer/src/Composer/Command/AuditCommand.php3-g3jlAvendor/composer/composer/src/Composer/Command/ValidateCommand.phpm$-gm$撌r=vendor/composer/composer/src/Composer/Command/FundCommand.php-g{Gvendor/composer/composer/src/Composer/Command/PackageDiscoveryTrait.phpO-gOG:Dvendor/composer/composer/src/Composer/Command/ScriptAliasCommand.php -g \ Fvendor/composer/composer/src/Composer/Command/CreateProjectCommand.php^-g^4Ѥ=vendor/composer/composer/src/Composer/Command/BaseCommand.phpA-gA4nAvendor/composer/composer/src/Composer/Command/OutdatedCommand.phpB-gBGEvendor/composer/composer/src/Composer/Command/DumpAutoloadCommand.php-g=vendor/composer/composer/src/Composer/Command/HomeCommand.phpC-gCrjBvendor/composer/composer/src/Composer/Command/ReinstallCommand.php#-g#" ?vendor/composer/composer/src/Composer/Command/RemoveCommand.php;-g;'/=vendor/composer/composer/src/Composer/Command/ShowCommand.php%-g% EO@vendor/composer/composer/src/Composer/Command/InstallCommand.php-g q=vendor/composer/composer/src/Composer/Command/InitCommand.php([-g([(!#ͤBvendor/composer/composer/src/Composer/Command/RunScriptCommand.php-grm?vendor/composer/composer/src/Composer/Command/ConfigCommand.phpȜ-gȜJ瑤Avendor/composer/composer/src/Composer/Command/LicensesCommand.php-g8$䂤?vendor/composer/composer/src/Composer/Command/UpdateCommand.phpM-gMWoؤ?vendor/composer/composer/src/Composer/Command/StatusCommand.php{ -g{ CGvendor/composer/composer/src/Composer/Command/BaseDependencyCommand.php3-g3@vendor/composer/composer/src/Composer/Command/DependsCommand.php-gvNBvendor/composer/composer/src/Composer/Command/ProhibitsCommand.php-g &Jvendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php-gYjCvendor/composer/composer/src/Composer/Command/SelfUpdateCommand.phpi-gi@vendor/composer/composer/src/Composer/Command/RequireCommand.phps-gsޤAvendor/composer/composer/src/Composer/Command/CompletionTrait.php#-g#"iCvendor/composer/composer/src/Composer/Command/ClearCacheCommand.phpX -gX (Avendor/composer/composer/src/Composer/Command/DiagnoseCommand.phpF-gFÞ?vendor/composer/composer/src/Composer/Command/GlobalCommand.php-g~i>vendor/composer/composer/src/Composer/Command/AboutCommand.php-g =vendor/composer/composer/src/Composer/Command/ExecCommand.php>-g>Ƙi3vendor/composer/composer/src/Composer/Installer.php-gMImvendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterInterface.php-gmvendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreAllPlatformRequirementFilter.php-gunvendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php -g f qvendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreNothingPlatformRequirementFilter.php-gukvendor/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterFactory.php-g$¤Avendor/composer/composer/src/Composer/Installer/PackageEvents.php"-g"]mCvendor/composer/composer/src/Composer/Installer/BinaryInstaller.php8-g8b>Cvendor/composer/composer/src/Composer/Installer/PluginInstaller.phpw-gw0\Kvendor/composer/composer/src/Composer/Installer/BinaryPresenceInterface.php-gDvendor/composer/composer/src/Composer/Installer/LibraryInstaller.php&,-g&,Fvendor/composer/composer/src/Composer/Installer/InstallerInterface.php1-g1K;Hvendor/composer/composer/src/Composer/Installer/MetapackageInstaller.php -g ն٤Dvendor/composer/composer/src/Composer/Installer/ProjectInstaller.php -g Mvendor/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php-gvӤGvendor/composer/composer/src/Composer/Installer/InstallationManager.php`-g`@!Avendor/composer/composer/src/Composer/Installer/NoopInstaller.phpY -gY ^.Cvendor/composer/composer/src/Composer/Advisory/SecurityAdvisory.php-gݭJvendor/composer/composer/src/Composer/Advisory/PartialSecurityAdvisory.php-gu:vendor/composer/composer/src/Composer/Advisory/Auditor.php=-g=̶ҤJvendor/composer/composer/src/Composer/Advisory/IgnoredSecurityAdvisory.phpk-gkK`Rvendor/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php-gBvendor/composer/composer/src/Composer/Exception/NoSslException.php-g;P2vendor/composer/composer/src/Composer/Compiler.php--g-zq9vendor/composer/composer/src/Composer/Package/Package.phpD-gDi?f6vendor/composer/composer/src/Composer/Package/Link.php -g +HJvendor/composer/composer/src/Composer/Package/CompletePackageInterface.php-g}{+Ivendor/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php$-g$Pvendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.phpq -gq ߶qGvendor/composer/composer/src/Composer/Package/Archiver/PharArchiver.php -g ǁMLvendor/composer/composer/src/Composer/Package/Archiver/BaseExcludeFilter.php-g@ݤPvendor/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFilter.php-gߵKvendor/composer/composer/src/Composer/Package/Archiver/GitExcludeFilter.php-g^Pvendor/composer/composer/src/Composer/Package/Archiver/ComposerExcludeFilter.php-gޣLvendor/composer/composer/src/Composer/Package/Archiver/ArchiverInterface.php-g;wFvendor/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php -g Fvendor/composer/composer/src/Composer/Package/CompleteAliasPackage.php-glN(>vendor/composer/composer/src/Composer/Package/AliasPackage.phpe'-ge'Ҥ8vendor/composer/composer/src/Composer/Package/Locker.php/X-g/XBvendor/composer/composer/src/Composer/Package/PackageInterface.php0-g0FGvendor/composer/composer/src/Composer/Package/Version/VersionBumper.phpS-gSpIvendor/composer/composer/src/Composer/Package/Version/StabilityFilter.php-g5Hvendor/composer/composer/src/Composer/Package/Version/VersionGuesser.phpWH-gWHkSIvendor/composer/composer/src/Composer/Package/Version/VersionSelector.php0-g0 Gvendor/composer/composer/src/Composer/Package/Version/VersionParser.php -g  ?Nvendor/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.phpu-gu_UPvendor/composer/composer/src/Composer/Package/Loader/InvalidPackageException.phpo-go,ҤDvendor/composer/composer/src/Composer/Package/Loader/ArrayLoader.phpF-gFW Hvendor/composer/composer/src/Composer/Package/Loader/LoaderInterface.phpj-gj7Jvendor/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php--g-qkW|Cvendor/composer/composer/src/Composer/Package/Loader/JsonLoader.phpc-gcܝ@ =vendor/composer/composer/src/Composer/Package/BasePackage.php-g$8Cvendor/composer/composer/src/Composer/Package/Comparer/Comparer.php-gfɋBvendor/composer/composer/src/Composer/Package/RootAliasPackage.php-grAvendor/composer/composer/src/Composer/Package/CompletePackage.php@-g@ewFvendor/composer/composer/src/Composer/Package/RootPackageInterface.php-gS=vendor/composer/composer/src/Composer/Package/RootPackage.phpZ -gZ kDvendor/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php-g)==vendor/composer/composer/src/Composer/Console/Application.php|-g|CoCvendor/composer/composer/src/Composer/Console/GithubActionError.phpl-glg`+Evendor/composer/composer/src/Composer/Console/Input/InputArgument.php -g & oCvendor/composer/composer/src/Composer/Console/Input/InputOption.php -g (CEvendor/composer/composer/src/Composer/Console/HtmlOutputFormatter.php1 -g1 g?Ѥ*vendor/composer/composer/src/bootstrap.php7-g7t(vendor/composer/ca-bundle/res/cacert.pem,-g,r%!vendor/composer/ca-bundle/LICENSE-g*!^`#vendor/composer/ca-bundle/README.md1-g1>VuĤ'vendor/composer/ca-bundle/composer.json5-g5y:*vendor/composer/ca-bundle/src/CaBundle.phpE+-gE+&V!vendor/composer/autoload_psr4.php-g%vendor/composer/autoload_classmap.phpE-gE f"vendor/composer/platform_check.php-g #vendor/composer/autoload_static.phpm-gm_!vendor/composer/autoload_real.php-gFvendor/composer/semver/LICENSE-gBh#vendor/composer/semver/CHANGELOG.mdi'-gi'[L vendor/composer/semver/README.mdH -gH }Τ$vendor/composer/semver/composer.json-gz)/vendor/composer/semver/src/CompilingMatcher.php -g F'vendor/composer/semver/src/Interval.phpu-gu)vendor/composer/semver/src/Comparator.php< -g< ^:vendor/phpdocumentor/type-resolver/src/Types/Iterable_.phpF-gF 'yBvendor/phpdocumentor/type-resolver/src/Types/CallableParameter.php-g/9vendor/phpdocumentor/type-resolver/src/Types/ArrayKey.php-g?n)7vendor/phpdocumentor/type-resolver/src/Types/Never_.php-g '8vendor/phpdocumentor/type-resolver/src/Types/Static_.php-g{6@<vendor/phpdocumentor/type-resolver/src/Types/ClassString.php_-g_g8vendor/phpdocumentor/type-resolver/src/Types/Parent_.php-gip7vendor/phpdocumentor/type-resolver/src/Types/Scalar.php-gؤ8vendor/phpdocumentor/type-resolver/src/Types/Context.php -g fYK=vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php-g&;vendor/phpdocumentor/type-resolver/src/Types/Collection.php-g䅝=vendor/phpdocumentor/type-resolver/src/Types/Intersection.php$-g$?vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php7-g7v#?vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php -g C`9vendor/phpdocumentor/type-resolver/src/Types/Compound.php-g5vendor/phpdocumentor/type-resolver/src/Types/This.phpg-gg~+67vendor/phpdocumentor/type-resolver/src/Types/Array_.php-g NK7vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php-g/vendor/phpdocumentor/type-resolver/src/Type.php-gq48vendor/phpdocumentor/type-resolver/src/FqsenResolver.php -g ͢Bvendor/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php-gFI<vendor/phpdocumentor/type-resolver/src/PseudoTypes/List_.php-gOEvendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php}-g}i@vendor/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php+-g+NGCvendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.phpA-gA֭Z$Evendor/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php|-g|Dvendor/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php-g곤?vendor/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php(-g(^6=vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php-g/Fvendor/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php-gIC3Bvendor/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.phpv-gv{Avendor/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php-g4AYDvendor/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.phpz-gz*Hvendor/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php-gy"ѤCvendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php-gR4Dvendor/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.phpz-gzCvendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php -g IFvendor/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php-goe4Avendor/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php-gfrdNvendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php-gDvendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php-g,Fvendor/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php~-g~kc<vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php-gW@vendor/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php3-g3pFvendor/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.phpw-gwpEvendor/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.phpe-ge7Bvendor/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.phpM-gM*9Fvendor/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.phpw-gw.5vendor/phpdocumentor/type-resolver/src/PseudoType.php|-g|}0vendor/phpdocumentor/reflection-docblock/LICENSE8-g8ʤ2vendor/phpdocumentor/reflection-docblock/README.md[ -g[ \S6vendor/phpdocumentor/reflection-docblock/composer.json-g@vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php0-g0O?&Dvendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.phpH-gHgդGvendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.phpI-gI T=vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php-gῤDvendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php -g ROJLvendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php<-g<FJDvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php -g ,Lvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php-gֻNvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php-gK銤Cvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php-gj Ivendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php-g_=vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.phpm -gm W}¤9vendor/paragonie/constant_time_encoding/src/Base32Hex.php9 -g9 fm>vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php -g %o8vendor/paragonie/constant_time_encoding/src/Encoding.php,-g,R2~@vendor/paragonie/constant_time_encoding/src/EncoderInterface.php-gs:6vendor/paragonie/constant_time_encoding/src/Base32.php<-g<$HC3vendor/paragonie/constant_time_encoding/src/Hex.php-gbFǤEvendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php -g ?Na6vendor/paragonie/constant_time_encoding/src/Binary.php -g ތ7vendor/paragonie/constant_time_encoding/src/RFC4648.php-g6vendor/paragonie/constant_time_encoding/src/Base64.phpc$-gc$K#vendor/spomky-labs/cbor-php/LICENSE,-g,C%vendor/spomky-labs/cbor-php/README.md[+-g[+)vendor/spomky-labs/cbor-php/composer.json'-g'-k'vendor/spomky-labs/cbor-php/SECURITY.md-gǤ0vendor/spomky-labs/cbor-php/src/StringStream.phpe-ge&o:vendor/spomky-labs/cbor-php/src/OtherObject/TrueObject.php-gb1F;vendor/spomky-labs/cbor-php/src/OtherObject/BreakObject.phpX-gX&cDvendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectInterface.phpt-gtаȤJvendor/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.phpQ-gQt =vendor/spomky-labs/cbor-php/src/OtherObject/GenericObject.php-gku5;vendor/spomky-labs/cbor-php/src/OtherObject/FalseObject.php-g= ?vendor/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.phpd-gdIM(Jvendor/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php-g]Kvendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php-gIHvendor/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.phpq-gqWF<vendor/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php -g :j:vendor/spomky-labs/cbor-php/src/OtherObject/NullObject.php-g.Bvendor/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php~-g~=*F4vendor/spomky-labs/cbor-php/src/DecoderInterface.php-g\f4vendor/spomky-labs/cbor-php/src/ByteStringObject.php-gBlDvendor/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php*-g*`갤'vendor/spomky-labs/cbor-php/src/Tag.phpc-gc}+vendor/spomky-labs/cbor-php/src/Decoder.php#-g#"I9vendor/spomky-labs/cbor-php/src/UnsignedIntegerObject.php -g 򽩜6vendor/spomky-labs/cbor-php/src/AbstractCBORObject.phpY-gY@z>0vendor/spomky-labs/cbor-php/src/Normalizable.php-gxӤ4vendor/spomky-labs/cbor-php/src/LengthCalculator.php|-g|N`/vendor/spomky-labs/cbor-php/src/OtherObject.php-g?73*vendor/spomky-labs/cbor-php/src/Stream.php-g$c4vendor/spomky-labs/cbor-php/src/TextStringObject.php-g1aMDvendor/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php3-g3Q>vendor/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php -g cR¤=vendor/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php-gy8+vendor/spomky-labs/cbor-php/src/MapItem.php-g)vendor/spomky-labs/cbor-php/src/Utils.phpv-gvp#.vendor/spomky-labs/cbor-php/src/ListObject.php-g0S-vendor/spomky-labs/cbor-php/src/MapObject.phpg-gg/k.vendor/spomky-labs/cbor-php/src/CBORObject.php~-g~4.vendor/spomky-labs/cbor-php/src/Tag/UriTag.php-g)<vendor/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php-gܤ=vendor/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php_-g_[ؠd:vendor/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php -g ;vendor/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php-gcG4vendor/spomky-labs/cbor-php/src/Tag/TagInterface.phph-gh4vendor/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php-g}3vendor/spomky-labs/cbor-php/src/Tag/BigFloatTag.php -g M@Ǥ/vendor/spomky-labs/cbor-php/src/Tag/CBORTag.php}-g}%Ƥ/vendor/spomky-labs/cbor-php/src/Tag/MimeTag.php-g<,3vendor/spomky-labs/cbor-php/src/Tag/DatetimeTag.php-gbʤ7vendor/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php-g lM1vendor/spomky-labs/cbor-php/src/Tag/Base64Tag.php-g|㨤9vendor/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php-gM9=vendor/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php-g|}2vendor/spomky-labs/cbor-php/src/Tag/TagManager.phpE-gEa4vendor/spomky-labs/cbor-php/src/Tag/TimestampTag.php -g qJ2vendor/spomky-labs/cbor-php/src/Tag/GenericTag.php-g229vendor/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php-g k9vendor/spomky-labs/cbor-php/src/NegativeIntegerObject.php -g bx7(vendor/spomky-labs/pki-framework/LICENSES-gSt*vendor/spomky-labs/pki-framework/README.md-g7/V.vendor/spomky-labs/pki-framework/composer.json -g eD,vendor/spomky-labs/pki-framework/SECURITY.mdI-gI,)5vendor/spomky-labs/pki-framework/src/ASN1/Element.php<-g<9t9vendor/spomky-labs/pki-framework/src/ASN1/Util/BigInt.php -g `}8vendor/spomky-labs/pki-framework/src/ASN1/Util/Flags.php-g Bvendor/spomky-labs/pki-framework/src/ASN1/Component/Identifier.php-gJ=>vendor/spomky-labs/pki-framework/src/ASN1/Component/Length.php-gri @vendor/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveType.php,-g,SZe2=vendor/spomky-labs/pki-framework/src/ASN1/Type/BaseString.php-gM"~Fvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BMPString.php_-g_.Dvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Boolean.php9-g9p@Dvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Integer.phpa -ga @nHvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/RelativeOID.php-glbJvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VisibleString.php-gwnCvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Number.php-gzڡGvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTF8String.php-gbFvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BitString.php-g+Fvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/IA5String.php-gc&kLvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UniversalString.php-gl0ޤJvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GraphicString.php-gWMvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectDescriptor.php-gY1Avendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Real.phpQ-gQ~^Lvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/PrintableString.php-giTȘ@vendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/EOC.php-g!¤Evendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NullType.php-goMvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectIdentifier.php-gz&Gvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Enumerated.php:-g:NJvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NumericString.php-gy{Hvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/OctetString.php2-g2yLvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralizedTime.php7-g7l Dvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTCTime.php: -g: 3W-NKvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VideotexString.php-g=đLvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/CharacterString.php>-g>Fvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/T61String.php-g_Jvendor/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralString.php-gwӺ;vendor/spomky-labs/pki-framework/src/ASN1/Type/TimeType.php;-g;-R Ivendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitTagging.php-gWqMvendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ContextSpecificType.php-gXNvendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitlyTaggedType.php&-g&Evendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/PrivateType.php-g4eYIvendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ApplicationType.php-gCFNvendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitlyTaggedType.php@-g@Gvendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/DERTaggedType.php-g}LVHvendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/TaggedTypeWrap.php'-g':Ivendor/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitTagging.php-g\Gvendor/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Sequence.php[ -g[ xBvendor/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Set.php$-g$~Pvendor/spomky-labs/pki-framework/src/ASN1/Type/Constructed/ConstructedString.php-g2L:Bvendor/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveString.php-g@$<vendor/spomky-labs/pki-framework/src/ASN1/Type/Structure.phpM-gMf<;vendor/spomky-labs/pki-framework/src/ASN1/Type/BaseTime.php-gCLbBvendor/spomky-labs/pki-framework/src/ASN1/Type/UnspecifiedType.php/?-g/??qФ=vendor/spomky-labs/pki-framework/src/ASN1/Type/TaggedType.php -g m=vendor/spomky-labs/pki-framework/src/ASN1/Type/StringType.php-g&Avendor/spomky-labs/pki-framework/src/ASN1/Type/UniversalClass.php-go5vendor/spomky-labs/pki-framework/src/ASN1/DERData.php-g($ĤAvendor/spomky-labs/pki-framework/src/ASN1/Feature/ElementBase.php-g}vendor/spomky-labs/pki-framework/src/X509/Certificate/Time.php -g nbvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CRLDistributionPointsExtension.php -g Xgvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectDirectoryAttributesExtension.php& -g& K+Ynvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/SubjectAccessDescription.phpw-gwe\gvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AccessDescription.php-gpvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AuthorityAccessDescription.phpJ-gJ(~sbvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NoRevocationAvailableExtension.php-g^vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyConstraintsExtension.php -g v!gvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityInformationAccessExtension.php -g evendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectInformationAccessExtension.php' -g' .î^vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/TargetInformationExtension.phpN -gN tc(Uvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/KeyUsageExtension.php -g W).Uvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetName.php-gHARvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Targets.php -g `%Qvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Target.phps-gsG]bVvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetGroup.php-g1*`vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappings/PolicyMapping.phph-ghŤ\vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraintsExtension.phpp -gp iXvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/FreshestCRLExtension.phpU-gUE Tvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/UnknownExtension.php-gmbvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/IssuerAlternativeNameExtension.php-g7@A^`vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePoliciesExtension.phpx -gx ]vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/InhibitAnyPolicyExtension.phpf-gfUPbvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/RelativeName.phpe-geiwXgvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPoint.php-gpӿ^vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/FullName.php-g4avendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/ReasonFlags.php -g dŤkvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPointName.php-gTQcvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtrees.php-ghL\bvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtree.php -g K]vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/ExtendedKeyUsageExtension.php-gWLWvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AAControlsExtension.php-gerevendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/NoticeReference.phpa-ga ivendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyQualifierInfo.php-gDrivendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/UserNoticeQualifier.php -g 4sgvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyInformation.phpt-gtҫavendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/DisplayText.php6-g6Ťbvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/CPSQualifier.phpK-gK$vu[vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappingsExtension.php-gp'iMvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/Extension.php'-g'bcvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityKeyIdentifierExtension.php-gpTcvendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectAlternativeNameExtension.php-g 6+]vendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/BasicConstraintsExtension.php -g ?zavendor/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectKeyIdentifierExtension.php-g)VSEvendor/spomky-labs/pki-framework/src/X509/Certificate/Certificate.php-g7;Jvendor/spomky-labs/pki-framework/src/X509/Certificate/UniqueIdentifier.php-gqJvendor/spomky-labs/pki-framework/src/X509/Certificate/CertificateChain.php -g N8Bvendor/spomky-labs/pki-framework/src/X509/Certificate/Validity.phpx-gx$ҤKvendor/spomky-labs/pki-framework/src/X509/Certificate/CertificateBundle.phpC-gCHvendor/spomky-labs/pki-framework/src/X509/Certificate/TBSCertificate.php8-g8b^Dvendor/spomky-labs/pki-framework/src/X509/Certificate/Extensions.php$-g$[Fvendor/spomky-labs/pki-framework/src/X509/GeneralName/RegisteredID.php-gZ3Gvendor/spomky-labs/pki-framework/src/X509/GeneralName/DirectoryName.php]-g]^Fvendor/spomky-labs/pki-framework/src/X509/GeneralName/EDIPartyName.php-gNoߤCvendor/spomky-labs/pki-framework/src/X509/GeneralName/OtherName.php-gV$dCvendor/spomky-labs/pki-framework/src/X509/GeneralName/IPAddress.php-g?UEvendor/spomky-labs/pki-framework/src/X509/GeneralName/X400Address.php-gTEvendor/spomky-labs/pki-framework/src/X509/GeneralName/IPv4Address.php!-g!#Fvendor/spomky-labs/pki-framework/src/X509/GeneralName/GeneralNames.php-g\֤Svendor/spomky-labs/pki-framework/src/X509/GeneralName/UniformResourceIdentifier.php-geDvendor/spomky-labs/pki-framework/src/X509/GeneralName/RFC822Name.php-gMpnEvendor/spomky-labs/pki-framework/src/X509/GeneralName/GeneralName.phpD -gD Evendor/spomky-labs/pki-framework/src/X509/GeneralName/IPv6Address.php-g IpAvendor/spomky-labs/pki-framework/src/X509/GeneralName/DNSName.php(-g(YjDvendor/spomky-labs/pki-framework/src/X509/Feature/DateTimeHelper.php-g$ucvendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationConfig.php-gU\cvendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationResult.php\ -g\ c[]vendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/ValidatorState.php)-g)0p\vendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidator.phpB-gB~ievendor/spomky-labs/pki-framework/src/X509/CertificationPath/PathBuilding/CertificationPathBuilder.php-gh_vendor/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathBuildingException.php-gvavendor/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathValidationException.phpC-gCWb'Qvendor/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyNode.phpT-gTRnQvendor/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyTree.php+5-g+51ؤQvendor/spomky-labs/pki-framework/src/X509/CertificationPath/CertificationPath.php-gsOvendor/spomky-labs/pki-framework/src/X509/Exception/X509ValidationException.php-g?$ivendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AccessIdentityAttributeValue.php5-g53cZvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrValue.php -g f# Yvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/SvceAuthInfo.php -g Ghmvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AuthenticationInfoAttributeValue.phpN-gN˯Ťkvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/ChargingIdentityAttributeValue.php-gd`vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/GroupAttributeValue.php-gvR[vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrSyntax.php-g_vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/RoleAttributeValue.php-gq1Mvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attributes.php-gprOvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/IssuerSerial.php-ghUIvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Holder.php-gpSIvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/V2Form.php -g ~[vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificateInfo.phpK&-gK&lzSvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/ObjectDigestInfo.php -g >Pvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertIssuer.phpB-gBy0Wvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificate.php-gXvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertValidityPeriod.php$-g$tYvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidator.php-gmvendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/Exception/ACValidationException.php -g K`vendor/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidationConfig.php-g6Wvendor/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequest.php-g`bvendor/spomky-labs/pki-framework/src/X509/CertificationRequest/Attribute/ExtensionRequestValue.phpD-gD Mvendor/spomky-labs/pki-framework/src/X509/CertificationRequest/Attributes.php-g[vendor/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequestInfo.php-gX6vendor/spomky-labs/pki-framework/src/X501/ASN1/RDN.php-gu晤@vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeType.php@-g@7PRvendor/spomky-labs/pki-framework/src/X501/ASN1/Collection/SequenceOfAttributes.php-gxDcMvendor/spomky-labs/pki-framework/src/X501/ASN1/Collection/SetOfAttributes.php2-g2%Qvendor/spomky-labs/pki-framework/src/X501/ASN1/Collection/AttributeCollection.php"-g",L<vendor/spomky-labs/pki-framework/src/X501/ASN1/Attribute.php#-g#9Svendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/LocalityNameValue.php-g`Pvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/GivenNameValue.php-ggWvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationNameValue.php-g09Lvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/TitleValue.php-gf2Svendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SerialNumberValue.php-gGPvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/AttributeValue.php-gSg&Rvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/DescriptionValue.php-gGϤRvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CountryNameValue.php-gkQvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CommonNameValue.php-g40LNvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SurnameValue.php-glPvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/PseudonymValue.php-gZvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/StateOrProvinceNameValue.php-g ˤ^vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/PrintableStringValue.php-gRpYvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/DirectoryString.php-gWWvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/UnknownAttributeValue.php< -g< %U]vendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationalUnitNameValue.php-g6ۺKvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/NameValue.php-gHvendor/spomky-labs/pki-framework/src/X501/ASN1/AttributeTypeAndValue.phpe -ge z\7vendor/spomky-labs/pki-framework/src/X501/ASN1/Name.phpP-gP:9vendor/spomky-labs/pki-framework/src/X501/DN/DNParser.phpd(-gd(Gvendor/spomky-labs/pki-framework/src/X501/MatchingRule/MatchingRule.phpP-gP~j2Jvendor/spomky-labs/pki-framework/src/X501/MatchingRule/CaseIgnoreMatch.php-gEʤIvendor/spomky-labs/pki-framework/src/X501/MatchingRule/CaseExactMatch.php-g}Qvendor/spomky-labs/pki-framework/src/X501/MatchingRule/StringPrepMatchingRule.php{-g{峿Fvendor/spomky-labs/pki-framework/src/X501/MatchingRule/BinaryMatch.php-g r@vendor/spomky-labs/pki-framework/src/X501/StringPrep/MapStep.phpn-gnTFvendor/spomky-labs/pki-framework/src/X501/StringPrep/NormalizeStep.php -g qDvendor/spomky-labs/pki-framework/src/X501/StringPrep/PrepareStep.php-go*Fvendor/spomky-labs/pki-framework/src/X501/StringPrep/TranscodeStep.phpA -gA B Fvendor/spomky-labs/pki-framework/src/X501/StringPrep/CheckBidiStep.php-gtIdGvendor/spomky-labs/pki-framework/src/X501/StringPrep/StringPreparer.php-go< IEvendor/spomky-labs/pki-framework/src/X501/StringPrep/ProhibitStep.php-g[vendor/spomky-labs/pki-framework/src/X501/StringPrep/InsignificantNonSubstringSpaceStep.php!-g!Q6|Ovendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed25519Signature.php-gMvendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed448Signature.php-gPbOvendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/GenericSignature.phpB-gB~Jvendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/ECSignature.php-gKvendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/RSASignature.phpY-gYފ-Hvendor/spomky-labs/pki-framework/src/CryptoTypes/Signature/Signature.php-gU(Pvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/OneAsymmetricKey.php)-g)NM@dvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/Attribute/OneAsymmetricKeyAttributes.php-gHPvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPublicKey.php -g 3:Qvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPrivateKey.phpO-gOUWvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSASSAPSSPrivateKey.phpj-gjf*Nvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPublicKey.phpm-gmҤOvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPrivateKey.php*-g*QOM2Ovendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECConversion.php -g ҒIvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKey.php3-g3ZhNvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKeyInfo.php-gLn+Yvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PrivateKey.phpj -gj "Xvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PublicKey.php-g;.^vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PublicKey.php-gO_vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PublicKey.php-g+/_vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PrivateKey.php-gQ`vendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PrivateKey.php-g bvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PublicKey.php-g.)fvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PublicKey.php-g4Icvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PrivateKey.php-gvVgvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PrivateKey.php3-g3D3cvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PublicKey.php-gʙdvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PrivateKey.php-g.:Mvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKeyInfo.php-g3DJvendor/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKey.php0-g0Ixdvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/SpecificAlgorithmIdentifier.phpW-gWy \vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifier.phpp-gp%H}vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA384WithRSAEncryptionAlgorithmIdentifier.php-gO+zvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD2WithRSAEncryptionAlgorithmIdentifier.php-gQߕޤuvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA256AlgorithmIdentifier.php-g-uvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA224AlgorithmIdentifier.php-g zvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD5WithRSAEncryptionAlgorithmIdentifier.php-g+yvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC3279RSASignatureAlgorithmIdentifier.php-g)afzvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD4WithRSAEncryptionAlgorithmIdentifier.php-gwlyvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC4055RSASignatureAlgorithmIdentifier.phpl-gl_esԤuvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA512AlgorithmIdentifier.php-g6 f{rvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RSASignatureAlgorithmIdentifier.php-g|Ǥ}vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA256WithRSAEncryptionAlgorithmIdentifier.php-g`%svendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA1AlgorithmIdentifier.php-gbduvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA384AlgorithmIdentifier.php-g,Pqvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECSignatureAlgorithmIdentifier.php-g_<}vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA512WithRSAEncryptionAlgorithmIdentifier.php-g{vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA1WithRSAEncryptionAlgorithmIdentifier.php-g1}vendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA224WithRSAEncryptionAlgorithmIdentifier.php-g&novendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA224AlgorithmIdentifier.php-gФgvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA224AlgorithmIdentifier.php-g1]̤ovendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA256AlgorithmIdentifier.php-gLgvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA256AlgorithmIdentifier.php-gFlvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/RFC4231HMACAlgorithmIdentifier.phps-gsTEovendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA512AlgorithmIdentifier.php-gNgvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA512AlgorithmIdentifier.php-gIˤmvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA1AlgorithmIdentifier.php-gl devendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA2AlgorithmIdentifier.php-g dvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/MD5AlgorithmIdentifier.php-g:evendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA1AlgorithmIdentifier.phpy-gyovendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA384AlgorithmIdentifier.php-g/4gvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA384AlgorithmIdentifier.php-gMaA4ivendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/RC2CBCAlgorithmIdentifier.php-gmvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESEDE3CBCAlgorithmIdentifier.phpg-ggplvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES192CBCAlgorithmIdentifier.php-givendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AESCBCAlgorithmIdentifier.php-gqzivendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/CipherAlgorithmIdentifier.php8-g8 "¤ivendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESCBCAlgorithmIdentifier.php-gHYnvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/BlockCipherAlgorithmIdentifier.phpd-gd~lvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES128CBCAlgorithmIdentifier.php|-g|Wϸlvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES256CBCAlgorithmIdentifier.php-g| Ĥrvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/ECPublicKeyAlgorithmIdentifier.php/-g/Dmvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X25519AlgorithmIdentifier.php+-g+0Ŕkvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X448AlgorithmIdentifier.php#-g#oœ#pvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410EdAlgorithmIdentifier.php-g ߎtvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAEncryptionAlgorithmIdentifier.php-gseRlvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed448AlgorithmIdentifier.php-gְovendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410XAlgorithmIdentifier.php-gL~.zvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAPSSSSAEncryptionAlgorithmIdentifier.php-gZnvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed25519AlgorithmIdentifier.php-gcvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierFactory.php$-g$#ꨤmvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/SignatureAlgorithmIdentifier.php-g3!gvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/PRFAlgorithmIdentifier.php-g!$tvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AsymmetricCryptoAlgorithmIdentifier.php -g Chvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/HashAlgorithmIdentifier.php-g&-nvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/EncryptionAlgorithmIdentifier.php-gbOhvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AlgorithmIdentifierType.phpy-gyl̤dvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierProvider.php-gk\dcvendor/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/GenericAlgorithmIdentifier.php-gCI  vendor/spomky-labs/otphp/LICENSE@-g@xi"vendor/spomky-labs/otphp/README.md%-g%z@&vendor/spomky-labs/otphp/composer.json-g; $vendor/spomky-labs/otphp/SECURITY.md-g? m%vendor/spomky-labs/otphp/src/TOTP.php-g>s?(vendor/spomky-labs/otphp/src/Factory.php+ -g+ 0$-vendor/spomky-labs/otphp/src/OTPInterface.php -g zr.vendor/spomky-labs/otphp/src/TOTPInterface.php-g*$vendor/spomky-labs/otphp/src/OTP.php-gB%vendor/spomky-labs/otphp/src/HOTP.php= -g= hct.vendor/spomky-labs/otphp/src/HOTPInterface.php=-g=ߤ1vendor/spomky-labs/otphp/src/FactoryInterface.phpr-gr¤/vendor/spomky-labs/otphp/src/ParameterTrait.php-gda&$vendor/spomky-labs/otphp/src/Url.php# -g# >쐡.vendor/spomky-labs/otphp/src/InternalClock.php5-g5GƤ$vendor/doctrine/deprecations/LICENSE)-g)"0&vendor/doctrine/deprecations/README.md -g {*vendor/doctrine/deprecations/composer.json-gx+?vendor/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php-g V0vendor/doctrine/deprecations/src/Deprecation.php$-g$)vendor/firebase/php-jwt/LICENSE-g#$vendor/firebase/php-jwt/CHANGELOG.md'-g'ާ!vendor/firebase/php-jwt/README.md4-g4%vendor/firebase/php-jwt/composer.json-gܤ9vendor/firebase/php-jwt/src/SignatureInvalidException.phpu-guϽ4vendor/firebase/php-jwt/src/BeforeValidException.phpt-gtu0,vendor/firebase/php-jwt/src/CachedKeySet.php-g ؤ#vendor/firebase/php-jwt/src/Key.php-glx+#vendor/firebase/php-jwt/src/JWK.phpA,-gA,@vendor/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php-gky0vendor/firebase/php-jwt/src/ExpiredException.phpp-gp7#vendor/firebase/php-jwt/src/JWT.php\-g\X wvendor/brick/math/LICENSEA-gAݸLvendor/brick/math/CHANGELOG.mdGJ-gGJDsvendor/brick/math/composer.jsonS-gS}s&vendor/brick/math/src/RoundingMode.php -g ;vendor/brick/math/src/Internal/Calculator/GmpCalculator.php-g;>vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php -g E}EG>vendor/brick/math/src/Internal/Calculator/NativeCalculator.php4-g4B-vendor/brick/math/src/Internal/Calculator.phpI-gI}$vendor/brick/math/src/BigInteger.phpi-gi#vendor/brick/math/src/BigNumber.php4=-g4=WO $vendor/brick/math/src/BigDecimal.phpdS-gdS쩤1vendor/brick/math/src/Exception/MathException.php-gE:9vendor/brick/math/src/Exception/NumberFormatException.php-gojQ;vendor/brick/math/src/Exception/NegativeNumberException.php-g +;;vendor/brick/math/src/Exception/DivisionByZeroException.php-gƁj<vendor/brick/math/src/Exception/IntegerOverflowException.php,-g,1C>*>vendor/brick/math/src/Exception/RoundingNecessaryException.php-gA%vendor/brick/math/src/BigRational.php .-g .58(vendor/justinrainbow/json-schema/LICENSE -g 2vendor/justinrainbow/json-schema/bin/validate-json-gFvendor/justinrainbow/json-schema/dist/schema/json-schema-draft-03.json-g-aߤFvendor/justinrainbow/json-schema/dist/schema/json-schema-draft-04.json-gNߤ*vendor/justinrainbow/json-schema/README.mdz-gz˱.vendor/justinrainbow/json-schema/composer.json-g7;vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php-g̤=vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php -g Ivendor/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php-ghJPvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php{-g{=6Gvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php-gߤPvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php -g UjNvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php-gMYNvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php -g ֤Nvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php-gl$МPvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php-g^ Svendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php3-g39¤Tvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php-g5qJvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php-gd5Pvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php.#-g.#'\vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php-gyYvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php:-g:*9Xvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php-gr(Svendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php<-g<U>Pvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php!-g!Fvendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php4 -g4 Hvendor/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php -g "Kvendor/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php -g hlAvendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php-gNqXvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php-g-,Tvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php-g_ǤGvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php-gx(Rvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php^ -g^ Rvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php -g /8Dvendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php$-g$AqCvendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php-g_9<Wvendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpb-gb`Pvendor/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.phpX-gX[Nvendor/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.phpo-goCrWvendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.phpj-gj*5Vvendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php-gN^vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php-gZHeQvendor/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.php'-g'AjTvendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.php_-g_PSvendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php-gnWTvendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.php\-g\@S6Rvendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpX-gXӔ]vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.phpe-geU3$Jvendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php.-g.VԠg1vendor/crell/api-problem/docker/php/81/Dockerfile-gD11vendor/crell/api-problem/docker/php/81/xdebug.inil-glb0>vendor/crell/api-problem/docker/php/conf.d/error_reporting.ini-glc¤!vendor/crell/api-problem/Makefile]-g]Zib*vendor/crell/api-problem/phpstan.neon.dist0-g0b+vendor/crell/api-problem/docker-compose.ymlb-gbRuv&vendor/crell/api-problem/composer.json-gVN+$vendor/crell/api-problem/SECURITY.mdw -gw _yU%vendor/crell/api-problem/default-.env-g]h Q4vendor/crell/api-problem/src/JsonEncodeException.php-gewF.vendor/crell/api-problem/src/HttpConverter.php6 -g6 1B3vendor/crell/api-problem/src/JsonParseException.phpH-gH%P(.vendor/crell/api-problem/src/JsonException.php -g 5-+vendor/crell/api-problem/src/ApiProblem.phpdH-gdH'Mvendor/psr/cache/CHANGELOG.md-g- Gvendor/psr/cache/README.md"-g"(AcӤvendor/psr/cache/LICENSE.txt8-g8Dfvendor/psr/cache/composer.json4-g4C/vendor/psr/cache/src/CacheItemPoolInterface.php-gY+vendor/psr/cache/src/CacheItemInterface.php&-g&=b1vendor/psr/cache/src/InvalidArgumentException.php:-g:MY'vendor/psr/cache/src/CacheException.php-gBJ#vendor/psr/event-dispatcher/LICENSE(-g(}]%vendor/psr/event-dispatcher/README.mdE-gES)vendor/psr/event-dispatcher/composer.jsonb-gbq=vendor/psr/event-dispatcher/src/ListenerProviderInterface.php-gbh<vendor/psr/event-dispatcher/src/EventDispatcherInterface.php-g;vendor/psr/event-dispatcher/src/StoppableEventInterface.php!-g!T>qvendor/psr/http-message/LICENSE=-g=$vendor/psr/http-message/CHANGELOG.md3-g3:\Y!vendor/psr/http-message/README.md-g%vendor/psr/http-message/composer.json-g76vendor/psr/http-message/src/ServerRequestInterface.phpH(-gH(#,vendor/psr/http-message/src/UriInterface.php/2-g/2קY/vendor/psr/http-message/src/StreamInterface.php -g 5vendor/psr/http-message/src/UploadedFileInterface.php-g 0vendor/psr/http-message/src/RequestInterface.phpG-gGir1vendor/psr/http-message/src/ResponseInterface.phpZ -gZ aG0vendor/psr/http-message/src/MessageInterface.php-g|Cvendor/psr/container/LICENSEy-gyOpvendor/psr/container/README.mdB-gBg?"vendor/psr/container/composer.json-gnY7vendor/psr/container/src/NotFoundExceptionInterface.php-gB@/vendor/psr/container/src/ContainerInterface.php%-g%)8vendor/psr/container/src/ContainerExceptionInterface.php-g vendor/psr/http-client/LICENSE=-g=S#vendor/psr/http-client/CHANGELOG.md-gz򪌤 vendor/psr/http-client/README.md%-g%F$vendor/psr/http-client/composer.json-gbϤ8vendor/psr/http-client/src/NetworkExceptionInterface.php-g6SB8vendor/psr/http-client/src/RequestExceptionInterface.phph-gh*c=.vendor/psr/http-client/src/ClientInterface.php!-g!{07vendor/psr/http-client/src/ClientExceptionInterface.php-gxzvendor/psr/log/LICENSE=-g=pOvendor/psr/log/README.mdB-gB'vendor/psr/log/composer.json`-g`],+vendor/psr/log/src/LoggerAwareInterface.php-gowvendor/psr/log/src/LogLevel.phpH-gHu'vendor/psr/log/src/LoggerAwareTrait.phpj-gjdz/vendor/psr/log/src/InvalidArgumentException.phpo-goMWd!vendor/psr/log/src/NullLogger.php-g<&vendor/psr/log/src/LoggerInterface.php -g c="vendor/psr/log/src/LoggerTrait.php -g  %vendor/psr/log/src/AbstractLogger.php-gqvendor/psr/clock/LICENSE8-g8lvendor/psr/clock/CHANGELOG.md-g<vendor/psr/clock/README.md-gGL[vendor/psr/clock/composer.json2-g2$DCM'vendor/psr/clock/src/ClockInterface.php-gH%vendor/psr/http-factory/LICENSE(-g(}]!vendor/psr/http-factory/README.md,-g,zwf%vendor/psr/http-factory/composer.json8-g88vendor/psr/http-factory/src/ResponseFactoryInterface.php2-g2ձ}6vendor/psr/http-factory/src/StreamFactoryInterface.php-ge<vendor/psr/http-factory/src/UploadedFileFactoryInterface.phpJ-gJnʉ3vendor/psr/http-factory/src/UriFactoryInterface.phpU-gU=vendor/psr/http-factory/src/ServerRequestFactoryInterface.php-gw97vendor/psr/http-factory/src/RequestFactoryInterface.php-g4(vendor/monolog/monolog/LICENSE'-g'#vendor/monolog/monolog/CHANGELOG.md-g䳑 vendor/monolog/monolog/README.mdA-gAo$vendor/monolog/monolog/composer.json3 -g3 >vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php -g i@vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php-g& :vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php-g)Bs;vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php-gpsHvendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php-gcJ<vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.phpY/-gY/q]Cvendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.phpJ-gJH:vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php-g:<vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php -g 7q<vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php-g~=vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php -g kVʤDvendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.phpz -gz U6X>vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php-g8=vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.phpO -gO Yvendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php-gz.Zvendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php-g\vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php -g ;Ӥ;vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php -g YCvendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php-g>vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.phpz-gzE^6vendor/monolog/monolog/src/Monolog/Handler/Handler.php-g|>vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php -g 7m>vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.phpG -gG B>vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.phpJ-gJ1Jvendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php-g'WHvendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php-g lDvendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php -g $?vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php4-g4Dvendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php$-g$ Aߤ<vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php-g9vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php-g- MBvendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php>-g>^nCvendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php-g<Bvendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php-g}=vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php -g nD=vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.phpU-gU٤Fvendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php-gN'x~:vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php-gcaAvendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php -g @vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.phpQ0-gQ0v֤>vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php -g nXk@vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php-gD>vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php -g goCvendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.phpY-gYh=vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php-g8vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php-gɤEvendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php-gO!֤>vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php-g%TgJvendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php-gAvendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php-gޤ:vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php-gNv<vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php5 -g5 EW<vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.phpa-gaӤBvendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php-gKdﮤ>vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php-gFvendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php-g f?vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php/-g/m@vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php'-g'9vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php -g |cU>vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php)-g)̤Fvendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php-gPK?vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php -g 2;vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php-g'?vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.phpI -gI T:vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php|-g|Wb:vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php%-g%paĤAvendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php$-g$39>vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php -g \+wHvendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php-gcl=vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php -g (ٌ;vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php -g :vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.phpF-gF!fBBvendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php-gbHHvendor/monolog/monolog/src/Monolog/JsonSerializableDateTimeImmutable.php-gkܤ-vendor/monolog/monolog/src/Monolog/Logger.php;Y-g;Y{Cvendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php-gbCvendor/monolog/monolog/src/Monolog/Attribute/WithMonologChannel.php-gGL8vendor/monolog/monolog/src/Monolog/DateTimeImmutable.phph-ghx\G4vendor/monolog/monolog/src/Monolog/Test/TestCase.php-gFԧc/vendor/monolog/monolog/src/Monolog/Registry.php-g=Bvendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php-g '1Gvendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.phpI -gI =vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.phpU -gU 8Ivendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php|-g|_`xCvendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php-g+@Evendor/monolog/monolog/src/Monolog/Processor/LoadAverageProcessor.php\-g\sHvendor/monolog/monolog/src/Monolog/Processor/ClosureContextProcessor.php-g:EgCvendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php-gO=vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php-gG?o=vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php-g\@@vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php-g)Gvendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php\-g\h=vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php-gHzCvendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php]-g]l(Evendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.phpi-gi3;w:vendor/monolog/monolog/src/Monolog/ResettableInterface.php-gZ̤4vendor/monolog/monolog/src/Monolog/SignalHandler.phpZ-gZN,vendor/monolog/monolog/src/Monolog/Level.php-gc#Bvendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php;-g; ؤBvendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php-ge>vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php&-g&D;>vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.phpm-gml SBvendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.phpC -gC mӼCvendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php-g̍QBvendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.phpQ -gQ n@@vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php-gאGvendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.phpI-gI4@vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php-gPaAvendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php-gդCvendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php-gAvendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php-g(QGEvendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.phpO-gOHBvendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php-g:Lvendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php-g@vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php-g氂Dvendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php'-g'6xq>vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php-gx 0vendor/monolog/monolog/src/Monolog/LogRecord.php -g 3vendor/monolog/monolog/src/Monolog/ErrorHandler.php'-g'4_,vendor/monolog/monolog/src/Monolog/Utils.phpr"-gr"c!vendor/studio24/rotate/LICENSE.md>-g>3ä"vendor/studio24/rotate/phpunit.xml-ggE vendor/studio24/rotate/README.md-g?/$vendor/studio24/rotate/composer.json-gWѤ.vendor/studio24/rotate/src/RotateException.php_-g_ ;%vendor/studio24/rotate/src/Rotate.php#-g#j-vendor/studio24/rotate/src/FilenameFormat.php-g=D-vendor/studio24/rotate/src/RotateAbstract.php-gD6vendor/studio24/rotate/src/FilenameFormatException.phpg-ggܙ%vendor/studio24/rotate/src/Delete.php|#-g|#ؤ0vendor/studio24/rotate/src/DirectoryIterator.phpk-gkmAGvendor/symfony/framework-bundle/DataCollector/AbstractDataCollector.php-gxϤEvendor/symfony/framework-bundle/DataCollector/RouterDataCollector.phpD-gD}Uvendor/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.phpU-gU~suܤ'vendor/symfony/framework-bundle/LICENSE,-g,U7vendor/symfony/framework-bundle/Test/KernelTestCase.phpA-gARBvendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php-g3>vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.phpe-ge}wDvendor/symfony/framework-bundle/Test/NotificationAssertionsTrait.php$-g$EBvendor/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php-g7Bvendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php!-g!탤9vendor/symfony/framework-bundle/Test/TestBrowserToken.php-g¾4vendor/symfony/framework-bundle/Test/WebTestCase.php-g5?vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php-g*6vendor/symfony/framework-bundle/Test/TestContainer.phpP-gPԔq,vendor/symfony/framework-bundle/CHANGELOG.md-gķ:vendor/symfony/framework-bundle/Translation/Translator.phpR-gR H7vendor/symfony/framework-bundle/Secrets/SodiumVault.phpK#-gK#?/7vendor/symfony/framework-bundle/Secrets/DotenvVault.php8 -g8 U:9vendor/symfony/framework-bundle/Secrets/AbstractVault.php-g~pIvendor/symfony/framework-bundle/Resources/bin/check-unused-known-tags.php-g1Avendor/symfony/framework-bundle/Resources/config/asset_mapper.php$-g$O)8vendor/symfony/framework-bundle/Resources/config/esi.php-g@vendor/symfony/framework-bundle/Resources/config/translation.phpM -gM Tפ?vendor/symfony/framework-bundle/Resources/config/serializer.phpy'-gy'PF?vendor/symfony/framework-bundle/Resources/config/form_debug.php-g">vendor/symfony/framework-bundle/Resources/config/validator.php-giL6Ǥ>vendor/symfony/framework-bundle/Resources/config/semaphore.php-g4.@vendor/symfony/framework-bundle/Resources/config/annotations.php -g ݋\>vendor/symfony/framework-bundle/Resources/config/profiling.php=-g=+;vendor/symfony/framework-bundle/Resources/config/mailer.phpr -gr 蟤Fvendor/symfony/framework-bundle/Resources/config/fragment_listener.phpw-gwVgFvendor/symfony/framework-bundle/Resources/config/translation_debug.php-g$Cvendor/symfony/framework-bundle/Resources/config/notifier_debug.php-gw0Avendor/symfony/framework-bundle/Resources/config/rate_limiter.php-g|s9vendor/symfony/framework-bundle/Resources/config/lock.php-gzHvendor/symfony/framework-bundle/Resources/config/identity_translator.php-gW@vendor/symfony/framework-bundle/Resources/config/http_client.phpx -gx ^?ϤAvendor/symfony/framework-bundle/Resources/config/mailer_debug.php-g`܄ =vendor/symfony/framework-bundle/Resources/config/services.php]#-g]#k:vendor/symfony/framework-bundle/Resources/config/cache.php"-g"-l7<vendor/symfony/framework-bundle/Resources/config/session.php-gwrFvendor/symfony/framework-bundle/Resources/config/mailer_transports.php -g i? Jvendor/symfony/framework-bundle/Resources/config/translation_providers.php -g ?H:vendor/symfony/framework-bundle/Resources/config/debug.php-gL_Evendor/symfony/framework-bundle/Resources/config/notifier_webhook.php-g,Fvendor/symfony/framework-bundle/Resources/config/fragment_renderer.php -g =vendor/symfony/framework-bundle/Resources/config/web_link.phpZ-gZOj<vendor/symfony/framework-bundle/Resources/config/routing.php-gAGvendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsdg-gg#`R=vendor/symfony/framework-bundle/Resources/config/notifier.php-gEcFvendor/symfony/framework-bundle/Resources/config/http_client_debug.php-g"5$<vendor/symfony/framework-bundle/Resources/config/request.php-gkP?9vendor/symfony/framework-bundle/Resources/config/test.php-g<vendor/symfony/framework-bundle/Resources/config/webhook.php-gP쌤Dvendor/symfony/framework-bundle/Resources/config/validator_debug.php-gGUCvendor/symfony/framework-bundle/Resources/config/error_renderer.php/-g/>vendor/symfony/framework-bundle/Resources/config/mime_type.php -g H̤>vendor/symfony/framework-bundle/Resources/config/messenger.php?#-g?#Y<vendor/symfony/framework-bundle/Resources/config/console.php3-g3uҤ8vendor/symfony/framework-bundle/Resources/config/uid.php=-g=SBvendor/symfony/framework-bundle/Resources/config/property_info.php -g j>vendor/symfony/framework-bundle/Resources/config/scheduler.php-g1@w8vendor/symfony/framework-bundle/Resources/config/ssi.php-g5{8vendor/symfony/framework-bundle/Resources/config/web.php-gk?֓Dvendor/symfony/framework-bundle/Resources/config/messenger_debug.php-go灤?vendor/symfony/framework-bundle/Resources/config/collectors.phpq-gq%(Cvendor/symfony/framework-bundle/Resources/config/routing/errors.xml-g>Dvendor/symfony/framework-bundle/Resources/config/routing/webhook.xml-gVcCvendor/symfony/framework-bundle/Resources/config/html_sanitizer.php-gPդ<vendor/symfony/framework-bundle/Resources/config/secrets.php-g*n9vendor/symfony/framework-bundle/Resources/config/form.php-gm17Evendor/symfony/framework-bundle/Resources/config/serializer_debug.php-gCvendor/symfony/framework-bundle/Resources/config/workflow_debug.php-gRRTCvendor/symfony/framework-bundle/Resources/config/mailer_webhook.php -g dea>vendor/symfony/framework-bundle/Resources/config/form_csrf.phpD-gDA3U=vendor/symfony/framework-bundle/Resources/config/workflow.php-g#m7YBvendor/symfony/framework-bundle/Resources/config/security_csrf.php-g~ܤHvendor/symfony/framework-bundle/Resources/config/notifier_transports.php^3-g^3|?vendor/symfony/framework-bundle/Resources/config/debug_prod.php-g_QDvendor/symfony/framework-bundle/Resources/config/property_access.php-gBʤ;vendor/symfony/framework-bundle/Resources/config/assets.php-gv'@vendor/symfony/framework-bundle/Resources/config/cache_debug.php-g%]Avendor/symfony/framework-bundle/Resources/config/remote_event.php-g ä<vendor/symfony/framework-bundle/Resources/config/process.phpc-gc1vendor/symfony/framework-bundle/KernelBrowser.php-gDvendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php^ -g^ hrHvendor/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.phpc-gcgpJvendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php -g $bΤAvendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php-g)Gvendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php-g2eEvendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php -g ^MKvendor/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php-gҧFvendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php-glAvendor/symfony/framework-bundle/Controller/AbstractController.phpH-gHAvendor/symfony/framework-bundle/Controller/TemplateController.php -g kAvendor/symfony/framework-bundle/Controller/ControllerResolver.php3-g30Avendor/symfony/framework-bundle/Controller/RedirectController.php-gHǤ)vendor/symfony/framework-bundle/README.md!-g!q7vendor/symfony/framework-bundle/HttpCache/HttpCache.php -g R 3vendor/symfony/framework-bundle/FrameworkBundle.php3-g3ب >vendor/symfony/framework-bundle/Command/SecretsListCommand.php -g cc4Jvendor/symfony/framework-bundle/Command/CachePoolInvalidateTagsCommand.phpK-gK,ؤ@vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.phpw -gw A=vendor/symfony/framework-bundle/Command/CacheClearCommand.php(-g(~<vendor/symfony/framework-bundle/Command/XliffLintCommand.php-gvtcHvendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php -g Avendor/symfony/framework-bundle/Command/AbstractConfigCommand.phpi-giVP>vendor/symfony/framework-bundle/Command/RouterDebugCommand.php-gs`iDvendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php{D-g{DRFvendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php8-g8!@vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php'-g']3%Avendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php-g~T}Avendor/symfony/framework-bundle/Command/CachePoolClearCommand.php-gZ Q~@vendor/symfony/framework-bundle/Command/ContainerLintCommand.php\-g\]6Jvendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php1 -g1 dƃ|Bvendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php-g\>vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php -g :5Τ?vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.phpD-gD&Gvendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php-g ّYAvendor/symfony/framework-bundle/Command/ContainerDebugCommand.phps<-gs<_qCvendor/symfony/framework-bundle/Command/TranslationDebugCommand.phpa<-ga<1g;vendor/symfony/framework-bundle/Command/YamlLintCommand.phpA-gAFs@vendor/symfony/framework-bundle/Command/CachePoolListCommand.php-g;qFvendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php-g֤Bvendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php -g yUɤDvendor/symfony/framework-bundle/Command/BuildDebugContainerTrait.php -g ҥ8vendor/symfony/framework-bundle/Command/AboutCommand.php-gn٤>vendor/symfony/framework-bundle/Command/RouterMatchCommand.php7-g7}S=vendor/symfony/framework-bundle/Command/SecretsSetCommand.php:-g:>vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php4)-g4)E^%Jvendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php!-g!)\Jvendor/symfony/framework-bundle/Routing/AttributeRouteControllerLoader.php-gv1)Ovendor/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php-gny@vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php-gb 2vendor/symfony/framework-bundle/Routing/Router.php-g~Un<vendor/symfony/framework-bundle/Routing/DelegatingLoader.php -g դJvendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php -g y,Evendor/symfony/framework-bundle/DependencyInjection/Configuration.php.`vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php -g j(vcvendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.phpW-gWW*ͤOvendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.phpt-gtb"Rvendor/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php-goXvendor/symfony/framework-bundle/DependencyInjection/Compiler/ErrorLoggerCompilerPass.php-g9/]vendor/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php-gZvendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php#-g#,Zvendor/symfony/framework-bundle/DependencyInjection/Compiler/EnableLoggerDebugModePass.php-g}V`vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php@ -g@ y`1Vvendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.phpY -gY Nx\vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.phpV-gV0#_vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php-g~YMvendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php -g &1jvendor/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php -g k)̤Yvendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php-g`:W-vendor/symfony/framework-bundle/composer.json-gcFD ;vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.phpd -gd ٟO7vendor/symfony/framework-bundle/Console/Application.phpE -gE '23Evendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.phpm-gmJLDvendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.phpj-gjksnUAvendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php6-g6Evendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.phpD-gDvFIvendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php8I-g8IhCvendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php-g*Ivendor/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php-gcQvendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php -g Su%vendor/symfony/monolog-bundle/LICENSE)-g)Ǥ*vendor/symfony/monolog-bundle/CHANGELOG.md-g:L:vendor/symfony/monolog-bundle/Resources/config/monolog.xml. -g. 0yKEvendor/symfony/monolog-bundle/Resources/config/schema/monolog-1.0.xsd'-g')X<vendor/symfony/monolog-bundle/SwiftMailer/MessageFactory.php-g'vendor/symfony/monolog-bundle/README.mdY-gY/vendor/symfony/monolog-bundle/MonologBundle.php-g@gFvendor/symfony/monolog-bundle/DependencyInjection/MonologExtension.phpi-giveCvendor/symfony/monolog-bundle/DependencyInjection/Configuration.php-gvrPvendor/symfony/monolog-bundle/DependencyInjection/Compiler/AddProcessorsPass.php -g RPvendor/symfony/monolog-bundle/DependencyInjection/Compiler/LoggerChannelPass.php-gOvendor/symfony/monolog-bundle/DependencyInjection/Compiler/DebugHandlerPass.php -g HSQvendor/symfony/monolog-bundle/DependencyInjection/Compiler/FixEmptyLoggerPass.php-gDNZvendor/symfony/monolog-bundle/DependencyInjection/Compiler/AddSwiftMailerTransportPass.php-g*Q +vendor/symfony/monolog-bundle/composer.json-gLJ%vendor/symfony/polyfill-php73/LICENSE,-g,'vendor/symfony/polyfill-php73/Php73.phps-gsD\?vendor/symfony/polyfill-php73/Resources/stubs/JsonException.phpE-gE8S+vendor/symfony/polyfill-php73/bootstrap.php-g|'vendor/symfony/polyfill-php73/README.md/-g/m+vendor/symfony/polyfill-php73/composer.json-g tCvendor/symfony/serializer/DataCollector/SerializerDataCollector.php?-g?8(vendor/symfony/serializer/Serializer.phpG-gG=уIvendor/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.phpu -gu  5<vendor/symfony/serializer/Mapping/ClassMetadataInterface.php3-g3闙3vendor/symfony/serializer/Mapping/ClassMetadata.phpV -gV ŏ=<vendor/symfony/serializer/Mapping/Loader/AttributeLoader.php+5-g+5y7vendor/symfony/serializer/Mapping/Loader/FileLoader.phpF-gFhդ<vendor/symfony/serializer/Mapping/Loader/LoaderInterface.phpY-gY lޤ;vendor/symfony/serializer/Mapping/Loader/YamlFileLoader.php-grFavendor/symfony/serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd-g7:vendor/symfony/serializer/Mapping/Loader/XmlFileLoader.php-gW8vendor/symfony/serializer/Mapping/Loader/LoaderChain.php-gS*=vendor/symfony/serializer/Mapping/Loader/AnnotationLoader.php-gaIvendor/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php-g2@vendor/symfony/serializer/Mapping/AttributeMetadataInterface.php -g v5?vendor/symfony/serializer/Mapping/ClassDiscriminatorMapping.php-g2qJvendor/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.phpp-gpA @vendor/symfony/serializer/Mapping/Factory/ClassResolverTrait.php+-g+u鏤Bvendor/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php-g5Gvendor/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php-gJvendor/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php7 -g7 @IPKvendor/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php-g/7vendor/symfony/serializer/Mapping/AttributeMetadata.php-gj\1vendor/symfony/serializer/SerializerInterface.php}-g}wpFvendor/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php-gHFvendor/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php_-g_gdrGvendor/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php-g\Gvendor/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php-g 89vendor/symfony/serializer/Context/ContextBuilderTrait.php-gW6>vendor/symfony/serializer/Context/SerializerContextBuilder.php-g޵R=vendor/symfony/serializer/Context/ContextBuilderInterface.php-gn Ovendor/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php#-g#DQvendor/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php-g,PRvendor/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php-gsڤUvendor/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php/-g/gBYvendor/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php1-g1zPvendor/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php-g\oqWvendor/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.phpQ-gQ2Svendor/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.phpg-ggS`vendor/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php7-g7gOUvendor/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php!-g!t;9Qvendor/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php-gr㽤Lvendor/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php-gB4Qvendor/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php-g8Uvendor/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.phpB-gBѤ6vendor/symfony/serializer/Attribute/SerializedName.php-gpl.vendor/symfony/serializer/Attribute/Ignore.php-g/vendor/symfony/serializer/Attribute/Context.php -g Oq'8vendor/symfony/serializer/Attribute/DiscriminatorMap.php-gӤ6vendor/symfony/serializer/Attribute/SerializedPath.php-g<0vendor/symfony/serializer/Attribute/MaxDepth.php-g[v.vendor/symfony/serializer/Attribute/Groups.php-g!x !vendor/symfony/serializer/LICENSE,-g,U&vendor/symfony/serializer/CHANGELOG.md6<-g6<qSx0vendor/symfony/serializer/Encoder/CsvEncoder.php&-g&.B5&Bvendor/symfony/serializer/Encoder/ContextAwareDecoderInterface.php-go׍2vendor/symfony/serializer/Encoder/ChainEncoder.phpg -gg A06vendor/symfony/serializer/Encoder/DecoderInterface.php/-g/ Bvendor/symfony/serializer/Encoder/ContextAwareEncoderInterface.php-gQ{NAvendor/symfony/serializer/Encoder/NormalizationAwareInterface.phpv-gv /g6vendor/symfony/serializer/Encoder/EncoderInterface.php-g_ J2vendor/symfony/serializer/Encoder/ChainDecoder.php-g}[0vendor/symfony/serializer/Encoder/JsonEncode.php-gۤ1vendor/symfony/serializer/Encoder/JsonEncoder.php-gw0vendor/symfony/serializer/Encoder/JsonDecode.php<-g<Dh$1vendor/symfony/serializer/Encoder/YamlEncoder.phpq -gq !y]0vendor/symfony/serializer/Encoder/XmlEncoder.phpH-gHpbRJvendor/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php7-g7Ƭc7vendor/symfony/serializer/Annotation/SerializedName.php[-g[PR/vendor/symfony/serializer/Annotation/Ignore.phpC-gC 𽩤0vendor/symfony/serializer/Annotation/Context.php-g;i*9vendor/symfony/serializer/Annotation/DiscriminatorMap.phpB-gBR?7vendor/symfony/serializer/Annotation/SerializedPath.php[-g[ޢ6X1vendor/symfony/serializer/Annotation/MaxDepth.phpI-gIBY/vendor/symfony/serializer/Annotation/Groups.php^-g^wLNLvendor/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php^-g^$7Cvendor/symfony/serializer/Extractor/ObjectPropertyListExtractor.php{-g{E6vendor/symfony/serializer/SerializerAwareInterface.php-gM#vendor/symfony/serializer/README.mdJ-gJMc%Bvendor/symfony/serializer/NameConverter/NameConverterInterface.php-gpvEqJvendor/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php-g6Fvendor/symfony/serializer/NameConverter/MetadataAwareNameConverter.php-g.]Mvendor/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php8-g8\Ѥ2vendor/symfony/serializer/Command/DebugCommand.phpy-gy2 3;vendor/symfony/serializer/Normalizer/DateTimeNormalizer.php-ga‡Z>vendor/symfony/serializer/Normalizer/MimeMessageNormalizer.phpD-gDBr͌@vendor/symfony/serializer/Normalizer/DenormalizableInterface.phpv-gv:vendor/symfony/serializer/Normalizer/ProblemNormalizer.php-gKIvendor/symfony/serializer/Normalizer/CacheableSupportsMethodInterface.php"-g"Jgɤ>vendor/symfony/serializer/Normalizer/ObjectToPopulateTrait.php--g-Ґ~}<vendor/symfony/serializer/Normalizer/FormErrorNormalizer.php -g cIJvendor/symfony/serializer/Normalizer/ContextAwareDenormalizerInterface.php7-g7#:vendor/symfony/serializer/Normalizer/ArrayDenormalizer.php -g Avendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.phpו-gוX?vendor/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php -g 6Ǥ?vendor/symfony/serializer/Normalizer/UnwrappingDenormalizer.php} -g} /)=vendor/symfony/serializer/Normalizer/NormalizerAwareTrait.phpk-gk#Avendor/symfony/serializer/Normalizer/NormalizerAwareInterface.php%-g%:]RCvendor/symfony/serializer/Normalizer/JsonSerializableNormalizer.php1 -g1 PC:vendor/symfony/serializer/Normalizer/DataUriNormalizer.php-g%Hvendor/symfony/serializer/Normalizer/ContextAwareNormalizerInterface.php-g+9vendor/symfony/serializer/Normalizer/CustomNormalizer.phpB -gB O(Cvendor/symfony/serializer/Normalizer/DenormalizerAwareInterface.php/-g/<ǖ?vendor/symfony/serializer/Normalizer/DateIntervalNormalizer.php-gzԋ;vendor/symfony/serializer/Normalizer/PropertyNormalizer.php -g :9vendor/symfony/serializer/Normalizer/ObjectNormalizer.php6'-g6'ЯOQ;vendor/symfony/serializer/Normalizer/AbstractNormalizer.phpa-gaPt?vendor/symfony/serializer/Normalizer/TranslatableNormalizer.php-gZ7(G6vendor/symfony/serializer/Normalizer/UidNormalizer.php-gru>vendor/symfony/serializer/Normalizer/DenormalizerInterface.php -g Vi3>vendor/symfony/serializer/Normalizer/NormalizableInterface.php-g?vendor/symfony/serializer/Normalizer/GetSetMethodNormalizer.php-g#=vendor/symfony/serializer/Normalizer/BackedEnumNormalizer.php,-g,gJvendor/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php-go<vendor/symfony/serializer/Normalizer/NormalizerInterface.php -g e?vendor/symfony/serializer/Normalizer/DenormalizerAwareTrait.php{-g{o2vendor/symfony/serializer/SerializerAwareTrait.php`-g`ĝ|@vendor/symfony/serializer/DependencyInjection/SerializerPass.php -g 6vendor/symfony/serializer/Exception/LogicException.php-gA:vendor/symfony/serializer/Exception/ExceptionInterface.php-gZaLvendor/symfony/serializer/Exception/MissingConstructorArgumentsException.php-ga@vendor/symfony/serializer/Exception/UnexpectedValueException.php-grǤ8vendor/symfony/serializer/Exception/RuntimeException.php-gVXEvendor/symfony/serializer/Exception/NotNormalizableValueException.phpc-gcN͜@vendor/symfony/serializer/Exception/InvalidArgumentException.php-gn Bvendor/symfony/serializer/Exception/CircularReferenceException.php-gs5>vendor/symfony/serializer/Exception/BadMethodCallException.php-g} 8vendor/symfony/serializer/Exception/MappingException.php-gǠۤ<vendor/symfony/serializer/Exception/UnsupportedException.php-gBvendor/symfony/serializer/Exception/NotEncodableValueException.php-g\53Gvendor/symfony/serializer/Exception/PartialDenormalizationException.phpM-gMDBvendor/symfony/serializer/Exception/UnsupportedFormatException.php-gG`k@vendor/symfony/serializer/Exception/ExtraAttributesException.php-g3ٌ'vendor/symfony/serializer/composer.json -g ɮ4vendor/symfony/serializer/Debug/TraceableEncoder.php'-g'hͤ7vendor/symfony/serializer/Debug/TraceableSerializer.php-g&Ix7vendor/symfony/serializer/Debug/TraceableNormalizer.phpa-ga ;ݤ*vendor/symfony/polyfill-php80/PhpToken.php-gs’`%vendor/symfony/polyfill-php80/LICENSE,-g, K:vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.phpw-gw=7T8<vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php>-g>g;vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php-gMK<Evendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.phpG-gGֈ+<vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php-gt]\ڤ+vendor/symfony/polyfill-php80/bootstrap.php-g.Ĥ'vendor/symfony/polyfill-php80/README.md-g"tF'vendor/symfony/polyfill-php80/Php80.php-gH+vendor/symfony/polyfill-php80/composer.jsonb-gbF7vendor/symfony/monolog-bridge/Handler/MailerHandler.php-g1dHvendor/symfony/monolog-bridge/Handler/CompatibilityProcessingHandler.php-g8vendor/symfony/monolog-bridge/Handler/ConsoleHandler.php-gѺ Svendor/symfony/monolog-bridge/Handler/FingersCrossed/HttpCodeActivationStrategy.php-gcSvendor/symfony/monolog-bridge/Handler/FingersCrossed/NotFoundActivationStrategy.phpT-gTs:vendor/symfony/monolog-bridge/Handler/ServerLogHandler.php -g \~>vendor/symfony/monolog-bridge/Handler/CompatibilityHandler.php-g!E9vendor/symfony/monolog-bridge/Handler/NotifierHandler.php -g %ˤ8vendor/symfony/monolog-bridge/Handler/FirePHPHandler.php-gJ:vendor/symfony/monolog-bridge/Handler/ChromePhpHandler.php0-g0ݤFvendor/symfony/monolog-bridge/Handler/ElasticsearchLogstashHandler.php-gI6(vendor/symfony/monolog-bridge/Logger.php- -g- y%vendor/symfony/monolog-bridge/LICENSE,-g,U*vendor/symfony/monolog-bridge/CHANGELOG.md -g `s:vendor/symfony/monolog-bridge/Processor/TokenProcessor.php<-g<]Dvendor/symfony/monolog-bridge/Processor/SwitchUserTokenProcessor.php-gA ܊8vendor/symfony/monolog-bridge/Processor/WebProcessor.php-gBvendor/symfony/monolog-bridge/Processor/CompatibilityProcessor.php!-g!6$:vendor/symfony/monolog-bridge/Processor/RouteProcessor.php -g <Cvendor/symfony/monolog-bridge/Processor/ConsoleCommandProcessor.phpJ-gJZUBvendor/symfony/monolog-bridge/Processor/AbstractTokenProcessor.php-gdC:vendor/symfony/monolog-bridge/Processor/DebugProcessor.php -g c4'vendor/symfony/monolog-bridge/README.md-g=~<vendor/symfony/monolog-bridge/Formatter/ConsoleFormatter.php-gPp>vendor/symfony/monolog-bridge/Formatter/VarDumperFormatter.php0-g0r~ݤBvendor/symfony/monolog-bridge/Formatter/CompatibilityFormatter.php-g˦k:vendor/symfony/monolog-bridge/Command/ServerLogCommand.php-g+vendor/symfony/monolog-bridge/composer.json-g-}b9vendor/symfony/cache/DataCollector/CacheDataCollector.php-gb:XP"vendor/symfony/cache/CacheItem.php-gg9#vendor/symfony/cache/Psr16Cache.php=-g=8`cvendor/symfony/cache/LICENSE,-g,X+vendor/symfony/cache/PruneableInterface.php-ga]!vendor/symfony/cache/CHANGELOG.mdo-goʗXJ5vendor/symfony/cache/Traits/RedisClusterNodeProxy.php-g&yF/vendor/symfony/cache/Traits/RelayProxyTrait.php-gR*vendor/symfony/cache/Traits/RedisTrait.phpQt-gQt`+vendor/symfony/cache/Traits/Redis5Proxy.php׷-g׷\٤2vendor/symfony/cache/Traits/RedisCluster6Proxy.phps-gsQ*vendor/symfony/cache/Traits/ProxyTrait.php%-g%P5vendor/symfony/cache/Traits/FilesystemCommonTrait.php9-g91vendor/symfony/cache/Traits/RedisClusterProxy.php-g`"*vendor/symfony/cache/Traits/RedisProxy.php-gG.r.vendor/symfony/cache/Traits/ContractsTrait.php&-g&.M=*vendor/symfony/cache/Traits/RelayProxy.php-gVz"0vendor/symfony/cache/Traits/Redis6ProxyTrait.php -g P,vendor/symfony/cache/Traits/ValueWrapper.phpE-gEi72vendor/symfony/cache/Traits/RedisCluster5Proxy.php\-g\UҤ/vendor/symfony/cache/Traits/FilesystemTrait.php -g 7+vendor/symfony/cache/Traits/Redis6Proxy.php-gX4vendor/symfony/cache/Traits/Relay/GeosearchTrait.php'-g'7/vendor/symfony/cache/Traits/Relay/MoveTrait.php-gb2vendor/symfony/cache/Traits/Relay/PfcountTrait.php-gD/vendor/symfony/cache/Traits/Relay/CopyTrait.php-gѽ9vendor/symfony/cache/Traits/Relay/NullableReturnTrait.phpZ-gZ*zʤ/vendor/symfony/cache/Traits/Relay/HsetTrait.php-g E3vendor/symfony/cache/Traits/Relay/GetrangeTrait.php-gXԖ4vendor/symfony/cache/Traits/AbstractAdapterTrait.php\0-g\01Ť7vendor/symfony/cache/Traits/RedisCluster6ProxyTrait.php-gXm-vendor/symfony/cache/Adapter/ProxyAdapter.php_-g_<,vendor/symfony/cache/Adapter/ApcuAdapter.phpX-gXS;vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php-gƫ}1vendor/symfony/cache/Adapter/TraceableAdapter.php-g bJ6+vendor/symfony/cache/Adapter/PdoAdapter.phpA-gA-vendor/symfony/cache/Adapter/ArrayAdapter.php,-g,45vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php0-g017vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php-g<^,vendor/symfony/cache/Adapter/NullAdapter.php-g:@4vendor/symfony/cache/Adapter/ParameterNormalizer.php-g+0vendor/symfony/cache/Adapter/TagAwareAdapter.php,-g,mX0vendor/symfony/cache/Adapter/PhpFilesAdapter.php(-g( &4vendor/symfony/cache/Adapter/DoctrineDbalAdapter.phpA-gAnƬq9vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php -g ?1vendor/symfony/cache/Adapter/MemcachedAdapter.php4-g4l9 -vendor/symfony/cache/Adapter/RedisAdapter.php/-g/-U=$1vendor/symfony/cache/Adapter/AdapterInterface.php-g$B:vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php#-g#ˤ9vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php-g6s:-vendor/symfony/cache/Adapter/Psr16Adapter.php*-g*$\-vendor/symfony/cache/Adapter/ChainAdapter.php]"-g]"x2vendor/symfony/cache/Adapter/FilesystemAdapter.php-g(Acb0vendor/symfony/cache/Adapter/AbstractAdapter.php2-g2@28vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php1-g1;,0vendor/symfony/cache/Adapter/PhpArrayAdapter.php/-g/Ť%vendor/symfony/cache/LockRegistry.php-g)?Ӥ,vendor/symfony/cache/ResettableInterface.php-gNRvendor/symfony/cache/README.md-g`t:9vendor/symfony/cache/Messenger/EarlyExpirationHandler.php7 -g7 r9vendor/symfony/cache/Messenger/EarlyExpirationMessage.php -g %<vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php -g q5vendor/symfony/cache/Marshaller/DefaultMarshaller.phpK-gKh&5vendor/symfony/cache/Marshaller/DeflateMarshaller.php-gC7vendor/symfony/cache/Marshaller/MarshallerInterface.php3-g3Ǚ6vendor/symfony/cache/Marshaller/TagAwareMarshaller.php -g t4vendor/symfony/cache/Marshaller/SodiumMarshaller.php` -g` F:vendor/symfony/cache/DependencyInjection/CachePoolPass.php,'-g,'VM@vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php-gm}?vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php -g tAvendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php-gŁ:1vendor/symfony/cache/Exception/LogicException.php-g9d;vendor/symfony/cache/Exception/InvalidArgumentException.php-gj1vendor/symfony/cache/Exception/CacheException.php-gQ4"vendor/symfony/cache/composer.json-gFw-vendor/symfony/polyfill-ctype/bootstrap80.phpr-grF)%vendor/symfony/polyfill-ctype/LICENSE,-g,+vendor/symfony/polyfill-ctype/bootstrap.php@-g@jQ9'vendor/symfony/polyfill-ctype/README.md^-g^lHk'vendor/symfony/polyfill-ctype/Ctype.php-g /+vendor/symfony/polyfill-ctype/composer.json-g9%vendor/symfony/polyfill-php81/LICENSE,-g,0Fvendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php-g5+@vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php-gJT+vendor/symfony/polyfill-php81/bootstrap.php-g<P'vendor/symfony/polyfill-php81/README.md-g'vendor/symfony/polyfill-php81/Php81.php-g 3E+vendor/symfony/polyfill-php81/composer.json-g#@Fvendor/symfony/security-bundle/DataCollector/SecurityDataCollector.php>.-g>.n&vendor/symfony/security-bundle/LICENSE,-g,U+vendor/symfony/security-bundle/CHANGELOG.mdCD-gCD ;?vendor/symfony/security-bundle/Security/LazyFirewallContext.php -g Ӈ=vendor/symfony/security-bundle/Security/UserAuthenticator.php>-g>@;vendor/symfony/security-bundle/Security/FirewallContext.phpC-gC7{Ȥ7vendor/symfony/security-bundle/Security/FirewallMap.php; -g; 5r\:vendor/symfony/security-bundle/Security/FirewallConfig.php -g `9p>vendor/symfony/security-bundle/Security/FirewallAwareTrait.php-gsWvendor/symfony/security-bundle/Resources/config/security_authenticator_access_token.php-g43MUCvendor/symfony/security-bundle/Resources/config/templating_twig.php-g@']Fvendor/symfony/security-bundle/Resources/config/security_listeners.php-gNeUvendor/symfony/security-bundle/Resources/config/security_authenticator_login_link.php -g +Bvendor/symfony/security-bundle/Resources/config/security_debug.php3-g36!H!Avendor/symfony/security-bundle/Resources/config/debug_console.php-gGvendor/symfony/security-bundle/Resources/config/schema/security-1.0.xsdX-gXf#;vendor/symfony/security-bundle/Resources/config/console.php-g ,Cvendor/symfony/security-bundle/Resources/config/password_hasher.php-gJ>vendor/symfony/security-bundle/Resources/config/collectors.php-gu|Jvendor/symfony/security-bundle/Resources/config/security_authenticator.php-gVQ<vendor/symfony/security-bundle/Resources/config/security.php .-g .អVvendor/symfony/security-bundle/Resources/config/security_authenticator_remember_me.php -g K Avendor/symfony/security-bundle/Resources/views/Collector/icon.svg-g0צKvendor/symfony/security-bundle/Resources/views/Collector/security.html.twige-geYDvendor/symfony/security-bundle/CacheWarmer/ExpressionCacheWarmer.phpq-gq501vendor/symfony/security-bundle/SecurityBundle.php-g7-X(vendor/symfony/security-bundle/README.md-g[AHvendor/symfony/security-bundle/RememberMe/DecoratedRememberMeHandler.php^-g^H:yLvendor/symfony/security-bundle/RememberMe/FirewallAwareRememberMeHandler.php@-g@G٤?vendor/symfony/security-bundle/Command/DebugFirewallCommand.php"-g"ž&x<vendor/symfony/security-bundle/Routing/LogoutRouteLoader.php=-g=פ+vendor/symfony/security-bundle/Security.php%-g% Jvendor/symfony/security-bundle/LoginLink/FirewallAwareLoginLinkHandler.php -g ߡHvendor/symfony/security-bundle/DependencyInjection/MainConfiguration.phpS9-gS9|cvendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php3 -g3 Vkvendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcUserInfoTokenHandlerFactory.php -g ~Gfvendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/ServiceTokenHandlerFactory.php-gCWߤhvendor/symfony/security-bundle/DependencyInjection/Security/AccessToken/TokenHandlerFactoryInterface.php-gw(Xvendor/symfony/security-bundle/DependencyInjection/Security/UserProvider/LdapFactory.php -g HX\vendor/symfony/security-bundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php-gbHqivendor/symfony/security-bundle/DependencyInjection/Security/UserProvider/UserProviderFactoryInterface.php-gviXvendor/symfony/security-bundle/DependencyInjection/Security/Factory/LoginLinkFactory.phpm-gmpSʤ\vendor/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php -g (腊\vendor/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginLdapFactory.php-gRzZvendor/symfony/security-bundle/DependencyInjection/Security/Factory/AccessTokenFactory.php-gAYXvendor/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginFactory.phpv -gv zä\vendor/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.phpK-gKpRbvendor/symfony/security-bundle/DependencyInjection/Security/Factory/CustomAuthenticatorFactory.php-gXiYvendor/symfony/security-bundle/DependencyInjection/Security/Factory/RemoteUserFactory.php-g:Pդevendor/symfony/security-bundle/DependencyInjection/Security/Factory/AuthenticatorFactoryInterface.phpG-gG3SYvendor/symfony/security-bundle/DependencyInjection/Security/Factory/RememberMeFactory.php*-g*隤Wvendor/symfony/security-bundle/DependencyInjection/Security/Factory/AbstractFactory.php-gpSvendor/symfony/security-bundle/DependencyInjection/Security/Factory/X509Factory.php-gVr@avendor/symfony/security-bundle/DependencyInjection/Security/Factory/SignatureAlgorithmFactory.phpf-gfP hvendor/symfony/security-bundle/DependencyInjection/Security/Factory/FirewallListenerFactoryInterface.php-g}/Xvendor/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginFactory.php-g nvendor/symfony/security-bundle/DependencyInjection/Security/Factory/StatelessAuthenticatorFactoryInterface.php -g 9 ̤Xvendor/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicFactory.php-gsoFXvendor/symfony/security-bundle/DependencyInjection/Security/Factory/LdapFactoryTrait.phpm -gm 盤^vendor/symfony/security-bundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php-g.bHvendor/symfony/security-bundle/DependencyInjection/SecurityExtension.php-g=2W[bvendor/symfony/security-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php-gߐ*7^vendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php -g І;Wvendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterLdapLocatorPass.phpW-gW9khvendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPass.php -g ǓYvendor/symfony/security-bundle/DependencyInjection/Compiler/SortFirewallListenersPass.phpO -gO դevendor/symfony/security-bundle/DependencyInjection/Compiler/ReplaceDecoratedRememberMeHandlerPass.php -g >y^vendor/symfony/security-bundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php-g xUvendor/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php -g rҤVvendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterEntryPointPass.php-gd%ivendor/symfony/security-bundle/DependencyInjection/Compiler/MakeFirewallsEventDispatcherTraceablePass.php` -g` U p3[vendor/symfony/security-bundle/DependencyInjection/Compiler/CleanRememberMeVerifierPass.php-g"*AXvendor/symfony/security-bundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php -g 8I,vendor/symfony/security-bundle/composer.json -g ֛Bvendor/symfony/security-bundle/Debug/TraceableFirewallListener.phpN-gNZ.8vendor/symfony/security-bundle/Debug/WrappedListener.php-gD?vendor/symfony/security-bundle/Debug/TraceableListenerTrait.phpj-gjqU<vendor/symfony/security-bundle/Debug/WrappedLazyListener.php-g 9Avendor/symfony/security-bundle/EventListener/FirewallListener.php-g+C=vendor/symfony/security-bundle/EventListener/VoteListener.phpB-gB<ˊϤ4vendor/symfony/config/ResourceCheckerConfigCache.php~-g~pvendor/symfony/config/LICENSE,-g,U'vendor/symfony/config/Util/XmlUtils.php$-g$U6<vendor/symfony/config/Util/Exception/XmlParsingException.php-g䢗<vendor/symfony/config/Util/Exception/InvalidXmlException.php4-g4"vendor/symfony/config/CHANGELOG.mde-ge(,.vendor/symfony/config/ConfigCacheInterface.php-g 1.vendor/symfony/config/FileLocatorInterface.php-g %vendor/symfony/config/ConfigCache.php-gS5vendor/symfony/config/ConfigCacheFactoryInterface.php-g^&%vendor/symfony/config/FileLocator.php4 -g4 =2vendor/symfony/config/ResourceCheckerInterface.php-gåؤvendor/symfony/config/README.mdT-gT'vendor/symfony/config/Loader/Loader.php-gIѤ>vendor/symfony/config/Loader/DirectoryAwareLoaderInterface.php-gj=+vendor/symfony/config/Loader/FileLoader.php-gbUL2vendor/symfony/config/Loader/ParamConfigurator.phpq-gqn݁0vendor/symfony/config/Loader/LoaderInterface.phpy-gyঽ8vendor/symfony/config/Loader/LoaderResolverInterface.php-gG/3/vendor/symfony/config/Loader/LoaderResolver.phpF-gF)%%1vendor/symfony/config/Loader/DelegatingLoader.php-gΚ%/vendor/symfony/config/Loader/GlobFileLoader.php-g[.vendor/symfony/config/Definition/FloatNode.php-gŤ-vendor/symfony/config/Definition/BaseNode.php:-g:qY60vendor/symfony/config/Definition/NumericNode.php)-g) ä:vendor/symfony/config/Definition/ConfigurableInterface.phpo-gojש,0vendor/symfony/config/Definition/IntegerNode.phpV-gV(;vendor/symfony/config/Definition/PrototypeNodeInterface.phpp-gp<5@2vendor/symfony/config/Definition/Configuration.php-g j8vendor/symfony/config/Definition/PrototypedArrayNode.php,-g,d#.vendor/symfony/config/Definition/Processor.php -g \@vendor/symfony/config/Definition/Loader/DefinitionFileLoader.php -g "2vendor/symfony/config/Definition/NodeInterface.phpL-gLQ-vendor/symfony/config/Definition/EnumNode.php -g |0vendor/symfony/config/Definition/BooleanNode.php-g BHvendor/symfony/config/Definition/Configurator/DefinitionConfigurator.phpy-gy=.vendor/symfony/config/Definition/ArrayNode.php.-g.ͤ/vendor/symfony/config/Definition/ScalarNode.php}-g}GrI;vendor/symfony/config/Definition/ConfigurationInterface.php-g_+8vendor/symfony/config/Definition/Builder/ExprBuilder.phpL-gL:^?vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php-g<9vendor/symfony/config/Definition/Builder/MergeBuilder.php-g|Bvendor/symfony/config/Definition/Builder/NumericNodeDefinition.phpm-gmMg8vendor/symfony/config/Definition/Builder/NodeBuilder.php-g|פCvendor/symfony/config/Definition/Builder/VariableNodeDefinition.phpg-gg?@vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php=-g=M}Bvendor/symfony/config/Definition/Builder/BuilderAwareInterface.phpl-gl%>vendor/symfony/config/Definition/Builder/ValidationBuilder.php-g] 8vendor/symfony/config/Definition/Builder/TreeBuilder.phpE-gEOBvendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php-g\+F}@vendor/symfony/config/Definition/Builder/NodeParentInterface.php-g ʤAvendor/symfony/config/Definition/Builder/NormalizationBuilder.php-gXäBvendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php-gYDqJvendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php-gΣAvendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php-g*@@vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php-gю;vendor/symfony/config/Definition/Builder/NodeDefinition.phpf-gf3ԤDvendor/symfony/config/Definition/Exception/DuplicateKeyException.phpS-gSgIvendor/symfony/config/Definition/Exception/InvalidDefinitionException.php-greCvendor/symfony/config/Definition/Exception/InvalidTypeException.php-g2@vendor/symfony/config/Definition/Exception/UnsetKeyException.php*-g*%2dLvendor/symfony/config/Definition/Exception/InvalidConfigurationException.php-giJvendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php_-g_:8vendor/symfony/config/Definition/Exception/Exception.php-gRrO1vendor/symfony/config/Definition/VariableNode.php -g o?vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php -g 0>vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php'-g'@vendor/symfony/config/Resource/SelfCheckingResourceInterface.php-g2Ф/vendor/symfony/config/Resource/FileResource.php-ga:vendor/symfony/config/Resource/ReflectionClassResource.php-gh[>vendor/symfony/config/Resource/SelfCheckingResourceChecker.php}-g}r3vendor/symfony/config/Resource/ComposerResource.php2-g23Pu8vendor/symfony/config/Resource/FileExistenceResource.php-gw}4vendor/symfony/config/Resource/ResourceInterface.php-g8I9vendor/symfony/config/Resource/ClassExistenceResource.php-gT$4vendor/symfony/config/Resource/DirectoryResource.php -g C/vendor/symfony/config/Resource/GlobResource.phpW!-gW!׏38vendor/symfony/config/Builder/ConfigBuilderInterface.php-g{O(vendor/symfony/config/Builder/Method.php-g@֤.vendor/symfony/config/Builder/ClassBuilder.php-g*vendor/symfony/config/Builder/Property.php,-g,_Avendor/symfony/config/Builder/ConfigBuilderGeneratorInterface.php-g8vendor/symfony/config/Builder/ConfigBuilderGenerator.phpR-gR& 7vendor/symfony/config/Exception/LoaderLoadException.php-g/zNvendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php[-g[`ܤDvendor/symfony/config/Exception/FileLocatorFileNotFoundException.phpK-gKf#vendor/symfony/config/composer.json-gM,vendor/symfony/config/ConfigCacheFactory.phpS-gScġ;vendor/symfony/config/ResourceCheckerConfigCacheFactory.php5-g5YbDvendor/symfony/security-http/RateLimiter/DefaultLoginRateLimiter.php-gb4vendor/symfony/security-http/Attribute/IsGranted.php-g`A6vendor/symfony/security-http/Attribute/CurrentUser.php!-g!C$vendor/symfony/security-http/LICENSE,-g,U5vendor/symfony/security-http/Util/TargetPathTrait.phpb-gb6=Y)vendor/symfony/security-http/CHANGELOG.md -g k,vendor/symfony/security-http/FirewallMap.phpf-gfr)vendor/symfony/security-http/Firewall.php]-g]Jvendor/symfony/security-http/AccessToken/AccessTokenExtractorInterface.phpf-gf}PHvendor/symfony/security-http/AccessToken/AccessTokenHandlerInterface.php-gmslGvendor/symfony/security-http/AccessToken/HeaderAccessTokenExtractor.php8-g8hFvendor/symfony/security-http/AccessToken/ChainAccessTokenExtractor.php'-g'g Jvendor/symfony/security-http/AccessToken/Oidc/OidcUserInfoTokenHandler.php-gmɤ;vendor/symfony/security-http/AccessToken/Oidc/OidcTrait.php-g̤Bvendor/symfony/security-http/AccessToken/Oidc/OidcTokenHandler.php-g!]6Uvendor/symfony/security-http/AccessToken/Oidc/Exception/InvalidSignatureException.php-g+FLQvendor/symfony/security-http/AccessToken/Oidc/Exception/MissingClaimException.php-g Evendor/symfony/security-http/AccessToken/FormEncodedBodyExtractor.phpm-gm}Fvendor/symfony/security-http/AccessToken/QueryAccessTokenExtractor.php-gw:vendor/symfony/security-http/Logout/LogoutUrlGenerator.phpv-gv+/vendor/symfony/security-http/SecurityEvents.php-g78vendor/symfony/security-http/Firewall/AccessListener.php -g 8ä9vendor/symfony/security-http/Firewall/ContextListener.php5-g5M-:vendor/symfony/security-http/Firewall/AbstractListener.phpq-gqFvendor/symfony/security-http/Firewall/AuthenticatorManagerListener.phpj-gjʯ;vendor/symfony/security-http/Firewall/ExceptionListener.phpf(-gf(tiCvendor/symfony/security-http/Firewall/FirewallListenerInterface.php=-g=99vendor/symfony/security-http/Firewall/ChannelListener.php -g 2<vendor/symfony/security-http/Firewall/SwitchUserListener.phpE$-gE$hް8vendor/symfony/security-http/Firewall/LogoutListener.php-g(3\Fvendor/symfony/security-http/Controller/SecurityTokenValueResolver.php-gJ;Y=vendor/symfony/security-http/Controller/UserValueResolver.php -g ؉M&vendor/symfony/security-http/README.md-gk<vendor/symfony/security-http/RememberMe/ResponseListener.php-gGvendor/symfony/security-http/RememberMe/PersistentRememberMeHandler.phpc-gcTKљFvendor/symfony/security-http/RememberMe/RememberMeHandlerInterface.php -g  ~¤=vendor/symfony/security-http/RememberMe/RememberMeDetails.phpQ -gQ Gk<[Evendor/symfony/security-http/RememberMe/AbstractRememberMeHandler.phpX-gXa*Fvendor/symfony/security-http/RememberMe/SignatureRememberMeHandler.php -g xo$fMvendor/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php-g3iNvendor/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php-g(6*vendor/symfony/security-http/HttpUtils.php-ge5vendor/symfony/security-http/FirewallMapInterface.php-g9JLvendor/symfony/security-http/Authenticator/Token/PostAuthenticationToken.phpT-gTHPvendor/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.phpj-gj9Mvendor/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php -g eEvendor/symfony/security-http/Authenticator/AuthenticatorInterface.phpS -gS v Avendor/symfony/security-http/Authenticator/FallbackUserLoader.php-g٤Dvendor/symfony/security-http/Authenticator/AbstractAuthenticator.php-g REvendor/symfony/security-http/Authenticator/HttpBasicAuthenticator.phpe-geZEvendor/symfony/security-http/Authenticator/LoginLinkAuthenticator.php?-g?!6Evendor/symfony/security-http/Authenticator/JsonLoginAuthenticator.php-g7$;Nvendor/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php-gYWW@vendor/symfony/security-http/Authenticator/Passport/Passport.php$-g$;!2Xvendor/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php-gPUvendor/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php-g@1Wvendor/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.phpV-gVRWvendor/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php-gyΤLvendor/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.phpi-gi$Rvendor/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.phpV-gVĤGvendor/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php-gV5פMvendor/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.phpK-gKp"Lvendor/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php-g˙Au@vendor/symfony/security-http/Authenticator/X509Authenticator.php -g }Gvendor/symfony/security-http/Authenticator/AccessTokenAuthenticator.php-gYTSFvendor/symfony/security-http/Authenticator/RemoteUserAuthenticator.php-gqEvendor/symfony/security-http/Authenticator/FormLoginAuthenticator.phpS-gSeQ8Tvendor/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php-ghʆ`Kvendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.phpO-gOӊ2Zvendor/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.phpg -gg Fvendor/symfony/security-http/Authenticator/RememberMeAuthenticator.php-gAuKvendor/symfony/security-http/Authorization/AccessDeniedHandlerInterface.phpz-gz(3vendor/symfony/security-http/AccessMapInterface.phpi-giHY%;vendor/symfony/security-http/LoginLink/LoginLinkDetails.phpe-geZ/;vendor/symfony/security-http/LoginLink/LoginLinkHandler.php -g ̸@vendor/symfony/security-http/LoginLink/LoginLinkNotification.php -g ֽDvendor/symfony/security-http/LoginLink/LoginLinkHandlerInterface.php-g\SWvendor/symfony/security-http/LoginLink/Exception/InvalidLoginLinkExceptionInterface.php-gHFNvendor/symfony/security-http/LoginLink/Exception/InvalidLoginLinkException.php-g\vendor/symfony/security-http/LoginLink/Exception/InvalidLoginLinkAuthenticationException.php-g-g>Cvendor/symfony/security-http/Authentication/AuthenticationUtils.php -g جRvendor/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php -g cUvendor/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.phpI-gI&4QJvendor/symfony/security-http/Authentication/UserAuthenticatorInterface.php-g >Dvendor/symfony/security-http/Authentication/AuthenticatorManager.php6-g6c 9Svendor/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php-gN"*vendor/symfony/security-http/AccessMap.php~-g~tZvendor/symfony/uid/MaxUuid.php-gSw4vendor/symfony/uid/README.md\-g\2vendor/symfony/uid/Command/GenerateUuidCommand.php(-g(vF@2vendor/symfony/uid/Command/GenerateUlidCommand.php-g->1vendor/symfony/uid/Command/InspectUuidCommand.php -g +}1vendor/symfony/uid/Command/InspectUlidCommand.php-g0>Ȉvendor/symfony/uid/UuidV1.phpV-gVʤvendor/symfony/uid/UuidV3.php^-g^(Lvendor/symfony/uid/UuidV6.phpN-gNͤvendor/symfony/uid/UuidV7.php-g, aä3vendor/symfony/uid/Factory/TimeBasedUuidFactory.php--g-i`mU*vendor/symfony/uid/Factory/UuidFactory.php> -g> Xw5vendor/symfony/uid/Factory/RandomBasedUuidFactory.php[-g[\(R*vendor/symfony/uid/Factory/UlidFactory.php-g)ݿ3vendor/symfony/uid/Factory/NameBasedUuidFactory.php-g0 A vendor/symfony/uid/composer.json-gs ۤ,vendor/symfony/uid/TimeBasedUidInterface.php-gQvendor/symfony/uid/UuidV5.php^-g^Avendor/symfony/uid/UuidV4.php-g<<vendor/symfony/event-dispatcher/EventDispatcherInterface.php-ga=vendor/symfony/event-dispatcher/Attribute/AsEventListener.php-g$'vendor/symfony/event-dispatcher/LICENSE,-g,U,vendor/symfony/event-dispatcher/CHANGELOG.md] -g] uE~3vendor/symfony/event-dispatcher/EventDispatcher.php9#-g9#ή&)vendor/symfony/event-dispatcher/README.mdW-gW,fB<vendor/symfony/event-dispatcher/EventSubscriberInterface.php-gA{)<vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php-gw0vendor/symfony/event-dispatcher/GenericEvent.php -g d Mvendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php -g i٤Kvendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php-g&{-vendor/symfony/event-dispatcher/composer.json-gRBvendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php0-g0U*u9vendor/symfony/event-dispatcher/Debug/WrappedListener.php-gokŤ+vendor/symfony/var-dumper/Cloner/Cursor.phpH-gHcq.vendor/symfony/var-dumper/Cloner/VarCloner.php)-g) 4vendor/symfony/var-dumper/Cloner/ClonerInterface.php-gze7vendor/symfony/var-dumper/Cloner/Internal/NoDefault.php4-g4ߞ4vendor/symfony/var-dumper/Cloner/DumperInterface.phpo-gok3vendor/symfony/var-dumper/Cloner/AbstractCloner.php]-g]$^)vendor/symfony/var-dumper/Cloner/Data.php5-g5G)vendor/symfony/var-dumper/Cloner/Stub.phpk-gkXܤ!vendor/symfony/var-dumper/LICENSE,-g,.z5vendor/symfony/var-dumper/Test/VarDumperTestTrait.phpV -gV F&vendor/symfony/var-dumper/CHANGELOG.md -g "D.vendor/symfony/var-dumper/Caster/GmpCaster.php -g " 5vendor/symfony/var-dumper/Caster/ReflectionCaster.php;-g;-,/vendor/symfony/var-dumper/Caster/StubCaster.php -g @v2vendor/symfony/var-dumper/Caster/SymfonyCaster.php -g Ҥ.vendor/symfony/var-dumper/Caster/FrameStub.php-gaa7vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php#-g#DJ.vendor/symfony/var-dumper/Caster/FFICaster.php-gь/vendor/symfony/var-dumper/Caster/DateCaster.php;-g;C7>.vendor/symfony/var-dumper/Caster/PdoCaster.php -g ɤ6vendor/symfony/var-dumper/Caster/XmlResourceCaster.php| -g| 3vendor/symfony/var-dumper/Caster/ResourceCaster.php -g ~4vendor/symfony/var-dumper/Caster/ExceptionCaster.phpmA-gmASL6vendor/symfony/var-dumper/Caster/UninitializedStub.phpy-gy0:-vendor/symfony/var-dumper/Caster/DsCaster.phpS-gSc-vendor/symfony/var-dumper/Caster/LinkStub.phpH -gH ϼ4vendor/symfony/var-dumper/Caster/MemcachedCaster.php-gY#g 3vendor/symfony/var-dumper/Caster/DoctrineCaster.phpG-gG55 2vendor/symfony/var-dumper/Caster/RdKafkaCaster.php-g9#1vendor/symfony/var-dumper/Caster/MysqliCaster.php-g,vendor/symfony/var-dumper/Caster/ImgStub.php-gͤ.vendor/symfony/var-dumper/Caster/ClassStub.php?-g?7V.vendor/symfony/var-dumper/Caster/TraceStub.php-g_1vendor/symfony/var-dumper/Caster/CutArrayStub.php-gQG0vendor/symfony/var-dumper/Caster/PgSqlCaster.phpj-gj'K4+vendor/symfony/var-dumper/Caster/Caster.php*-g*n.vendor/symfony/var-dumper/Caster/SplCaster.php]-g]4Dӻ.vendor/symfony/var-dumper/Caster/ConstStub.php-g3Ôk/vendor/symfony/var-dumper/Caster/ScalarStub.phpF-gFfA/vendor/symfony/var-dumper/Caster/DsPairStub.phpn-gn0 /vendor/symfony/var-dumper/Caster/IntlCaster.php-g0vendor/symfony/var-dumper/Caster/RedisCaster.php-g$OP0vendor/symfony/var-dumper/Caster/FiberCaster.phpf-gfK2vendor/symfony/var-dumper/Caster/ImagineCaster.php-g|gdߤ/vendor/symfony/var-dumper/Caster/AmqpCaster.phpH-gH.vendor/symfony/var-dumper/Caster/DOMCaster.phpN-gNt/vendor/symfony/var-dumper/Caster/UuidCaster.php-gE74vendor/symfony/var-dumper/Caster/XmlReaderCaster.php -g 5-vendor/symfony/var-dumper/Caster/ArgsStub.php -g O-vendor/symfony/var-dumper/Caster/EnumStub.php-g`",vendor/symfony/var-dumper/Caster/CutStub.php-g7vendor/symfony/var-dumper/Resources/bin/var-dump-server-g':vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css -g Dva8vendor/symfony/var-dumper/Resources/js/htmlDescriptor.jsb-gbh|6vendor/symfony/var-dumper/Resources/functions/dump.phpU-gU</vendor/symfony/var-dumper/Server/Connection.php -g xΤ/vendor/symfony/var-dumper/Server/DumpServer.php -g U駤#vendor/symfony/var-dumper/README.md_-g_Fq7vendor/symfony/var-dumper/Command/ServerDumpCommand.php-gS+Hvendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php-ga*>vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php -g d?vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php-g ?vendor/symfony/var-dumper/Exception/ThrowingCasterException.php-gä1vendor/symfony/var-dumper/Dumper/ServerDumper.php-gDZ8vendor/symfony/var-dumper/Dumper/DataDumperInterface.php@-g@o/Mvendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php(-g(EFfKvendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php-goꭤGvendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php-gy9.LJvendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php-gu3vendor/symfony/var-dumper/Dumper/AbstractDumper.php0-g0.vendor/symfony/var-dumper/Dumper/CliDumper.phpZ-gZ'9vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php-gU/vendor/symfony/var-dumper/Dumper/HtmlDumper.php<-g< F 'vendor/symfony/var-dumper/composer.jsonw-gw%E'vendor/symfony/var-dumper/VarDumper.php-gϤ!vendor/symfony/filesystem/LICENSE,-g,U&vendor/symfony/filesystem/CHANGELOG.md-gI(vendor/symfony/filesystem/Filesystem.phpt-gt1"vendor/symfony/filesystem/Path.php f-g f׀s#vendor/symfony/filesystem/README.md-g<vendor/symfony/filesystem/Exception/IOExceptionInterface.php-g :vendor/symfony/filesystem/Exception/ExceptionInterface.php-g(l`Ф8vendor/symfony/filesystem/Exception/RuntimeException.php-gA3vendor/symfony/filesystem/Exception/IOException.php-g0@vendor/symfony/filesystem/Exception/InvalidArgumentException.php-g$ =vendor/symfony/filesystem/Exception/FileNotFoundException.php-g[:'vendor/symfony/filesystem/composer.json{-g{zqGvendor/symfony/security-csrf/TokenStorage/NativeSessionTokenStorage.php -g .פAvendor/symfony/security-csrf/TokenStorage/SessionTokenStorage.phpK -gK <_Lvendor/symfony/security-csrf/TokenStorage/ClearableTokenStorageInterface.php3-g3Cvendor/symfony/security-csrf/TokenStorage/TokenStorageInterface.php-g7䭤$vendor/symfony/security-csrf/LICENSE,-g,U)vendor/symfony/security-csrf/CHANGELOG.md-g>**vendor/symfony/security-csrf/CsrfToken.php-g3&vendor/symfony/security-csrf/README.md-g:vendor/symfony/security-csrf/CsrfTokenManagerInterface.php-gyɤEvendor/symfony/security-csrf/TokenGenerator/UriSafeTokenGenerator.php-g1Gvendor/symfony/security-csrf/TokenGenerator/TokenGeneratorInterface.php-gvendor/symfony/finder/LICENSE,-g,U"vendor/symfony/finder/CHANGELOG.md -g 3gvendor/symfony/finder/Glob.php2-g2Avendor/symfony/finder/README.md-gC/vendor/symfony/finder/Iterator/LazyIterator.php-gWđ;vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php'-g'n!<vendor/symfony/finder/Iterator/FilecontentFilterIterator.php-g\v:c=vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php -g N:vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpk-gk4-9vendor/symfony/finder/Iterator/FilenameFilterIterator.phpn-gnMNQ:vendor/symfony/finder/Iterator/DateRangeFilterIterator.php-g9z֤7vendor/symfony/finder/Iterator/CustomFilterIterator.php-g ʤ=vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.phpO-gO Avendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php5 -g5 `3vendor/symfony/finder/Iterator/SortableIterator.php3-g3뛽;vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpn-gnO9vendor/symfony/finder/Iterator/FileTypeFilterIterator.php|-g|Aj5vendor/symfony/finder/Iterator/PathFilterIterator.php-g(#vendor/symfony/finder/Gitignore.php -g Q)9vendor/symfony/finder/Exception/AccessDeniedException.php-g>vendor/symfony/finder/Exception/DirectoryNotFoundException.php-g)#vendor/symfony/finder/composer.json*-g*_-vendor/symfony/polyfill-php83/bootstrap81.php-gŽp$%vendor/symfony/polyfill-php83/LICENSE,-g,t=Bvendor/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.phpH-gH<ܐ;vendor/symfony/polyfill-php83/Resources/stubs/DateError.php=-g=ˤ:vendor/symfony/polyfill-php83/Resources/stubs/Override.php-gNsE?vendor/symfony/polyfill-php83/Resources/stubs/DateException.phpE-gE Ovendor/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.phpY-gYMߤAvendor/symfony/polyfill-php83/Resources/stubs/DateObjectError.phpG-gG .ITvendor/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php^-g^KNvendor/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.phpX-gXWߤ@vendor/symfony/polyfill-php83/Resources/stubs/DateRangeError.phpF-gFL;Nvendor/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.phpX-gXgVvendor/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php`-g`6+vendor/symfony/polyfill-php83/bootstrap.php-g{Jc'vendor/symfony/polyfill-php83/README.md-g}'vendor/symfony/polyfill-php83/Php83.php -g \9>+vendor/symfony/polyfill-php83/composer.json-g{V>vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php%+-g%+p q@vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php-g]%Gvendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php/-g/D @vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php -g W}}>vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php -g R Cvendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php-gAvendor/symfony/http-kernel/DataCollector/RequestDataCollector.phpo>-go>se>vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.phpl-glkD:vendor/symfony/http-kernel/DataCollector/DataCollector.phpB -gB r@vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.phpV)-gV)>W @vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php<-g<?vendor/symfony/http-kernel/DataCollector/EventDataCollector.phpG-gGJݤCvendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.phpU-gU 5vendor/symfony/http-kernel/Attribute/AsController.php-gUT@vendor/symfony/http-kernel/Attribute/AsTargetedValueResolver.php -g w.vendor/symfony/http-kernel/Attribute/Cache.phpX -gX LҌ7vendor/symfony/http-kernel/Attribute/MapQueryString.php-gu~7vendor/symfony/http-kernel/Attribute/WithHttpStatus.php^-g^ 4vendor/symfony/http-kernel/Attribute/MapDateTime.php-gj:vendor/symfony/http-kernel/Attribute/MapRequestPayload.php)-g)-"y5vendor/symfony/http-kernel/Attribute/WithLogLevel.php-gFH6vendor/symfony/http-kernel/Attribute/ValueResolver.php-g \:vendor/symfony/http-kernel/Attribute/MapQueryParameter.php\-g\%"vendor/symfony/http-kernel/LICENSE,-g,URvendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php-g͞1Bvendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php-gSIvendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php-gD{\Ǥ'vendor/symfony/http-kernel/CHANGELOG.mdQ-gQ1vendor/symfony/http-kernel/Config/FileLocator.phpw-gw/vendor/symfony/http-kernel/HttpClientKernel.php-gu*D2vendor/symfony/http-kernel/TerminableInterface.php-g Avendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php*-g*雗=vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.phpJ-gJ7<vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php-gr2 5vendor/symfony/http-kernel/Resources/welcome.html.php-gi)vendor/symfony/http-kernel/HttpKernel.php--g-¤?vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php-g Q 6vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php-gQĤ<vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php3-g3P@ˤ?vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php-g{w]b,vendor/symfony/http-kernel/Bundle/Bundle.php-g~o5vendor/symfony/http-kernel/Bundle/BundleInterface.php-g"z4vendor/symfony/http-kernel/Bundle/AbstractBundle.php-g|`5vendor/symfony/http-kernel/Bundle/BundleExtension.php -g Y]=.vendor/symfony/http-kernel/KernelInterface.php-gJ::vendor/symfony/http-kernel/Controller/ArgumentResolver.php -g -g>BEvendor/symfony/http-kernel/Controller/ContainerControllerResolver.php-gfPvendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php@-g@SOvendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php|-g|wSOvendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php-g^(2Vvendor/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php-gg,Kvendor/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php-gybޤRvendor/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php0-g0NsVvendor/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.phpD"-gD"rnPvendor/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php -g 7Ovendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php-g05Ovendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php-goXvendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php-gq?柤[vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php: -g: <Qvendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php3-g38?Cvendor/symfony/http-kernel/Controller/ArgumentResolverInterface.phpt-gtq/mEvendor/symfony/http-kernel/Controller/ControllerResolverInterface.phpy-gy5ݰʤCvendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php-gD@vendor/symfony/http-kernel/Controller/ValueResolverInterface.php-g@9<vendor/symfony/http-kernel/Controller/ControllerResolver.php0(-g0(7nlEvendor/symfony/http-kernel/Controller/TraceableControllerResolver.phpJ-gJ#@Hvendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php-g%$vendor/symfony/http-kernel/README.md-g7Evendor/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php:-g:Ze>vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php-gb^b;vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php%-g% Ivendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php-g,JAvendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php-gǛ<<vendor/symfony/http-kernel/Fragment/FragmentUriGenerator.php$-g$;vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php%-g%p@vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php/ -g/ r07vendor/symfony/http-kernel/Fragment/FragmentHandler.php-g<̤@vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php+-g+rT+vendor/symfony/http-kernel/KernelEvents.phpd-gdZ$,vendor/symfony/http-kernel/HttpCache/Esi.php -g K\2vendor/symfony/http-kernel/HttpCache/HttpCache.phpk-gkJ.vendor/symfony/http-kernel/HttpCache/Store.php9-g9j=;vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php-grGvendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php:-g:)Ou>vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php!-g!t7vendor/symfony/http-kernel/HttpCache/StoreInterface.php-g+,vendor/symfony/http-kernel/HttpCache/Ssi.phpR -gR Y:vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php-gڄ:vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php1-g1イ2vendor/symfony/http-kernel/HttpKernelInterface.php-gZ)vendor/symfony/http-kernel/Log/Logger.php2-g2Y8X7vendor/symfony/http-kernel/Log/DebugLoggerInterface.phpD-gD'V:vendor/symfony/http-kernel/Log/DebugLoggerConfigurator.phpH-gH,;vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php(-g(|r/vendor/symfony/http-kernel/Profiler/Profile.phpo-go#0vendor/symfony/http-kernel/Profiler/Profiler.php-g27ya@vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php-g0ĤGvendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php-gPCvendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php-g/vRvendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php-g2@Hvendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php-g&ˏRvendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php-gT Qvendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php-g:Hvendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php-g6v=vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php)-g)Q*<vendor/symfony/http-kernel/DependencyInjection/Extension.php_-g_ʍ/Vvendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.phpY -gY FTYvendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php.-g.zM\vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php -g 5 դMvendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php-gEvendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php-g<>vendor/symfony/http-kernel/Exception/ConflictHttpException.phpc-gc6vendor/symfony/http-kernel/Exception/HttpException.phpN-gNդBvendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php-g8Avendor/symfony/http-kernel/Exception/InvalidMetadataException.phpj-gj;녤Dvendor/symfony/http-kernel/Exception/LengthRequiredHttpException.phpi-gi lIvendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.phpw-gw3Hvendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.phpm-gmm%:vendor/symfony/http-kernel/Exception/GoneHttpException.php_-g_eyJvendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.phpo-goaM}Hvendor/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php-gZis<vendor/symfony/http-kernel/Exception/LockedHttpException.phpe-gepehHvendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.phpm-gm=?vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php}-g}֚5Bvendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php-g6HHg@vendor/symfony/http-kernel/Exception/BadRequestHttpException.phpe-geՑQvendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php-gt< eCvendor/symfony/http-kernel/Exception/NotAcceptableHttpException.phph-gh(ޤJvendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php-gcԤ>vendor/symfony/http-kernel/Exception/NotFoundHttpException.phpj-gjVzFvendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php-giנBvendor/symfony/http-kernel/Exception/ResolverNotFoundException.php-gy +4vendor/symfony/http-kernel/Event/ControllerEvent.phpj-gjw.Ƥ3vendor/symfony/http-kernel/Event/ExceptionEvent.php-gp-7vendor/symfony/http-kernel/Event/FinishRequestEvent.php-gTY2vendor/symfony/http-kernel/Event/ResponseEvent.php-g,73vendor/symfony/http-kernel/Event/TerminateEvent.php-gVC=vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php -g nT0vendor/symfony/http-kernel/Event/KernelEvent.php-gDBc1vendor/symfony/http-kernel/Event/RequestEvent.php-g ׁ.vendor/symfony/http-kernel/Event/ViewEvent.php-g(vendor/symfony/http-kernel/composer.jsonm -gm -m2vendor/symfony/http-kernel/RebootableInterface.php<-g<pLX1%vendor/symfony/http-kernel/Kernel.phpw-gwr[(vendor/symfony/http-kernel/UriSigner.php-g2[{8vendor/symfony/http-kernel/Debug/VirtualRequestStack.phpI-gIU&=vendor/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php-gP=vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.phps -gs |6vendor/symfony/http-kernel/Debug/FileLinkFormatter.php-g0vendor/symfony/http-kernel/HttpKernelBrowser.php-gi\Evendor/symfony/http-kernel/EventListener/StreamedResponseListener.php-g}>Ť=vendor/symfony/http-kernel/EventListener/ResponseListener.php-gPUȤ;vendor/symfony/http-kernel/EventListener/LocaleListener.php -g 7)<=vendor/symfony/http-kernel/EventListener/FragmentListener.php8 -g8 vCvendor/symfony/http-kernel/EventListener/CacheAttributeListener.php1-g1ۤDvendor/symfony/http-kernel/EventListener/AbstractSessionListener.phpd0-gd0o!Dvendor/symfony/http-kernel/EventListener/ValidateRequestListener.php-gxKvendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.phpo-go>JȤFvendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php-gq =vendor/symfony/http-kernel/EventListener/ProfilerListener.php<-g<<3W>vendor/symfony/http-kernel/EventListener/SurrogateListener.phpU-gUMBvendor/symfony/http-kernel/EventListener/DebugHandlersListener.php-gn@vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php -g 9vendor/symfony/http-kernel/EventListener/DumpListener.php%-g%ۤ:vendor/symfony/http-kernel/EventListener/ErrorListener.php!-g! O<vendor/symfony/http-kernel/EventListener/SessionListener.php-g ;vendor/symfony/http-kernel/EventListener/RouterListener.php-gG]9vendor/symfony/yaml/LICENSE,-g,Uvendor/symfony/yaml/Parser.phpI-gIqŤ vendor/symfony/yaml/CHANGELOG.md-gĤvendor/symfony/yaml/Escaper.php -g +vendor/symfony/yaml/Resources/bin/yaml-lint-g3VԈvendor/symfony/yaml/README.md-gـT!vendor/symfony/yaml/Unescaper.phpK -gK 脱vendor/symfony/yaml/Dumper.php-ghvendor/symfony/yaml/Inline.php-gXwtvendor/symfony/yaml/Yaml.php -g LϽ+vendor/symfony/yaml/Command/LintCommand.php'-g'te/vendor/symfony/yaml/Exception/DumpException.php-g?<̤4vendor/symfony/yaml/Exception/ExceptionInterface.php-g,P2vendor/symfony/yaml/Exception/RuntimeException.php-g#OU0vendor/symfony/yaml/Exception/ParseException.php -g mFB'vendor/symfony/yaml/Tag/TaggedValue.php-gs$!vendor/symfony/yaml/composer.json-gZܦ)vendor/symfony/string/CodePointString.phpN-gNJvendor/symfony/string/LICENSE,-g,զ_Ϥ"vendor/symfony/string/CHANGELOG.mdz-gzub(vendor/symfony/string/AbstractString.phpI-gIk-vendor/symfony/string/Resources/functions.phpc-gcȤ<vendor/symfony/string/Resources/data/wcswidth_table_zero.phpF-gFMI<vendor/symfony/string/Resources/data/wcswidth_table_wide.phpk-gk/3vendor/symfony/string/Inflector/FrenchInflector.php-gQ6vendor/symfony/string/Inflector/InflectorInterface.phpR-gR_4vendor/symfony/string/Inflector/EnglishInflector.phpC-gCQ~vendor/symfony/string/README.md+-g+L/vendor/symfony/string/AbstractUnicodeString.phppb-gpbc|Q$vendor/symfony/string/LazyString.php-g$vendor/symfony/string/ByteString.phpv9-gv9}'vendor/symfony/string/UnicodeString.php1-g16vendor/symfony/string/Exception/ExceptionInterface.php_-g_ :4vendor/symfony/string/Exception/RuntimeException.php~-g~)Ʉ<vendor/symfony/string/Exception/InvalidArgumentException.php-gB;8#vendor/symfony/string/composer.json-g#2vendor/symfony/string/Slugger/SluggerInterface.php-g.vendor/symfony/string/Slugger/AsciiSlugger.php-g[=M4vendor/symfony/security-core/Role/SwitchUserRole.php-g'v<vendor/symfony/security-core/Role/RoleHierarchyInterface.php]-g]Բ'*vendor/symfony/security-core/Role/Role.php-gi֜3vendor/symfony/security-core/Role/RoleHierarchy.php-gUՈCvendor/symfony/security-core/Validator/Constraints/UserPassword.php"-g"<0Lvendor/symfony/security-core/Validator/Constraints/UserPasswordValidator.php~ -g~ ^$vendor/symfony/security-core/LICENSE,-g,UDvendor/symfony/security-core/Test/AccessDecisionStrategyTestCase.php -g ABvendor/symfony/security-core/Signature/ExpiredSignatureStorage.php-g`5Nvendor/symfony/security-core/Signature/Exception/InvalidSignatureException.php-g[.ܤNvendor/symfony/security-core/Signature/Exception/ExpiredSignatureException.php-g(::vendor/symfony/security-core/Signature/SignatureHasher.php-gd5A)vendor/symfony/security-core/CHANGELOG.md -g &Cvendor/symfony/security-core/Resources/translations/security.sq.xlfS-gSB&^Cvendor/symfony/security-core/Resources/translations/security.ru.xlf-gmCvendor/symfony/security-core/Resources/translations/security.hy.xlf-gBCvendor/symfony/security-core/Resources/translations/security.fr.xlfU-gU$Cvendor/symfony/security-core/Resources/translations/security.fa.xlf-gIѤCvendor/symfony/security-core/Resources/translations/security.pl.xlf-guCvendor/symfony/security-core/Resources/translations/security.sv.xlf-gcnCvendor/symfony/security-core/Resources/translations/security.el.xlf8-g8yvaHvendor/symfony/security-core/Resources/translations/security.sr_Cyrl.xlf-gCvendor/symfony/security-core/Resources/translations/security.en.xlfl-glgBZCvendor/symfony/security-core/Resources/translations/security.ja.xlf-gHFvendor/symfony/security-core/Resources/translations/security.pt_BR.xlf-giH! Cvendor/symfony/security-core/Resources/translations/security.no.xlf-g~RҤCvendor/symfony/security-core/Resources/translations/security.vi.xlf,-g,aCvendor/symfony/security-core/Resources/translations/security.ur.xlf-ggCvendor/symfony/security-core/Resources/translations/security.nn.xlf-glCvendor/symfony/security-core/Resources/translations/security.nl.xlf-g"֤Cvendor/symfony/security-core/Resources/translations/security.cy.xlfv-gvFŤCvendor/symfony/security-core/Resources/translations/security.af.xlf-gojoCvendor/symfony/security-core/Resources/translations/security.lv.xlfc-gc@ۤCvendor/symfony/security-core/Resources/translations/security.ar.xlf-gODCvendor/symfony/security-core/Resources/translations/security.lb.xlf)-g)z7Cvendor/symfony/security-core/Resources/translations/security.tr.xlf-g0˵Cvendor/symfony/security-core/Resources/translations/security.lt.xlfv-gv@ȤFvendor/symfony/security-core/Resources/translations/security.zh_CN.xlf-gDCvendor/symfony/security-core/Resources/translations/security.ca.xlf-g Cvendor/symfony/security-core/Resources/translations/security.be.xlf.-g. ZZCvendor/symfony/security-core/Resources/translations/security.th.xlf-gx=ݤCvendor/symfony/security-core/Resources/translations/security.uz.xlfl-glMCvendor/symfony/security-core/Resources/translations/security.mk.xlf-gڞCvendor/symfony/security-core/Resources/translations/security.bs.xlf-g%}oCvendor/symfony/security-core/Resources/translations/security.bg.xlf-gd캤Hvendor/symfony/security-core/Resources/translations/security.sr_Latn.xlf6-g6dξCvendor/symfony/security-core/Resources/translations/security.uk.xlf-g6VFvendor/symfony/security-core/Resources/translations/security.zh_TW.xlf-gȈfCvendor/symfony/security-core/Resources/translations/security.cs.xlf-gS0k3Cvendor/symfony/security-core/Resources/translations/security.tl.xlf-g%$Cvendor/symfony/security-core/Resources/translations/security.my.xlf-g[vCvendor/symfony/security-core/Resources/translations/security.nb.xlf-g~RҤCvendor/symfony/security-core/Resources/translations/security.mn.xlf-gއCvendor/symfony/security-core/Resources/translations/security.az.xlf^-g^9Cvendor/symfony/security-core/Resources/translations/security.eu.xlf-gbs`Cvendor/symfony/security-core/Resources/translations/security.he.xlfh-ghuCvendor/symfony/security-core/Resources/translations/security.hr.xlf[-g[Cvendor/symfony/security-core/Resources/translations/security.pt.xlf-g5>Cvendor/symfony/security-core/Resources/translations/security.et.xlf-gsCvendor/symfony/security-core/Resources/translations/security.de.xlfV-gV:Cvendor/symfony/security-core/Resources/translations/security.sl.xlf-gACvendor/symfony/security-core/Resources/translations/security.it.xlf-gaCvendor/symfony/security-core/Resources/translations/security.gl.xlf8-g8ϏCvendor/symfony/security-core/Resources/translations/security.es.xlfQ-gQcP)Cvendor/symfony/security-core/Resources/translations/security.hu.xlf:-g:KYCvendor/symfony/security-core/Resources/translations/security.da.xlf-gmmCvendor/symfony/security-core/Resources/translations/security.fi.xlf-g TCvendor/symfony/security-core/Resources/translations/security.id.xlf-gx"Cvendor/symfony/security-core/Resources/translations/security.sk.xlf-g^PCvendor/symfony/security-core/Resources/translations/security.ro.xlfy-gyAzeJvendor/symfony/security-core/User/AttributesBasedUserProviderInterface.phpN-gNu.vendor/symfony/security-core/User/OidcUser.php-g9vendor/symfony/security-core/User/InMemoryUserChecker.php-gl3vendor/symfony/security-core/User/UserInterface.php<-g<l;vendor/symfony/security-core/User/UserProviderInterface.phpI -gI ̤9vendor/symfony/security-core/User/MissingUserProvider.php-gE6vendor/symfony/security-core/User/ChainUserChecker.phpd-gdOϤNvendor/symfony/security-core/User/LegacyPasswordAuthenticatedUserInterface.php1-g1,?vendor/symfony/security-core/User/PasswordUpgraderInterface.php-g}m2vendor/symfony/security-core/User/InMemoryUser.phpX -gX H:vendor/symfony/security-core/User/InMemoryUserProvider.php-g,aR8vendor/symfony/security-core/User/EquatableInterface.phpm-gmCHvendor/symfony/security-core/User/PasswordAuthenticatedUserInterface.php-ghΤ:vendor/symfony/security-core/User/UserCheckerInterface.phpb-gbP7vendor/symfony/security-core/User/ChainUserProvider.php -g &vendor/symfony/security-core/README.md-g{u!Lvendor/symfony/security-core/Authorization/AuthorizationCheckerInterface.php2-g2OIvendor/symfony/security-core/Authorization/ExpressionLanguageProvider.phpV-gV@)5Mvendor/symfony/security-core/Authorization/TraceableAccessDecisionManager.php -g T(Dvendor/symfony/security-core/Authorization/AccessDecisionManager.phpl-gl0ո Mvendor/symfony/security-core/Authorization/AccessDecisionManagerInterface.php}-g},tCvendor/symfony/security-core/Authorization/Voter/VoterInterface.php-g])Lvendor/symfony/security-core/Authorization/Voter/CacheableVoterInterface.php~-g~9Dvendor/symfony/security-core/Authorization/Voter/ExpressionVoter.php3 -g3 Gvendor/symfony/security-core/Authorization/Voter/RoleHierarchyVoter.phpl-glH??Cvendor/symfony/security-core/Authorization/Voter/TraceableVoter.php)-g)'J:vendor/symfony/security-core/Authorization/Voter/Voter.phpf -gf 5~>vendor/symfony/security-core/Authorization/Voter/RoleVoter.php-gPj^Gvendor/symfony/security-core/Authorization/Voter/AuthenticatedVoter.phpC-gCAAvendor/symfony/security-core/Authorization/ExpressionLanguage.php-g8CyCvendor/symfony/security-core/Authorization/AuthorizationChecker.php-gwHvendor/symfony/security-core/Authorization/Strategy/PriorityStrategy.php-g 7^Ivendor/symfony/security-core/Authorization/Strategy/UnanimousStrategy.php/-g/Kvendor/symfony/security-core/Authorization/Strategy/AffirmativeStrategy.php-g مIvendor/symfony/security-core/Authorization/Strategy/ConsensusStrategy.php-gդWvendor/symfony/security-core/Authorization/Strategy/AccessDecisionStrategyInterface.php]-g]pf)vendor/symfony/security-core/Security.php -g @vendor/symfony/security-core/Exception/AccessDeniedException.phpZ-gZpthDvendor/symfony/security-core/Exception/InvalidCsrfTokenException.php}-g}O:vendor/symfony/security-core/Exception/LogoutException.php-gy'פ9vendor/symfony/security-core/Exception/LogicException.php-g$2@vendor/symfony/security-core/Exception/LazyResponseException.php-g.'Svendor/symfony/security-core/Exception/CustomUserMessageAuthenticationException.php -g qHV=vendor/symfony/security-core/Exception/ExceptionInterface.php-g^ Bvendor/symfony/security-core/Exception/BadCredentialsException.php-gh ;vendor/symfony/security-core/Exception/RuntimeException.php-g> <vendor/symfony/security-core/Exception/DisabledException.phpv-gvϤֽAvendor/symfony/security-core/Exception/TokenNotFoundException.php-g( Dvendor/symfony/security-core/Exception/ProviderNotFoundException.php-gRFvendor/symfony/security-core/Exception/SessionUnavailableException.phpz-gz{YCvendor/symfony/security-core/Exception/InvalidArgumentException.php-gW.Bvendor/symfony/security-core/Exception/AccountExpiredException.php-gO Ivendor/symfony/security-core/Exception/AuthenticationExpiredException.phpG-gG%.DVvendor/symfony/security-core/Exception/TooManyLoginAttemptsAuthenticationException.php}-g}j?vendor/symfony/security-core/Exception/CookieTheftException.php-gm Ivendor/symfony/security-core/Exception/AuthenticationServiceException.php-gt%Cvendor/symfony/security-core/Exception/UnsupportedUserException.phpJ-gJjۤAvendor/symfony/security-core/Exception/AccountStatusException.php-gc%Rvendor/symfony/security-core/Exception/CustomUserMessageAccountStatusException.php-g* Nvendor/symfony/security-core/Exception/InsufficientAuthenticationException.php&-g&[d:vendor/symfony/security-core/Exception/LockedException.phpl-gl0믤Bvendor/symfony/security-core/Exception/AuthenticationException.php+ -g+ l@vendor/symfony/security-core/Exception/UserNotFoundException.php@-g@򼓤Uvendor/symfony/security-core/Exception/AuthenticationCredentialsNotFoundException.php-gbbFvendor/symfony/security-core/Exception/CredentialsExpiredException.php-g8hCvendor/symfony/security-core/Authentication/Token/AbstractToken.phpb-gbߤ7 ?vendor/symfony/security-core/Authentication/Token/NullToken.php -g iƤWvendor/symfony/security-core/Authentication/Token/Storage/UsageTrackingTokenStorage.php -g l Jvendor/symfony/security-core/Authentication/Token/Storage/TokenStorage.php4-g4gSvendor/symfony/security-core/Authentication/Token/Storage/TokenStorageInterface.php-g%NEvendor/symfony/security-core/Authentication/Token/RememberMeToken.php-g 5LqEvendor/symfony/security-core/Authentication/Token/SwitchUserToken.phpm-gm8Kvendor/symfony/security-core/Authentication/Token/PreAuthenticatedToken.php-g.Dvendor/symfony/security-core/Authentication/Token/TokenInterface.php1 -g1 =N*ݤKvendor/symfony/security-core/Authentication/Token/UsernamePasswordToken.php-gzTvendor/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php`-g`JKvendor/symfony/security-core/Authentication/AuthenticationTrustResolver.phpw-gw4 Svendor/symfony/security-core/Authentication/RememberMe/PersistentTokenInterface.php-gPvendor/symfony/security-core/Authentication/RememberMe/InMemoryTokenProvider.php'-g'=Mvendor/symfony/security-core/Authentication/RememberMe/CacheTokenVerifier.php -g -LuJvendor/symfony/security-core/Authentication/RememberMe/PersistentToken.php-gIjQvendor/symfony/security-core/Authentication/RememberMe/TokenVerifierInterface.php-gҤQvendor/symfony/security-core/Authentication/RememberMe/TokenProviderInterface.php-gܪAvendor/symfony/security-core/Event/AuthenticationSuccessEvent.phpu-gu:vendor/symfony/security-core/Event/AuthenticationEvent.php-g:7x0vendor/symfony/security-core/Event/VoteEvent.php--g-*vendor/symfony/security-core/composer.json -g x45vendor/symfony/security-core/AuthenticationEvents.php-g"a䚤,vendor/symfony/deprecation-contracts/LICENSE,-g, K1vendor/symfony/deprecation-contracts/CHANGELOG.md-gh{#1vendor/symfony/deprecation-contracts/function.php-gOݤ.vendor/symfony/deprecation-contracts/README.md-gX2vendor/symfony/deprecation-contracts/composer.jsonS-gS=6(vendor/symfony/routing/CompiledRoute.php6-g6k栤*vendor/symfony/routing/Attribute/Route.php-gMT|vendor/symfony/routing/LICENSE,-g,U(vendor/symfony/routing/RouteCompiler.php8-g8 u#vendor/symfony/routing/CHANGELOG.md6-g6V^)vendor/symfony/routing/RequestContext.php`-g`)-ͤ+vendor/symfony/routing/Annotation/Route.php-gm\:vendor/symfony/routing/Matcher/RequestMatcherInterface.php+-g+<=vendor/symfony/routing/Matcher/ExpressionLanguageProvider.php-g~-vendor/symfony/routing/Matcher/UrlMatcher.php'-g' #ФBvendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.phpo-go0 H6vendor/symfony/routing/Matcher/UrlMatcherInterface.php-gP-2Ȥ5vendor/symfony/routing/Matcher/CompiledUrlMatcher.php-g*g6vendor/symfony/routing/Matcher/TraceableUrlMatcher.phpJ-gJ@Bvendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.phpJ-gJ 3I7vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php-g\Pܤ@vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.phpg-ggxI{$Avendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php-gkR@vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php-g˥9vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php<-g<ðKʤ vendor/symfony/routing/README.md-grɤ9vendor/symfony/routing/Generator/CompiledUrlGenerator.php -g XA~1vendor/symfony/routing/Generator/UrlGenerator.php;-g;Yn'Fvendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php-gdfФ:vendor/symfony/routing/Generator/UrlGeneratorInterface.php -g Y3 8Dvendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.phpi-gifEFvendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php-g;vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php$-g$αh*vendor/symfony/routing/RouteCollection.phpO+-gO+u6vendor/symfony/routing/Requirement/EnumRequirement.php-g2vendor/symfony/routing/Requirement/Requirement.phpR-gR1$7vendor/symfony/routing/RequestContextAwareInterface.php6-g6t7vendor/symfony/routing/Loader/AnnotationClassLoader.php-gtD0:vendor/symfony/routing/Loader/AttributeDirectoryLoader.php -g Tst5vendor/symfony/routing/Loader/AttributeFileLoader.php-gMKI0vendor/symfony/routing/Loader/YamlFileLoader.php/-g/14%6vendor/symfony/routing/Loader/AnnotationFileLoader.php-g<vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd9-g9*#/vendor/symfony/routing/Loader/PhpFileLoader.php-g@5vendor/symfony/routing/Loader/Psr4DirectoryLoader.php -g *>/vendor/symfony/routing/Loader/XmlFileLoader.phpF-gF=k.vendor/symfony/routing/Loader/ObjectLoader.phpq -gq !v|?vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php!-g!Avendor/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php -g (Ivendor/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php3 -g3 }2 @vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php9-g9,s>vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.phpS-gSӤ@vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php-g{ Evendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php-g֠P@vendor/symfony/routing/Loader/Configurator/AliasConfigurator.php-gBvendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php-gaAvendor/symfony/routing/Loader/Configurator/ImportConfigurator.php -g O6vendor/symfony/routing/Loader/AttributeClassLoader.php>-g> K1vendor/symfony/routing/Loader/ContainerLoader.php-g:1vendor/symfony/routing/Loader/DirectoryLoader.php-g]/0vendor/symfony/routing/Loader/GlobFileLoader.php-g.]/vendor/symfony/routing/Loader/ClosureLoader.php-g ;vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php-g7 h vendor/symfony/routing/Route.php/-g/_*vendor/symfony/routing/RouterInterface.php"-g"WF!vendor/symfony/routing/Router.phpt/-gt/-X1vendor/symfony/routing/RouteCompilerInterface.php-gT vendor/symfony/routing/Alias.php -g äQvendor/symfony/routing/DependencyInjection/AddExpressionLanguageProvidersPass.php-gTwBvendor/symfony/routing/DependencyInjection/RoutingResolverPass.php"-g"K˶>vendor/symfony/routing/Exception/ResourceNotFoundException.php2-g2FL"17vendor/symfony/routing/Exception/ExceptionInterface.php-g&;vendor/symfony/routing/Exception/RouteNotFoundException.php-g C5vendor/symfony/routing/Exception/RuntimeException.php-g$>GHvendor/symfony/routing/Exception/MissingMandatoryParametersException.phpC-gCjYKФ=vendor/symfony/routing/Exception/InvalidArgumentException.php-g֤>vendor/symfony/routing/Exception/MethodNotAllowedException.phpp-gp.ִ=vendor/symfony/routing/Exception/NoConfigurationException.php-grDvendor/symfony/routing/Exception/RouteCircularReferenceException.php>-g>\T>vendor/symfony/routing/Exception/InvalidParameterException.php-g!N$vendor/symfony/routing/composer.jsony-gyP?vendor/symfony/service-contracts/ServiceSubscriberInterface.php -g }uP?vendor/symfony/service-contracts/ServiceCollectionInterface.php-g}V@vendor/symfony/service-contracts/Attribute/SubscribedService.php-gi7vendor/symfony/service-contracts/Attribute/Required.php-g`e(vendor/symfony/service-contracts/LICENSE,-g,@vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.phpH -gH 5#!1<vendor/symfony/service-contracts/Test/ServiceLocatorTest.php-g]1C-vendor/symfony/service-contracts/CHANGELOG.md-gh{#*vendor/symfony/service-contracts/README.mdJ-gJГ3vendor/symfony/service-contracts/ResetInterface.php-gB4=vendor/symfony/service-contracts/ServiceProviderInterface.php-gB쯇;vendor/symfony/service-contracts/ServiceSubscriberTrait.php -g FBvendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php& -g& 8vendor/symfony/service-contracts/ServiceLocatorTrait.php-g?.vendor/symfony/service-contracts/composer.json-g3'9vendor/symfony/property-info/PhpStan/NameScopeFactory.php-gr2vendor/symfony/property-info/PhpStan/NameScope.php-gd)ݤ?vendor/symfony/property-info/PropertyInfoExtractorInterface.php-gU-R%vendor/symfony/property-info/Type.php-g1ɤ$vendor/symfony/property-info/LICENSE,-g,H6vendor/symfony/property-info/Util/PhpDocTypeHelper.php-g0Ƥ7vendor/symfony/property-info/Util/PhpStanTypeHelper.php#-g#> )vendor/symfony/property-info/CHANGELOG.md-g.;vendor/symfony/property-info/PropertyInfoCacheExtractor.phpE -gE ؍Dvendor/symfony/property-info/PropertyWriteInfoExtractorInterface.php-gxBy\Avendor/symfony/property-info/PropertyAccessExtractorInterface.php-g2$C?vendor/symfony/property-info/PropertyTypeExtractorInterface.phpQ-gQ1vendor/symfony/property-info/PropertyReadInfo.php-g  ;vendor/symfony/property-info/Extractor/PhpStanExtractor.php.-g.G>vendor/symfony/property-info/Extractor/SerializerExtractor.php-g ?vendor/symfony/property-info/Extractor/ConstructorExtractor.php-g-UTvendor/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php-gjv\>vendor/symfony/property-info/Extractor/ReflectionExtractor.php-g:vendor/symfony/property-info/Extractor/PhpDocExtractor.php&0-g&0ddFvendor/symfony/property-info/PropertyDescriptionExtractorInterface.php -g  82vendor/symfony/property-info/PropertyWriteInfo.php -g C&vendor/symfony/property-info/README.md-g'7Cvendor/symfony/property-info/PropertyReadInfoExtractorInterface.php-g:|`դHvendor/symfony/property-info/PropertyInitializableExtractorInterface.php-gOW6vendor/symfony/property-info/PropertyInfoExtractor.php -g yh?vendor/symfony/property-info/PropertyListExtractorInterface.php-gJ$Pvendor/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.phpY-gY[cEvendor/symfony/property-info/DependencyInjection/PropertyInfoPass.php)-g) *vendor/symfony/property-info/composer.json-gj3vendor/symfony/http-foundation/StreamedResponse.php -g <:vendor/symfony/http-foundation/RequestMatcherInterface.php|-g|3Q5vendor/symfony/http-foundation/BinaryFileResponse.php2-g2އ+vendor/symfony/http-foundation/InputBag.php7-g7sĤIvendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php -g -3Jvendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php -g ¤Rvendor/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php-gU&vendor/symfony/http-foundation/LICENSE,-g,UJvendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.phpL-gLf_Dvendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.phpJ-gJZ^Mvendor/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php-gUIvendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php-gI[x`Gvendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php.-g.PJvendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.phpE-gEK¤Gvendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php,-g,Dvendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php<-g<& Lvendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php-g'`7Evendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php-g^)Evendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php-g<پJ,vendor/symfony/http-foundation/ServerBag.php-g+vendor/symfony/http-foundation/CHANGELOG.mduL-guLM,vendor/symfony/http-foundation/File/File.php-gޯԤ.vendor/symfony/http-foundation/File/Stream.php-gx4vendor/symfony/http-foundation/File/UploadedFile.php^'-g^'b[Gvendor/symfony/http-foundation/File/Exception/AccessDeniedException.phpi-giYAvendor/symfony/http-foundation/File/Exception/NoFileException.php-g-AFvendor/symfony/http-foundation/File/Exception/IniSizeFileException.php-g IJvendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php-g :ݤHvendor/symfony/http-foundation/File/Exception/ExtensionFileException.php-g)?vendor/symfony/http-foundation/File/Exception/FileException.php-gj2Avendor/symfony/http-foundation/File/Exception/UploadException.php-gSIvendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php9-g9d-Gvendor/symfony/http-foundation/File/Exception/FormSizeFileException.php-gm;Gvendor/symfony/http-foundation/File/Exception/FileNotFoundException.phpY-gY{WɈFvendor/symfony/http-foundation/File/Exception/PartialFileException.php-g*Gvendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php-gn +vendor/symfony/http-foundation/Response.php-gu)vendor/symfony/http-foundation/Cookie.phpJ/-gJ/"f/vendor/symfony/http-foundation/AcceptHeader.php{ -g{ G1vendor/symfony/http-foundation/RequestMatcher.php-gյnҤ4vendor/symfony/http-foundation/ResponseHeaderBag.php-g4֭.vendor/symfony/http-foundation/HeaderUtils.php$-g$4Fvendor/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php>-g>Dvendor/symfony/http-foundation/RequestMatcher/PathRequestMatcher.phpd-gdw|Fvendor/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php-gTKDvendor/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php-g2Dvendor/symfony/http-foundation/RequestMatcher/HostRequestMatcher.phpR-gRsJvendor/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php-gdJvendor/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php-gQ̤Fvendor/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php,-g,s>MCvendor/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php2-g2ti/vendor/symfony/http-foundation/RequestStack.php -g J3vendor/symfony/http-foundation/RedirectResponse.php9 -g9 V/vendor/symfony/http-foundation/JsonResponse.phpj-gjOP/(vendor/symfony/http-foundation/README.md-g&*vendor/symfony/http-foundation/Request.php-gBFF;vendor/symfony/http-foundation/ExpressionRequestMatcher.php-g|*/vendor/symfony/http-foundation/ParameterBag.php-g6*vendor/symfony/http-foundation/IpUtils.php -g Rz^3vendor/symfony/http-foundation/AcceptHeaderItem.php -g :67vendor/symfony/http-foundation/StreamedJsonResponse.php-gؕSҤ,vendor/symfony/http-foundation/UrlHelper.phpq -gq `Kl6vendor/symfony/http-foundation/ChainRequestMatcher.phpx-gxX!,vendor/symfony/http-foundation/HeaderBag.php-gZdL*vendor/symfony/http-foundation/FileBag.php-g"4ϤHvendor/symfony/http-foundation/Exception/ConflictingHeadersException.php-g,ŇEvendor/symfony/http-foundation/Exception/UnexpectedValueException.phpx-gx ȕFvendor/symfony/http-foundation/Exception/RequestExceptionInterface.php-gR@vendor/symfony/http-foundation/Exception/BadRequestException.php-gUڤIvendor/symfony/http-foundation/Exception/SuspiciousOperationException.php-g':vendor/symfony/http-foundation/Exception/JsonException.php-gEvendor/symfony/http-foundation/Exception/SessionNotFoundException.phpY-gY1,vendor/symfony/http-foundation/composer.jsonv-gv^D,vendor/symfony/http-foundation/UriSigner.php! -g! Jvendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php-gGf=Avendor/symfony/http-foundation/Session/Attribute/AttributeBag.php -g Hvendor/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php4-g4Bvendor/symfony/http-foundation/Session/SessionFactoryInterface.php-gf*2vendor/symfony/http-foundation/Session/Session.php-g<)7vendor/symfony/http-foundation/Session/SessionUtils.php-g'Mvendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php-gr@Qvendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php-gդPvendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php)-g)oLvendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php-gASTvendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php~-g~|%Svendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php-gwbRvendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php -g Dt|Mvendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php-gGҭqPvendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.phpG-gG$Nvendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php -g GOvendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php -g mIRvendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php -g oڤGvendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php7-g7w`Jvendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php/-g/{Pvendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php-gYPZLvendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.phpB -gB Fvendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php-g<Nvendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php!-g! Jvendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php-gfQvendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.phpw-gw]nIvendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php-g*8Qvendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php-gɤ>vendor/symfony/http-foundation/Session/Storage/MetadataBag.php -g Jvendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php -g Q3U;vendor/symfony/http-foundation/Session/SessionInterface.php-gOY>Cvendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php -g ԖޤBvendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php-gu1Ф9vendor/symfony/http-foundation/Session/Flash/FlashBag.php -g vɅ9vendor/symfony/http-foundation/Session/SessionFactory.phpG-gG :vendor/symfony/http-foundation/Session/SessionBagProxy.php-g >vendor/symfony/http-foundation/Session/SessionBagInterface.phpW-gW#9,vendor/symfony/var-exporter/Instantiator.php -g +vendor/symfony/var-exporter/ProxyHelper.phpF-gFtk#vendor/symfony/var-exporter/LICENSE,-g,(vendor/symfony/var-exporter/CHANGELOG.md-gt?(vendor/symfony/var-exporter/Hydrator.php -g aZ(8vendor/symfony/var-exporter/Internal/LazyObjectState.php-g7!4;vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php'-g'*<}M/vendor/symfony/var-exporter/Internal/Values.php-g`ǿ8vendor/symfony/var-exporter/Internal/LazyObjectTrait.php)-g);ޣ1vendor/symfony/var-exporter/Internal/Hydrator.php)-g)J"1vendor/symfony/var-exporter/Internal/Registry.php@-g@#2vendor/symfony/var-exporter/Internal/Reference.php -g #Jn1vendor/symfony/var-exporter/Internal/Exporter.phpyA-gyAGUS.vendor/symfony/var-exporter/LazyGhostTrait.php";-g";SԤ%vendor/symfony/var-exporter/README.md--g-".vendor/symfony/var-exporter/LazyProxyTrait.php1-g1!+vendor/symfony/var-exporter/VarExporter.phpR-gReH3vendor/symfony/var-exporter/LazyObjectInterface.phpa-ga@#8vendor/symfony/var-exporter/Exception/LogicException.php-g-ʤ<vendor/symfony/var-exporter/Exception/ExceptionInterface.phpd-gd@vendor/symfony/var-exporter/Exception/ClassNotFoundException.php1-g1wwFvendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php>-g>})vendor/symfony/var-exporter/composer.jsonr-gr~jEvendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php -g ޺Ivendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.phpR-gRMvendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php* -g* ^zKvendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php-g1'$vendor/symfony/error-handler/LICENSE,-g,զ_Ϥ)vendor/symfony/error-handler/CHANGELOG.md-gD9Bvendor/symfony/error-handler/Resources/bin/patch-type-declarations -g d"mMvendor/symfony/error-handler/Resources/bin/extract-tentative-return-types.php-gmE?vendor/symfony/error-handler/Resources/views/exception.html.php/-g/<vendor/symfony/error-handler/Resources/views/traces.html.php -g nAvendor/symfony/error-handler/Resources/views/traces_text.html.php-gj+2:vendor/symfony/error-handler/Resources/views/logs.html.php) -g) _&;vendor/symfony/error-handler/Resources/views/trace.html.php` -g` 39;vendor/symfony/error-handler/Resources/views/error.html.phpd-gdxDvendor/symfony/error-handler/Resources/views/exception_full.html.php-gEޤ?vendor/symfony/error-handler/Resources/assets/css/exception.css B-g BRDvendor/symfony/error-handler/Resources/assets/css/exception_full.css -g *bc;vendor/symfony/error-handler/Resources/assets/css/error.css-g%7Jvendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svgQ-gQpBvendor/symfony/error-handler/Resources/assets/images/icon-book.svg-gEvendor/symfony/error-handler/Resources/assets/images/icon-support.svgz-gzS̤Fvendor/symfony/error-handler/Resources/assets/images/chevron-right.svg-g Jvendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php -g 9꒤Ivendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg-gUEvendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg-g%0ɤBvendor/symfony/error-handler/Resources/assets/images/icon-copy.svg -g "ȖGvendor/symfony/error-handler/Resources/assets/images/favicon.png.base64-g"i^Kvendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg-g-Lvendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg-gs0=vendor/symfony/error-handler/Resources/assets/js/exception.js4-g4C#8vendor/symfony/error-handler/Internal/TentativeTypes.php-g&vendor/symfony/error-handler/Debug.phpH-gHs ߤFvendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php -g <?vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php-g +2Evendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php-gsۤ@vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php]-g]Yc@vendor/symfony/error-handler/ErrorRenderer/FileLinkFormatter.phpP-gPY&vendor/symfony/error-handler/README.md=-g=\1vendor/symfony/error-handler/DebugClassLoader.php#-g#qY0vendor/symfony/error-handler/BufferingLogger.phpA-gAZ-vendor/symfony/error-handler/ErrorHandler.phpuk-gukw)/vendor/symfony/error-handler/ThrowableUtils.php{-g{-F7vendor/symfony/error-handler/Error/OutOfMemoryError.php[-g[N;vendor/symfony/error-handler/Error/UndefinedMethodError.php-gV[1vendor/symfony/error-handler/Error/FatalError.php -g Ff=vendor/symfony/error-handler/Error/UndefinedFunctionError.php-glnB9vendor/symfony/error-handler/Error/ClassNotFoundError.php-gEp;vendor/symfony/error-handler/Exception/FlattenException.phpI.-gI.ޱњ?vendor/symfony/error-handler/Exception/SilencedErrorContext.phpr-gr+*vendor/symfony/error-handler/composer.json-gny&4vendor/symfony/cache-contracts/CallbackInterface.php]-g]oW$0vendor/symfony/cache-contracts/ItemInterface.php6-g6# &vendor/symfony/cache-contracts/LICENSE,-g,+vendor/symfony/cache-contracts/CHANGELOG.md-gh{#1vendor/symfony/cache-contracts/CacheInterface.php2 -g2 5(vendor/symfony/cache-contracts/README.mdF-gF_-vendor/symfony/cache-contracts/CacheTrait.php -g iW9vendor/symfony/cache-contracts/TagAwareCacheInterface.php-g1swc,vendor/symfony/cache-contracts/composer.json-gAv7vendor/symfony/dependency-injection/EnvVarProcessor.php2-g2sF;vendor/symfony/dependency-injection/ContainerAwareTrait.phpO-gO4rSBvendor/symfony/dependency-injection/ExpressionLanguageProvider.php\-g\lD1vendor/symfony/dependency-injection/Container.php6-g6S8vendor/symfony/dependency-injection/ReverseContainer.php -g 4)Ȥ0vendor/symfony/dependency-injection/Variable.php-ghpPvendor/symfony/dependency-injection/Extension/ConfigurableExtensionInterface.php#-g#ᅋ~Dvendor/symfony/dependency-injection/Extension/ExtensionInterface.php`-g`^ NCvendor/symfony/dependency-injection/Extension/AbstractExtension.php-gW$@vendor/symfony/dependency-injection/Extension/ExtensionTrait.php -g V;vendor/symfony/dependency-injection/Extension/Extension.php-g0BKvendor/symfony/dependency-injection/Extension/PrependExtensionInterface.phpS-gSNC6Qvendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.phpS-gS)?vendor/symfony/dependency-injection/Attribute/Autoconfigure.php-gZӤBvendor/symfony/dependency-injection/Attribute/AutowireIterator.php-go=vendor/symfony/dependency-injection/Attribute/AsDecorator.phpo-goY|Hvendor/symfony/dependency-injection/Attribute/AutowireServiceClosure.php-g^#5>vendor/symfony/dependency-injection/Attribute/AsTaggedItem.php-gk8vendor/symfony/dependency-injection/Attribute/Target.php-gA6vendor/symfony/dependency-injection/Attribute/When.php-gXˤCvendor/symfony/dependency-injection/Attribute/AutowireDecorated.php-g+h@vendor/symfony/dependency-injection/Attribute/TaggedIterator.php-guAvendor/symfony/dependency-injection/Attribute/AutowireLocator.phpe -ge Bvendor/symfony/dependency-injection/Attribute/AutowireCallable.phpT-gT鼎`:vendor/symfony/dependency-injection/Attribute/Autowire.php] -g] sOBvendor/symfony/dependency-injection/Attribute/AutoconfigureTag.php-g ?vendor/symfony/dependency-injection/Attribute/TaggedLocator.php-g鱞>vendor/symfony/dependency-injection/Attribute/MapDecorated.phpb-gb\9vendor/symfony/dependency-injection/Attribute/Exclude.php-ga)9vendor/symfony/dependency-injection/Attribute/AsAlias.php-g+vendor/symfony/dependency-injection/LICENSE,-g,U0vendor/symfony/dependency-injection/CHANGELOG.mdhI-ghIZ[Qvendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php)-g)}~Jvendor/symfony/dependency-injection/Config/ContainerParametersResource.php-g5Jvendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php -g /Avendor/symfony/dependency-injection/Argument/AbstractArgument.php-g1iDvendor/symfony/dependency-injection/Argument/RewindableGenerator.php-gsGvendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php-g/c=>vendor/symfony/dependency-injection/Argument/BoundArgument.php-g>))Avendor/symfony/dependency-injection/Argument/IteratorArgument.php6-g62Ҥ<vendor/symfony/dependency-injection/Argument/LazyClosure.php_ -g_ a5ѤGvendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.phpu -gu Bvendor/symfony/dependency-injection/Argument/ArgumentInterface.phpN-gN?vendor/symfony/dependency-injection/Argument/ServiceLocator.php#-g#ěs@Gvendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php*-g*k8vendor/symfony/dependency-injection/ContainerBuilder.php-gAcZ7vendor/symfony/dependency-injection/ChildDefinition.phpp -gp /o1vendor/symfony/dependency-injection/Reference.php-gͯJvendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php -g U]Ovendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php-g!Avendor/symfony/dependency-injection/ParameterBag/ParameterBag.php$-g$AҤJvendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php-gAvendor/symfony/dependency-injection/ParameterBag/ContainerBag.php-g#OGvendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php-g0P2vendor/symfony/dependency-injection/Definition.phpP-gPD@vendor/symfony/dependency-injection/EnvVarProcessorInterface.php-g90-vendor/symfony/dependency-injection/README.mdC-gC<:vendor/symfony/dependency-injection/ContainerInterface.phpd -gd ʤ9vendor/symfony/dependency-injection/Loader/FileLoader.php<-g<(٤=vendor/symfony/dependency-injection/Loader/YamlFileLoader.php -g Qd2Ovendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsdB-gBo<vendor/symfony/dependency-injection/Loader/PhpFileLoader.php!-g!g<vendor/symfony/dependency-injection/Loader/XmlFileLoader.php-gBd<vendor/symfony/dependency-injection/Loader/IniFileLoader.php -g j}Pvendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php4-g4gPvendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php9 -g9 CaQvendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php-gwTvendor/symfony/dependency-injection/Loader/Configurator/FromCallableConfigurator.php-g6nMvendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php1-g1DLvendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.phpN-gNX_^Qvendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php-g.Pvendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.phpl-gl s_Pvendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php-g Tvendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php-gMNvendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php-g(Ovendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.phpd-gd'DKvendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php-gpNvendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php-gPvendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php{-g{2ѤUvendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.phpE-gE^7Tvendor/symfony/dependency-injection/Loader/Configurator/Traits/FromCallableTrait.php -g \ Qvendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.phpb-gb*'ѤLvendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php[-g[BfLvendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.phpD-gD5RLvendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.phpG-gGF8Pvendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php-ggeMvendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.phpL-gLbPvendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.phpM-gMPSvendor/symfony/dependency-injection/Loader/Configurator/Traits/ConstructorTrait.phpU-gU86$Pvendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php-gԏ)Xvendor/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php-g#yKvendor/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.phpj-gjWvendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php -g fۤRvendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php-g!RQvendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php-g4Mvendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php-gRF,bUvendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.phpR-gR<Qvendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php -g oRvendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php-g"Ovendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php-gA[_v>vendor/symfony/dependency-injection/Loader/DirectoryLoader.php2-g2 =vendor/symfony/dependency-injection/Loader/GlobFileLoader.php`-g`<vendor/symfony/dependency-injection/Loader/ClosureLoader.php-g5=vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php -g Ğ}Kvendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php-g5=Mvendor/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php-gp<Fvendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php-gvOΤVvendor/symfony/dependency-injection/LazyProxy/Instantiator/LazyServiceInstantiator.php-g(dVvendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.phpd-gd翓Tvendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php~-g~0ND:vendor/symfony/dependency-injection/ExpressionLanguage.phpb-gb!UO6vendor/symfony/dependency-injection/ServiceLocator.php-g9x"D6vendor/symfony/dependency-injection/TypedReference.php3-g3adt-vendor/symfony/dependency-injection/Alias.php -g nZԤUvendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php-gt9@vendor/symfony/dependency-injection/Exception/LogicException.php-g}|ȤFvendor/symfony/dependency-injection/Exception/EnvNotFoundException.php-g˜&Lvendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php"-g" Dvendor/symfony/dependency-injection/Exception/ExceptionInterface.php~-g~Fvendor/symfony/dependency-injection/Exception/OutOfBoundsException.php-gOnSvendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php_-g_Ke&Jvendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php-gФBvendor/symfony/dependency-injection/Exception/RuntimeException.php -g  Jvendor/symfony/dependency-injection/Exception/InvalidArgumentException.php'-g'Hvendor/symfony/dependency-injection/Exception/BadMethodCallException.php-g,wKvendor/symfony/dependency-injection/Exception/AutowiringFailedException.php-gMOvendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php0-g0IGvendor/symfony/dependency-injection/Exception/EnvParameterException.php-g=&)@vendor/symfony/dependency-injection/TaggedContainerInterface.php-gJ.1vendor/symfony/dependency-injection/Parameter.phpf-gfsDEvendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php-g'fMvendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php-g]Lvendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php-gGlMvendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php@ -g@ p脤Tvendor/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php -g Lvendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php!-g!g PK;vendor/symfony/dependency-injection/Compiler/PassConfig.phpm-gm1&Fvendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php -g jEvendor/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.phpK -gK 7ɤJvendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php-gJvendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php1-g1WMvendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php-g:IDHvendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php-g%dDvendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php$*-g$* BHvendor/symfony/dependency-injection/Compiler/AutowireAsDecoratorPass.php-g3Kvendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php-gv3Mvendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php-gQYFvendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php8*-g8*c3Rvendor/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php-gHlRvendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php8-g8yOvendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php -g cWKvendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php3-g3췤Ovendor/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php-g1xOvendor/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php- -g- zhJvendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php'-g'$Ivendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php-gXBPvendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php!-g!?Jvendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.phpi-gi^nMvendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.phpB -gB BLvendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php -g xp=vendor/symfony/dependency-injection/Compiler/AutowirePass.php8{-g8{an+Fvendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php-gJRvendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.phpq-gq?Kvendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php-g]Lvendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php -g ;l]vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php-gLפJvendor/symfony/dependency-injection/Compiler/RemoveBuildParametersPass.php-gvgEvendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php-gzp Qvendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php -g F0Avendor/symfony/dependency-injection/Compiler/ResolveClassPass.php]-g]v`Nvendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php-gQKvendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php6-g6YB Ovendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php-ga%Cvendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php< -g< sY[Jvendor/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php-glDNvendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php-g٭vFvendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php-g&Svendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.phpa-gap6Lvendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php&-g&W9vendor/symfony/dependency-injection/Compiler/Compiler.php -g ˤFvendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php-g Mvendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php-g^0Lvendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php-g`#{=vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php#-g#sO9vendor/symfony/dependency-injection/Dumper/YamlDumper.php"8-g"8Oˤ8vendor/symfony/dependency-injection/Dumper/Preloader.php-gv{8vendor/symfony/dependency-injection/Dumper/XmlDumper.phpH-gH]߸>vendor/symfony/dependency-injection/Dumper/DumperInterface.phpV-gVs#5vendor/symfony/dependency-injection/Dumper/Dumper.php-gU;a8vendor/symfony/dependency-injection/Dumper/PhpDumper.php5-g5Fp1vendor/symfony/dependency-injection/composer.json-g2=vendor/symfony/dependency-injection/EnvVarLoaderInterface.php-gbkr?vendor/symfony/dependency-injection/ContainerAwareInterface.php-g=>vendor/symfony/clock/LICENSE,-g,t=1vendor/symfony/clock/Test/ClockSensitiveTrait.php-gI!vendor/symfony/clock/CHANGELOG.md-gCJ&vendor/symfony/clock/Resources/now.php-g5䏤(vendor/symfony/clock/ClockAwareTrait.php-g3vendor/symfony/clock/README.md-gI"vendor/symfony/clock/MockClock.php -g $ivendor/symfony/clock/Clock.phpS -gS *R''vendor/symfony/clock/MonotonicClock.php -g }Z'vendor/symfony/clock/ClockInterface.phpL-gLz֚&"vendor/symfony/clock/DatePoint.php-gФ"vendor/symfony/clock/composer.json-g GPҤ$vendor/symfony/clock/NativeClock.php/-g/ur+:vendor/symfony/password-hasher/PasswordHasherInterface.php-g-<>vendor/symfony/password-hasher/Hasher/SodiumPasswordHasher.php-g^~Bvendor/symfony/password-hasher/Hasher/CheckPasswordLengthTrait.php-gB+.<vendor/symfony/password-hasher/Hasher/UserPasswordHasher.phpK-gKr,Ф>vendor/symfony/password-hasher/Hasher/Pbkdf2PasswordHasher.php -g S8Fvendor/symfony/password-hasher/Hasher/PasswordHasherAwareInterface.php-gϡ*>vendor/symfony/password-hasher/Hasher/NativePasswordHasher.php-gQEvendor/symfony/password-hasher/Hasher/MessageDigestPasswordHasher.php -g r6k Evendor/symfony/password-hasher/Hasher/UserPasswordHasherInterface.phpr-gr4ΤAvendor/symfony/password-hasher/Hasher/PlaintextPasswordHasher.php[ -g[ Hvendor/symfony/password-hasher/Hasher/PasswordHasherFactoryInterface.php-g@Avendor/symfony/password-hasher/Hasher/MigratingPasswordHasher.php-grG?vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php&!-g&!FA&vendor/symfony/password-hasher/LICENSE,-g,U+vendor/symfony/password-hasher/CHANGELOG.md-gڰ@vendor/symfony/password-hasher/LegacyPasswordHasherInterface.php-gt(vendor/symfony/password-hasher/README.md-g!Bvendor/symfony/password-hasher/Command/UserPasswordHashCommand.php'-g'8 ;vendor/symfony/password-hasher/Exception/LogicException.php-gA?vendor/symfony/password-hasher/Exception/ExceptionInterface.php-gEWLEvendor/symfony/password-hasher/Exception/InvalidPasswordException.php-gL,vendor/symfony/password-hasher/composer.json-gvendor/symfony/process/LICENSE,-g,U+vendor/symfony/process/ExecutableFinder.php -g wt#vendor/symfony/process/CHANGELOG.md-g%8 vendor/symfony/process/README.md-g\3$Ϥ*vendor/symfony/process/Pipes/UnixPipes.php-g Q\-vendor/symfony/process/Pipes/WindowsPipes.php-gQ.vendor/symfony/process/Pipes/AbstractPipes.php-ge/vendor/symfony/process/Pipes/PipesInterface.php-g&vendor/symfony/process/InputStream.php -g 6ee6vendor/symfony/process/Messenger/RunProcessContext.php|-g|ɔ6vendor/symfony/process/Messenger/RunProcessMessage.php-g2$=vendor/symfony/process/Messenger/RunProcessMessageHandler.php%-g%0%vendor/symfony/process/PhpProcess.php -g 3x(vendor/symfony/process/PhpSubprocess.php-g:1.vendor/symfony/process/PhpExecutableFinder.php% -g% ޏx=vendor/symfony/process/Exception/ProcessSignaledException.php-g-n _3vendor/symfony/process/Exception/LogicException.php-giUQ7vendor/symfony/process/Exception/ExceptionInterface.php-g j%W;vendor/symfony/process/Exception/ProcessFailedException.phpp-gpۋ5vendor/symfony/process/Exception/RuntimeException.php-gP=vendor/symfony/process/Exception/ProcessTimedOutException.php-g8^Q=vendor/symfony/process/Exception/InvalidArgumentException.php-gڴ>vendor/symfony/process/Exception/RunProcessFailedException.php-gؤ$vendor/symfony/process/composer.json-gS.t'vendor/symfony/process/ProcessUtils.php-ga鍤"vendor/symfony/process/Process.php-g=vendor/symfony/console/DataCollector/CommandDataCollector.php-g& (vendor/symfony/console/ConsoleEvents.php-g. !vendor/symfony/console/Cursor.php-g\Fä&vendor/symfony/console/Application.php-g!(/vendor/symfony/console/Logger/ConsoleLogger.phpY-gYĠ™.vendor/symfony/console/Attribute/AsCommand.phpJ-gJcvendor/symfony/console/LICENSE,-g,U#vendor/symfony/console/CHANGELOG.md)-g)b_e9vendor/symfony/console/Input/StreamableInputInterface.php-g3y-+vendor/symfony/console/Input/ArrayInput.phpH-gHůx*vendor/symfony/console/Input/ArgvInput.php0-g0#.vendor/symfony/console/Input/InputArgument.php:-g: ț4vendor/symfony/console/Input/InputAwareInterface.phpc-gcQ,vendor/symfony/console/Input/InputOption.php!-g!!1g=0vendor/symfony/console/Input/InputDefinition.phpU.-gU.)ͤ,vendor/symfony/console/Input/StringInput.php -g G&vendor/symfony/console/Input/Input.phpl-gl;/vendor/symfony/console/Input/InputInterface.php|-g|kx'#vendor/symfony/console/Terminal.php-g`HN2vendor/symfony/console/CI/GithubActionReporter.php+ -g+ @0vendor/symfony/console/Resources/completion.bash -g %}4vendor/symfony/console/Resources/bin/hiddeninput.exe$-g$v/vendor/symfony/console/Resources/completion.zsh -g ʤ0vendor/symfony/console/Resources/completion.fish-gKeդ5vendor/symfony/console/Output/TrimmedBufferOutput.phpY-gYG>d8vendor/symfony/console/Output/ConsoleOutputInterface.php=-g=B:0vendor/symfony/console/Output/BufferedOutput.phpQ-gQ*AS1vendor/symfony/console/Output/OutputInterface.php6 -g6 j8q/vendor/symfony/console/Output/AnsiColorMode.php -g oi+(vendor/symfony/console/Output/Output.php-g\Τ6vendor/symfony/console/Output/ConsoleSectionOutput.php9!-g9! /vendor/symfony/console/Output/ConsoleOutput.php-g:*,vendor/symfony/console/Output/NullOutput.phpO-gOp .vendor/symfony/console/Output/StreamOutput.php-g+%ؤAvendor/symfony/console/Completion/Output/FishCompletionOutput.php-g`Avendor/symfony/console/Completion/Output/BashCompletionOutput.php -g Q2Fvendor/symfony/console/Completion/Output/CompletionOutputInterface.php-g:]@vendor/symfony/console/Completion/Output/ZshCompletionOutput.php1-g10vendor/symfony/console/Completion/Suggestion.php7-g7/) Ϥ;vendor/symfony/console/Completion/CompletionSuggestions.php^-g^lx5vendor/symfony/console/Completion/CompletionInput.php -g jfO,vendor/symfony/console/Style/OutputStyle.php -g Vy -vendor/symfony/console/Style/SymfonyStyle.php;-g; &ˤ/vendor/symfony/console/Style/StyleInterface.php -g .2vendor/symfony/console/Question/ChoiceQuestion.php1-g1JY,vendor/symfony/console/Question/Question.php>-g>o[դ8vendor/symfony/console/Question/ConfirmationQuestion.php,-g,% vendor/symfony/console/README.md-gÆf9vendor/symfony/console/Formatter/OutputFormatterStyle.php -g yMBvendor/symfony/console/Formatter/OutputFormatterStyleInterface.php-gǡ=vendor/symfony/console/Formatter/NullOutputFormatterStyle.phpl-gl=vendor/symfony/console/Formatter/OutputFormatterInterface.php"-g"7V6_4vendor/symfony/console/Formatter/OutputFormatter.phpM -gM =b8vendor/symfony/console/Formatter/NullOutputFormatter.php-gB[Fvendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php-g* >vendor/symfony/console/Formatter/OutputFormatterStyleStack.php? -g? :;6vendor/symfony/console/Messenger/RunCommandMessage.php-g M6vendor/symfony/console/Messenger/RunCommandContext.php-g!B=vendor/symfony/console/Messenger/RunCommandMessageHandler.php-gyzo vendor/symfony/console/Color.php(-g(-8vendor/symfony/console/SignalRegistry/SignalRegistry.php-gG,eͤ3vendor/symfony/console/SignalRegistry/SignalMap.php-g(3vendor/symfony/console/SingleCommandApplication.php>-g>OA?vendor/symfony/console/CommandLoader/CommandLoaderInterface.phpV-gVX2?vendor/symfony/console/CommandLoader/ContainerCommandLoader.php -g ƒ=vendor/symfony/console/CommandLoader/FactoryCommandLoader.phpK-gK<4vendor/symfony/console/Descriptor/TextDescriptor.php0-g0f <vendor/symfony/console/Descriptor/ApplicationDescription.php(-g(#13vendor/symfony/console/Descriptor/XmlDescriptor.php&-g&,Eb9vendor/symfony/console/Descriptor/DescriptorInterface.phpm-gmB0vendor/symfony/console/Descriptor/Descriptor.php -g j@vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php')-g')Ǿ44vendor/symfony/console/Descriptor/JsonDescriptor.php%-g% ֤8vendor/symfony/console/Descriptor/MarkdownDescriptor.php-g4Qj/vendor/symfony/console/Tester/CommandTester.phpL -gL 5Ykؤ-vendor/symfony/console/Tester/TesterTrait.phpr-grƤ3vendor/symfony/console/Tester/ApplicationTester.php -g Z39vendor/symfony/console/Tester/CommandCompletionTester.phpD-gDT@vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php+-g+13vendor/symfony/console/Command/TraceableCommand.php](-g]( .vendor/symfony/console/Command/LazyCommand.php-goͤ0vendor/symfony/console/Command/LockableTrait.php3-g3.vendor/symfony/console/Command/HelpCommand.php -g 6_32vendor/symfony/console/Command/CompleteCommand.php#-g#sJ!.vendor/symfony/console/Command/ListCommand.php -g e\{8vendor/symfony/console/Command/DumpCompletionCommand.php-g+CQ=vendor/symfony/console/Command/SignalableCommandInterface.phpE-gEbO*vendor/symfony/console/Command/Command.php!Z-g!Za 啤,vendor/symfony/console/Helper/TableStyle.php!1-g!1'p,+vendor/symfony/console/Helper/TableRows.php[-g[{m֤7vendor/symfony/console/Helper/SymfonyQuestionHelper.php) -g) 7N1vendor/symfony/console/Helper/HelperInterface.phpV-gV̊+vendor/symfony/console/Helper/TableCell.php-ge9S/vendor/symfony/console/Helper/ProcessHelper.php-ge0vendor/symfony/console/Helper/TableSeparator.php!-g!n2/vendor/symfony/console/Helper/OutputWrapper.php -g lؤ1vendor/symfony/console/Helper/FormatterHelper.php-g0ɤ0vendor/symfony/console/Helper/TableCellStyle.php)-g)KӘ-vendor/symfony/console/Helper/ProgressBar.phpL-gLr6vendor/symfony/console/Helper/DebugFormatterHelper.php -g &+vendor/symfony/console/Helper/HelperSet.phpc-gcV.(vendor/symfony/console/Helper/Dumper.phpz-gz`2vendor/symfony/console/Helper/InputAwareHelper.php-gpc0vendor/symfony/console/Helper/QuestionHelper.phpXL-gXLʱbܤ(vendor/symfony/console/Helper/Helper.php-g+u'vendor/symfony/console/Helper/Table.php6{-g6{De3vendor/symfony/console/Helper/ProgressIndicator.php-gbN&2vendor/symfony/console/Helper/DescriptorHelper.phpd -gd Dvendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php-g43vendor/symfony/console/Exception/LogicException.php-g5;vendor/symfony/console/Exception/InvalidOptionException.php-g%:>vendor/symfony/console/Exception/RunCommandFailedException.php>-g>~7vendor/symfony/console/Exception/ExceptionInterface.php-goOȤ5vendor/symfony/console/Exception/RuntimeException.php-g ?vendor/symfony/console/Exception/NamespaceNotFoundException.php-gxD=vendor/symfony/console/Exception/InvalidArgumentException.php-gx Τ:vendor/symfony/console/Exception/MissingInputException.php-gL=vendor/symfony/console/Exception/CommandNotFoundException.php-g͆Ť6vendor/symfony/console/Event/ConsoleTerminateEvent.php-g[5Ť2vendor/symfony/console/Event/ConsoleErrorEvent.php-gz4vendor/symfony/console/Event/ConsoleCommandEvent.php>-g>y-vendor/symfony/console/Event/ConsoleEvent.php-g8(M3vendor/symfony/console/Event/ConsoleSignalEvent.php-g=|Ѯ$vendor/symfony/console/composer.jsonH-gH++vendor/symfony/console/Debug/CliRequest.phpq-gqekX6vendor/symfony/console/EventListener/ErrorListener.php -g h 0vendor/symfony/polyfill-mbstring/bootstrap80.php'-g'L#\M(vendor/symfony/polyfill-mbstring/LICENSE,-g,HBvendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php-g]SC@vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.phpU-gUD׎Fvendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php-goቤ@vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpO[-gO[(-vendor/symfony/polyfill-mbstring/Mbstring.php-gg_.vendor/symfony/polyfill-mbstring/bootstrap.php!-g!d*vendor/symfony/polyfill-mbstring/README.mdr-grA`.vendor/symfony/polyfill-mbstring/composer.json8-g85vendor/symfony/polyfill-intl-grapheme/bootstrap80.phpg -gg E{-vendor/symfony/polyfill-intl-grapheme/LICENSE,-g,H2vendor/symfony/polyfill-intl-grapheme/Grapheme.php &-g &83vendor/symfony/polyfill-intl-grapheme/bootstrap.php-g/vendor/symfony/polyfill-intl-grapheme/README.mdK-gKC>3vendor/symfony/polyfill-intl-grapheme/composer.json -g + vendor/ramsey/collection/LICENSE7-g7ŸԤ"vendor/ramsey/collection/README.md!-g!2&vendor/ramsey/collection/composer.jsonK-gKO2vendor/ramsey/collection/conventional-commits.json-gQ,$vendor/ramsey/collection/SECURITY.md-g1vendor/ramsey/collection/src/DoubleEndedQueue.php-ge,vendor/ramsey/collection/src/AbstractSet.php'-g'/vendor/ramsey/collection/src/QueueInterface.php-g*3vendor/ramsey/collection/src/AbstractCollection.phpV.-gV.6.vendor/ramsey/collection/src/AbstractArray.php-gPX&vendor/ramsey/collection/src/Queue.php3-g3D$vendor/ramsey/collection/src/Set.php4-g4 {:vendor/ramsey/collection/src/DoubleEndedQueueInterface.php(-g(6'&6vendor/ramsey/collection/src/Map/TypedMapInterface.php2-g2z5vendor/ramsey/collection/src/Map/AbstractTypedMap.php-gՊ1vendor/ramsey/collection/src/Map/MapInterface.php-gOA-vendor/ramsey/collection/src/Map/TypedMap.php -g G8vendor/ramsey/collection/src/Map/AssociativeArrayMap.php0-g0PǤ6vendor/ramsey/collection/src/Map/NamedParameterMap.php -g `@Q0vendor/ramsey/collection/src/Map/AbstractMap.php-g]T3-vendor/ramsey/collection/src/GenericArray.php-g/vendor/ramsey/collection/src/ArrayInterface.php'-g'5a%vendor/ramsey/collection/src/Sort.php{-g{Ȥ+vendor/ramsey/collection/src/Collection.php) -g) &'74vendor/ramsey/collection/src/CollectionInterface.php $-g $;eHvendor/ramsey/collection/src/Exception/UnsupportedOperationException.phpL-gLff?vendor/ramsey/collection/src/Exception/OutOfBoundsException.phpw-gw>vendor/ramsey/collection/src/Exception/CollectionException.php-gĴ@Cvendor/ramsey/collection/src/Exception/InvalidArgumentException.phps-gsڤAvendor/ramsey/collection/src/Exception/NoSuchElementException.phpD-gD LnBvendor/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php-gFvendor/ramsey/collection/src/Exception/CollectionMismatchException.phpM-gM\ć8vendor/ramsey/collection/src/Tool/ValueToStringTrait.php-g7m/vendor/ramsey/collection/src/Tool/TypeTrait.phpD-gDe9vendor/ramsey/collection/src/Tool/ValueExtractorTrait.phpT -gT ZXKvendor/ramsey/uuid/LICENSE7-g7T̤vendor/ramsey/uuid/README.md-g$ vendor/ramsey/uuid/composer.json-gVҤ$vendor/ramsey/uuid/src/functions.php5-g5 oj5vendor/ramsey/uuid/src/Validator/GenericValidator.php-g)7vendor/ramsey/uuid/src/Validator/ValidatorInterface.php-gB$o>vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php -g .V;vendor/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php -g Q53Τ:vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.phpg-gg;Q ?vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.phpu-gu?@vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.phpt-gt,Cvendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php|-g|7@s&>vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php0-g0ǤBvendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php-g=0N;vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php?-g?t=vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php9-g9z5vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php5-g5TE8vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php# -g# &1vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php -g 7|o/vendor/ramsey/uuid/src/Codec/CodecInterface.php/-g/T|0vendor/ramsey/uuid/src/Codec/GuidStringCodec.php-g@+,vendor/ramsey/uuid/src/Codec/StringCodec.php -g Ǟ7vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php\-g\lvendor/ramsey/uuid/src/Uuid.phpd-gdb@vendor/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php-g}Avendor/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php{-g{#~٣9vendor/ramsey/uuid/src/Provider/NodeProviderInterface.php-g ";vendor/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php -g a:vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php-gSVۤ9vendor/ramsey/uuid/src/Provider/TimeProviderInterface.phpS-gSm+;vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php-go>O=vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.phpj-gju};vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php-gp?vendor/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php-g60;vendor/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php4-g4L%vendor/ramsey/uuid/src/FeatureSet.php 2-g 2wP2vendor/ramsey/uuid/src/Rfc4122/FieldsInterface.phpO-gO`)vendor/ramsey/uuid/src/Rfc4122/UuidV8.php; -g; `$,vendor/ramsey/uuid/src/Rfc4122/Validator.php-gYB+vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php"-g"Ypg/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php-g",+vendor/ramsey/uuid/src/Rfc4122/NilTrait.php-gP)vendor/ramsey/uuid/src/Rfc4122/Fields.php-g28*vendor/ramsey/uuid/src/Rfc4122/NilUuid.php[-g[:*vendor/ramsey/uuid/src/Rfc4122/MaxUuid.phpZ-gZ; T0vendor/ramsey/uuid/src/Rfc4122/UuidInterface.php-g)B,vendor/ramsey/uuid/src/Rfc4122/TimeTrait.phpY-gYV/vendor/ramsey/uuid/src/Rfc4122/VariantTrait.phpb -gb f6.vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php@-g@̤)vendor/ramsey/uuid/src/Rfc4122/UuidV1.php-g_t)vendor/ramsey/uuid/src/Rfc4122/UuidV3.php-g|O$)vendor/ramsey/uuid/src/Rfc4122/UuidV2.php-ga /)vendor/ramsey/uuid/src/Rfc4122/UuidV6.php)-g)|x{)vendor/ramsey/uuid/src/Rfc4122/UuidV7.phpP-gP&Fo)vendor/ramsey/uuid/src/Rfc4122/UuidV5.php-gs)vendor/ramsey/uuid/src/Rfc4122/UuidV4.php-g%(vendor/ramsey/uuid/src/UuidInterface.php: -g: ƌ,vendor/ramsey/uuid/src/Math/RoundingMode.php-g3vendor/ramsey/uuid/src/Math/CalculatorInterface.php-gɤ3vendor/ramsey/uuid/src/Math/BrickMathCalculator.php-gu#/vendor/ramsey/uuid/src/UuidFactoryInterface.php-gGg9vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.phpX-gX5*59vendor/ramsey/uuid/src/Generator/NameGeneratorFactory.php-g-Z56vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.phpD-gD׺Z;vendor/ramsey/uuid/src/Generator/NameGeneratorInterface.phpG-gGLդ;vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php-g9vendor/ramsey/uuid/src/Generator/DceSecurityGenerator.php-g+>Bvendor/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php-g9vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php{-g{k 9vendor/ramsey/uuid/src/Generator/DefaultNameGenerator.php-gg$59vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php-g05vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php?-g?hi^;vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php-g>12vendor/ramsey/uuid/src/Generator/CombGenerator.php -g MO=vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php-g>59 <vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php3-g3r䍤:vendor/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php-g+qZ:vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.phpu-guH9&vendor/ramsey/uuid/src/BinaryUtils.php-g/&vendor/ramsey/uuid/src/UuidFactory.php=-g='vendor/ramsey/uuid/src/Type/Integer.php-gޤ$vendor/ramsey/uuid/src/Type/Time.php -g mlU+vendor/ramsey/uuid/src/Type/Hexadecimal.php -g q /vendor/ramsey/uuid/src/Type/NumberInterface.php-gL-vendor/ramsey/uuid/src/Type/TypeInterface.php-gw*'vendor/ramsey/uuid/src/Type/Decimal.php -g |Lf$vendor/ramsey/uuid/src/Guid/Guid.php& -g& rR&vendor/ramsey/uuid/src/Guid/Fields.php'-g'ُq+vendor/ramsey/uuid/src/Guid/GuidBuilder.php-g'2vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.phpB-gBG'vendor/ramsey/uuid/src/DegradedUuid.phpD-gD1vendor/ramsey/uuid/src/Fields/FieldsInterface.php-gm5h9vendor/ramsey/uuid/src/Fields/SerializableFieldsTrait.php-gs"2vendor/ramsey/uuid/src/DeprecatedUuidInterface.phpJ-gJ ¤6vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.phpu-gu27vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php;-g;-34vendor/ramsey/uuid/src/Builder/BuilderCollection.php -g %;2vendor/ramsey/uuid/src/Builder/FallbackBuilder.php-gS/Y5vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.phpT-gTVy:vendor/ramsey/uuid/src/Exception/RandomSourceException.php-g^E2vendor/ramsey/uuid/src/Exception/NodeException.php`-g`]6vendor/ramsey/uuid/src/Exception/DateTimeException.phpa-ga\8vendor/ramsey/uuid/src/Exception/TimeSourceException.phpQ-gQBvendor/ramsey/uuid/src/Exception/UnsupportedOperationException.phpV-gVJN:vendor/ramsey/uuid/src/Exception/InvalidBytesException.php_-g_/٤9vendor/ramsey/uuid/src/Exception/DceSecurityException.phpp-gp 2vendor/ramsey/uuid/src/Exception/NameException.phpf-gfv fY=vendor/ramsey/uuid/src/Exception/InvalidArgumentException.phpi-giv'ä=vendor/ramsey/uuid/src/Exception/BuilderNotFoundException.phpQ-gQ@c?vendor/ramsey/uuid/src/Exception/UnableToBuildUuidException.phpO-gORo;vendor/ramsey/uuid/src/Exception/UuidExceptionInterface.php-gK;Ҥ?vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php-gKI -vendor/ramsey/uuid/src/Nonstandard/Fields.php -g a+vendor/ramsey/uuid/src/Nonstandard/Uuid.php-gs2vendor/ramsey/uuid/src/Nonstandard/UuidBuilder.php-gN-vendor/ramsey/uuid/src/Nonstandard/UuidV6.phpT -gT qѤvendor/webmozart/assert/LICENSE<-g<t}$vendor/webmozart/assert/CHANGELOG.md-g!vendor/webmozart/assert/README.md>-g>|Ϥ%vendor/webmozart/assert/composer.json-g3p%vendor/webmozart/assert/src/Mixin.php5-g59(8vendor/webmozart/assert/src/InvalidArgumentException.phpi-gi{Lä&vendor/webmozart/assert/src/Assert.php-g=vendor/react/promise/LICENSEg-ggF!vendor/react/promise/CHANGELOG.md9-g9OT:vendor/react/promise/README.mdQY-gQY1 "vendor/react/promise/composer.json-gNjB-vendor/react/promise/src/PromiseInterface.php-gMFx8&vendor/react/promise/src/functions.php1--g1-t.vendor/react/promise/src/functions_include.php-gdx\$vendor/react/promise/src/Promise.php(-g(s;6%vendor/react/promise/src/Deferred.php0-g05vendor/react/promise/src/Internal/RejectedPromise.php -g |6vendor/react/promise/src/Internal/FulfilledPromise.php3 -g3 *7vendor/react/promise/src/Internal/CancellationQueue.php-gr26vendor/react/promise/src/Exception/LengthException.php^-g^?q9vendor/react/promise/src/Exception/CompositeException.phpa-ga' array ( 'type' => 'php', 'condition' => '^8.1', 'message' => 'The application requires the version "^8.1" or greater.', 'helpMessage' => 'The application requires the version "^8.1" or greater.', ), 1 => array ( 'type' => 'extension', 'condition' => 'json', 'message' => 'The application requires the extension "json". Enable it or install a polyfill.', 'helpMessage' => 'The application requires the extension "json".', ), 2 => array ( 'type' => 'extension', 'condition' => 'json', 'message' => 'The package "ramsey/uuid" requires the extension "json". Enable it or install a polyfill.', 'helpMessage' => 'The package "ramsey/uuid" requires the extension "json".', ), 3 => array ( 'type' => 'extension', 'condition' => 'json', 'message' => 'The package "web-auth/cose-lib" requires the extension "json". Enable it or install a polyfill.', 'helpMessage' => 'The package "web-auth/cose-lib" requires the extension "json".', ), 4 => array ( 'type' => 'extension', 'condition' => 'json', 'message' => 'The package "web-auth/webauthn-lib" requires the extension "json". Enable it or install a polyfill.', 'helpMessage' => 'The package "web-auth/webauthn-lib" requires the extension "json".', ), 5 => array ( 'type' => 'extension', 'condition' => 'zip', 'message' => 'The application requires the extension "zip". Enable it or install a polyfill.', 'helpMessage' => 'The application requires the extension "zip".', ), 6 => array ( 'type' => 'extension', 'condition' => 'openssl', 'message' => 'The package "composer/ca-bundle" requires the extension "openssl". Enable it or install a polyfill.', 'helpMessage' => 'The package "composer/ca-bundle" requires the extension "openssl".', ), 7 => array ( 'type' => 'extension', 'condition' => 'openssl', 'message' => 'The package "web-auth/cose-lib" requires the extension "openssl". Enable it or install a polyfill.', 'helpMessage' => 'The package "web-auth/cose-lib" requires the extension "openssl".', ), 8 => array ( 'type' => 'extension', 'condition' => 'openssl', 'message' => 'The package "web-auth/webauthn-lib" requires the extension "openssl". Enable it or install a polyfill.', 'helpMessage' => 'The package "web-auth/webauthn-lib" requires the extension "openssl".', ), 9 => array ( 'type' => 'extension', 'condition' => 'pcre', 'message' => 'The package "composer/ca-bundle" requires the extension "pcre". Enable it or install a polyfill.', 'helpMessage' => 'The package "composer/ca-bundle" requires the extension "pcre".', ), 10 => array ( 'type' => 'extension', 'condition' => 'filter', 'message' => 'The package "phpdocumentor/reflection-docblock" requires the extension "filter". Enable it or install a polyfill.', 'helpMessage' => 'The package "phpdocumentor/reflection-docblock" requires the extension "filter".', ), 11 => array ( 'type' => 'extension', 'condition' => 'xml', 'message' => 'The package "symfony/framework-bundle" requires the extension "xml". Enable it or install a polyfill.', 'helpMessage' => 'The package "symfony/framework-bundle" requires the extension "xml".', ), 12 => array ( 'type' => 'extension', 'condition' => 'xml', 'message' => 'The package "symfony/security-bundle" requires the extension "xml". Enable it or install a polyfill.', 'helpMessage' => 'The package "symfony/security-bundle" requires the extension "xml".', ), ); * 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; } array($baseDir . '/src'), 'HumbugBox3150\\Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), ); $vendorDir . '/composer/InstalledVersions.php', 'HumbugBox3150\\Composer\\Semver\\Comparator' => $vendorDir . '/composer/semver/src/Comparator.php', 'HumbugBox3150\\Composer\\Semver\\CompilingMatcher' => $vendorDir . '/composer/semver/src/CompilingMatcher.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\Bound' => $vendorDir . '/composer/semver/src/Constraint/Bound.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\Constraint' => $vendorDir . '/composer/semver/src/Constraint/Constraint.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\ConstraintInterface' => $vendorDir . '/composer/semver/src/Constraint/ConstraintInterface.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\MatchAllConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchAllConstraint.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchNoneConstraint.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir . '/composer/semver/src/Constraint/MultiConstraint.php', 'HumbugBox3150\\Composer\\Semver\\Interval' => $vendorDir . '/composer/semver/src/Interval.php', 'HumbugBox3150\\Composer\\Semver\\Intervals' => $vendorDir . '/composer/semver/src/Intervals.php', 'HumbugBox3150\\Composer\\Semver\\Semver' => $vendorDir . '/composer/semver/src/Semver.php', 'HumbugBox3150\\Composer\\Semver\\VersionParser' => $vendorDir . '/composer/semver/src/VersionParser.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Checker' => $baseDir . '/src/Checker.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IO' => $baseDir . '/src/IO.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IsExtensionFulfilled' => $baseDir . '/src/IsExtensionFulfilled.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IsFulfilled' => $baseDir . '/src/IsFulfilled.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IsPhpVersionFulfilled' => $baseDir . '/src/IsPhpVersionFulfilled.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Printer' => $baseDir . '/src/Printer.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Requirement' => $baseDir . '/src/Requirement.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\RequirementCollection' => $baseDir . '/src/RequirementCollection.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Terminal' => $baseDir . '/src/Terminal.php', ); array ( 'HumbugBox3150\\KevinGH\\RequirementChecker\\' => 41, 'HumbugBox3150\\Composer\\Semver\\' => 30, ), ); public static $prefixDirsPsr4 = array ( 'HumbugBox3150\\KevinGH\\RequirementChecker\\' => array ( 0 => __DIR__ . '/../..' . '/src', ), 'HumbugBox3150\\Composer\\Semver\\' => array ( 0 => __DIR__ . '/..' . '/composer/semver/src', ), ); public static $classMap = array ( 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'HumbugBox3150\\Composer\\Semver\\Comparator' => __DIR__ . '/..' . '/composer/semver/src/Comparator.php', 'HumbugBox3150\\Composer\\Semver\\CompilingMatcher' => __DIR__ . '/..' . '/composer/semver/src/CompilingMatcher.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\Bound' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Bound.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\Constraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Constraint.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\ConstraintInterface' => __DIR__ . '/..' . '/composer/semver/src/Constraint/ConstraintInterface.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\MatchAllConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchAllConstraint.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchNoneConstraint.php', 'HumbugBox3150\\Composer\\Semver\\Constraint\\MultiConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MultiConstraint.php', 'HumbugBox3150\\Composer\\Semver\\Interval' => __DIR__ . '/..' . '/composer/semver/src/Interval.php', 'HumbugBox3150\\Composer\\Semver\\Intervals' => __DIR__ . '/..' . '/composer/semver/src/Intervals.php', 'HumbugBox3150\\Composer\\Semver\\Semver' => __DIR__ . '/..' . '/composer/semver/src/Semver.php', 'HumbugBox3150\\Composer\\Semver\\VersionParser' => __DIR__ . '/..' . '/composer/semver/src/VersionParser.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Checker' => __DIR__ . '/../..' . '/src/Checker.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IO' => __DIR__ . '/../..' . '/src/IO.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IsExtensionFulfilled' => __DIR__ . '/../..' . '/src/IsExtensionFulfilled.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IsFulfilled' => __DIR__ . '/../..' . '/src/IsFulfilled.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\IsPhpVersionFulfilled' => __DIR__ . '/../..' . '/src/IsPhpVersionFulfilled.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Printer' => __DIR__ . '/../..' . '/src/Printer.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Requirement' => __DIR__ . '/../..' . '/src/Requirement.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\RequirementCollection' => __DIR__ . '/../..' . '/src/RequirementCollection.php', 'HumbugBox3150\\KevinGH\\RequirementChecker\\Terminal' => __DIR__ . '/../..' . '/src/Terminal.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInit7b1918d23e69dc64db20ca1f98396893::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit7b1918d23e69dc64db20ca1f98396893::$prefixDirsPsr4; $loader->classMap = ComposerStaticInit7b1918d23e69dc64db20ca1f98396893::$classMap; }, null, ClassLoader::class); } } = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInit7b1918d23e69dc64db20ca1f98396893::getInitializer($loader)); } else { $classMap = require __DIR__ . '/autoload_classmap.php'; if ($classMap) { $loader->addClassMap($classMap); } } $loader->setClassMapAuthoritative(true); $loader->register(true); return $loader; } } ', $version2); } public static function greaterThanOrEqualTo($version1, $version2) { return self::compare($version1, '>=', $version2); } public static function lessThan($version1, $version2) { return self::compare($version1, '<', $version2); } public static function lessThanOrEqualTo($version1, $version2) { return self::compare($version1, '<=', $version2); } public static function equalTo($version1, $version2) { return self::compare($version1, '==', $version2); } public static function notEqualTo($version1, $version2) { return self::compare($version1, '!=', $version2); } public static function compare($version1, $operator, $version2) { $constraint = new Constraint($operator, $version2); return $constraint->matchSpecific(new Constraint('==', $version1), \true); } } normalize($version)); $parsedConstraints = $versionParser->parseConstraints($constraints); return $parsedConstraints->matches($provider); } public static function satisfiedBy(array $versions, $constraints) { $versions = \array_filter($versions, function ($version) use($constraints) { return Semver::satisfies($version, $constraints); }); return \array_values($versions); } public static function sort(array $versions) { return self::usort($versions, self::SORT_ASC); } public static function rsort(array $versions) { return self::usort($versions, self::SORT_DESC); } private static function usort(array $versions, $direction) { if (null === self::$versionParser) { self::$versionParser = new VersionParser(); } $versionParser = self::$versionParser; $normalized = array(); foreach ($versions as $key => $version) { $normalizedVersion = $versionParser->normalize($version); $normalizedVersion = $versionParser->normalizeDefaultBranch($normalizedVersion); $normalized[] = array($normalizedVersion, $key); } \usort($normalized, function (array $left, array $right) use($direction) { if ($left[0] === $right[0]) { return 0; } if (Comparator::lessThan($left[0], $right[0])) { return -$direction; } return $direction; }); $sorted = array(); foreach ($normalized as $item) { $sorted[] = $versions[$item[1]]; } return $sorted; } } expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? \ltrim($matches[$index + 1], '.-') : ''); } if (!empty($matches[$index + 2])) { $version .= '-dev'; } return $version; } if (\preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { try { $normalized = $this->normalizeBranch($match[1]); if (\strpos($normalized, 'dev-') === \false) { return $normalized; } } catch (\Exception $e) { } } $extraMessage = ''; if (\preg_match('{ +as +' . \preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))?$}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version'; } elseif (\preg_match('{^' . \preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))? +as +}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; } throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage); } public function parseNumericAliasPrefix($branch) { if (\preg_match('{^(?P(\\d++\\.)*\\d++)(?:\\.x)?-dev$}i', $branch, $matches)) { return $matches['version'] . '.'; } return \false; } public function normalizeBranch($name) { $name = \trim($name); if (\preg_match('{^v?(\\d++)(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?$}i', $name, $matches)) { $version = ''; for ($i = 1; $i < 5; ++$i) { $version .= isset($matches[$i]) ? \str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; } return \str_replace('x', '9999999', $version) . '-dev'; } return 'dev-' . $name; } public function normalizeDefaultBranch($name) { if ($name === 'dev-master' || $name === 'dev-default' || $name === 'dev-trunk') { return '9999999-dev'; } return $name; } public function parseConstraints($constraints) { $prettyConstraint = $constraints; $orConstraints = \preg_split('{\\s*\\|\\|?\\s*}', \trim($constraints)); $orGroups = array(); foreach ($orConstraints as $constraints) { $andConstraints = \preg_split('{(?< ,]) *(? 1) { $constraintObjects = array(); foreach ($andConstraints as $constraint) { foreach ($this->parseConstraint($constraint) as $parsedConstraint) { $constraintObjects[] = $parsedConstraint; } } } else { $constraintObjects = $this->parseConstraint($andConstraints[0]); } if (1 === \count($constraintObjects)) { $constraint = $constraintObjects[0]; } else { $constraint = new MultiConstraint($constraintObjects); } $orGroups[] = $constraint; } $constraint = MultiConstraint::create($orGroups, \false); $constraint->setPrettyString($prettyConstraint); return $constraint; } private function parseConstraint($constraint) { if (\preg_match('{^([^,\\s]++) ++as ++([^,\\s]++)$}', $constraint, $match)) { $constraint = $match[1]; } if (\preg_match('{^([^,\\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) { $constraint = '' !== $match[1] ? $match[1] : '*'; if ($match[2] !== 'stable') { $stabilityModifier = $match[2]; } } if (\preg_match('{^(dev-[^,\\s@]+?|[^,\\s@]+?\\.x-dev)#.+$}i', $constraint, $match)) { $constraint = $match[1]; } if (\preg_match('{^(v)?[xX*](\\.[xX*])*$}i', $constraint, $match)) { if (!empty($match[1]) || !empty($match[2])) { return array(new Constraint('>=', '0.0.0.0-dev')); } return array(new MatchAllConstraint()); } $versionRegex = 'v?(\\d++)(?:\\.(\\d++|[xX*]))?(?:\\.(\\d++|[xX*]))?(?:\\.(\\d++|[xX*]))?' . self::$modifierRegex . '(?:\\+[^\\s]+)?'; if (\preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) { if (\strpos($constraint, '~>') === 0) { throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator'); } if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) { $position = 4; } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } for ($i = $position; $i >= 0; $i--) { if ($matches[$i] === 'x' || $matches[$i] === 'X' || $matches[$i] === '*') { $matches[$i] = '9999999'; } } $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new Constraint('>=', $lowVersion); $highPosition = \max(1, $position - 1); $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); return array($lowerBound, $upperBound); } if (\preg_match('{^\\^' . $versionRegex . '($)}i', $constraint, $matches)) { if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) { $position = 1; } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) { $position = 2; } else { $position = 3; } if ($position === 2 && ($matches[2] === 'x' || $matches[2] === 'X' || $matches[2] === '*')) { $position = 1; } $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new Constraint('>=', $lowVersion); $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); return array($lowerBound, $upperBound); } if (\preg_match('{^v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.[xX*])++$}', $constraint, $matches)) { if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev'; $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; if ($lowVersion === '0.0.0.0-dev') { return array(new Constraint('<', $highVersion)); } return array(new Constraint('>=', $lowVersion), new Constraint('<', $highVersion)); } if (\preg_match('{^(?P' . $versionRegex . ') +- +(?P' . $versionRegex . ')($)}i', $constraint, $matches)) { $lowStabilitySuffix = ''; if (empty($matches[6]) && empty($matches[8])) { $lowStabilitySuffix = '-dev'; } $lowVersion = $this->normalize($matches['from']); $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix); $empty = function ($x) { return $x === 0 || $x === '0' ? \false : empty($x); }; if (!$empty($matches[11]) && !$empty($matches[12]) || !empty($matches[14]) || !empty($matches[16])) { $highVersion = $this->normalize($matches['to']); $upperBound = new Constraint('<=', $highVersion); } else { $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]); $this->normalize($matches['to']); $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); } return array($lowerBound, $upperBound); } if (\preg_match('{^(<>|!=|>=?|<=?|==?)?\\s*(.*)}', $constraint, $matches)) { try { try { $version = $this->normalize($matches[2]); } catch (\UnexpectedValueException $e) { if (\substr($matches[2], -4) === '-dev') { $version = $this->normalize('dev-' . \substr($matches[2], 0, -4)); } else { throw $e; } } $op = $matches[1] ?: '='; if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') { $version .= '-' . $stabilityModifier; } elseif ('<' === $op || '>=' === $op) { if (!\preg_match('/-' . self::$modifierRegex . '$/', \strtolower($matches[2]))) { if (\strpos($matches[2], 'dev-') !== 0) { $version .= '-dev'; } } } return array(new Constraint($matches[1] ?: '=', $version)); } catch (\Exception $e) { } } $message = 'Could not parse version constraint ' . $constraint; if (isset($e)) { $message .= ': ' . $e->getMessage(); } throw new \UnexpectedValueException($message); } private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0') { for ($i = 4; $i > 0; --$i) { if ($i > $position) { $matches[$i] = $pad; } elseif ($i === $position && $increment) { $matches[$i] += $increment; if ($matches[$i] < 0) { $matches[$i] = $pad; --$position; if ($i === 1) { return null; } } } } return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; } private function expandStability($stability) { $stability = \strtolower($stability); switch ($stability) { case 'a': return 'alpha'; case 'b': return 'beta'; case 'p': case 'pl': return 'patch'; case 'rc': return 'RC'; default: return $stability; } } } constraints = $constraints; $this->conjunctive = $conjunctive; } public function getConstraints() { return $this->constraints; } public function isConjunctive() { return $this->conjunctive; } public function isDisjunctive() { return !$this->conjunctive; } public function compile($otherOperator) { $parts = array(); foreach ($this->constraints as $constraint) { $code = $constraint->compile($otherOperator); if ($code === 'true') { if (!$this->conjunctive) { return 'true'; } } elseif ($code === 'false') { if ($this->conjunctive) { return 'false'; } } else { $parts[] = '(' . $code . ')'; } } if (!$parts) { return $this->conjunctive ? 'true' : 'false'; } return $this->conjunctive ? \implode('&&', $parts) : \implode('||', $parts); } public function matches(ConstraintInterface $provider) { if (\false === $this->conjunctive) { foreach ($this->constraints as $constraint) { if ($provider->matches($constraint)) { return \true; } } return \false; } foreach ($this->constraints as $constraint) { if (!$provider->matches($constraint)) { return \false; } } return \true; } public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } public function __toString() { if ($this->string !== null) { return $this->string; } $constraints = array(); foreach ($this->constraints as $constraint) { $constraints[] = (string) $constraint; } return $this->string = '[' . \implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']'; } public function getLowerBound() { $this->extractBounds(); return $this->lowerBound; } public function getUpperBound() { $this->extractBounds(); return $this->upperBound; } public static function create(array $constraints, $conjunctive = \true) { if (0 === \count($constraints)) { return new MatchAllConstraint(); } if (1 === \count($constraints)) { return $constraints[0]; } $optimized = self::optimizeConstraints($constraints, $conjunctive); if ($optimized !== null) { list($constraints, $conjunctive) = $optimized; if (\count($constraints) === 1) { return $constraints[0]; } } return new self($constraints, $conjunctive); } private static function optimizeConstraints(array $constraints, $conjunctive) { if (!$conjunctive) { $left = $constraints[0]; $mergedConstraints = array(); $optimized = \false; for ($i = 1, $l = \count($constraints); $i < $l; $i++) { $right = $constraints[$i]; if ($left instanceof MultiConstraint && $left->conjunctive && $right instanceof MultiConstraint && $right->conjunctive && ($left0 = (string) $left->constraints[0]) && $left0[0] === '>' && $left0[1] === '=' && ($left1 = (string) $left->constraints[1]) && $left1[0] === '<' && ($right0 = (string) $right->constraints[0]) && $right0[0] === '>' && $right0[1] === '=' && ($right1 = (string) $right->constraints[1]) && $right1[0] === '<' && \substr($left1, 2) === \substr($right0, 3)) { $optimized = \true; $left = new MultiConstraint(\array_merge(array($left->constraints[0], $right->constraints[1]), \array_slice($left->constraints, 2), \array_slice($right->constraints, 2)), \true); } else { $mergedConstraints[] = $left; $left = $right; } } if ($optimized) { $mergedConstraints[] = $left; return array($mergedConstraints, \false); } } return null; } private function extractBounds() { if (null !== $this->lowerBound) { return; } foreach ($this->constraints as $constraint) { if (null === $this->lowerBound && null === $this->upperBound) { $this->lowerBound = $constraint->getLowerBound(); $this->upperBound = $constraint->getUpperBound(); continue; } if ($constraint->getLowerBound()->compareTo($this->lowerBound, $this->isConjunctive() ? '>' : '<')) { $this->lowerBound = $constraint->getLowerBound(); } if ($constraint->getUpperBound()->compareTo($this->upperBound, $this->isConjunctive() ? '<' : '>')) { $this->upperBound = $constraint->getUpperBound(); } } } } self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, '<=' => self::OP_LE, '>' => self::OP_GT, '>=' => self::OP_GE, '<>' => self::OP_NE, '!=' => self::OP_NE); /** @phpstan-var */ private static $transOpInt = array(self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', self::OP_GT => '>', self::OP_GE => '>=', self::OP_NE => '!='); /** @phpstan-var */ protected $operator; protected $version; protected $prettyString; protected $lowerBound; protected $upperBound; public function __construct($operator, $version) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $this->operator = self::$transOpStr[$operator]; $this->version = $version; } public function getVersion() { return $this->version; } public function getOperator() { return self::$transOpInt[$this->operator]; } public function matches(ConstraintInterface $provider) { if ($provider instanceof self) { return $this->matchSpecific($provider); } return $provider->matches($this); } public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } public static function getSupportedOperators() { return \array_keys(self::$transOpStr); } /** @phpstan-return */ public static function getOperatorConstant($operator) { return self::$transOpStr[$operator]; } public function versionCompare($a, $b, $operator, $compareBranches = \false) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $aIsBranch = 'dev-' === \substr($a, 0, 4); $bIsBranch = 'dev-' === \substr($b, 0, 4); if ($operator === '!=' && ($aIsBranch || $bIsBranch)) { return $a !== $b; } if ($aIsBranch && $bIsBranch) { return $operator === '==' && $a === $b; } if (!$compareBranches && ($aIsBranch || $bIsBranch)) { return \false; } return \version_compare($a, $b, $operator); } public function compile($otherOperator) { if ($this->version[0] === 'd' && 'dev-' === \substr($this->version, 0, 4)) { if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('$b && $v === %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return \sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } return 'false'; } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } return 'false'; } if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('\\version_compare($v, %s, \'==\')', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return \sprintf('$b || \\version_compare($v, %s, \'!=\')', \var_export($this->version, \true)); } return \sprintf('!$b && \\version_compare(%s, $v, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$otherOperator]); } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('$b || (!$b && \\version_compare($v, %s, \'!=\'))', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) { if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) { return '!$b'; } } elseif (self::OP_GT === $this->operator || self::OP_GE === $this->operator) { if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) { return '!$b'; } } if (self::OP_NE === $otherOperator) { return 'true'; } $codeComparison = \sprintf('\\version_compare($v, %s, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$this->operator]); if ($this->operator === self::OP_LE) { if ($otherOperator === self::OP_GT) { return \sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } elseif ($this->operator === self::OP_GE) { if ($otherOperator === self::OP_LT) { return \sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } return \sprintf('!$b && %s', $codeComparison); } public function matchSpecific(Constraint $provider, $compareBranches = \false) { $noEqualOp = \str_replace('=', '', self::$transOpInt[$this->operator]); $providerNoEqualOp = \str_replace('=', '', self::$transOpInt[$provider->operator]); $isEqualOp = self::OP_EQ === $this->operator; $isNonEqualOp = self::OP_NE === $this->operator; $isProviderEqualOp = self::OP_EQ === $provider->operator; $isProviderNonEqualOp = self::OP_NE === $provider->operator; if ($isNonEqualOp || $isProviderNonEqualOp) { if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && 'dev-' === \substr($provider->version, 0, 4)) { return \false; } if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && 'dev-' === \substr($this->version, 0, 4)) { return \false; } if (!$isEqualOp && !$isProviderEqualOp) { return \true; } return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); } if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) { if ('dev-' === \substr($this->version, 0, 4) || 'dev-' === \substr($provider->version, 0, 4)) { return \false; } return \true; } $version1 = $isEqualOp ? $this->version : $provider->version; $version2 = $isEqualOp ? $provider->version : $this->version; $operator = $isEqualOp ? $provider->operator : $this->operator; if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) { return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp && \version_compare($provider->version, $this->version, '==')); } return \false; } public function __toString() { return self::$transOpInt[$this->operator] . ' ' . $this->version; } public function getLowerBound() { $this->extractBounds(); return $this->lowerBound; } public function getUpperBound() { $this->extractBounds(); return $this->upperBound; } private function extractBounds() { if (null !== $this->lowerBound) { return; } if (\strpos($this->version, 'dev-') === 0) { $this->lowerBound = Bound::zero(); $this->upperBound = Bound::positiveInfinity(); return; } switch ($this->operator) { case self::OP_EQ: $this->lowerBound = new Bound($this->version, \true); $this->upperBound = new Bound($this->version, \true); break; case self::OP_LT: $this->lowerBound = Bound::zero(); $this->upperBound = new Bound($this->version, \false); break; case self::OP_LE: $this->lowerBound = Bound::zero(); $this->upperBound = new Bound($this->version, \true); break; case self::OP_GT: $this->lowerBound = new Bound($this->version, \false); $this->upperBound = Bound::positiveInfinity(); break; case self::OP_GE: $this->lowerBound = new Bound($this->version, \true); $this->upperBound = Bound::positiveInfinity(); break; case self::OP_NE: $this->lowerBound = Bound::zero(); $this->upperBound = Bound::positiveInfinity(); break; } } } &1', $output, $exitcode); return self::$stty = 0 === $exitcode; } private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { if (\preg_match('/^(\\d+)x(\\d+)(?: \\((\\d+)x(\\d+)\\))?$/', \trim(\getenv('ANSICON')), $matches)) { self::$width = (int) $matches[1]; self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { self::initDimensionsUsingStty(); } elseif (null !== ($dimensions = self::getConsoleMode())) { self::$width = (int) $dimensions[0]; self::$height = (int) $dimensions[1]; } } else { self::initDimensionsUsingStty(); } } private static function hasVt100Support() { return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support(\fopen('php://stdout', 'wb')); } private static function initDimensionsUsingStty() { if ($sttyString = self::getSttyColumns()) { if (\preg_match('/rows.(\\d+);.columns.(\\d+);/i', $sttyString, $matches)) { self::$width = (int) $matches[2]; self::$height = (int) $matches[1]; } elseif (\preg_match('/;.(\\d+).rows;.(\\d+).columns/i', $sttyString, $matches)) { self::$width = (int) $matches[2]; self::$height = (int) $matches[1]; } } } private static function getConsoleMode() { $info = self::readFromProcess('mode CON'); if (null === $info || !\preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) { return null; } return array((int) $matches[2], (int) $matches[1]); } private static function getSttyColumns() { return self::readFromProcess('stty -a | grep columns'); } private static function readFromProcess($command) { if (!\function_exists('proc_open')) { return null; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = \proc_open($command, $descriptorspec, $pipes, null, null, array('suppress_errors' => \true)); if (!\is_resource($process)) { return null; } $info = \stream_get_contents($pipes[1]); \fclose($pipes[1]); \fclose($pipes[2]); \proc_close($process); return $info; } } options = \implode(' ', $_SERVER['argv']); $shellVerbosity = $this->configureVerbosity(); $this->interactive = $this->checkInteractivity($shellVerbosity); $this->colorSupport = $this->checkColorSupport(); } public function isInteractive() { return $this->interactive; } public function getVerbosity() { return $this->verbosity; } public function hasColorSupport() { return $this->colorSupport; } public function hasParameter($values) { $values = (array) $values; foreach ($values as $value) { $regexp = \sprintf('/\\s%s\\b/', \str_replace(' ', '\\s+', \preg_quote($value, '/'))); if (1 === \preg_match($regexp, $this->options)) { return \true; } } return \false; } private function checkInteractivity($shellVerbosity) { if (-1 === $shellVerbosity) { return \false; } if (\true === $this->hasParameter(array('--no-interaction', '-n'))) { return \false; } if (\function_exists('posix_isatty') && !@\posix_isatty(\STDOUT) && \false === \getenv('SHELL_INTERACTIVE')) { return \false; } return \true; } private function configureVerbosity() { switch ($shellVerbosity = (int) \getenv('SHELL_VERBOSITY')) { case -1: $this->verbosity = self::VERBOSITY_QUIET; break; case 1: $this->verbosity = self::VERBOSITY_VERBOSE; break; case 2: $this->verbosity = self::VERBOSITY_VERY_VERBOSE; break; case 3: $this->verbosity = self::VERBOSITY_DEBUG; break; default: $shellVerbosity = 0; break; } if ($this->hasParameter(array('--quiet', '-q'))) { $this->verbosity = self::VERBOSITY_QUIET; $shellVerbosity = -1; } elseif ($this->hasParameter(array('-vvv', '--verbose=3', '--verbose 3'))) { $this->verbosity = self::VERBOSITY_DEBUG; $shellVerbosity = 3; } elseif ($this->hasParameter(array('-vv', '--verbose=2', '--verbose 2'))) { $this->verbosity = self::VERBOSITY_VERY_VERBOSE; $shellVerbosity = 2; } elseif ($this->hasParameter(array('-v', '--verbose=1', '--verbose 1', '--verbose'))) { $this->verbosity = self::VERBOSITY_VERBOSE; $shellVerbosity = 1; } return $shellVerbosity; } private function checkColorSupport() { if ($this->hasParameter(array('--ansi'))) { return \true; } if ($this->hasParameter(array('--no-ansi'))) { return \false; } if (\DIRECTORY_SEPARATOR === '\\') { return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support(\STDOUT) || \false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM'); } if (\function_exists('stream_isatty')) { return \stream_isatty(\STDOUT); } if (\function_exists('posix_isatty')) { return \posix_isatty(\STDOUT); } $stat = \fstat(\STDOUT); return $stat ? 020000 === ($stat['mode'] & 0170000) : \false; } } requiredExtension = $requiredExtension; } public function __invoke() { return \extension_loaded($this->requiredExtension); } } evaluateRequirements(); $io = new IO(); self::printCheck($checkPassed, new Printer($io->getVerbosity(), $io->hasColorSupport()), $requirements); return $checkPassed; } public static function printCheck($checkPassed, Printer $printer, RequirementCollection $requirements) { if (\false === $checkPassed && IO::VERBOSITY_VERY_VERBOSE > $printer->getVerbosity()) { $printer->setVerbosity(IO::VERBOSITY_VERY_VERBOSE); } $verbosity = IO::VERBOSITY_VERY_VERBOSE; $iniPath = $requirements->getPhpIniPath(); $printer->title('Box Requirements Checker', $verbosity); $printer->printv('> Using PHP ', $verbosity); $printer->printvln(\PHP_VERSION, $verbosity, 'green'); $printer->printvln('> PHP is using the following php.ini file:', $verbosity); if ($iniPath) { $printer->printvln(' ' . $iniPath, $verbosity, 'green'); } else { $printer->printvln(' WARNING: No configuration file (php.ini) used by PHP!', $verbosity, 'yellow'); } $printer->printvln('', $verbosity); if (\count($requirements) > 0) { $printer->printvln('> Checking Box requirements:', $verbosity); $printer->printv(' ', $verbosity); } else { $printer->printvln('> No requirements found.', $verbosity); } $errorMessages = array(); foreach ($requirements->getRequirements() as $requirement) { if ($errorMessage = $printer->getRequirementErrorMessage($requirement)) { if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { $printer->printvln('✘ ' . $requirement->getTestMessage(), IO::VERBOSITY_DEBUG, 'red'); $printer->printv(' ', IO::VERBOSITY_DEBUG); $errorMessages[] = $errorMessage; } else { $printer->printv('E', $verbosity, 'red'); $errorMessages[] = $errorMessage; } continue; } if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { $printer->printvln('✔ ' . $requirement->getHelpText(), IO::VERBOSITY_DEBUG, 'green'); $printer->printv(' ', IO::VERBOSITY_DEBUG); } else { $printer->printv('.', $verbosity, 'green'); } } if (IO::VERBOSITY_DEBUG !== $printer->getVerbosity() && \count($requirements) > 0) { $printer->printvln('', $verbosity); } if ($requirements->evaluateRequirements()) { $printer->block('OK', 'Your system is ready to run the application.', $verbosity, 'success'); } else { $printer->block('ERROR', 'Your system is not ready to run the application.', $verbosity, 'error'); $printer->title('Fix the following mandatory requirements:', $verbosity, 'red'); foreach ($errorMessages as $errorMessage) { $printer->printv(' * ' . $errorMessage, $verbosity); } } $printer->printvln('', $verbosity); } private static function retrieveRequirements() { if (null === self::$requirementsConfig) { self::$requirementsConfig = __DIR__ . '/../.requirements.php'; } $config = (require self::$requirementsConfig); $requirements = new RequirementCollection(); foreach ($config as $constraint) { $requirements->addRequirement('php' === $constraint['type'] ? new IsPhpVersionFulfilled($constraint['condition']) : new IsExtensionFulfilled($constraint['condition']), $constraint['message'], $constraint['helpMessage']); } return $requirements; } } requiredPhpVersion = $requiredPhpVersion; } public function __invoke() { return Semver::satisfies(\sprintf('%d.%d.%d', \PHP_MAJOR_VERSION, \PHP_MINOR_VERSION, \PHP_RELEASE_VERSION), $this->requiredPhpVersion); } } requirements); } #[\ReturnTypeWillChange] public function count() { return \count($this->requirements); } public function add(Requirement $requirement) { $this->requirements[] = $requirement; } public function addRequirement($checkIsFulfilled, $testMessage, $helpText) { $this->add(new Requirement($checkIsFulfilled, $testMessage, $helpText)); } public function getRequirements() { return $this->requirements; } public function getPhpIniPath() { return \get_cfg_var('cfg_file_path'); } public function evaluateRequirements() { return \array_reduce($this->requirements, function ($checkPassed, Requirement $requirement) { return $checkPassed && $requirement->isFulfilled(); }, \true); } } "\x1b[0m", 'red' => "\x1b[31m", 'green' => "\x1b[32m", 'yellow' => "\x1b[33m", 'title' => "\x1b[33m", 'error' => "\x1b[37;41m", 'success' => "\x1b[30;42m"); private $verbosity; private $supportColors; private $width; public function __construct($verbosity, $supportColors, $width = null) { if (null === $width) { $terminal = new Terminal(); $width = $terminal->getWidth(); } $this->verbosity = $verbosity; $this->supportColors = $supportColors; $this->width = $width ?: 80; } public function getVerbosity() { return $this->verbosity; } public function setVerbosity($verbosity) { $this->verbosity = $verbosity; } public function title($title, $verbosity, $style = null) { if (null === $style) { $style = 'title'; } $this->printvln('', $verbosity, $style); $this->printvln($title, $verbosity, $style); $this->printvln(\str_repeat('=', \min(\strlen($title), $this->width)), $verbosity, $style); $this->printvln('', $verbosity, $style); } public function getRequirementErrorMessage(Requirement $requirement) { if ($requirement->isFulfilled()) { return null; } $errorMessage = \wordwrap($requirement->getTestMessage(), $this->width - 3, \PHP_EOL . ' ') . \PHP_EOL; return $errorMessage; } public function block($title, $message, $verbosity, $style = null) { $prefix = ' [' . $title . '] '; $lineLength = $this->width - \strlen($prefix) - 1; if ($lineLength < 0) { $lineLength = 0; } $message = $prefix . \trim($message); $lines = array(); $remainingMessage = $message; $wrapped = \wordwrap($remainingMessage, $lineLength, '¬'); $wrapped = \explode('¬', $wrapped); do { $line = \array_shift($wrapped); if ($lines && $lineLength > 0) { $line = \str_repeat(' ', \strlen($prefix)) . \ltrim($line); } $lines[] = \str_pad($line, $this->width, ' ', \STR_PAD_RIGHT); } while (\count($wrapped)); $this->printvln('', $verbosity); $this->printvln(\str_repeat(' ', $this->width), $verbosity, $style); foreach ($lines as $line) { $this->printvln($line, $verbosity, $style); } $this->printv(\str_repeat(' ', $this->width), $verbosity, $style); $this->printvln('', $verbosity); } public function printvln($message, $verbosity, $style = null) { $this->printv($message, $verbosity, $style); $this->printv(\PHP_EOL, $verbosity, null); } public function printv($message, $verbosity, $style = null) { if ($verbosity > $this->verbosity) { return; } $message = \wordwrap($message, $this->width); $message = \sprintf('%s%s%s', $this->supportColors && isset($this->styles[$style]) ? $this->styles[$style] : '', $message, $this->supportColors ? $this->styles['reset'] : ''); echo $message; } } checkIsFulfilled = $checkIsFulfilled; $this->testMessage = $testMessage; $this->helpText = $helpText; } public function isFulfilled() { if (null === $this->fulfilled) { $this->fulfilled = $this->checkIsFulfilled->__invoke(); } return (bool) $this->fulfilled; } public function getIsFullfilledChecker() { return $this->checkIsFulfilled; } public function getTestMessage() { return $this->testMessage; } public function getHelpText() { return $this->helpText; } } GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. Contao Managerhandle($request); $response->send(); $kernel->terminate($request, $response); } catch (Throwable $throwable) { ApiProblemResponse::createFromException($throwable, '@symfony_env@' !== 'prod')->send(); } .widget-radio-button legend{margin-bottom:2px}.widget-radio-button>div{position:relative;margin:.25em 0}.widget-radio-button input{position:absolute;visibility:hidden}.widget-radio-button label{display:block;padding-left:25px;background:url(../img/widget-radio--off.4e93f443.svg) 0 -1px no-repeat;background-size:20px 20px}.widget-radio-button input:checked+label{background-image:url(../img/widget-radio--on.181461b6.svg)}.widget-radio-button input:disabled+label{opacity:.5}.setup__directories{margin-top:2em}.setup__directories>dt{margin-top:1em;font-weight:600}.setup__directories>dd{margin:0;word-break:break-all}.setup__directories>dd span{background-color:var(--highlight-bg);color:var(--highlight-color);font-weight:400}.link-more{position:relative;display:inline-block}p:empty+.link-more{margin-left:0}.link-more button{width:auto;height:auto;padding:0 0 5px;background:transparent;color:var(--link);font-size:13px;font-weight:300;line-height:inherit;border:none;cursor:pointer}.link-more button:hover{text-decoration:underline}.link-more__menu{outline:none}.link-more ul{transform:translateX(-50%)}.package-link{display:flex;-moz-column-gap:8px;column-gap:8px;justify-content:space-between;width:100%;padding-bottom:4px;margin-bottom:4px;border-bottom:1px solid var(--border--light)}.package-link:last-child{padding-bottom:0;margin-bottom:0;border-bottom:none}.package-link__details{padding:5px 0;line-height:18px}.package-link__name{display:inline;font-weight:600}.package-link__name:after{content:": "}.package-link__text{display:inline}.package-link__actions{display:flex;margin-left:20px;margin:0 -4px}.package-link__actions>*{margin:0 4px}.package-link--limit .package-link__details{display:flex}.package-link--limit .package-link__name{white-space:nowrap}.package-link--limit .package-link__text{display:-webkit-box;overflow:hidden;line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical;padding:0 10px 0 5px}.package-funding[data-v-5a8fd14b]{padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--funding-rgb),.025) url(../img/funding.cf78a0a0.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid rgba(var(--funding-rgb),.5);border-radius:6px}.package-funding>div[data-v-5a8fd14b]{overflow:hidden}.package-funding span[data-v-5a8fd14b]{margin-right:15px}.package-funding a[data-v-5a8fd14b]{position:relative;display:inline-block;margin:0 20px 0 0;padding-left:16px;color:var(--funding);background:url(../img/link-funding.b25cd92d.svg) 0 50% no-repeat;background-size:13px 13px}.package-funding a[data-v-5a8fd14b]:before{content:"|";position:absolute;left:-12px}.package-funding a[data-v-5a8fd14b]:nth-child(2):before{content:none}.package-popup{position:fixed;display:flex;flex-direction:column;justify-content:flex-start;width:100%;max-width:none;height:100%;background:var(--popup-bg);z-index:10;opacity:1}.package-popup>*{flex-basis:auto;flex-grow:1}.package-popup__loader{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:50px 0}.package-popup__loader p{margin:1em}.package-popup__headline{position:relative;flex-grow:0;flex-shrink:1;padding:7px 30px 6px;background:var(--popup-hl-bg);color:#fff;font-size:18px;font-weight:300;line-height:1.5;text-align:center}.package-popup__button{display:block;float:right;position:absolute;top:0;margin:4px 0;padding:4px;background:none;border:1px solid transparent;border-radius:5px;cursor:pointer}.package-popup__button--previous{left:4px}.package-popup__button--close{right:4px}.package-popup__button svg{display:block;width:22px;height:22px}.package-popup__button:hover{background-color:#db6f00}.package-popup__summary{flex-grow:0;padding:25px 35px}@media(min-width:600px){.package-popup__summary{display:flex}}.package-popup__logo{border-radius:6px;float:right;height:60px;width:60px;margin-left:1em;background:#f7f7f7}@media(min-width:600px){.package-popup__logo{display:block;float:left;width:110px;height:110px;margin:-10px 16px 0 -10px}}.package-popup__icon{display:flex;align-items:center;justify-content:center;height:100%}.package-popup__icon--fallback{display:none}.package-popup__icon img{width:50px;height:50px;max-height:100%;-o-object-fit:contain;object-fit:contain}@media(min-width:600px){.package-popup__icon img{width:90px;height:90px}}.package-popup__text{display:flex;flex-direction:column;flex-grow:1}@media(min-width:600px){.package-popup__text{width:200px}}.package-popup__title{margin:0;line-height:1.4;overflow-wrap:break-word}.package-popup__authors{flex-grow:1;font-size:13px;margin-bottom:.5em}.package-popup__author{display:inline-block;margin-right:2px}.package-popup__author:after{color:var(--text);content:", "}.package-popup__author:last-child:after{content:none}.package-popup__stats{display:inline-block;margin-right:15px;margin-top:.5em;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.package-popup__stats--private{padding-left:20px;background-image:var(--svg--private);background-size:15px 15px}.package-popup__stats--updated{background-image:var(--svg--updated)}.package-popup__stats--downloads{background-image:var(--svg--downloads)}.package-popup__stats--favers{background-image:var(--svg--favers)}.package-popup__actions{display:flex;flex-direction:column;gap:10px;margin-top:1em}@media(min-width:600px){.package-popup__actions{justify-content:space-between;margin:0 0 0 25px;width:200px}}.package-popup__installed{margin-top:1em}.package-popup__abandoned{margin:0 0 20px;padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--hint-rgb),.3) url(../img/hint.ba2ac97e.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid var(--hint-link);border-radius:6px}.package-popup__funding{margin:0 0 20px}.package-popup__tabs{position:relative;flex-grow:revert}.package-popup__tabs:after,.package-popup__tabs:before{content:"";display:block;position:absolute;top:0;bottom:1px;width:7px;background:linear-gradient(-90deg,transparent 0,var(--popup-bg) 50%);z-index:1;pointer-events:none}.package-popup__tabs:after{background:linear-gradient(90deg,transparent 0,var(--popup-bg) 50%);right:0}.package-popup__tabs-list{flex-shrink:0;flex-grow:0;display:flex;-moz-column-gap:4px;column-gap:4px;height:40px;min-width:100%;overflow-x:auto;scrollbar-width:none;overflow-y:hidden;margin:0;padding:0 7px;list-style-type:none}.package-popup__tabs-list:after{content:"";position:absolute;inset:auto 0 0;height:1px;background:var(--border--light);z-index:-1}.package-popup__tab{position:relative;top:1px;flex-grow:1;padding:0;height:39px;line-height:39px;text-align:center;border:1px solid var(--border--light);border-top-left-radius:6px;border-top-right-radius:6px}.package-popup__tab--active{background:var(--tab-content);border-bottom:1px solid var(--tab-content)}.package-popup__tab button{display:flex;justify-content:center;align-items:center;width:100%;height:100%;margin:0;padding:0 10px;border:none;background:transparent;cursor:pointer;outline:none}.package-popup__tab button:disabled{color:var(--border)!important;cursor:not-allowed}.package-popup__pill{position:relative;top:-2px;display:inline-block;margin-left:5px;padding:2px 5px;font-size:10px;font-weight:400;background:var(--border--light);border-radius:40%}.package-popup__pill--highlight{color:var(--clr-btn);background:var(--btn-primary)}.package-popup__tabcontent{position:relative;padding:25px 35px;overflow-y:auto;background:var(--tab-content)}@media(min-width:960px)and (min-height:700px){.package-popup__tabcontent{height:450px}}.package-popup__description{margin:1em 0;white-space:pre-wrap}@media(min-width:960px){.package-popup{position:relative;display:block;top:0;left:50%;width:750px;margin-left:-375px;height:auto;border-radius:8px}.package-popup__headline{border-radius:8px 8px 0 0}.package-popup__tabcontent{border-radius:0 0 8px 8px}}@media(min-width:960px)and (min-height:700px){.package-popup{position:absolute;top:50%;transform:translateY(-50%)}}.package-popup__installed strong{margin-right:5px}@media(min-width:600px){.package-popup__installed{display:flex;flex-direction:column;justify-content:flex-end;text-align:center}.package-popup__installed strong{display:block;margin:0}}.package-popup__update{background:var(--btn-primary) url(../img/button-update.ad79c617.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__incompatible,.package-popup__update{margin:0 0 20px;padding:10px 20px 10px 50px;color:var(--clr-btn);border-radius:var(--border-radius)}.package-popup__incompatible{background:var(--contao) url(../img/button-incompatible.3eb2b686.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__funding+.package-popup__update{margin-top:-10px}.theme-details__constraint{flex-grow:1}.file-tree{margin:0;padding:0;list-style:none}.file-tree__folder{position:relative;padding-left:20px}.file-tree__folder:before{content:"";position:absolute;left:10px;top:6px;width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid var(--text);transition:transform .1s ease-in-out}.file-tree__folder--open:before{transform:rotate(90deg)}.file-tree__file{padding-left:20px}.file-tree button{background:none;border:none;font-weight:400;cursor:pointer}.setup__versions{margin:0;padding:0 0 0 15px}.setup__version{margin:.5em 0;text-align:left}.setup__version--warning{color:var(--btn-alert)}.setup__releaseplan{margin-top:1.5em}.setup__fielddesc--version{margin-bottom:-1em!important}.setup__core-features{margin:5px 0 0 5px;font-size:12px}.setup__theme-image{max-width:100%;height:auto;border:1px solid var(--border)}.setup__theme p{margin:1em 0}.setup__theme-upload{position:absolute!important;visibility:hidden}.setup__themes{padding:0 14px}.setup__themes-results{display:grid;gap:14px}@media(min-width:1024px){.setup__themes-results{grid-template-columns:repeat(2,1fr)}.setup__themes-results-item{flex-basis:calc(50% - 16px);margin-left:8px;margin-right:8px}}.setup__themes-item{border:1px solid var(--tiles-bdr)}.setup__themes-more{margin-top:20px;text-align:center}.setup__theme-search{margin:20px 0 0;text-align:center}.setup__theme-search--empty{padding-top:60px;background:url(../img/sad.c7de6e95.svg) top no-repeat;background-size:50px 50px}.setup__theme-search--offline{padding-top:60px;background:url(../img/offline.0c23d1ce.svg) top no-repeat;background-size:50px 50px}.setup__theme-search--loader .sk-circle{width:50px;height:50px;margin:0 auto 20px}.setup__theme-search button{margin-top:2em}.setup__fielddesc--warning{padding:10px 10px 10px 40px;background:var(--hint-bg) url(../img/hint.ba2ac97e.svg) 10px 10px no-repeat}.setup__tabs{margin:1em 0}.setup__tab-controls{display:flex}.setup__tab-control{flex-grow:1;padding:4px 10px;border:none;border-top:1px solid var(--border);border-left:1px solid var(--border);background:none;cursor:pointer}.setup__tab-control:last-child{border-right:1px solid var(--border)}.setup__tab-control--active{border-color:var(--btn);background:var(--btn);color:#fff}.setup__tab{border:1px solid var(--border)}.setup__tab--files{white-space:pre;overflow:scroll;height:200px}.setup__requires{width:100%;border-collapse:collapse}.setup__requires td,.setup__requires th{margin:0;padding:3px 10px;text-align:start;vertical-align:top}.setup__requires th{background:var(--btn);color:#fff}.setup__requires td{border-bottom:1px solid var(--border)}.setup__requires tr:last-child td{border-bottom:none}.setup__requires tr:nth-child(odd) td{background:var(--table-odd-bg)}.setup__or{position:relative;overflow:hidden;margin:1em 0;text-align:center}.setup__or:before{content:"";position:absolute;top:.8em;left:0;right:0;display:block;height:1px;background:var(--border);z-index:1}.setup__or span{position:relative;padding:0 10px;background:var(--popup-bg);z-index:2}.view-setup{padding-top:40px}.view-setup footer{margin-top:40px}.view-setup__steps{padding:0 0 50px 0}.view-setup__steps ul{display:flex;margin:0;padding:0;list-style-type:none}.view-setup__steps li{display:flex;justify-content:center;align-items:center;flex-grow:1;position:relative;height:6px;margin:0;padding:0}.view-setup__steps li:before{content:"";position:absolute;left:-50%;right:50%;background:var(--border);height:5px}.view-setup__steps li:after{content:"";position:absolute;top:-18px;left:50%;margin-left:-21px;width:42px;height:42px;color:#fff;text-indent:0;text-align:center;line-height:35px;background:var(--border);border-radius:50%;z-index:1}.view-setup__steps li:first-child:before{content:none}.view-setup__steps li.active:after,.view-setup__steps li.active:before{background:var(--contao)}.view-setup__steps button{display:flex;justify-content:center;align-items:center;background:transparent;border:none;z-index:10;cursor:pointer}.view-setup__steps button:disabled{cursor:default}.view-setup__steps svg{fill:#fff}.view-setup__main{text-align:center}.view-setup__party{font-size:64px}.view-setup__headline{margin:10px 0 20px;padding:15px 0;font-size:42px;font-weight:100}.view-setup__description{max-width:500px;margin:1em 25px}.view-setup__start.widget-button{height:50px;margin:30px 10px 0;padding:0 50px;font-size:1.2em;line-height:50px}.view-setup__continue.widget-button{width:80%!important;margin:10px 0 0}.view-setup__funding{width:80%;margin:50px auto 0;padding:20px 25px;border:2px solid var(--funding);border-radius:var(--border-radius);background:rgba(var(--funding-rgb),.025);font-weight:400}.view-setup__funding figure{margin-bottom:1em}.view-setup__funding p{margin:0 0 .5em 0}.view-setup__funding-link{margin:1em 0 0}@media(min-width:960px){.view-setup{padding-top:80px}.view-setup footer{margin-top:80px}.view-setup__steps{padding-bottom:80px}.view-setup__headline{margin:20px 0 40px;font-size:64px}.view-setup__continue.widget-button{width:auto!important;margin:25px 10px 0;padding:0 20px}.view-setup__description{max-width:550px;margin:1em auto;font-size:1.2em}.view-setup__funding{display:flex;margin:60px auto -20px;text-align:left}.view-setup__funding figure{margin-right:25px}}.setup__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.setup__header .widget-button{margin-top:1em}.setup__icon{background:var(--contao);border-radius:10px;padding:10px}.setup__headline{margin-top:20px;margin-bottom:25px;font-size:36px;font-weight:100;line-height:1}.setup__description,.setup__warning{margin:1em 0;text-align:justify}.setup__warning{color:var(--btn-alert);font-weight:600}.setup__form{position:relative;max-width:280px;margin:0 auto 50px;opacity:1}.setup__form svg.setup__check{display:block;width:80px;height:80px;margin:0 auto 2em;fill:var(--btn-primary)}.setup__form .widget-select,.setup__form .widget-text{margin-top:10px}.setup__form .widget-select label,.setup__form .widget-text label{display:block;margin-bottom:5px;font-weight:400}.setup__form .widget-checkbox{margin-top:20px;font-weight:400}.setup__form .widget-radio-button{margin-top:20px}.setup__fields{margin-bottom:2em}.setup__fields--center{text-align:center}.setup__fields .button-group .widget-button{margin-bottom:1px}.setup__fieldtitle{margin-bottom:.5em;font-size:18px;font-weight:600;line-height:30px}.setup__fielddesc{margin-bottom:1em;text-align:left}.setup__fielddesc code{word-break:break-word}.setup__actions{display:flex;flex-wrap:wrap;gap:10px}.setup__actions--center{justify-content:center}.setup__actions .button-group,.setup__actions .widget-button{flex-grow:1}.setup__actions .button-group--inline,.setup__actions .widget-button--inline{flex-grow:0}@media(min-width:960px){.setup{padding-top:100px}.setup__header{float:left;width:470px;max-width:none;padding:0 60px 50px}.setup__form{float:left;width:370px;max-width:none;margin:0 50px 50px}.setup__form .widget-select label,.setup__form .widget-text label{display:block;float:left;width:120px;padding-top:10px;font-weight:400}.setup__form .widget-select input,.setup__form .widget-select select,.setup__form .widget-text input,.setup__form .widget-text select{width:250px!important}}.view-account__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.view-account__product{margin-top:15px;margin-bottom:40px;font-weight:600}.view-account__product strong{display:block;margin-bottom:10px;font-size:54px;font-weight:100;line-height:1}.view-account__headline{margin-bottom:.5em;font-size:18px;font-weight:600;line-height:30px}.view-account__description{margin-bottom:1em;text-align:justify}.view-account__form,.view-account__totp{position:relative;max-width:280px;margin:0 auto}.view-account__form .widget-button,.view-account__totp .widget-button{margin-top:1.5em}.view-account__form .widget-text{margin-top:10px}.view-account__form .widget-text label{display:block;padding-bottom:5px}.view-account__contribute{max-width:280px;margin:60px auto 0;font-size:12px;text-align:center}.view-account__contribute br{display:none}@media(min-width:960px){.view-account{display:flex;flex-flow:row wrap;align-items:center;padding-top:50px}.view-account__form,.view-account__header,.view-account__totp{padding:50px;width:50%;max-width:none}.view-account__form .widget-text label{float:left;width:120px;padding-top:10px;font-weight:400}.view-account__form input[type=password],.view-account__form input[type=text],.view-account__form select{width:250px!important}.view-account__form .button-group,.view-account__form .widget-button--anchor{width:250px;margin-left:120px}.view-account__contribute{max-width:840px}.view-account__contribute br{display:block}}.boot-check{padding:10px}.boot-check:after{display:table;clear:both;content:""}.boot-check__icon{float:left}.boot-check__icon .sk-circle{width:34px;height:34px;margin:3px}.boot-check__icon svg{display:block;width:40px;height:40px}.boot-check__icon--success svg{fill:var(--btn-primary)}.boot-check__icon--info svg,.boot-check__icon--warning svg{fill:var(--btn-warning)}.boot-check__icon--error svg{fill:var(--btn-alert)}.boot-check__label{margin-left:50px}.boot-check__description,.boot-check__detail,.boot-check__title{margin:0;line-height:inherit;overflow:hidden;text-overflow:ellipsis}.boot-check__detail{margin-top:5px;font-size:12px}.boot-check__action{margin-left:50px}.boot-check__action button{margin:15px 0 10px;height:33px;line-height:33px}@media(min-width:960px){.boot-check__label{float:left;width:540px;margin-left:10px}.boot-check__action{float:right;margin:0 0 0 10px;width:140px;text-align:center}.boot-check__action button{margin:3px 0}.boot-check__action a[target=_blank]{display:inline-block;margin:10px 0;padding-left:20px;background:var(--svg--link-blank) left center no-repeat;background-size:16px 16px}}.view-boot__header{margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.view-boot__icon{background:var(--contao);border-radius:10px;padding:10px}.view-boot__headline{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-boot__description{margin:0;font-weight:600}.view-boot__loading{width:30px;margin:0 auto 40px}.view-boot__loading .sk-circle{width:30px;height:30px}.view-boot__checks{margin:0 16px 50px}.view-boot__checks .boot-check:nth-child(odd){border-radius:var(--border-radius);background:var(--table-odd-bg)}.view-boot__summary{margin:50px 0 0}.view-boot__summary--error svg{width:100%;height:40px;fill:var(--btn-alert)}.view-boot__issue{max-width:60%;margin:10px auto;text-align:center;color:var(--btn-alert);line-height:1.2em}.view-boot__safeMode{margin:2em auto 0}.view-boot__continue,.view-boot__safeMode{clear:both;display:block!important;width:220px!important}.view-boot__continue{margin:0 auto}@media(min-width:960px){.view-boot__checks{margin:0 80px 50px}}.link-more{position:relative;display:inline-block}p:empty+.link-more{margin-left:0}.link-more button{width:auto;height:auto;padding:0 0 5px;background:transparent;color:var(--link);font-size:13px;font-weight:300;line-height:inherit;border:none;cursor:pointer}.link-more button:hover{text-decoration:underline}.link-more__menu{outline:none}.link-more ul{transform:translateX(-50%)}.package-link{display:flex;-moz-column-gap:8px;column-gap:8px;justify-content:space-between;width:100%;padding-bottom:4px;margin-bottom:4px;border-bottom:1px solid var(--border--light)}.package-link:last-child{padding-bottom:0;margin-bottom:0;border-bottom:none}.package-link__details{padding:5px 0;line-height:18px}.package-link__name{display:inline;font-weight:600}.package-link__name:after{content:": "}.package-link__text{display:inline}.package-link__actions{display:flex;margin-left:20px;margin:0 -4px}.package-link__actions>*{margin:0 4px}.package-link--limit .package-link__details{display:flex}.package-link--limit .package-link__name{white-space:nowrap}.package-link--limit .package-link__text{display:-webkit-box;overflow:hidden;line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical;padding:0 10px 0 5px}.package-funding[data-v-5a8fd14b]{padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--funding-rgb),.025) url(../img/funding.cf78a0a0.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid rgba(var(--funding-rgb),.5);border-radius:6px}.package-funding>div[data-v-5a8fd14b]{overflow:hidden}.package-funding span[data-v-5a8fd14b]{margin-right:15px}.package-funding a[data-v-5a8fd14b]{position:relative;display:inline-block;margin:0 20px 0 0;padding-left:16px;color:var(--funding);background:url(../img/link-funding.b25cd92d.svg) 0 50% no-repeat;background-size:13px 13px}.package-funding a[data-v-5a8fd14b]:before{content:"|";position:absolute;left:-12px}.package-funding a[data-v-5a8fd14b]:nth-child(2):before{content:none}.package-popup{position:fixed;display:flex;flex-direction:column;justify-content:flex-start;width:100%;max-width:none;height:100%;background:var(--popup-bg);z-index:10;opacity:1}.package-popup>*{flex-basis:auto;flex-grow:1}.package-popup__loader{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:50px 0}.package-popup__loader p{margin:1em}.package-popup__headline{position:relative;flex-grow:0;flex-shrink:1;padding:7px 30px 6px;background:var(--popup-hl-bg);color:#fff;font-size:18px;font-weight:300;line-height:1.5;text-align:center}.package-popup__button{display:block;float:right;position:absolute;top:0;margin:4px 0;padding:4px;background:none;border:1px solid transparent;border-radius:5px;cursor:pointer}.package-popup__button--previous{left:4px}.package-popup__button--close{right:4px}.package-popup__button svg{display:block;width:22px;height:22px}.package-popup__button:hover{background-color:#db6f00}.package-popup__summary{flex-grow:0;padding:25px 35px}@media(min-width:600px){.package-popup__summary{display:flex}}.package-popup__logo{border-radius:6px;float:right;height:60px;width:60px;margin-left:1em;background:#f7f7f7}@media(min-width:600px){.package-popup__logo{display:block;float:left;width:110px;height:110px;margin:-10px 16px 0 -10px}}.package-popup__icon{display:flex;align-items:center;justify-content:center;height:100%}.package-popup__icon--fallback{display:none}.package-popup__icon img{width:50px;height:50px;max-height:100%;-o-object-fit:contain;object-fit:contain}@media(min-width:600px){.package-popup__icon img{width:90px;height:90px}}.package-popup__text{display:flex;flex-direction:column;flex-grow:1}@media(min-width:600px){.package-popup__text{width:200px}}.package-popup__title{margin:0;line-height:1.4;overflow-wrap:break-word}.package-popup__authors{flex-grow:1;font-size:13px;margin-bottom:.5em}.package-popup__author{display:inline-block;margin-right:2px}.package-popup__author:after{color:var(--text);content:", "}.package-popup__author:last-child:after{content:none}.package-popup__stats{display:inline-block;margin-right:15px;margin-top:.5em;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.package-popup__stats--private{padding-left:20px;background-image:var(--svg--private);background-size:15px 15px}.package-popup__stats--updated{background-image:var(--svg--updated)}.package-popup__stats--downloads{background-image:var(--svg--downloads)}.package-popup__stats--favers{background-image:var(--svg--favers)}.package-popup__actions{display:flex;flex-direction:column;gap:10px;margin-top:1em}@media(min-width:600px){.package-popup__actions{justify-content:space-between;margin:0 0 0 25px;width:200px}}.package-popup__installed{margin-top:1em}.package-popup__abandoned{margin:0 0 20px;padding:10px 20px 10px 50px;font-weight:400;font-size:12px;line-height:1.8;background:rgba(var(--hint-rgb),.3) url(../img/hint.ba2ac97e.svg) 15px 50% no-repeat;background-size:23px 23px;border:1px solid var(--hint-link);border-radius:6px}.package-popup__funding{margin:0 0 20px}.package-popup__tabs{position:relative;flex-grow:revert}.package-popup__tabs:after,.package-popup__tabs:before{content:"";display:block;position:absolute;top:0;bottom:1px;width:7px;background:linear-gradient(-90deg,transparent 0,var(--popup-bg) 50%);z-index:1;pointer-events:none}.package-popup__tabs:after{background:linear-gradient(90deg,transparent 0,var(--popup-bg) 50%);right:0}.package-popup__tabs-list{flex-shrink:0;flex-grow:0;display:flex;-moz-column-gap:4px;column-gap:4px;height:40px;min-width:100%;overflow-x:auto;scrollbar-width:none;overflow-y:hidden;margin:0;padding:0 7px;list-style-type:none}.package-popup__tabs-list:after{content:"";position:absolute;inset:auto 0 0;height:1px;background:var(--border--light);z-index:-1}.package-popup__tab{position:relative;top:1px;flex-grow:1;padding:0;height:39px;line-height:39px;text-align:center;border:1px solid var(--border--light);border-top-left-radius:6px;border-top-right-radius:6px}.package-popup__tab--active{background:var(--tab-content);border-bottom:1px solid var(--tab-content)}.package-popup__tab button{display:flex;justify-content:center;align-items:center;width:100%;height:100%;margin:0;padding:0 10px;border:none;background:transparent;cursor:pointer;outline:none}.package-popup__tab button:disabled{color:var(--border)!important;cursor:not-allowed}.package-popup__pill{position:relative;top:-2px;display:inline-block;margin-left:5px;padding:2px 5px;font-size:10px;font-weight:400;background:var(--border--light);border-radius:40%}.package-popup__pill--highlight{color:var(--clr-btn);background:var(--btn-primary)}.package-popup__tabcontent{position:relative;padding:25px 35px;overflow-y:auto;background:var(--tab-content)}@media(min-width:960px)and (min-height:700px){.package-popup__tabcontent{height:450px}}.package-popup__description{margin:1em 0;white-space:pre-wrap}@media(min-width:960px){.package-popup{position:relative;display:block;top:0;left:50%;width:750px;margin-left:-375px;height:auto;border-radius:8px}.package-popup__headline{border-radius:8px 8px 0 0}.package-popup__tabcontent{border-radius:0 0 8px 8px}}@media(min-width:960px)and (min-height:700px){.package-popup{position:absolute;top:50%;transform:translateY(-50%)}}.package-popup__installed strong{margin-right:5px}@media(min-width:600px){.package-popup__installed{display:flex;flex-direction:column;justify-content:flex-end;text-align:center}.package-popup__installed strong{display:block;margin:0}}.package-popup__update{background:var(--btn-primary) url(../img/button-update.ad79c617.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__incompatible,.package-popup__update{margin:0 0 20px;padding:10px 20px 10px 50px;color:var(--clr-btn);border-radius:var(--border-radius)}.package-popup__incompatible{background:var(--contao) url(../img/button-incompatible.3eb2b686.svg) 15px 50% no-repeat;background-size:23px 23px}.package-popup__funding+.package-popup__update{margin-top:-10px}.popup-overlay{position:fixed;inset:0;z-index:1000;background:var(--popup-overlay-bg)}@media(min-width:960px){.popup-overlay{padding:20px 0;overflow-y:auto}}.popup-overlay__popup{position:fixed;display:block;top:50%;left:50%;width:500px;max-width:90%;background:var(--popup-bg);z-index:10;opacity:1;transform:translate(-50%,-50%);border-radius:var(--border-radius);overflow:hidden}.popup-overlay__headline{position:relative;margin-bottom:0;padding:7px 30px 6px;background:var(--popup-hl-bg);font-size:18px;color:#fff;font-weight:300;line-height:1.5em;text-align:center}.popup-overlay__headline--primary{background-color:var(--btn-primary)}.popup-overlay__headline--alert{background-color:var(--btn-alert)}.popup-overlay__content{padding:2em 20px}.popup-overlay__actions{display:flex;justify-content:center;gap:10px;flex-wrap:wrap;padding:0 20px 2em}.popup-overlay__actions .widget-button{width:auto;height:35px;padding:0 30px;line-height:35px}@media(min-width:550px){.popup-overlay__actions,.popup-overlay__content{padding-left:40px;padding-right:40px}}.loader__item{float:left;width:16px;height:16px;margin-right:1px;background-color:var(--contao);animation:loading 1.4s ease-in-out infinite both}.loader__item--20{animation-delay:-.64s}.loader__item--40{animation-delay:-.48s}.loader__item--60{animation-delay:-.32s}.loader__item--80{animation-delay:-.16s}@keyframes loading{0%,90%,to{opacity:0}20%{opacity:1}}.loader__text{float:left;width:40px}.sk-circle{width:25px;height:25px;position:relative}.sk-circle .sk-child{width:100%;height:100%;position:absolute;left:0;top:0}.sk-circle .sk-child:before{content:"";display:block;margin:0 auto;width:15%;height:15%;background-color:var(--text);border-radius:100%;animation:sk-circleBounceDelay 1.2s ease-in-out infinite both}.sk-circle .sk-circle2{transform:rotate(30deg)}.sk-circle .sk-circle3{transform:rotate(60deg)}.sk-circle .sk-circle4{transform:rotate(90deg)}.sk-circle .sk-circle5{transform:rotate(120deg)}.sk-circle .sk-circle6{transform:rotate(150deg)}.sk-circle .sk-circle7{transform:rotate(180deg)}.sk-circle .sk-circle8{transform:rotate(210deg)}.sk-circle .sk-circle9{transform:rotate(240deg)}.sk-circle .sk-circle10{transform:rotate(270deg)}.sk-circle .sk-circle11{transform:rotate(300deg)}.sk-circle .sk-circle12{transform:rotate(330deg)}.sk-circle .sk-circle2:before{animation-delay:-1.1s}.sk-circle .sk-circle3:before{animation-delay:-1s}.sk-circle .sk-circle4:before{animation-delay:-.9s}.sk-circle .sk-circle5:before{animation-delay:-.8s}.sk-circle .sk-circle6:before{animation-delay:-.7s}.sk-circle .sk-circle7:before{animation-delay:-.6s}.sk-circle .sk-circle8:before{animation-delay:-.5s}.sk-circle .sk-circle9:before{animation-delay:-.4s}.sk-circle .sk-circle10:before{animation-delay:-.3s}.sk-circle .sk-circle11:before{animation-delay:-.2s}.sk-circle .sk-circle12:before{animation-delay:-.1s}@keyframes sk-circleBounceDelay{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.widget-button .loader{width:25px;margin:0 auto}.widget-button .sk-circle .sk-child:before{background-color:#fff}.loading-button{position:relative}.loading-button>.loader{position:absolute;left:calc(50% - 12.5px);top:calc(50% - 12.5px)}.loading-button>.loading{visibility:hidden}.theme-switch{position:relative;display:inline-block}.theme-switch button{width:auto;height:auto;padding:0 0 0 24px;background:transparent;color:var(--text);font-size:12px;font-weight:300;line-height:20px;background:var(--svg--color-scheme) left center no-repeat;background-size:20px 20px;border:none;cursor:pointer}.theme-switch button:hover{color:var(--black)}.package-logo--fallback[data-v-9c1c5f6c]{display:flex;justify-content:center;align-items:center}svg[data-v-9c1c5f6c]{width:80px;height:80px;fill:#ccc}.discover-package{display:flex;flex-direction:column;position:relative;overflow:hidden;background:var(--tiles-bg);border:1px solid var(--tiles-bdr);border-radius:14px}.discover-package.is--hint{border-color:var(--border--light)}.discover-package.is--hint .discover-package__inside>*{opacity:.65}.discover-package__hint{position:relative;background:var(--border--light);padding:8px 16px;font-weight:400;font-size:12px;line-height:1.2;z-index:1}.discover-package__hint p a{display:inline-block;padding-right:10px}.discover-package__hint p a:first-child{margin-left:10px}.discover-package__hint p a:not(:first-child):before{padding-right:10px;content:"|"}.discover-package__inside{flex-grow:1;padding:16px}.discover-package__abandoned{display:inline-block;margin-bottom:1em;padding:2px 5px;color:#fff;font-size:12px;font-weight:600;background:var(--btn-alert);cursor:help;z-index:10}@media(min-width:600px){.discover-package__abandoned{position:absolute;top:20px;left:-25px;padding:2px 30px;border-top:1px solid var(--btn-alert-active);transform:rotate(-45deg)}}.discover-package__icon{border-radius:6px;height:60px;width:60px;background:#f7f7f7;margin:0 auto 10px;position:absolute;right:16px}.discover-package__icon>figure{display:flex;align-items:center;justify-content:center;height:100%;max-height:140px}.discover-package__icon img,.discover-package__icon svg{border-radius:4px;width:50px;height:50px;max-height:100%;-o-object-fit:contain;object-fit:contain}.discover-package__details{display:flex;flex-direction:column;justify-content:space-between;min-height:96px}.discover-package__headline{margin-bottom:.2em;line-height:1;overflow-wrap:break-word;margin-right:70px}.discover-package__headline em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.discover-package__versions{display:flex;flex-wrap:wrap;gap:5px;list-style:none;margin:5px 0;padding:0}.discover-package__version{display:inline-flex;justify-content:center;padding:3px 5px;border-radius:4px;line-height:1;min-width:40px;font-size:13px;color:#fff;background:var(--badge-bg);pointer-events:none}.discover-package__description{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;margin-bottom:1em;margin-right:70px}.discover-package__description em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.discover-package__more{display:flex;flex-flow:row wrap;align-items:flex-end;flex-grow:1;gap:4px;line-height:28px}.discover-package__counts{flex-grow:1;justify-content:flex-start}.discover-package__count{display:inline-block;margin-right:15px;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.discover-package__count--private{background-image:var(--svg--private)}.discover-package__count--updated{background-image:var(--svg--updated)}.discover-package__count--downloads{background-image:var(--svg--downloads)}.discover-package__count--favers{background-image:var(--svg--favers)}.discover-package__actions{flex-grow:1;display:flex;justify-content:flex-end;gap:8px}@media(max-width:599.98px){.discover-package__headline-container{display:flex;flex-direction:column-reverse}}@media(min-width:600px){.discover-package__inside{text-align:initial;display:flex;padding:0}.discover-package__icon{width:130px;height:100%;min-height:130px;margin:0;border-radius:0;position:revert;right:revert}.discover-package__icon img{width:100px;height:100px}.discover-package__icon svg{width:90px;height:90px}.discover-package__details{padding:16px;height:100%;min-height:90px;max-width:calc(100% - 130px);flex:1}.discover-package__versions{float:right;margin:-3px 0 0 16px}.discover-package__description,.discover-package__headline{margin-right:0}.discover-package__more{flex-direction:row}.discover-package__actions{justify-content:end}}.vueperslide{white-space:normal;background-size:cover;flex-shrink:0;display:block;width:100%;position:relative}.vueperslide--clone-1{position:absolute;top:0;bottom:0;right:100%}.vueperslides--rtl .vueperslide--clone-1{right:auto;left:100%}.vueperslide[href]{-webkit-user-drag:none}.vueperslide__image{background-size:cover}.vueperslide__image,.vueperslide__loader{position:absolute;top:0;left:0;right:0;bottom:0}.vueperslide__loader{display:flex;flex-direction:column;align-items:center;justify-content:center}.vueperslide__content-wrapper:not(.vueperslide__content-wrapper--outside-top):not(.vueperslide__content-wrapper--outside-bottom){height:100%;margin:auto}.vueperslides--fade .vueperslide{position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;transition:opacity ease-in-out;transition-duration:inherit}.vueperslides--fade .vueperslide--active,.vueperslides--fade .vueperslide--visible{z-index:1;opacity:1}.vueperslides--slide-image-inside .vueperslide{overflow:hidden}.vueperslides--3d .vueperslide{position:absolute;z-index:-1;height:100%}.vueperslides--3d .vueperslide--active,.vueperslides--3d .vueperslide--next-slide,.vueperslides--3d .vueperslide--previous-slide{z-index:0}.vueperslides--3d .vueperslide--active{z-index:1}.vueperslides--3d .vueperslide[face=front]{transform:rotateY(90deg) translate(-50%) rotateY(-90deg)}.vueperslides--3d .vueperslide[face=right]{transform:rotateY(90deg) translate(50%);transform-origin:100% 0}.vueperslides--3d .vueperslide[face=back]{transform:rotateY(270deg) translate(-50%) rotateY(-90deg)}.vueperslides--3d .vueperslide[face=left]{transform:rotateY(270deg) translate(-50%);transform-origin:0 0}.vueperslides:not(.no-shadow):not(.vueperslides--3d) .vueperslides__parallax-wrapper:after,.vueperslides:not(.no-shadow):not(.vueperslides--3d) .vueperslides__parallax-wrapper:before{content:"";position:absolute;bottom:100%;left:-1em;right:-1em;height:2em;box-shadow:0 0 20px #00000040;z-index:2}.vueperslides:not(.no-shadow):not(.vueperslides--3d) .vueperslides__parallax-wrapper:after{top:100%;bottom:auto}.vueperslides__arrows{color:#fff}.vueperslides__arrows--outside{color:currentColor}.vueperslides__arrow{top:50%;background-color:transparent;border:none;opacity:.7}.vueperslides--rtl .vueperslides__arrow--next,.vueperslides__arrow--prev{right:auto;left:.5em}.vueperslides--rtl .vueperslides__arrow--prev,.vueperslides__arrow--next{left:auto;right:.5em}.vueperslides__arrow:hover{opacity:1}.vueperslides--rtl .vueperslides__arrows--outside .vueperslides__arrow--next,.vueperslides__arrows--outside .vueperslides__arrow--prev{right:auto;left:-3.5em}.vueperslides--rtl .vueperslides__arrows--outside .vueperslides__arrow--prev,.vueperslides__arrows--outside .vueperslides__arrow--next{left:auto;right:-3.5em}.vueperslides__paused{top:.7em;right:.7em;opacity:0;text-shadow:0 0 3px rgba(0,0,0,.4);z-index:1}.vueperslides:hover .vueperslides__paused{opacity:1}.vueperslides__bullets:not(.vueperslides__bullets--outside){color:#fff}.vueperslides__bullet{margin:1.5em .6em;padding:0;border:none;background:none}.vueperslides__bullet .default{width:12px;height:12px;border-radius:12px;border:1px solid currentColor;background-color:transparent;box-shadow:0 0 1px #00000080,0 0 3px #0000004d;transition:.4s ease-in-out;box-sizing:border-box}.vueperslides__bullet .default span{display:none}.vueperslides__bullet--active .default{border-width:6px}.vueperslide,.vueperslide__image{background-position:50%}.vueperslide__video{outline:none}.vueperslide--no-pointer-events:before{content:"";position:absolute;top:0;bottom:0;left:0;right:0}.vueperslide__content-wrapper:not(.vueperslide__content-wrapper--outside-top):not(.vueperslide__content-wrapper--outside-bottom){display:flex;flex:1 1 auto;flex-direction:column;align-items:center;justify-content:center;text-align:center}.vueperslide--has-image-inside .vueperslide__content-wrapper,.vueperslide--has-video .vueperslide__content-wrapper,.vueperslide__content-wrapper.parallax-fixed-content{position:absolute;z-index:2;top:0;bottom:0;left:0;right:0;display:flex;flex-direction:column;justify-content:center;align-items:center;pointer-events:none}.vueperslides{position:relative}.vueperslides--fixed-height .vueperslide,.vueperslides--fixed-height .vueperslides__inner,.vueperslides--fixed-height .vueperslides__parallax-wrapper{height:inherit}.vueperslides--fixed-height .vueperslides__parallax-wrapper{padding-bottom:0!important}.vueperslides--fixed-height.vueperslides--bullets-outside{margin-bottom:4em}.vueperslides__inner{position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.vueperslides__parallax-wrapper{position:relative;overflow:hidden}.vueperslides--3d .vueperslides__parallax-wrapper{overflow:visible}.vueperslides__track{position:absolute;top:0;height:100%;left:0;right:0;overflow:hidden;z-index:1}.vueperslides--parallax .vueperslides__track{height:200%;transform:translateY(0)}.vueperslides--touchable .vueperslides__track{cursor:ew-resize;cursor:grab}.vueperslides--touchable .vueperslides__track--dragging,.vueperslides--touchable .vueperslides__track--mousedown{cursor:grabbing}.vueperslides--3d .vueperslides__track{overflow:visible;perspective:100em}.vueperslides__track-inner{white-space:nowrap;transition:transform .5s ease-in-out;height:100%;display:flex}.vueperslides--no-animation .vueperslides__track-inner{transition-duration:0s!important}.vueperslides--fade .vueperslides__track-inner{white-space:normal;transition:none}.vueperslides--3d .vueperslides__track-inner{transform-style:preserve-3d}.vueperslides__track--mousedown .vueperslides__track-inner{transition:transform .25s ease-in-out!important}.vueperslides__track--dragging .vueperslides__track-inner{transition:none}.vueperslides__arrow{position:absolute;font-size:inherit;color:inherit;text-align:center;transform:translateY(-50%);transition:.3s ease-in-out;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;outline:none;z-index:2;line-height:1}.vueperslides__arrow svg{vertical-align:middle;stroke:currentColor;fill:none;width:3.5em;padding:1em;stroke-width:1;transition:.3s ease-in-out;box-sizing:border-box}.vueperslides__arrow svg:hover{stroke-width:1.3}.vueperslides__paused{position:absolute;transition:.3s ease-in-out}.vueperslides__bullets{display:flex;justify-content:center;position:absolute;bottom:0;left:0;right:0}.vueperslides__bullets--outside{position:relative}.vueperslides__bullet,.vueperslides__bullets button{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;outline:none;z-index:2;display:flex;justify-content:center;align-items:center;color:inherit}.vueperslides__bullet::-moz-focus-inner,.vueperslides__bullets button::-moz-focus-inner{border:0}.vueperslides__fractions{position:absolute;top:.8em;left:.5em;z-index:2;padding:.2em 1em;border:1px solid hsla(0,0%,100%,.5);border-radius:2em;background:#fff3;color:#fff}.vueperslides__progress{position:absolute;top:0;left:0;right:0;z-index:2;height:6px;color:#000000b3}.vueperslides__progress>*{position:absolute;top:0;bottom:0;left:0;background:currentColor;transition:.3s ease-in-out}img[data-v-8007fa0a]{width:100%;aspect-ratio:2}@media(min-width:1200px){.ads[data-v-8007fa0a]{margin:59px 0 69px}}.link[data-v-8007fa0a]{padding-top:5px;text-align:right}.link a[data-v-8007fa0a]{padding-left:16px;font-size:.8em;color:inherit;background:var(--svg--link-blank) left center no-repeat;background-size:13px 13px}.container[data-v-8007fa0a]{position:relative;background:var(--popup-bg);box-shadow:var(--ad-shadow);border-radius:14px;overflow:hidden}.package-sorting{margin:20px 0 15px;text-align:right}.package-sorting__label{display:inline-block;text-transform:uppercase}.package-sorting__label:after{content:":"}.package-sorting__group{position:relative;display:inline-flex;flex-direction:column;margin:0;padding:0 15px 0 0;list-style-type:none;text-align:left}.package-sorting__group:after{content:"";position:absolute;top:.8em;right:0;width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #777}.package-sorting__item{display:none;margin:0 0 0 10px;padding:3px 0;text-transform:uppercase;cursor:pointer;border-bottom:2px solid transparent}.package-sorting__item:hover{color:var(--link)}.package-sorting__item--open{display:inline}.package-sorting__item--active{display:inline;color:var(--link);border-bottom:2px solid var(--link)}@media(min-width:600px){.package-sorting__group{flex-direction:row;justify-content:flex-end;padding:0}.package-sorting__group:after{content:none}.package-sorting__item{display:inline}}.search-bar{position:relative}.search-bar__input{height:50px!important;padding-right:45px!important;border-radius:50px!important}.search-bar__button{position:absolute;top:0;right:5px;display:flex;align-items:center;width:38px;height:50px;margin:0;padding:7px;line-height:36px;border:none;background:none;outline:none}.package-search{position:relative}.package-search__input{max-width:400px;margin:0 20px}@media(min-width:1024px){.package-search__input{margin-right:0}}.package-search__headline{font-size:18px;font-weight:300;margin:30px 0 10px}.package-search__results{display:grid;gap:20px;margin-bottom:20px}@media(min-width:1024px){.package-search__results{grid-template-columns:repeat(2,1fr)}}.package-search__status{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.package-search__status--empty{padding-top:140px;background:url(../img/sad.c7de6e95.svg) top no-repeat;background-size:100px 100px}.package-search__status--offline{padding-top:140px;background:url(../img/offline.0c23d1ce.svg) top no-repeat;background-size:100px 100px}.package-search__status--loader .sk-circle{width:100px;height:100px;margin:0 auto 40px}.package-search__status button{margin-top:2em}.package-search__explain{font-size:16px}.package-search__more{margin:10px 0 30px;text-align:center}.package-search__more-button{display:inline-block;margin:0 auto;padding:0;text-transform:uppercase;background:none;border:none;cursor:pointer}.package-search__more-button:hover{text-decoration:underline}.package-search__algolia{display:block;width:200px;margin:50px auto 0}.link-menu{position:absolute;display:block;left:50%;margin:0;padding:0;text-align:center;list-style-type:none;white-space:nowrap;background:var(--form-bg);border-top:3px solid var(--text);border-radius:5px;z-index:100;box-shadow:0 0 1px var(--shadow)}.link-menu:before{position:absolute;left:50%;top:-7px;width:0;height:0;margin-left:-4px;border-style:solid;border-width:0 3.5px 4px 3.5px;border-color:transparent transparent var(--text) transparent;content:""}.link-menu--align-left{left:0;right:auto}.link-menu--align-left:before{left:17px;right:auto}.link-menu--align-right{left:auto;right:0}.link-menu--align-right:before{left:auto;right:17px}.link-menu--valign-top{bottom:0;border-top:none;border-bottom:3px solid var(--text);box-shadow:0 0 2px var(--shadow)}.link-menu--valign-top:before{top:auto;bottom:-7px;border-width:4px 3.5px 0 3.5px;border-color:var(--text) transparent transparent transparent}.link-menu--contao{border-color:var(--contao)}.link-menu--contao:before{border-bottom-color:var(--contao)}.link-menu--contao.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--contao)}.link-menu--primary{border-color:var(--btn-primary)}.link-menu--primary:before{border-bottom-color:var(--btn-primary)}.link-menu--primary.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--btn-primary)}.link-menu--warning{border-color:var(--btn-warning)}.link-menu--warning:before{border-bottom-color:var(--btn-warning)}.link-menu--warning.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--btn-warning)}.link-menu--alert{border-color:var(--btn-alert)}.link-menu--alert:before{border-bottom-color:var(--btn-alert)}.link-menu--alert.link-menu--valign-top:before{border-bottom-color:transparent;border-top-color:var(--btn-alert)}.link-menu__item{margin:0;padding:0;display:block}.link-menu__action{display:block;margin:2px;border-radius:5px;padding:8px 16px;color:var(--text);cursor:pointer}.link-menu__action:hover{color:var(--text);background:var(--focus);text-decoration:none}.vjs-tree-brackets{cursor:pointer}.vjs-tree-brackets:hover{color:#1890ff}.vjs-check-controller{position:absolute;left:0}.vjs-check-controller.is-checked .vjs-check-controller-inner{background-color:#1890ff;border-color:#0076e4}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-checkbox:after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-radio:after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.vjs-check-controller .vjs-check-controller-inner{display:inline-block;position:relative;border:1px solid #bfcbd9;border-radius:2px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box;width:16px;height:16px;background-color:#fff;z-index:1;cursor:pointer;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.vjs-check-controller .vjs-check-controller-inner:after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:2px solid #fff;border-left:0;border-top:0;height:8px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:4px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;-webkit-transform-origin:center;transform-origin:center}.vjs-check-controller .vjs-check-controller-inner.is-radio{border-radius:100%}.vjs-check-controller .vjs-check-controller-inner.is-radio:after{border-radius:100%;height:4px;background-color:#fff;left:50%;top:50%}.vjs-check-controller .vjs-check-controller-original{opacity:0;outline:none;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.vjs-carets{position:absolute;right:0;cursor:pointer}.vjs-carets svg{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.vjs-carets:hover{color:#1890ff}.vjs-carets-close{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.vjs-tree-node{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative;line-height:20px}.vjs-tree-node.has-carets{padding-left:15px}.vjs-tree-node.has-carets.has-selector,.vjs-tree-node.has-selector{padding-left:30px}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f7ff}.vjs-tree-node .vjs-indent{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative}.vjs-tree-node .vjs-indent-unit{width:1em}.vjs-tree-node .vjs-indent-unit.has-line{border-left:1px dashed #bfcbd9}.vjs-tree-node.dark.is-highlight,.vjs-tree-node.dark:hover{background-color:#2e4558}.vjs-node-index{position:absolute;right:100%;margin-right:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.vjs-colon{white-space:pre}.vjs-comment{color:#bfcbd9}.vjs-value{word-break:break-word}.vjs-value-null,.vjs-value-undefined{color:#d55fde}.vjs-value-boolean,.vjs-value-number{color:#1d8ce0}.vjs-value-string{color:#13ce66}.vjs-tree{font-family:Monaco,Menlo,Consolas,Bitstream Vera Sans Mono,monospace;font-size:14px;text-align:left}.vjs-tree.is-virtual{overflow:auto}.vjs-tree.is-virtual .vjs-tree-node{white-space:nowrap}[data-notivue=promise-resolve],[data-notivue=success]{--nv-bg:var(--nv-success-bg);--nv-fg:var(--nv-success-fg);--nv-accent:var(--nv-success-accent,var(--nv-global-accent));--nv-border:var(--nv-success-border)}[data-notivue=error],[data-notivue=promise-reject]{--nv-bg:var(--nv-error-bg);--nv-fg:var(--nv-error-fg);--nv-accent:var(--nv-error-accent,var(--nv-global-accent));--nv-border:var(--nv-error-border)}[data-notivue=warning]{--nv-bg:var(--nv-warning-bg);--nv-fg:var(--nv-warning-fg);--nv-accent:var(--nv-warning-accent,var(--nv-global-accent));--nv-border:var(--nv-warning-border)}[data-notivue=info]{--nv-bg:var(--nv-info-bg);--nv-fg:var(--nv-info-fg);--nv-accent:var(--nv-info-accent,var(--nv-global-accent));--nv-border:var(--nv-info-border)}[data-notivue=promise]{--nv-bg:var(--nv-promise-bg);--nv-fg:var(--nv-promise-fg);--nv-accent:var(--nv-promise-accent,var(--nv-global-accent));--nv-border:var(--nv-promise-border)}.Notivue__notification{--tip-width:calc(var(--tip-width-fx, 1)*var(--nv-tip-width, 0px));box-sizing:border-box;position:relative;width:var(--nv-min-width,auto);max-width:var(--nv-width,100%);background-color:var(--nv-bg,var(--nv-global-bg));display:flex;align-items:var(--nv-y-align);border-radius:var(--nv-radius,0);border:var(--nv-border-width,0) solid var(--nv-border,var(--nv-global-border));box-shadow:var(--nv-shadow,0 0 transparent),inset var(--tip-width) 0 0 var(--nv-accent)}.Notivue__notification *{box-sizing:border-box;touch-action:manipulation}.Notivue__notification[data-notivue-has-title=true]{align-items:var(--nv-y-align-has-title,var(--nv-y-align))}.Notivue__icon{display:flex;justify-content:center;align-items:center;overflow:visible;min-width:var(--nv-icon-size);width:var(--nv-icon-size);height:var(--nv-icon-size);margin:var(--nv-spacing) 0 var(--nv-spacing) var(--nv-spacing);color:var(--nv-accent)}.Notivue__content{--nv-content-space:calc(var(--nv-spacing) + var(--nv-spacing)*0.15);display:flex;flex-direction:column;flex-grow:1;text-align:inherit;padding:var(--nv-content-space)}.Notivue__content-title{line-height:1.15;font-weight:700;color:var(--nv-fg,var(--nv-global-fg));font-size:var(--nv-title-size);margin:0 0 .33em;padding:0}.Notivue__transition-enter-active{--dur-easing:.5s cubic-bezier(.16,1,.3,1);transition:opacity var(--dur-easing),transform var(--dur-easing)}@media (prefers-reduced-motion:reduce){.Notivue__transition-enter-active{transition:none}}.Notivue__transition-enter-from{opacity:0;transform:scale(.8)}.Notivue__transition-enter-to{opacity:1;transform:scale(1)}.Notivue__transition-leave-active{transition:opacity 0ms ease}.Notivue__transition-leave-from,.Notivue__transition-leave-to{opacity:0}.Notivue__content-message{max-height:250px;overflow:auto;line-height:1.375;margin:0;padding:0;white-space:pre-line}.Notivue__close,.Notivue__content-message{color:var(--nv-fg,var(--nv-global-fg));font-size:var(--nv-message-size)}.Notivue__close{position:relative;cursor:pointer;padding:calc(var(--nv-spacing)/2);margin:var(--nv-spacing) var(--nv-spacing) var(--nv-spacing) 0;font-weight:700;border:none;background:none;line-height:1;-webkit-tap-highlight-color:rgba(0,0,0,0)}.Notivue__close:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:var(--nv-fg,var(--nv-global-fg));opacity:0;border-radius:calc(var(--nv-radius)/2);transition:opacity .1s ease-out}@media (hover:hover){.Notivue__close:hover{opacity:1}.Notivue__close:hover:after{opacity:.1}.Notivue__close:hover .Notivue__close-icon{opacity:1}}.Notivue__close-icon{width:var(--nv-icon-size);height:var(--nv-icon-size);display:flex;color:var(--nv-fg,var(--nv-global-fg));pointer-events:none;opacity:.65}.Notivue__spinner{transform-origin:center;animation:Notivue__spinner-kf .75s linear infinite}@keyframes Notivue__spinner-kf{to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.Notivue__duplicate,.Notivue__spinner{animation:none}}[dir=rtl] .Notivue__notification{--tip-width-fx:-1}[dir=rtl] .Notivue__icon{margin:var(--nv-spacing) var(--nv-spacing) var(--nv-spacing) 0}[dir=rtl] .Notivue__content-message{font-size:calc(var(--nv-message-size) + .1em)}[dir=rtl] .Notivue__content-title{font-size:calc(var(--nv-title-size) + .1em)}[dir=rtl] .Notivue__close{margin:var(--nv-spacing) 0 var(--nv-spacing) var(--nv-spacing)}.Notivue__duplicate{animation:Notivue__duplicate-kf .3s cubic-bezier(.16,1,.3,1) forwards}@keyframes Notivue__duplicate-kf{0%{transform:scale(1);opacity:1}50%{transform:scale(1.035);opacity:.8}to{transform:scale(1);opacity:1}}[data-notivue-align=top] .Notivue__enter,[data-notivue-align=top] .Notivue__leave{--notivue-ty:-200%}[data-notivue-align=bottom] .Notivue__enter,[data-notivue-align=bottom] .Notivue__leave{--notivue-ty:200%}.Notivue__enter{animation:Notivue__enter-kf .35s cubic-bezier(.5,1,.25,1)}.Notivue__leave{animation:Notivue__leave-kf .35s ease}.Notivue__clearAll{animation:Notivue__clearAll-kf .5s cubic-bezier(.22,1,.36,1)}@keyframes Notivue__enter-kf{0%{transform:translate3d(0,var(--notivue-ty),0) scale(.25);opacity:0}to{transform:translateZ(0) scale(1);opacity:1}}@keyframes Notivue__leave-kf{0%{transform:translateZ(0) scale(1);opacity:.7}to{transform:translate3d(0,var(--notivue-ty),0) scale(0);opacity:0}}@keyframes Notivue__clearAll-kf{0%{opacity:1}to{opacity:0}}.config-check__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.config-check__icon{background:var(--contao);border-radius:10px;padding:10px}.config-check__headline{margin-top:20px;margin-bottom:25px;font-size:36px;font-weight:100;line-height:1}.config-check__description{text-align:justify}.config-check__form{position:relative;max-width:280px;margin:0 auto 50px}.config-check__form .widget-select,.config-check__form .widget-text{margin-top:20px}.config-check__form .widget-select label,.config-check__form .widget-text label{display:block;margin-bottom:5px;font-weight:400}.config-check__fields{margin-bottom:2em}.config-check__fieldtitle{margin-bottom:.5em;font-size:18px;font-weight:600;line-height:30px}.config-check__fielddesc{margin-bottom:1em}.config-check__issues{margin-bottom:1em;color:var(--btn-alert)}.config-check__issues p{font-weight:600}.config-check__issues ul{margin:0;padding:0}.config-check__issues li{margin:.5em 0 0 25px;padding:0}.config-check .widget-button{margin-bottom:.5em}@media(min-width:960px){.config-check{padding-top:100px}.config-check__header{float:left;width:470px;max-width:none;padding:0 60px 100px}.config-check__form{float:left;width:370px;max-width:none;margin:20px 50px 0;padding-bottom:100px}.config-check__form .widget-select label,.config-check__form .widget-text label{display:block;float:left;width:120px;padding-top:10px;font-weight:400}}.view-login__header{max-width:280px;margin:0 auto 60px;padding-top:40px;text-align:center}.view-login__product{margin-top:15px;font-size:38px;font-weight:100;line-height:1}.view-login__form{position:relative;max-width:280px;margin:0 auto 80px}.view-login__form input{padding-right:30px;margin:5px 0 10px}.view-login__locked{max-width:290px;margin:-20px auto 60px;padding:20px;background:var(--btn-alert);color:#fff;text-align:center}.view-login__locked strong{white-space:pre}.view-login__headline{margin-bottom:0}.view-login__description{margin-top:.5em;margin-bottom:30px}.view-login label{position:absolute;text-indent:-999em;pointer-events:none}.view-login label[for=ctrl_username]{top:0;bottom:0;margin:auto;right:13px;width:16px;height:16px;background:url(../img/person.00d78897.svg) 0 0 no-repeat;background-size:16px 16px;z-index:10}.view-login label[for=ctrl_password]{top:0;bottom:0;margin:auto;right:12px;width:16px;height:16px;background:url(../img/lock.3c42a55f.svg) 0 0 no-repeat;background-size:14px 14px;z-index:10}.view-login__password input,.view-login__user input{margin:0}.view-login__user input{border-radius:var(--border-radius) var(--border-radius) 0 0!important}.view-login__password{margin-top:-1px}.view-login__password input{border-radius:0 0 var(--border-radius) var(--border-radius)!important}.view-login .widget-text--password button{opacity:0}.view-login__link{display:block;margin-top:1em;font-size:12px;text-align:right}.view-login__button{margin:6px 0}.widget-text+.view-login__button{margin:12px 0 0}.view-login__button .sk-circle{color:#fff;text-align:center}.view-login .fragment-footer{display:block}body.nav-active{overflow:hidden!important}#app{transition:transform .4s cubic-bezier(.55,0,.1,1)}.nav-active #app{overflow-y:visible;transform:translateX(-280px)}@media(min-width:1024px){.nav-active #app{transform:none}}.navigation{float:right}.navigation__toggle{display:block;float:right;position:relative;margin:5px 15px;padding:0;width:30px;height:30px;cursor:pointer;z-index:20}.navigation__toggle span,.navigation__toggle span:after,.navigation__toggle span:before{content:"";display:block;width:100%;height:4px;background:var(--text);border-radius:4px;position:absolute}.navigation__toggle span{transition-duration:75ms;transition-timing-function:cubic-bezier(.215,.61,.355,1);top:50%;margin-top:-2px}.navigation__toggle span:before{top:-10px;transition:top 75ms ease .12s,opacity 75ms ease}.navigation__toggle span:after{bottom:-10px;transition:bottom 75ms ease .12s,transform 75ms cubic-bezier(.55,.055,.675,.19)}.nav-active .navigation__toggle span{transform:rotate(45deg);transition-delay:.12s;transition-timing-function:cubic-bezier(.215,.61,.355,1)}.nav-active .navigation__toggle span:before{top:0;opacity:0;transition:top 75ms ease,opacity 75ms ease .12s}.nav-active .navigation__toggle span:after{transition:bottom 75ms ease,transform 75ms cubic-bezier(.215,.61,.355,1) .12s;bottom:0;transform:rotate(-90deg)}.navigation__group,.navigation__item{list-style-type:none;margin:0;padding:0}.navigation__group--main{position:fixed;top:0;bottom:0;right:-280px;width:280px;padding:20px;overflow-y:auto;overflow-scrolling:touch;background:var(--header-main-bg);border-left:1px solid var(--header-bdr);z-index:10}.navigation__item a{display:block;padding:12px 10px;font-size:16px;color:var(--text);white-space:pre}.navigation__item a:hover{text-decoration:none}.navigation__item a[href]:hover{color:var(--link)}.navigation__item--main>a{text-transform:uppercase}.navigation__item--sub>a{margin-left:15px}.navigation__item--icon svg{display:none}.navigation__item-badge{position:relative;top:-2px;margin-left:8px;padding:2px 5px;font-size:10px;color:var(--clr-btn);font-weight:600;background:var(--contao);border-radius:40%}@media(min-width:1024px){.navigation__toggle{display:none}.navigation__group--main{position:inherit;top:auto;bottom:auto;right:auto;width:auto;padding:0;overflow:visible;background:none;border:none;box-shadow:none;transform:none;transition:none}.navigation__group--sub{display:none;position:absolute;left:50%;min-width:180px;margin-top:-3px;text-align:center;background:var(--form-bg);border-top:3px solid var(--link);border-radius:5px;transform:translateX(-50%);z-index:100;box-shadow:0 0 2px var(--shadow)}.navigation__group--sub:before{position:absolute;left:50%;top:-7px;width:0;height:0;margin-left:-4px;border-style:solid;border-width:0 3.5px 4px 3.5px;border-color:transparent transparent var(--link) transparent;content:""}.navigation__group--right{left:auto;right:7px;transform:translateX(0)}.navigation__group--right:before{left:auto;right:18px}.navigation__item{position:relative;display:inline-block;padding:0 8px}.navigation__item.router-link-active>a,.navigation__item:hover>a{color:var(--link)!important;border-bottom:3px solid var(--link)}.navigation__item:hover>.navigation__group--sub{display:block}.navigation__item--sub{display:block;margin:calc(var(--border-radius)/2);border-radius:var(--border-radius)}.navigation__item--sub a{margin:0;border:none!important}.navigation__item--sub.router-link-active,.navigation__item--sub:hover{background:var(--focus)}.navigation__item--sub.router-link-active a,.navigation__item--sub:hover a{color:var(--text)!important}.navigation__item--icon>a{padding-top:7px}.navigation__item--icon>a svg{display:inline;position:relative;top:4px;width:22px;height:22px;fill:var(--text)}.navigation__item--icon>a:hover svg{fill:var(--link)}.navigation__item--icon>a span{display:none}.navigation:hover li>a{border:none}.navigation:hover li:hover>a{border-bottom:3px solid var(--link)}.navigation:hover li:hover>a svg{fill:var(--link)}}.logout-warning{text-align:center}.logout-warning__countdown{margin:20px 0;font:600 4em/1.6 SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:var(--btn-warning)}.fragment-footer{width:280px;margin:10px auto 0;padding:15px 0 25px;font-size:12px;text-align:center;border-top:1px solid var(--footer-bdr)}.fragment-footer--main{width:auto;margin-top:52px!important;padding:20px 0}.fragment-footer--boxed{border-color:var(--footer-fragment-bdr)}.fragment-footer__product{font-weight:300}.fragment-footer__links{margin:5px 0 0;padding:0;list-style-type:none}.fragment-footer__links li{display:inline-block}.fragment-footer__links li:not(:first-child):before{content:"|";padding:0 10px 0 8px}.fragment-footer__links a{display:inline!important;color:var(--link-footer)}.fragment-footer__settings{margin-top:10px;display:flex;flex-flow:column;justify-content:center;gap:10px}.fragment-footer__language{position:relative;display:inline-block}.fragment-footer__language button{width:auto;height:auto;padding:0 0 0 25px;background:transparent;color:var(--text);font-size:12px;font-weight:300;line-height:20px;background:var(--svg--language) left center no-repeat;background-size:20px 20px;border:none;cursor:pointer}.fragment-footer__language button:hover{color:var(--black)}.fragment-footer__language ul{display:grid;overflow:hidden;grid-template-columns:1fr 1fr;grid-auto-flow:row;gap:2px;padding:2px;bottom:25px;white-space:nowrap;transform:translateX(-50%)}.fragment-footer__language li a{display:block;padding:6px;border-radius:5px;color:var(--text);cursor:pointer}.fragment-footer__language li a.active{font-weight:600}.fragment-footer__language li a.active,.fragment-footer__language li a:hover{color:var(--text);background:var(--focus);text-decoration:none}@media(min-width:960px){.fragment-footer{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:16px;align-content:center}.fragment-footer--boxed .fragment-footer__product,.fragment-footer--main .fragment-footer__product{margin-right:auto}.fragment-footer--boxed .fragment-footer__links,.fragment-footer--main .fragment-footer__links{order:15;margin:0 0 0 auto}.fragment-footer--boxed .fragment-footer__settings,.fragment-footer--main .fragment-footer__settings{flex-flow:row;margin-top:0}.fragment-footer--boxed{width:840px}}.layout-main{overflow:hidden;min-height:100vh}.layout-main__header{height:56px;padding:8px;background:var(--header-main-bg)}.layout-main__header--margin{margin-bottom:30px}.layout-main__badge-title{background:var(--border);color:var(--text);padding:2px 5px;position:relative;top:-5px;border-radius:8px;font-size:.75rem;font-weight:600;line-height:1;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical;word-break:break-word;overflow:hidden;text-overflow:ellipsis}.layout-main__subheader{margin:0 0 45px;padding:20px 0;background:var(--header-bg);border-bottom:1px solid var(--header-bdr)}.layout-main__subheader-inside{display:flex;justify-content:center;align-items:center;flex-direction:column}.layout-main__news{width:320px;height:50px;margin-bottom:20px}.layout-main .search-bar{width:100%;margin:0}.layout-main__logo{display:inline;color:var(--text);text-decoration:none;font-weight:100;font-size:27px;line-height:40px}.layout-main__logo img{float:left;margin:0 10px 0 12px}@media(min-width:1024px){.layout-main__logo img{margin-left:0}}.layout-main footer,.layout-main__content,.layout-main__subheader-inside{position:relative;margin:0 20px}.layout-main__has-badge-title{display:flex;justify-content:space-between}.layout-main__has-badge-title .layout-main__logo{display:flex}.layout-main__has-badge-title .layout-main__title{display:flex;flex-wrap:wrap;align-items:center;line-height:1;-moz-column-gap:10px;column-gap:10px;row-gap:5px}@media(max-width:600px){.layout-main__badge-title{max-width:220px}}@media(min-width:700px){.layout-main__subheader-inside{flex-direction:row}.layout-main__news{margin:0 20px 0 0}}@media(min-width:1024px){.layout-main__has-badge-title .navigation__group--main{display:flex}.layout-main footer,.layout-main__content,.layout-main__subheader-inside{max-width:960px;margin:0 auto}}@media(min-width:1200px){.layout-main footer,.layout-main__content,.layout-main__subheader-inside{max-width:1180px}}.confirm-button{position:relative}.confirm-button__icon{display:none;position:absolute;opacity:0;z-index:100}.confirm-button__icon--confirm{display:block;animation:confirm_button .5s ease-out 0s}.confirm-button__icon svg{fill:var(--btn-primary);width:100%;height:100%}@keyframes confirm_button{0%{opacity:1;height:10px;width:10px;left:calc(50% - 5px);top:calc(50% - 5px)}to{opacity:0;height:150px;width:150px;left:calc(50% - 75px);top:calc(50% - 75px)}}.package-tools{position:relative;clear:both;text-align:center}@media(min-width:800px){.package-tools{margin-bottom:40px}}.package-tools__button.widget-button{margin-bottom:10px}@media(min-width:800px){.package-tools{display:flex;justify-content:center;align-items:center}.package-tools__button.widget-button{width:auto;margin:0 15px;padding:0 15px}}.package-actions{position:fixed;left:0;right:0;bottom:0;max-height:0;background:#000;background:rgba(0,0,0,.8);color:#fff;transition:max-height .4s ease;z-index:100}.package-actions--active{max-height:200px}.package-actions__inner{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;margin:0;padding:12px;text-align:right}@media(min-width:1024px){.package-actions__inner{max-width:976px;margin:0 auto;padding-left:0;padding-right:0}}@media(min-width:1200px){.package-actions__inner{max-width:1196px}}.package-actions__text{flex-grow:1;display:initial;margin:0 8px;font-weight:600}.package-actions__button{display:block;padding:0 15px!important;margin:8px}.package-actions__button--dryRun{width:auto!important;flex-grow:1}@media(min-width:600px){.package-actions__button{width:auto!important}.package-actions__button--dryRun{flex-grow:0}}.package-actions__button-group{display:block;width:100%;margin:8px}.package-actions__button-group>.button-group__primary{padding:0 15px!important}@media(min-width:600px){.package-actions__button-group{width:auto!important}}.package{position:relative;margin-bottom:20px;background:var(--tiles-bg);border:1px solid var(--tiles-bdr);border-radius:14px}.package.is--hint{border-color:var(--btn-alert)}.package--contao:not(:last-child){margin-bottom:5em}.package__hint{position:relative;background:var(--hint-bg);padding:8px 16px;font-weight:400;font-size:12px;line-height:1.8;border-radius:14px 14px 0 0;z-index:1}.package__hint p a{display:inline-block;padding-right:10px}.package__hint p a:first-child{margin-left:10px}.package__hint p a:not(:first-child):before{padding-right:10px;content:"|"}.package__hint-close{float:right;padding-left:18px;color:var(--hint-link);background:url(../img/close.8b27dbcb.svg) 0 no-repeat;background-size:14px 14px}.package__inside{position:relative;padding:16px}.package__inside:after{display:table;clear:both;content:""}.package__badge{display:inline-block;margin-bottom:.5em;padding:2px 5px;color:#fff;font-size:12px;font-weight:600;background:var(--btn-alert);border-radius:var(--border-radius);cursor:help}.package__icon{border-radius:6px;height:60px;width:60px;background:#f7f7f7;margin:0 auto 10px;position:absolute;right:16px}.package__icon>figure{display:flex;align-items:center;justify-content:center;height:100%}.package__icon img,.package__icon svg{border-radius:4px;width:50px;height:50px;max-height:100%;-o-object-fit:contain;object-fit:contain}.package__details{min-height:96px}.package__about{margin-bottom:20px}.package__headline{position:relative;margin-bottom:.2em;line-height:1;overflow-wrap:break-word;margin-right:70px}.package__headline em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.package__title{display:block;margin-right:10px}.package__description{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;margin-bottom:1em;margin-right:70px}.package__description em{background-color:var(--highlight-bg);color:var(--highlight-color);font-style:normal}.package__additional{margin-top:-5px}.package .package__release{text-align:right;margin-bottom:5px}.package__version--additional{margin-bottom:5px}.package__version--additional strong{margin-right:10px}.package__version--release{display:none}.package__version--release time{display:block}.package__version--missing{padding:4px 8px;background:var(--btn-alert);border-radius:var(--border-radius);color:#fff;font-weight:700}.package__version-update{display:inline-block;margin:0 0 2px;padding:1px 8px;color:#fff;border-radius:var(--border-radius)}.package__version-update--available{background:var(--btn-primary)}.package__version-update--error{background:var(--btn-alert)}.package__version-update--none{background:var(--border)}.package__version-latest{float:right;position:relative;right:-7px;width:24px;height:20px;background:var(--btn-primary) url(../img/button-update.ad79c617.svg) center center/20px 20px no-repeat}.package__actions{display:flex;flex-flow:column;gap:5px}.package__actions .button-group button{margin-bottom:0!important}@media(min-width:600px){.package__description,.package__title{margin-right:0}.package__hint{padding-left:52px;background:rgba(var(--hint-rgb),.9) url(../img/hint.ba2ac97e.svg) 12px 5px no-repeat;background-size:28px 28px}.package__inside{display:flex;align-items:stretch;padding:0}.package__headline--badge{display:flex;gap:6px;align-items:flex-start}.package__headline{margin:0 0 8px}.package__badge{order:1;margin:0 0 0 2px}.package__icon{width:130px;height:auto;min-height:130px;margin:0;border-radius:12px 0 0 12px;position:revert;right:revert}.package__icon img,.package__icon svg{width:110px;height:110px}.is--hint .package__icon{border-top-left-radius:0}.package--contao{overflow:hidden}.package--contao .package__icon{border-radius:0}.package__details{padding:16px;height:100%;min-height:90px;max-width:calc(100% - 130px);flex:1}.package.is--hint .package__icon{border-top-left-radius:0}}@media(min-width:680px){.package .package__release{display:block;float:left;width:33%}.package__actions{float:right;width:64%;flex-flow:row;gap:4%;text-align:right}.package__actions>*{flex:1}}@media(min-width:1024px){.package__version--additional{display:none}.package__version--release{display:block;margin-top:15px;text-align:center}.package__version-update{display:block;margin:2px 0 0}.package__about{float:left;width:396px;margin-bottom:0}.package .package__release{width:180px;margin-left:20px;margin-bottom:0}.package__actions{flex-flow:column;gap:10px;width:180px;margin-left:20px}.package__details{display:flex;align-self:center;align-items:flex-start}}@media(min-width:1200px){.package__about{width:616px}}.progress-bar{position:relative;width:100%;height:30px;background:var(--clr-btn);border:2px solid var(--btn-warning);color:#000;font-weight:600;text-align:center;line-height:26px}.progress-bar__bar{position:absolute;overflow:hidden;left:0;right:0;top:0;bottom:0;background:var(--btn-warning)}.progress-bar__bar span{display:block;color:var(--clr-btn);text-align:center}.feature-package{display:flex;flex-wrap:wrap;padding:6px 16px;border-top:1px solid var(--border--light)}.feature-package__name{font-weight:600;white-space:nowrap}.feature-package__name:after{content:": "}.feature-package__text{flex-grow:1;display:-webkit-box;overflow:hidden;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical;margin-right:.5em;padding:4px 0;line-height:20px}.feature-package__text--hint{display:inline;-webkit-line-clamp:none;line-clamp:none}.feature-package__badge{margin-left:5px;padding:2px 8px;background:var(--btn-alert);border-radius:var(--border-radius);font-size:12px;font-weight:600;line-height:19px;color:#fff;cursor:help}.feature-package__hint{line-height:1.2;padding:2px 5px;background:var(--hint-bg);font-size:12px}.feature-package__actions{flex-grow:1;display:flex;justify-content:flex-end;margin:0 -4px 0 0}.feature-package__actions>*{margin:0 4px}.feature-package__restore{padding-left:18px;font-size:12px;color:var(--hint-link);background:url(../img/close.8b27dbcb.svg) 0 no-repeat;background-size:14px 14px;border:none;outline:none;cursor:pointer}.feature-package__restore:hover{text-decoration:underline}@media(min-width:800px){.feature-package{flex-wrap:nowrap}}@media(min-width:1024px){.feature-package__hint{padding:8px 10px 8px 36px;background:var(--hint-bg) url(../img/hint.ba2ac97e.svg) 10px 5px no-repeat;background-size:20px 20px}.feature-package__actions{margin:0 -4px 0 0}}.package-constraint input[type=text][data-v-1e421d04]{margin-right:2px;background:#fff;border:2px solid var(--btn-warning);color:var(--black);font-weight:600;text-align:center;border-top-right-radius:0;border-bottom-right-radius:0}.package-constraint input[type=text][data-v-1e421d04]::-moz-placeholder{color:#fff;opacity:1}.package-constraint input[type=text][data-v-1e421d04]::placeholder{color:#fff;opacity:1}.package-constraint input[type=text][data-v-1e421d04]:disabled{color:var(--clr-btn);opacity:1;background:var(--btn-warning);-webkit-text-fill-color:var(--clr-btn)}.package-constraint input[type=text].disabled[data-v-1e421d04]{background:var(--border);border-color:var(--border)}.package-constraint input[type=text].error[data-v-1e421d04]{animation:input-error .15s linear 3}.package-constraint>input[type=text][data-v-1e421d04],.package-constraint>input[type=text][data-v-1e421d04]:disabled{float:left;width:calc(100% - 32px)}.package-constraint button[data-v-1e421d04]{position:relative;width:30px;background:var(--btn-warning);line-height:20px;text-indent:-999em;border-top-left-radius:0;border-bottom-left-radius:0}.package-constraint button[data-v-1e421d04]:hover{background:var(--btn-warning-active);border-color:var(--btn-warning-active)}.package-constraint button[data-v-1e421d04]:before{position:absolute;left:50%;top:50%;margin:-10px 0 0 -10px}.package-constraint button.rotate[data-v-1e421d04]:before{animation:release-validating-1e421d04 2s linear infinite}@keyframes release-validating-1e421d04{to{transform:rotate(1turn)}}@media(min-width:1024px){.package-constraint button[data-v-1e421d04],.package-constraint input[type=text][data-v-1e421d04]{height:30px}}.button-group{display:flex;gap:1px;position:relative}.button-group__primary.widget-button{flex-grow:1;border-top-right-radius:0;border-bottom-right-radius:0}.button-group__more.widget-button{flex-shrink:0;width:38px;padding:7px;border-top-left-radius:0;border-bottom-left-radius:0}.button-group__more.widget-button svg{width:24px;height:24px}.button-group__group{position:absolute;top:39px;width:100%;z-index:100}.button-group__group:focus{outline:none}.button-group__group .widget-button{margin-top:1px}.button-group__group .link-menu{margin-top:3px}.button-group__group--top{top:auto;bottom:39px}.button-group__group--top .link-menu{margin-top:0;margin-bottom:3px}.composer-package__stats{display:inline-block;margin-right:15px;padding-left:18px;font-size:13px;background-position:0 50%;background-repeat:no-repeat;background-size:13px 13px}.composer-package__stats--license{padding-left:0}.composer-package__stats--versions{display:inline-flex;flex-wrap:wrap;gap:5px;list-style:none;margin:0 15px 0 0;padding:0}.composer-package__stats--version{padding:3px 5px;line-height:1;border:1px solid var(--border);border-radius:4px}.composer-package__stats--funding{width:16px;background-image:url(../img/funding.cf78a0a0.svg);background-size:16px 16px;background-repeat:no-repeat;text-decoration:none!important}.package-uploads__overlay{top:0;bottom:0;right:0;left:0;position:fixed;z-index:9999;opacity:.6;text-align:center;background:#000}.package-uploads__overlay div{margin:-.5em 0 0;position:absolute;top:50%;left:0;right:0;transform:translateY(-50%);font-size:40px;color:#fff;padding:0}.cloud-status{margin-left:8px;position:relative}.cloud-status__button{margin-left:0;margin-right:0;padding-left:8px;cursor:help!important}.cloud-status__popup{position:absolute;text-align:center;left:0;bottom:55px;margin:0;padding:0 0 15px;outline:none;background:var(--form-bg);color:var(--text);border-bottom:3px solid var(--contao);border-radius:5px;box-shadow:0 0 2px var(--shadow);z-index:100}.cloud-status__popup:after{position:absolute;left:38px;bottom:-6px;width:0;height:0;margin-left:-4px;border-style:solid;border-width:4px 3.5px 0 3.5px;border-color:var(--contao) transparent transparent transparent;content:""}.cloud-status__popup--error{color:var(--clr-btn);background-color:var(--btn-alert);border-color:var(--btn-alert)}.cloud-status__popup--error:after{left:27px;border-color:var(--btn-alert) transparent transparent transparent}.cloud-status__headline{padding:15px 20px 0;font-size:16px;white-space:pre}.cloud-status__version{margin:0 0 8px;font-size:12px}.cloud-status__link{display:inline-block;margin:15px 10px 0}.cloud-status__error{padding:8px 20px 8px;-webkit-hyphens:auto;hyphens:auto}.cloud-status table{width:100%;margin-top:12px;text-align:left;border-spacing:0;border-collapse:collapse}.cloud-status th{padding:3px 5px 3px 20px}.cloud-status td{padding:3px 20px 3px 0}.cloud-status tr:nth-child(odd){background:var(--table-odd-bg)}.package-list{position:relative}.package-list__status{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.package-list__status .sk-circle{width:100px;height:100px;margin:0 auto 40px}.package-list__headline{font-size:18px;font-weight:300;margin:30px 0 10px}.animate-blur-in,.animate-blur-out,.layout-boxed{display:table;width:100%;height:100%}.layout-boxed__cell{display:table-cell;overflow:hidden;vertical-align:middle;padding:10px}.layout-boxed__container{position:relative;max-width:380px;margin:0 auto;background:var(--popup-bg);border-radius:8px}@media(min-width:960px){.layout-boxed__container{margin-top:20px;margin-bottom:20px}.layout-boxed__container--wide{max-width:940px}}.widget-checkbox input{position:absolute;visibility:hidden}.widget-checkbox label{position:relative;display:block;padding-left:25px;text-align:left}.widget-checkbox label:before{content:"";position:absolute;left:0;width:20px;height:20px;background:url(../img/widget-checkbox--off.73856538.svg) 0 0 no-repeat;background-size:20px 20px}.widget-checkbox input:checked+label:before{background-image:url(../img/widget-checkbox--on.8b830157.svg)}.widget-checkbox input:disabled+label{opacity:.5}.widget-checkbox .widget__description{padding-left:25px}.widget-checkbox .widget__description--disabled{opacity:.5}.user-scope__label{margin:0;padding:0}.user-scope__item{padding:5px 0 0}.user-scope__item--required label{opacity:1!important}.user-scope__item--required label:before{opacity:.5}.view-oauth__header{max-width:280px;margin:0 auto 40px;padding-top:40px;text-align:center}.view-oauth__icon{background:var(--contao);border-radius:10px;padding:10px}.view-oauth__product{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-oauth__form{position:relative;max-width:280px;margin:0 auto 60px;text-align:center}.view-oauth__form input,.view-oauth__form select{margin:5px 0 10px}.view-oauth__description{margin-top:.5em;margin-bottom:.5em}.view-oauth__client{margin:1em 0;font-size:32px}.view-oauth__scopes{text-align:left}.view-oauth__warning{color:var(--btn-alert);margin-top:2em;margin-bottom:2em}.view-oauth__button{margin-top:1em}.view-oauth__button .sk-circle{color:#fff;text-align:center}.message-overlay{position:relative}.message-overlay__blur{opacity:.75;filter:blur(2px);transition:opacity .5s,filter .5s}.message-overlay__overlay{position:absolute;display:flex;justify-content:center;align-items:center;left:0;right:0;top:0;bottom:0}.message-overlay__message{padding:10px;font-size:2em;font-weight:400;text-align:center}.maintenance{margin-bottom:14px;background:var(--tiles-bg);border-radius:var(--border-radius)}.maintenance__inside{padding:10px 20px 20px}.maintenance__inside:after{display:table;clear:both;content:""}@media(min-width:1024px){.maintenance__inside{padding:25px 20px}}.maintenance__image{display:none}.maintenance__image img{width:100%;height:100%;border-radius:var(--border-radius);overflow:hidden}@media(min-width:1024px){.maintenance__image{display:block;float:left;width:90px;height:90px;margin-right:20px}}.maintenance__about{margin-bottom:20px}@media(min-width:1024px){.maintenance__about{float:left;width:510px;margin-bottom:0}}.maintenance__about h1{position:relative;margin-bottom:5px}.maintenance__about p{margin:0 0 1em;display:inline}.maintenance__error,.maintenance__warning{position:relative;top:-2px;margin-left:.5em;padding:2px 8px;font-size:14px;line-height:1em;font-weight:300;background:var(--btn-warning);color:var(--clr-btn);border-radius:var(--border-radius)}.maintenance__error{background:var(--btn-alert)}@media(min-width:600px){.maintenance__actions{margin:0 -10px}}@media(min-width:1024px){.maintenance__actions{float:right;width:280px;margin:0 0 0 40px}}.maintenance__actions>.button-group,.maintenance__actions>button{width:100%;margin-bottom:10px}@media(min-width:600px){.maintenance__actions>.button-group,.maintenance__actions>button{float:right;width:calc(50% - 20px);margin:0 10px}}@media(min-width:1024px){.maintenance__actions>.button-group,.maintenance__actions>button{width:100%;margin:0 0 10px}}.maintenance__loader{width:50px;margin:0 auto}.maintenance__loader .sk-circle{width:50px;height:50px}.log-viewer__status{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.log-viewer__status--empty{padding-top:140px;background:url(../img/warning.9a7cd776.svg) top no-repeat;background-size:100px 100px}.log-viewer__status--loader .sk-circle{width:100px;height:100px;margin:0 auto 40px}.log-viewer__status button{margin-top:2em}.log-viewer__loading{width:30px;margin:40px auto}.log-viewer__loading .sk-circle{width:30px;height:30px}.log-viewer__filters{display:flex;justify-content:space-between;flex-wrap:wrap;gap:20px}.log-viewer__filters>div{display:flex;align-items:flex-end;gap:20px}.log-viewer__filters a{flex-shrink:0}.log-viewer__file{flex-shrink:1;display:flex;align-items:flex-end}.log-viewer__file select{border-right:none;border-top-right-radius:0;border-bottom-right-radius:0}.log-viewer__file button{border-top-left-radius:0;border-bottom-left-radius:0}.log-viewer__list{margin-top:2em;padding-bottom:1px;background:var(--form-bg);border-radius:var(--border-radius)}@media(min-width:600px){.log-viewer__list{overflow-y:scroll;max-height:calc(100vh - 300px)}}.log-viewer__line{position:relative;padding:10px 0;border-bottom:1px solid var(--border--light)}@media(min-width:600px){.log-viewer__line{display:flex}}.log-viewer__line:hover{background:var(--focus)}.log-viewer__line:last-child{border-bottom:none}.log-viewer__line--header{display:none}@media(min-width:600px){.log-viewer__line--header{display:flex;position:sticky;top:0;z-index:1;font-weight:600;background:var(--log-header-bg)!important;color:#fff;border-top-left-radius:2px;border-top-right-radius:2px;border-bottom-color:var(--border)}}.log-viewer__line--alert:before,.log-viewer__line--critical:before,.log-viewer__line--emergency:before,.log-viewer__line--error:before,.log-viewer__line--warning:before{content:"";position:absolute;left:0;top:-1px;bottom:-1px;width:4px;background:var(--btn-alert)}.log-viewer__line--warning:before{background:var(--btn-warning)}.log-viewer__line--raw{padding:5px 10px;background:#24292e;border-bottom:none;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:#f6f8fa;font-size:.8em;line-height:1.5;white-space:pre-wrap}.log-viewer__line--raw:hover{background:#2f363d}.log-viewer__more{display:flex;justify-content:center;padding:20px}.log-viewer__content,.log-viewer__meta{padding:10px 20px}.log-viewer__content--header,.log-viewer__meta--header{padding:0 20px!important}.log-viewer__meta{padding-bottom:0;flex-shrink:0;font-style:italic}.log-viewer__meta--header{font-style:normal}@media(min-width:600px){.log-viewer__meta{width:220px;padding-bottom:10px}}.log-viewer__content{flex-grow:1}.log-viewer__datetime{display:block}@media(min-width:600px){.log-viewer__datetime{margin-bottom:1em}}.log-viewer__badge{display:inline-block;margin-right:10px;padding:1px 4px;background:var(--border);border-radius:var(--border-radius);font-size:.9em;font-weight:400;text-transform:lowercase}.log-viewer__badge--desktop{display:none}@media(min-width:600px){.log-viewer__badge--desktop{display:inline-block}.log-viewer__badge--mobile{display:none}}.log-viewer__badge--channel{padding-top:0;padding-bottom:0;border:1px solid var(--border);background:var(--white)}.log-viewer__badge--level-warning{background:var(--btn-warning);color:#fff}.log-viewer__badge--level-alert,.log-viewer__badge--level-critical,.log-viewer__badge--level-emergency,.log-viewer__badge--level-error{background:var(--btn-alert);color:#fff}.log-viewer__message span:nth-child(2n){font-weight:600;color:var(--black)}.log-viewer__details{display:flex;align-items:center;margin-top:1em}.log-viewer__toggle{margin-right:10px;padding:0;border:none;background:none;color:var(--link);text-decoration:none;cursor:pointer}.log-viewer__toggle:hover{text-decoration:underline}.log-viewer__json{margin:10px 0 0}.invite-user__check{text-align:center}.invite-user__check svg{width:60px;height:60px;fill:var(--btn-primary)}.invite-user__check,.invite-user__text{margin-bottom:1em}.invite-user__url{display:block;margin-top:2em}.invite-user__help{display:block;margin-top:1em;font-size:12px}.invite-user__clipboard{margin:1em 0}.widget-text input::-webkit-inner-spin-button,.widget-text input::-webkit-outer-spin-button{display:none}.widget-text input[type=number]{-webkit-appearance:textfield!important;-moz-appearance:textfield!important;appearance:textfield!important}.widget-text--password input{padding-right:40px!important}.widget__password-toggle{position:absolute;right:8px;bottom:2px;padding:0;margin:0;background:none;border:none;cursor:pointer}.widget__password-toggle--hidden svg{fill:var(--btn-primary)}.widget__password-toggle--visible svg{fill:var(--btn)}.setup-totp__qr{margin:2em;text-align:center}.setup-totp__qr svg{width:200px;height:200px}.setup-totp__uri{display:block;margin:1em 0;word-break:break-all}.disable-totp__text{margin-bottom:1em}.change-password .widget{margin:1em 0 0}.user-manager__loading{margin:100px 0;text-align:center;font-size:20px;line-height:1.5em}.user-manager__loading .sk-circle{width:100px;height:100px;margin:0 auto 40px}.user-manager__list{display:grid;grid-template:1fr/1fr;gap:20px}@media(min-width:600px){.user-manager__list{grid-template:1fr/repeat(2,1fr)}}@media(min-width:800px){.user-manager__list{grid-template:1fr/repeat(3,1fr)}}@media(min-width:1200px){.user-manager__list{grid-template:1fr/repeat(4,1fr)}}.user-manager__item{position:relative;overflow:hidden;display:flex;flex-direction:column;padding:16px;background:var(--tiles-bg);border:1px solid 1px solid var(--tiles-bdr);border-radius:14px}.user-manager__you{position:absolute;top:15px;right:-25px;width:100px;color:#fff;font-weight:600;line-height:1.5;text-align:center;background:var(--btn-primary);transform-origin:center center;transform:rotate(45deg)}.user-manager__new{margin-top:60px;text-align:center}.user-manager__spacer{flex-grow:1;min-height:1em}.user-manager__username{font-size:18px;font-weight:600}.user-manager__scope{margin-top:1em}.user-manager .widget-button{margin-top:5px}.view-error{position:fixed;left:0;right:0;top:0;bottom:0;padding:10px;color:#e8e8e8;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:13px;line-height:1.2;background-color:rgba(0,0,0,.851);background-position:0 0;background-repeat:repeat;z-index:9998}.view-error,.view-error__close{display:flex;justify-content:center;align-items:center}.view-error__close{position:absolute;top:15px;right:10px;width:35px;height:35px;background:none;border:none;cursor:pointer;z-index:10}.view-error__close:hover{border:1px solid #fff}.view-error__content{display:flex;flex-direction:column;align-items:center;max-width:800px;max-height:100vh;line-height:1.5;text-align:center}.view-error__icon{display:block;height:100px;margin:2em 0;fill:#fff}.view-error__status{margin-bottom:1em;padding:2px 4px;background-color:#e36049;border-radius:var(--border-radius)}.view-error__headline{margin:0;font-size:1em;line-height:1.5}.view-error__status a{color:#e8e8e8;text-decoration:underline}.view-error__details{display:block;margin-top:2em;white-space:pre-line}.view-error__debug{align-self:flex-start;max-height:60vh;overflow-y:auto;margin-top:2em;text-align:left;white-space:pre-line}.view-error__actions{margin:4em 0;text-align:center}.view-error__link{margin:10px;padding:10px 20px;border:1px solid #fff;border-radius:4px;color:#fff}.button-menu{position:relative}.button-menu__primary.widget-button{float:left;width:calc(100% - 39px);border-top-right-radius:0;border-bottom-right-radius:0}.button-menu__more.widget-button{float:right;width:38px;padding:7px;border-top-left-radius:0;border-bottom-left-radius:0}.button-menu__more.widget-button svg{width:24px;height:24px}.button-menu__menu{display:flex;flex-direction:column;position:absolute;top:38px;right:0;width:auto;z-index:100;background:var(--form-bg);border-radius:var(--border-radius)}.button-menu__menu:before{content:"";position:absolute;top:-5px;right:15px;width:0;height:0;border-right:none;border-bottom:none;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid var(--form-bg)}.button-menu__menu:focus{outline:none}.button-menu__menu button{padding:8px 16px;background:none;border:none;text-align:left;white-space:nowrap;border-bottom:1px solid var(--border);cursor:pointer}.button-menu__menu button:hover{color:var(--text);background:var(--focus)}.button-menu__menu button:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.button-menu__menu button:last-child{border-bottom:none;border-bottom-left-radius:2px;border-bottom-right-radius:2px}.button-menu__menu .link-menu{margin-top:3px}.console-operation{position:relative;padding:0 16px;text-align:left;font-size:12px;color:#959da5}.console-operation__summary{margin-left:13px;padding:8px;box-sizing:border-box;outline:none}.console-operation__summary--console{margin-left:0}.console-operation summary{cursor:pointer}.console-operation__status{display:inline-block;position:relative;box-sizing:border-box;padding-right:8px;width:24px;height:18px;text-align:center;vertical-align:middle}.console-operation__icon{position:absolute;left:0;top:0}.console-operation__icon--skipped{fill:#666b71}.console-operation__icon--pending{fill:#dbab0a}.console-operation__icon--active{fill:#dbab0a;animation:console-active 1s linear infinite}@keyframes console-active{0%{transform:rotate(0deg)}50%{transform:rotate(180deg)}to{transform:rotate(359deg)}}.console-operation__icon--success{fill:var(--btn-primary)}.console-operation__icon--error{fill:var(--btn-alert)}.console-operation__label{display:inline-block;overflow:hidden;max-width:750px;vertical-align:top}.console-operation__title{display:inline;margin:0;color:#fff}.console-operation__title--disabled{text-decoration:line-through}.console-operation__description{display:inline;margin:0 0 0 10px}.console-operation__console{position:relative;overflow-y:auto;max-height:280px}.console-operation__lines{padding:8px 0 16px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:#f6f8fa;line-height:1.5;white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word}.console-operation__line{display:flex}.console-operation__line:hover{background-color:#2f363d}.console-operation__line-number{display:inline-block;overflow:hidden;width:48px;min-width:48px;color:#959da5;text-align:right;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;user-select:none}.console-operation__line-content{display:inline-block;margin-left:16px;vertical-align:middle}.console-operation__scroll{position:sticky;left:0;right:0;display:flex;justify-content:center;align-items:flex-end;width:100%;height:30px;padding:0;border:none;cursor:pointer}.console-operation__scroll svg{fill:#fff;width:16px;height:16px}.console-operation__scroll--top{top:0;background:linear-gradient(#24292e,rgba(36,41,46,.502) 50%)}.console-operation__scroll--top svg{transform:rotate(180deg)}.console-operation__scroll--bottom{bottom:0;background:linear-gradient(rgba(36,41,46,.502),#24292e 50%)}.console-operation__scroll--bottom svg{transform:rotate(0deg)}.console{background:#24292e;border-radius:8px}.console__header{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;padding:12px 12px 12px 24px;border-bottom:1px solid #444d56}.console__headline{margin:0;font-size:inherit;line-height:1.5;color:#fff}.console__description{color:#959da5;font-size:12px}.console__actions{display:flex;flex-wrap:nowrap;align-items:center}.console__action,.console__action>button{height:30px!important;line-height:30px!important;width:auto!important;min-width:0;margin:0 2px;padding:0 5px!important;border:none!important}.console__action:hover,.console__action>button:hover{background-color:#2f363d!important}.console__action--active,.console__action>button--active{background-color:#586069!important}.console__operations{padding:20px 0}.view-task__header{margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.view-task__icon{background:var(--contao);border-radius:10px;padding:10px}.view-task__headline{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-task__description{margin:0;font-weight:600}.view-task__actions{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-top:2em}@media(min-width:960px){.view-task__actions{flex-direction:row}}.view-task .widget-button{width:280px;height:35px;margin:5px;padding:0 30px;line-height:35px}@media(min-width:960px){.view-task .widget-button{width:auto}}.view-task__main{margin:0 50px 50px}.view-task__loading{width:30px;margin:40px auto}.view-task__loading .sk-circle{width:30px;height:30px}.view-task__sponsor{margin:-30px 50px 50px;text-align:center}@media(min-width:960px){.view-task__sponsor br{display:none}}.view-task__donate{position:relative;top:5px;margin-left:.5em;line-height:0}:root{--text:#535353;--link:#f47c00;--body-bg:#ebe6db;--link-footer:#2a7887;--tiles-bg:#fff;--tiles-bdr:#ddd3bc;--popup-hl-bg:#f47c00;--popup-bg:#fff;--popup-header:#fff;--popup-overlay-bg:hsla(41,29%,89%,.35);--tab-content:#f8f9fb;--highlight-bg:#ff0;--highlight-color:#535353;--shadow:#ccbfa2;--contao:#f47c00;--badge-bg:var(--contao);--ad-shadow:0 1px 5px 1px rgba(0,0,0,.2);--black:#000;--funding:#ea4aaa;--funding-rgb:234,74,170;--form-bg:#fff;--border:#ccc;--border--light:#e9eef1;--focus:#f9f9f9;--clr-btn:#fff;--btn:#737373;--btn-active:#666;--btn-primary:#31a64b;--btn-primary-active:#2b9242;--btn-warning:#db8c41;--btn-warning-active:#d77f2c;--btn-alert:#db5041;--btn-alert-active:#d73c2c;--btn-info:#6a8ca6;--btn-info-active:#5c7f9a;--btn-funding:#ea4aaa;--btn-funding-active:#e7339f;--btn-disabled:#ccc;--hint-bg:#e8c8bc;--hint-rgb:232,200,188;--hint-link:#bd2e20;--header-bg:#e5dfcf;--header-bdr:#dcd8cc;--footer-bdr:#bbb;--svg--link-blank:url(../img/link-blank.eb57b3fa.svg);--svg--private:url(../img/private.a1c65662.svg);--svg--updated:url(../img/updated.3b47bebb.svg);--svg--downloads:url(../img/downloads.c1db2a9e.svg);--svg--favers:url(../img/favers.056e2836.svg);--svg--language:url(../img/language.582b2920.svg);--svg--color-scheme:url(../img/color_scheme.d527d153.svg)}html[data-color-scheme=dark]{color-scheme:dark;--text:#ddd;--link:#f47c00;--body-bg:#0f0f11;--tiles-bg:#212227;--tiles-bdr:#303236;--popup-hl-bg:#292c32;--popup-bg:#1b1d21;--popup-overlay-bg:rgba(0,0,0,.35);--tab-content:#212227;--highlight-bg:#f47c00;--highlight-color:#fff;--shadow:transparent;--badge-bg:var(--border--light);--ad-shadow:none;--btn:#3c3f4c;--btn-active:#25272f;--black:#fff;--form-bg:#151619;--border:#44464b;--border--light:#2e2e34;--focus:#1e2024;--btn-info:#25455f;--btn-info-active:#253846;--btn-disabled:#151517;--opacity-disabled:0.5;--hint-rgb:57,9,20;--header-bg:#1b1d21;--header-bdr:#1b1d21;--footer-bdr:#414448;--svg--link-blank:url(../img/link-blank--dark.07eeaee6.svg);--svg--private:url(../img/private--dark.41b90022.svg);--svg--updated:url(../img/updated--dark.c21fdd5b.svg);--svg--downloads:url(../img/downloads--dark.034bf7a3.svg);--svg--favers:url(../img/favers--dark.4765f7d4.svg);--svg--language:url(../img/language--dark.a24e849e.svg);--svg--color-scheme:url(../img/color_scheme--dark.ef0f0aed.svg)}html[data-color-scheme=dark] #contao-network{background:#292c32!important;color:#ddd!important}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}#app,body,html{height:100%}blockquote,body,figure,form,p{margin:0;padding:0}article,aside,figcaption,figure,footer,header,main,nav,section{display:block}body,div,fieldset,form,h1,h2,h3,h4,h5,h6,html,p{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none}body{background:var(--body-bg);overflow-y:hidden}#app{overflow-y:scroll}fieldset{border:none;margin:0;padding:0}legend{-webkit-padding-start:0;-webkit-padding-end:0}figure{line-height:0}body,button,input,textarea{font:300 14px/1.4 -apple-system,system-ui,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;color:var(--text)}strong{font-weight:600}code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}input,select,textarea{font-size:99%}input:disabled,select:disabled,textarea:disabled{color:var(--text);-webkit-text-fill-color:var(--text);cursor:text}input::-ms-clear,input::-ms-reveal,select::-ms-clear,select::-ms-reveal,textarea::-ms-clear,textarea::-ms-reveal{display:none}.invisible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}h1,h2,h3,h4,h5,h6{font-size:inherit;line-height:inherit;font-weight:600;margin:0}a{color:var(--link);text-decoration:none}a:hover{text-decoration:underline}h1{font-size:18px;line-height:30px;margin-bottom:10px}@keyframes input-error{0%{left:0}25%{left:-5px}75%{left:5px}to{left:0}}.widget{position:relative}.widget__error{display:none;position:absolute;left:0;right:0;margin:0;padding:4px 10px;color:var(--clr-btn);background:var(--btn-alert);border-radius:2px;transform:translateY(6px);z-index:10;white-space:pre-line}.widget__error:after,.widget__error:before{bottom:100%;left:30px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.widget__error:after{border-bottom-color:var(--btn-alert);border-width:3px;margin-left:-3px}.widget__error:before{border-bottom-color:var(--btn-alert);border-width:5px;margin-left:-5px}input:focus+*+.widget__error,input:focus+.widget__error,input:hover+*+.widget__error,input:hover+.widget__error,select:hover+.widget__error{display:block}.widget__description{margin-top:2px;font-size:12px}input:not([type=checkbox]):not([type=radio]),select{position:relative;width:100%;height:38px;padding:0 20px;background:var(--form-bg);border:1px solid var(--border);border-radius:6px;color:var(--text);-webkit-appearance:none;-moz-appearance:none;appearance:none}input:not([type=checkbox]):not([type=radio]):focus,select:focus{outline:none;background-color:var(--focus)}.widget--validate input:not([type=checkbox]):not([type=radio]):not(:-moz-placeholder-shown):valid,.widget--validate select:not(:-moz-placeholder-shown):valid{border-color:var(--btn-primary)}.widget--validate input:not([type=checkbox]):not([type=radio]):not(:placeholder-shown):valid,.widget--validate select:not(:placeholder-shown):valid{border-color:var(--btn-primary)}.widget--validate input:not([type=checkbox]):not([type=radio]):not(:-moz-placeholder-shown):invalid,.widget--validate select:not(:-moz-placeholder-shown):invalid{border-color:var(--btn-alert)}.widget--validate input:not([type=checkbox]):not([type=radio]):not(:placeholder-shown):invalid,.widget--validate select:not(:placeholder-shown):invalid{border-color:var(--btn-alert)}.widget--error input:not([type=checkbox]):not([type=radio]),.widget--error select{border-color:var(--btn-alert);animation:input-error .15s linear 3}select{padding-right:30px}.widget-select:after{position:absolute;right:12px;bottom:16px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid var(--border);content:"";pointer-events:none}.widget-button{display:inline-block;width:100%;height:38px;padding:0;border:none;background-color:var(--btn);color:var(--clr-btn);font-weight:600;line-height:38px;text-decoration:none;text-align:center;white-space:nowrap;cursor:pointer;border-radius:5px}.widget-button:active,.widget-button:hover{background-color:var(--btn-active)}.widget-button--inline{width:auto!important;min-width:100px;padding:0 20px}.widget-button--transparent{background:transparent}.widget-button--small{height:28px;width:auto!important;min-width:0;padding:0 15px;font-size:13px;line-height:28px;font-weight:300}.widget-button--small:before,.widget-button--small>:before{top:3px!important;width:15px!important;height:15px!important;margin-right:6px!important;background-size:15px 15px!important}.widget-button--primary{--btn:var(--btn-primary);--btn-active:var(--btn-primary-active)}.widget-button--warning{--btn:var(--btn-warning);--btn-active:var(--btn-warning-active)}.widget-button--alert{--btn:var(--btn-alert);--btn-active:var(--btn-alert-active)}.widget-button--info{--btn:var(--btn-info);--btn-active:var(--btn-info-active)}.widget-button--funding{--btn:var(--btn-funding);--btn-active:var(--btn-funding-active)}.widget-button--add:before{background-image:url(../img/button-add.759df12e.svg)}.widget-button--check:before{background-image:url(../img/button-check.7a3b5ada.svg)}.widget-button--clipboard:before{background-image:url(../img/button-clipboard.9ef63d39.svg)}.widget-button--cloud:before{background-image:url(../img/button-cloud.bc42f267.svg)}.widget-button--cloud-off:before{background-image:url(../img/button-cloud-off.dd8ba18e.svg)}.widget-button--console:before{background-image:url(../img/button-console.05dcdfc4.svg)}.widget-button--database:before{background-image:url(../img/button-database.5282fc7e.svg)}.widget-button--download:before{background-image:url(../img/button-download.e1ba6f25.svg)}.widget-button--edit:before{background-image:url(../img/button-edit.40a4be06.svg)}.widget-button--gear:before{background-image:url(../img/button-gear.a2dc1f09.svg)}.widget-button--hide:before{background-image:url(../img/button-hide.d23f6533.svg)}.widget-button--details:before{background-image:url(../img/button-details.161475b3.svg)}.widget-button--link:before{background-image:url(../img/button-link.dd42e161.svg)}.widget-button--lock:before{background-image:url(../img/button-lock.98988f08.svg)}.widget-button--maintenance:before{background-image:url(../img/button-maintenance.93830369.svg)}.widget-button--more:before{background-image:url(../img/button-more.e3eb2622.svg)}.widget-button--power:before{background-image:url(../img/button-power.298a8072.svg)}.widget-button--run:before{background-image:url(../img/button-run.b6310c5a.svg)}.widget-button--save:before{background-image:url(../img/button-save.3b5224de.svg)}.widget-button--search:before{background-image:url(../img/button-search.44ce1d4b.svg)}.widget-button--show:before{background-image:url(../img/button-show.2336e1d9.svg)}.widget-button--trash:before{background-image:url(../img/button-trash.855f57fa.svg)}.widget-button--unlock:before{background-image:url(../img/button-unlock.51b76e07.svg)}.widget-button--update:before{background-image:url(../img/button-update.ad79c617.svg)}.widget-button--upload:before{background-image:url(../img/button-upload.ca8e9cfc.svg)}.widget-button .icon-selector:before,.widget-button--add:before,.widget-button--check:before,.widget-button--clipboard:before,.widget-button--cloud-off:before,.widget-button--cloud:before,.widget-button--console:before,.widget-button--database:before,.widget-button--details:before,.widget-button--download:before,.widget-button--edit:before,.widget-button--gear:before,.widget-button--hide:before,.widget-button--link:before,.widget-button--lock:before,.widget-button--maintenance:before,.widget-button--more:before,.widget-button--power:before,.widget-button--run:before,.widget-button--save:before,.widget-button--search:before,.widget-button--show:before,.widget-button--trash:before,.widget-button--unlock:before,.widget-button--update:before,.widget-button--upload:before{position:relative;display:inline-block;top:5px;width:20px;height:20px;margin-right:8px;background-position:50%;background-repeat:no-repeat;background-size:20px 20px;content:""}.widget-button .icon-selector:empty:before,.widget-button--add:empty:before,.widget-button--check:empty:before,.widget-button--clipboard:empty:before,.widget-button--cloud-off:empty:before,.widget-button--cloud:empty:before,.widget-button--console:empty:before,.widget-button--database:empty:before,.widget-button--details:empty:before,.widget-button--download:empty:before,.widget-button--edit:empty:before,.widget-button--gear:empty:before,.widget-button--hide:empty:before,.widget-button--link:empty:before,.widget-button--lock:empty:before,.widget-button--maintenance:empty:before,.widget-button--more:empty:before,.widget-button--power:empty:before,.widget-button--run:empty:before,.widget-button--save:empty:before,.widget-button--search:empty:before,.widget-button--show:empty:before,.widget-button--trash:empty:before,.widget-button--unlock:empty:before,.widget-button--update:empty:before,.widget-button--upload:empty:before{margin-right:0!important}.widget-button:empty{min-width:auto;padding:0 10px}.widget-button:empty:before{margin-right:0!important}.widget-button:hover{text-decoration:none}.widget-button.disabled,.widget-button:disabled{background-color:var(--btn-disabled)!important;border-color:var(--btn-disabled)!important;cursor:not-allowed;opacity:var(--opacity-disabled,1)}.widget-button.disabled{pointer-events:none}.widget-button--anchor{height:auto;background:none!important;line-height:inherit;font-weight:inherit;color:var(--link);text-decoration:none;cursor:pointer}.widget-button--anchor:hover{text-decoration:underline!important}.widget-button--anchor.disabled,.widget-button--anchor:disabled{background:none!important}label{padding:0}.widget--required label:after{margin-left:2px;content:"*";color:var(--btn-alert)}input:-webkit-autofill,select:-webkit-autofill{-webkit-text-fill-color:var(--text);-webkit-box-shadow:inset 0 0 0 1000px hsla(0,0%,100%,0);-webkit-transition:background-color 5000s ease-in-out 0s;transition:background-color 5000s ease-in-out 0s}.animate-initializing{animation:initializing 1s linear infinite}@keyframes initializing{0%{opacity:.5}50%{opacity:1}to{opacity:.5}}.animate-blur-in{z-index:-1;opacity:.5;filter:blur(4px);transition:opacity .35s,filter .5s}.animate-blur-out{opacity:1;transition:opacity .35s}.animate-fade-enter-active,.animate-fade-leave-active{transition-duration:.2s;transition-property:opacity;transition-timing-function:ease}.animate-fade-enter,.animate-fade-leave-active{opacity:0}.animate-flip-enter-active,.animate-flip-leave-active{transform-style:preserve-3d;backface-visibility:hidden;transition-duration:.5s;transition-property:transform,opacity}.animate-flip-leave-active{transform:perspective(600px) rotateY(0deg);opacity:1}.animate-flip-leave-to{transform:perspective(600px) rotateY(90deg);transition-timing-function:ease-in;opacity:0}.animate-flip-enter-active{transform:perspective(400px) rotateY(270deg);opacity:0}.animate-flip-enter-to{transform:perspective(400px) rotateY(1turn);transition-timing-function:ease-out;opacity:1}:root{--header-main-bg:#fff;--footer-fragment-bdr:#eee;--table-odd-bg:#f5f9fa;--border-radius:6px;--log-header-bg:var(--shadow)}html[data-color-scheme=dark]{--header-main-bg:#292c32;--footer-fragment-bdr:var(--footer-bdr);--table-odd-bg:var(--tiles-bg);--link-footer:#fff;--hint-bg:#151619;--hint-rgb:21,22,25;--log-header-bg:var(--btn)}html[data-color-scheme=dark] .vjs-tree-node:hover{background-color:#2b3439}.color-scheme--light,html[data-color-scheme=dark] .color-scheme--dark{display:initial}.color-scheme--dark,html[data-color-scheme=dark] .color-scheme--light{display:none}.app-hint{position:absolute;top:0;left:0;right:0;height:27px;padding:4px 8px;background:var(--btn-info);color:#fff;text-align:center;z-index:100}.app-hint--warning{background:var(--btn-warning)}.app-hint--alert{background:var(--btn-alert)}.app-hint__description{display:none}@media(min-width:600px){.app-hint__description{display:inline}}.app-hint__link{margin:0;padding:0;background:none;border:none;color:#fff;text-decoration:underline;cursor:pointer}.app-hint+div{padding-top:25px}.view-init{display:table;width:100%;height:100%}.view-init__cell{display:table-cell;font-size:1.5em;text-align:center;vertical-align:middle}.database-migration__header{margin-left:auto;margin-right:auto;padding:40px 0;text-align:center}.database-migration__icon{background:var(--contao);border-radius:10px;padding:10px}.database-migration__headline{margin-top:.5em;margin-bottom:.5em;font-size:36px;font-weight:100;line-height:1}.database-migration__description{margin:0 50px;font-weight:600}.database-migration__actions{display:flex;flex-direction:column;justify-content:center;align-items:center;margin-top:2em;padding:0 50px}@media(min-width:960px){.database-migration__actions{flex-direction:row}}.database-migration .widget-button{width:280px;height:35px;margin:5px;padding:0 30px;line-height:35px}@media(min-width:960px){.database-migration .widget-button{width:auto}}.database-migration__main{margin:0 50px 50px;background:#24292e}.database-migration__loading{width:30px;margin:40px auto}.database-migration__loading .sk-circle{width:30px;height:30px}.view-recovery__header{max-width:280px;margin-left:auto;margin-right:auto;padding:40px 0 10px;text-align:center}.view-recovery__icon{background:var(--contao);border-radius:10px;padding:10px}.view-recovery__headline{margin-top:15px;font-size:36px;font-weight:100;line-height:1}.view-recovery__content{margin:0 30px 50px}@media(min-width:960px){.view-recovery__content{margin-left:50px;margin-right:50px}}.view-recovery__description{font-weight:600;max-width:600px;margin:0 auto;text-align:center}.view-recovery__console{margin:30px 0 60px}.view-recovery__option{margin:50px 0 0;padding:20px 20px 30px;background:var(--table-odd-bg);text-align:center}.view-recovery__option h3{position:relative;top:-40px;margin-bottom:-25px;font-size:2em;font-weight:300}.view-recovery__option button{margin-top:1.5em}.view-recovery__failed{margin:10px 0;color:var(--btn-alert);font-weight:600}"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[120],{8120:function(e){e.exports=JSON.parse('{"ui.app.title":"Extensions Contao","ui.app.loading":"Chargement de la liste des extensions…","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Publicité dans la liste des extensions","ui.discover.loading":"Chargement…","ui.discover.offline":"Impossible de récupérer des résultats.","ui.discover.offlineExplain":"Vérifiez votre connexion Internet et désactivez les bloqueurs JavaScript dans votre navigateur.","ui.discover.offlineButton":"Réessayer","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"Pas de résultats pour {query}","ui.discover.more":"Plus de résulats","ui.discover.sortBy":"Trier par","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Mis à jour","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Téléchargements","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Note","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Détails","ui.discover.latestPackages":"Extensions les plus récentes et mises à jour","ui.discover.faversPackages":"Extensions les mieux notées","ui.discover.downloadsPackages":"Extensions les plus téléchargées","ui.package.homepage":"Site web du projet","ui.package.private":"Package privé","ui.package.privateTitle":"Les packages privés ne sont disponibles que chez le fournisseur (par exemple sous forme de téléchargement ZIP). Veuillez visiter le site Web pour plus d\'informations","ui.package.abandoned":"abandonné","ui.package.abandonedText":"Ce package est abandonné et n\'est plus maintenu.","ui.package.abandonedReplace":"Ce package est abandonné et n\'est plus maintenu. L\'auteur suggère d\'utiliser le package {replacement} à la place.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Extension précédente","ui.package-details.close":"Fermer les détails","ui.package-details.loading":"Chargement…","ui.package-details.tabDescription":"Description","ui.package-details.tabRequire":"Prérequis","ui.package-details.tabFeatures":"Fonctionnalités","ui.package-details.tabSuggest":"Suggestions","ui.package-details.tabConflict":"Conflits","ui.package-details.tabDependents":"Dépendants","ui.package-details.linkRequires":"nécessite","ui.package-details.linkReplaces":"remplaces","ui.package-details.linkProvides":"fournis","ui.package-details.linkConflicts":"conflits","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Dernière version","ui.package-details.released":"Publié le","ui.package-details.license":"License(s)","ui.package-details.authors":"de","ui.package-details.more":"Plus","ui.package-details.packagist":"Détails du Package","ui.package-details.metadata":"Editer les Metadata","ui.package-details.support_docs":"Documentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support","ui.package-details.support_issues":"Issues / Bug Report","ui.package-details.support_source":"Code source","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[523],{523:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Erweiterungen","ui.app.loading":"Lade Erweiterungsliste …","ui.app.language":"Sprache für den Contao Manager wechseln","ui.app.colorDark":"Dunkles Design","ui.app.colorDarkTitle":"Farbschema auf dunkel umstellen","ui.app.colorLight":"Helles Design","ui.app.colorLightTitle":"Farbschema auf hell umstellen","ui.discover.advertisement":"Anzeigen in der Erweiterungsliste","ui.discover.loading":"Laden …","ui.discover.offline":"Konnte keine Ergebnisse laden.","ui.discover.offlineExplain":"Prüfe deine Internet-Verbindung und deaktiviere alle JavaScript-Blocker.","ui.discover.offlineButton":"Erneut versuchen","ui.discover.searchPlaceholder":"{count} Erweiterungen durchsuchen …","ui.discover.empty":"Keine Ergebnisse für {query}","ui.discover.more":"Mehr Resultate","ui.discover.sortBy":"Sortieren nach","ui.discover.sortReleased":"Veröffentlicht","ui.discover.sortReleasedTitle":"Ergebnisse nach der Veröffentlichung sortieren","ui.discover.sortLatest":"Aktualisiert","ui.discover.sortLatestTitle":"Ergebnisse nach der letzten Aktualisierung sortieren","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Ergebnisse nach Anzahl Downloads sortieren","ui.discover.sortFavers":"Bewertung","ui.discover.sortFaversTitle":"Ergebnisse nach Bewertung sortieren","ui.discover.detailsButton":"Details","ui.discover.latestPackages":"Neuste und aktualisierte Erweiterungen","ui.discover.faversPackages":"Bestbewertete Erweiterungen","ui.discover.downloadsPackages":"Meistgeladene Erweiterungen","ui.package.homepage":"Projektwebseite","ui.package.private":"Privates Paket","ui.package.privateTitle":"Private Pakete sind nur vom jeweiligen Hersteller verfügbar (z.B. als ZIP-Download). Besuche die Webseite für weitere Informationen.","ui.package.abandoned":"verwaist","ui.package.abandonedText":"Diese Erweiterung ist verwaist und wird nicht mehr gepflegt.","ui.package.abandonedReplace":"Diese Erweiterung ist verwaist und wird nicht mehr gepflegt. Der Autor empfiehlt stattdessen das Paket {replacement} zu verwenden.","ui.package.contaoVersion":"Verfügbar für Contao","ui.package-details.previous":"Details der vorherigen Erweiterung","ui.package-details.close":"Details der Erweiterung schließen","ui.package-details.loading":"Laden …","ui.package-details.tabDescription":"Beschreibung","ui.package-details.tabRequire":"Abhängigkeiten","ui.package-details.tabFeatures":"Funktionen","ui.package-details.tabSuggest":"Empfehlungen","ui.package-details.tabConflict":"Konflikte","ui.package-details.tabDependents":"Abhängige","ui.package-details.linkRequires":"benötigt","ui.package-details.linkReplaces":"ersetzt","ui.package-details.linkProvides":"liefert","ui.package-details.linkConflicts":"inkompatibel mit","ui.package-details.funding":"Weiterentwicklung finanzieren!","ui.package-details.contaoVersions":"Unterstützte Contao-Version(en)","ui.package-details.latest":"Neuste Version","ui.package-details.released":"veröffentlicht am","ui.package-details.license":"Lizenz(en)","ui.package-details.authors":"von","ui.package-details.more":"Mehr","ui.package-details.packagist":"Paketdetails","ui.package-details.metadata":"Metadaten bearbeiten","ui.package-details.support_docs":"Dokumentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support-Forum","ui.package-details.support_issues":"Fehler melden","ui.package-details.support_source":"Quellcode","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS-Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[606],{2225:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Ligação Insegura !!","ui.app.httpsDescription":"Sem recurso a HTTPS os seus dados confidenciais serão transferidos sem encriptação.","ui.app.httpsLink":"Mais info","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Modo Guardar activado !!","ui.app.safeModeDescription":"Algumas características do Gestor de Contacto não estão disponíveis.","ui.app.safeModeExit":"Sair do modo seguro","ui.app.limitedHeadline":"Autenticação remota","ui.app.limitedDescription":"You have limited permissions due to passwordless login.","ui.app.limitedLogout":"Re-authenticate","ui.app.totpHeadline":"Security Notice","ui.app.totpDescription":"Configure two-factor authentication now to secure your account.","ui.app.totpSetup":"Configuração","ui.app.loading":"A iniciar o Contao Manager ...","ui.app.apiError":"API status não esperado -erro","ui.app.configSecurity1":"ALERTA DE SEGURANÇA!!! Directório de configuração sem protecção detectado","ui.app.configSecurity2":"O Contao Manager detetou que os seus ficheiros de configuração estão acessíveis publicamente. Todas as operações estão desativadas até que o directório esteja seguro, caso contrário um atacante poderá aceder a informações sensíveis sobre a sua instalação.\\n\\nPara corrigir esta situação, certifique-se que previne o acesso ao directório \\"contao-manager\\" no seu servidor. Para saber como o fazer, consulte o manual do seu webserver ou contacte o fornecedor de alojamento web.","ui.account.welcome":"Bem Vindo","ui.account.intro1":"Bem-vindo ao Contao Manager, uma ferramenta universal para instalar e gerir o Contao Open Source CMS. Se é novo nele, por favor {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} para começar","ui.account.introManual":"ler o manual","ui.account.intro2":"Se encontrar algum problema, verifique {ourGithubIssues} e sinta-se à vontade para criar um novo para qualquer coisa que ainda não tenha sido relatada.","ui.account.introIssues":"as nossas edições GitHub","ui.account.headline":"Utilizador","ui.account.description":"Para gerir a sua instalação, por favor crie uma conta para utilizar no Contao Manager. Certifique-se que é distinta da conta utilizada no Contao back e front end.","ui.account.username":"Utilizador","ui.account.password":"Senha","ui.account.passwordPlaceholder":"min. 8 caracteres","ui.account.passwordLength":"Por favor utilize o minimo de 8 caracteres.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Criar Conta","ui.account.usePassword":"Use password for login","ui.account.usePasskey":"Use Passkey for login","ui.account.totpHeadline":"Two-factor authentication","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Configure now","ui.account.totpSkip":"Configure later","ui.account.login":"Decline Invitation","ui.account.contribute1":"O Contao e o Contao Manager são patrocinados pela Associação Contao sem fins lucrativos.","ui.account.contribute2":"Por favor, considere contribuir para o código aberto por {donate}.","ui.account.contributeDonate":"fazer um donativo","ui.login.headline":"Iniciar sessão","ui.login.description":"Iniciar sessão para gerir a sua instalação.","ui.login.username":"Utilizador","ui.login.password":"Senha","ui.login.totpHeadline":"Two-factor authentication","ui.login.totpDescription":"Please enter your verification code to complete the login process.","ui.login.totp":"Verification code","ui.login.forgotPassword":"Esqueceu a sua senha?","ui.login.button":"Iniciar sessão","ui.login.passkey":"Sign In with Passkey","ui.login.cancel":"Cancelar","ui.login.locked":"O acesso foi negado porque o Gestor de Contacto está bloqueado. Para desbloquear, apagar o ficheiro {lockFile} no directório raiz do seu Contao.","ui.logout.headline":"Tempo de Sessão expirado.","ui.logout.warning":"Esteve inactivo por mais de 25 minutos. Por razões de segurança a sua sessão será terminada em breve.","ui.logout.expired":"A sua sessão foi terminada automaticamente porque esteve inactivo por mais de 30 minutos.","ui.logout.renew":"Manter sessão ativa","ui.logout.logout":"Terminar Sessão","ui.logout.login":"Voltar para inicio de sessão","ui.oauth.error":"Tentativa OAuth inválida. Verifique os parâmetros pedidos.","ui.oauth.https":"O redireccionamento do URI DEVE utilizar um protocolo seguro (https:) para evitar que o símbolo de autenticação seja transmitido em texto claro.","ui.oauth.headline":"Autenticação remota","ui.oauth.description":"A seguinte aplicação ou serviço está a solicitar acesso remoto ao Contao Manager.","ui.oauth.domain":"Antes de permitir o acesso, certifique-se de que conhece este URL e confie no seu proprietário!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Permitir Acesso","ui.oauth.deny":"Negar Acesso","ui.oauth.switchUser":"Switch User","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"Verificar Sistema","ui.boot.description":"Por favor espere, estamos a analisar o seu servidor...","ui.boot.issue1":"Problemas com a instalação detectados","ui.boot.issue2":"A sua instalação tem problemas que têm de ser resolvidos antes que o Gestor de Contacto possa ser utilizado.","ui.boot.run":"Iniciar o Contao Manager","ui.boot.safeMode":"Executar em Modo de Segurança","ui.recovery.headline":"Recuperação de Sistema","ui.recovery.description":"O Contao Manager detectou ficheiros que podem pertencer ao Contao, mas a linha de comandos não funciona como previsto.","ui.recovery.console":"Saída da Consola","ui.recovery.repairOptions":"Por favor escolha uma opção para reparar a sua instalação.","ui.recovery.repairHeadline":"Reparação Automática","ui.recovery.repairDescription":"Efectua uma tentativa de reparar automaticamente a instalação ao reconstruir a cache da aplicação e reinstalando os pacotes Composer.","ui.recovery.repairWarning":"Quaisquer modificações aos ficheiros vendor poderão ser apagadas durante o processo!","ui.recovery.repairFailed":"A reparação automática não teve sucesso. Usar o modo de segurança para reparar manualmente a instalação poderá resolver o problema.","ui.recovery.repairButton":"Executar Reparação de Sistema","ui.recovery.safeModeHeadline":"Modo de Segurança ","ui.recovery.safeModeDescription":"Executar o Contao Manager em Modo de Segurança permite gerir pacotes e correr tarefas de manutenção específicas, mas implementações que dependam de uma instalação Contao funcional não estarão disponíveis.","ui.recovery.safeModeButton":"Executar em Modo de Segurança","ui.server.pending":"Aguarde ...","ui.server.running":"A analisar ...","ui.server.error":"A verificação falhou devido a uma resposta inesperada do servidor.","ui.server.details":"Detalhes","ui.server.prerequisite":"A verificação falhou devido a um pré-requisito em falta.","ui.server.selfUpdate.title":"Actualizações Contao Manager","ui.server.selfUpdate.update":"Uma nova versão do Contao Manager {latest} está disponivel.","ui.server.selfUpdate.manualUpdate":"Está disponível uma nova versão do Contao Manager {latest}. O seu servidor não suporta actualizações automáticas, por favor descarregue a nova versão a partir de {download}.","ui.server.selfUpdate.latest":"Está a usar a versão mais recente {current}.","ui.server.selfUpdate.dev":"Versões de testes não suportam actualizações automáticas.","ui.server.selfUpdate.unsupported":"Uma nova versão está disponível mas não é compatível com a sua versão de PHP.","ui.server.selfUpdate.button":"Executar Auto-Update","ui.server.selfUpdate.continue":"Continuar","ui.server.config.title":"Configuração do Servidor","ui.server.config.setup":"Configurar","ui.server.config.change":"Alterar","ui.server.config.save":"Guardar","ui.server.config.cancel":"Cancelar","ui.server.config.customOption":"Outros ...","ui.server.config.description":"Para executar correctamente as tarefas de fundo, o Gestor de Contacto precisa de saber onde encontrar o binário de linha de comando PHP e como executar comandos separados do processo web.","ui.server.config.formTitle":"Configuração do Servidor","ui.server.config.formText":"Por favor introduza o caminho para o seu binário PHP. Certifique-se que o seu binário usa a mesma versao PHP que o seu processo web.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"A Composer Resolver Cloud permite instalar dependências Composer mesmo se o seu servidor não possuir memória local suficiente. Tenha em consideração que a sua informação de pacotes será transmitida para um servidor em nuvem mantido pela Contao Association.","ui.server.config.cloud":"Usar a Composer Resolver Cloud","ui.server.config.cli":"Binário PHP","ui.server.config.stateErrorCli":"Nenhum binário PHP válido foi encontrado no servidor. ","ui.server.config.stateErrorCloud":"A Composer Resolver Cloud não é suportada.","ui.server.config.stateSuccess":"Binário PHP em {php_cli}.","ui.server.php_web.title":"Processo Web PHP","ui.server.php_web.below7":"Encontrada a versão {version} PHP. Actualize para a versão PHP 7 assim que possivel!","ui.server.php_web.success":"Encontrada a versão PHP {version}, nenhum problema a reportar.","ui.server.php_cli.title":"Interface PHP Linha de Comandos","ui.server.php_cli.success":"Encontrada a versão PHP {version}, nenhum problema a reportar.","ui.server.composer.title":"Ambiente Composer","ui.server.composer.success":"Nenhum problema encontrado.","ui.server.composer.install":"Dependências Composer não instaladas.","ui.server.composer.button":"Instalar","ui.server.contao.title":"Instalação Contao","ui.server.contao.setup":"Configuração","ui.server.contao.check":"Check database","ui.server.contao.empty":"Nenhuma instalação Contao foi encontrada.","ui.server.contao.old":"A versão {version} do Contao não é compatível com o Contao Manager, actualize a sua instalação manualmente.","ui.server.contao.found":"Encontrado Contao com versão {version} (Versão API {api}).","ui.server.contao.connectionError":"Incapaz de se ligar ao servidor da base de dados.","ui.server.contao.connectionProblem":"Database problem found.","ui.server.contao.missingUser":"Conta administrativa não encontrada.","ui.setup.continue":"Continuar","ui.setup.manager":"Iniciar o Contao Manager","ui.setup.cancel":"Cancelar","ui.setup.welcome":"Bem Vindo","ui.setup.welcome1":"Este assistente irá levá-lo através dos passos necessários para configurar a sua instalação do CMS Contao Open Source.","ui.setup.welcome2":"If you have any questions, please find documentation, forums, a Slack channel and more on the {support} page.","ui.setup.support":"Apoio à Comunidade","ui.setup.start":"ComeceComece","ui.setup.complete":"Parabéns!","ui.setup.complete1":"Contao {version} has been installed successfully.","ui.setup.complete2":"To finish the setup process, please open the install tool to configure the database connection and create a back end user.","ui.setup.complete3":"You can now start to create your website in the Contao back end. If you need additional extensions, continue to the Contao Manager.","ui.setup.installTool":"Open the Install Tool","ui.setup.login":"Login to Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". An Open Source project like Contao requires amounts of money that can\'t be raised by a single person or company.\\nIf you have a website or sell websites built with Contao, we would love to see you contribute back financially to the product your business relies upon.","ui.setup.fundingLink":"Learn more","ui.setup.document-root.headline":"Configuração do Webserver","ui.setup.document-root.warning":"Para instalar o Contao através do Contao Manager, é necessário fixar a raiz do documento no servidor web.","ui.setup.document-root.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed if the folder structure is not correct or the folders are not empty.","ui.setup.document-root.description2":"Se não souber como configurar a raiz do seu documento, leia a documentação do Contacto ou contacte o seu fornecedor de alojamento.","ui.setup.document-root.documentation":"Ler a Documentação","ui.setup.document-root.conflictsTitle":"Directório de instalação não vazio","ui.setup.document-root.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and check again if you are sure they are unused.","ui.setup.document-root.ignoreConflicts":"Quero instalar o Contao no directório dos não vazios. Compreendo que isto pode substituir quaisquer ficheiros existentes no meu espaço web.","ui.setup.document-root.check":"Check again","ui.setup.document-root.create":"Criar directórios","ui.setup.document-root.change":"Change directories","ui.setup.document-root.formTitle":"Configuração de directório","ui.setup.document-root.formText1":"O Contao Manager pode criar automaticamente uma nova estrutura de directório no servidor.","ui.setup.document-root.formText2":"Será necessário configurar manualmente a raiz do novo documento (por exemplo, através de um painel de administração de alojamento).","ui.setup.document-root.autoconfig":"Compreendo que tenho de alterar a configuração do meu servidor. Não configurar a raiz do documento irá quebrar o Contao Manager e expor os ficheiros de configuração (incluindo detalhes de conta e palavras-passe)!","ui.setup.document-root.directory":"Novo Directório","ui.setup.document-root.currentRoot":"Raiz do documento actual","ui.setup.document-root.newRoot":"Novo Documento Raiz","ui.setup.document-root.finish":"Directórios de configuração","ui.setup.document-root.publicDir":"Utilizar {dir} para ficheiros públicos (para Contao {version})","ui.setup.document-root.directoryInvalid":"Por favor, introduza um nome de directório válido.","ui.setup.document-root.directoryExists":"O directório alvo já existe. Por favor, introduza um nome diferente.","ui.setup.document-root.confirmation":"O Contao Manager criou com sucesso o directório necessário para a sua instalação de Contao. Tem agora de configurar a raiz do documento no seu servidor web. Não volte a carregar esta página até lá.","ui.setup.document-root.reload":"Recarregar Página","ui.setup.document-root.success":"The directory structure on your web server is set up correctly!","ui.setup.document-root.installingProjectDir":"Application files will be installed to {dir}.","ui.setup.document-root.installingPublicDir":"Public files will be installed to {dir}.","ui.setup.document-root.installedProjectDir":"Application files are installed in {dir}.","ui.setup.document-root.installedPublicDir":"Public files are installed in {dir}.","ui.setup.create-project.headline":"Instalação Contao","ui.setup.create-project.description":"Contao development follows the principle of {semver}, a new minor version is released every six months. The currently supported releases are:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"Mais Recente","ui.setup.create-project.ltsTitle":"Suporte a Longo Prazo (LTS)","ui.setup.create-project.latestQ1":"Our latest version, offers the most features with support until February {year}.","ui.setup.create-project.latestQ3":"Our latest version, offers the most features with support until August {year}.","ui.setup.create-project.ltsText":"Our current LTS version, if you focus on stability. Offers long term support until February {year}.","ui.setup.create-project.pltsText":"The previous LTS version, still has long term support until February {year}.","ui.setup.create-project.requiresPHP":"Requires at least PHP {version}, you have PHP {current}.","ui.setup.create-project.releaseplan":"Ver o {contaoReleasePlan} para informações detalhadas.","ui.setup.create-project.releaseplanLink":"Plano de lançamento do Contao","ui.setup.create-project.installed":"Contao {version} is successfully installed on the server. Continue to set up your database or launch the Contao Manager to install a different version.","ui.setup.create-project.formTitle":"Select a distribution","ui.setup.create-project.formText":"Please choose which version should be installed.","ui.setup.create-project.version":"Versão","ui.setup.create-project.demo":"Install the Contao demo website","ui.setup.create-project.demoDescription":"The demo website helps you to get familiar with Contao and all of its core features. More themes can be found in the {store}.","ui.setup.create-project.coreOnly":"Instalação Mínima ( Apenas o \\"core\\")","ui.setup.create-project.noUpdate":"Ignorar Instalação (Utilizador avançado!)","ui.setup.create-project.theme":"Contao Theme","ui.setup.create-project.themeInstall":"To install a Contao theme, use the search input or upload a theme file (.cto/.zip) that supports installation through the Contao Manager.","ui.setup.create-project.themeBuy":"Make sure to visit the official {store}.","ui.setup.create-project.themeStore":"Contao Themes Store","ui.setup.create-project.themeUpload":"Upload theme file (.cto/.zip)","ui.setup.create-project.themeInvalid":"The uploaded file is not a Contao theme or does not support the Contao Manager.","ui.setup.create-project.themeWarning":"The Contao Manager cannot tell whether this theme is compatible with your server. Please check with the theme vendor if you have any questions.","ui.setup.create-project.themeTitle":"Review theme details","ui.setup.create-project.themeDetails":"The following dependencies and files will be installed with this theme.","ui.setup.create-project.themeRequire":"{count} Dependencies | {count} Dependencies","ui.setup.create-project.themeFiles":"{count} File | {count} Files","ui.setup.create-project.theme.or":"or search public themes","ui.setup.create-project.theme.search":"Search themes","ui.setup.create-project.theme.more":"More themes","ui.setup.create-project.theme.empty":"No themes matching {query}","ui.setup.create-project.theme.uploaded":"The theme file was uploaded successfully.","ui.setup.create-project.theme.packageName":"Package name","ui.setup.create-project.theme.version":"Versão","ui.setup.create-project.theme.authors":"Author(s)","ui.setup.create-project.install":"Instalar","ui.setup.create-project.cancel":"Cancelar","ui.setup.database-connection.headline":"Database Connection","ui.setup.database-connection.description":"Contao requires a MySQL database (or a compatible fork like MariaDB) to store pages, content, users and other relational data. Connection parameters are stored in the {env} file in the project root of your Contao installation.","ui.setup.database-connection.formTitle":"Connection Parameters","ui.setup.database-connection.formText":"Enter a database URL or fill in the username, password, server and database fields separately.","ui.setup.database-connection.url":"Database URL","ui.setup.database-connection.validUrl":"Database URL is invalid or connection to server failed.","ui.setup.database-connection.or":"or","ui.setup.database-connection.user":"Utilizador","ui.setup.database-connection.password":"Senha","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Database Name","ui.setup.database-connection.connected":"Successfully connected to database {database} on {server}.","ui.setup.database-connection.error":"Error connecting to the database.","ui.setup.database-connection.problem":"Contao has detected a problem with your database server.","ui.setup.database-connection.schemaTitle":"Database Schema","ui.setup.database-connection.migration":"There is one pending migration. | There are {count} pending migrations.","ui.setup.database-connection.schema":"There is one pending schema update. | There are {count} pending schema updates.","ui.setup.database-connection.noChanges":"Your database schema is up to date.","ui.setup.database-connection.check":"Check database","ui.setup.database-connection.skip":"Skip","ui.setup.database-connection.save":"Guardar","ui.setup.database-connection.change":"Change credentials","ui.setup.database-connection.restoreTitle":"Database Import","ui.setup.database-connection.restoreText":"The theme you just installed contains a database backup. Restore the database to import theme data or skip this step to start with a blank Contao installation. | The theme you just installed contains multiple database backups. Select a backup file to import theme data or skip this step to start with a blank Contao installation.","ui.setup.database-connection.backup":"Backup current database before import","ui.setup.database-connection.backupWarning":"All data in database will be overwritten on import! Create a backup first if the database is not empty.","ui.setup.database-connection.restore":"Import theme database","ui.setup.database-connection.restoreOption":"Backup from {date} ({size})","ui.setup.database-connection.restored":"Your theme database was successfully imported. Continue to validate your database schema.","ui.setup.backend-user.success":"An admin account for the Contao back end was found in your database. Use the Contao back end to add more users.","ui.setup.backend-user.error":"Unable to retrieve user list. Check the console output for details.","ui.setup.backend-user.headline":"Backend Account","ui.setup.backend-user.description":"To manage your website, you need to have at least one admin account for the Contao back end. Be aware that this account is not related to the Contao Manager.","ui.setup.backend-user.formTitle":"Criar Conta","ui.setup.backend-user.formText":"Please enter the details for the new back end account.","ui.setup.backend-user.username":"Utilizador","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-mail address","ui.setup.backend-user.emailInvalid":"Please enter a valid e-mail address","ui.setup.backend-user.password":"Senha","ui.setup.backend-user.passwordPlaceholder":"min. 8 caracteres","ui.setup.backend-user.passwordLength":"Por favor utilize o minimo de 8 caracteres.","ui.setup.backend-user.create":"Add account","ui.task.headline":"Tarefa de fundo","ui.task.loading":"Carregamento de detalhes ...","ui.task.created":"Carregamento de detalhes ...","ui.task.active":"Por favor aguarde enquanto o Gestor de Contacto está a executar operações de tarefas em segundo plano.","ui.task.complete":"Todas as operações são concluídas com sucesso. Verifique a saída da consola para mais detalhes.","ui.task.aborting":"Por favor aguarde enquanto as operações de fundo estão a ser canceladas.","ui.task.stopped":"Algumas operações de fundo foram canceladas. Por favor, verifique a saída da consola.","ui.task.error":"Uma operação de fundo parou inesperadamente. Por favor, verifique a saída da consola.","ui.task.failed":"O Gestor de Contao não conseguiu iniciar uma tarefa de fundo!","ui.task.failedDescription1":"Alguma coisa correu mal ao tentar executar operações em segundo plano.","ui.task.failedDescription2":"Se isto acontecer novamente, o seu servidor poderá não ser suportado.","ui.task.reportProblem":"Reportar um Problema","ui.task.sponsor":"Composer Cloud sponsored by {sponsor}","ui.task.buttonAudit":"Actualizar base de dados ","ui.task.buttonClose":"Fechar","ui.task.buttonConfirm":"Confirmar e Fechar","ui.task.buttonCancel":"Cancelar","ui.task.confirmCancel":"Tem a certeza que pretende interromper esta tarefa? Poderá afectar a instalação do Contao negativamente!","ui.task.autoclose":"Detalhes sobre o sucesso da tarefa","ui.console.toggle":"Mostrar/Esconder saída de Consola","ui.console.showLog":"Mostrar registo completo da consola","ui.console.copyLog":"Copiar log para prancheta","ui.migrate.headline":"Database Updates","ui.migrate.migrationsOnly":"(migrations only)","ui.migrate.schemaOnly":"(schema only)","ui.migrate.loading":"Please wait, we are checking your database …","ui.migrate.empty":"No pending migrations or schema updates found. Your database is up to date.","ui.migrate.emptyMigrations":"No pending migrations found. Make sure to also check for schema updates.","ui.migrate.emptySchema":"No pending schema updates found. Make sure to also check for migrations.","ui.migrate.pending":"Your database is not up to date. Please review the console output below and execute the changes.","ui.migrate.previousChanges":"A previous database migration was not confirmed.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.previousComplete":"A previous database migration was not confirmed, please review the console output below.\\nThere are no more pending changes.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Database updates have been applied.\\nThere are no more pending migrations or schema updates. Your database is up to date.","ui.migrate.problem":"Contao has detected a problem with your database server.\\nPlease review the console output below to find out what needs to be fixed. | Contao has detected problems with your database server.\\nPlease review the console output below to find out what needs to be fixed.","ui.migrate.warning":"Contao has detected a misconfiguration of your database server.\\nWarnings can be skipped temporarily, but should be fixed for optimal performance and data integrity.","ui.migrate.error":"The changes could not be applied. Your database might have been changed, please check again to retry.","ui.migrate.execute":"Execute","ui.migrate.close":"Fechar","ui.migrate.confirm":"Confirmar e Fechar","ui.migrate.cancel":"Cancelar","ui.migrate.continue":"Continuar","ui.migrate.setup":"Configuração","ui.migrate.skip":"Skip","ui.migrate.retry":"Check again","ui.migrate.retryAll":"Check all","ui.migrate.withDeletes":"Execute all database changes including DROP queries.","ui.migrate.migrationTitle":"Database Migrations","ui.migrate.schemaTitle":"Schema Updates","ui.migrate.problemTitle":"Database Problems","ui.migrate.warningTitle":"Database Warnings","ui.migrate.addTable":"Add table {table}","ui.migrate.dropTable":"Drop table {table}","ui.migrate.addField":"Add field {table}.{field}","ui.migrate.changeField":"Change field {table}.{field}","ui.migrate.dropField":"Drop field {table}.{field}","ui.migrate.createIndex":"Create index \\"{name}\\" on {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" on {table}","ui.widget.mandatory":"Este campo não pode estar vazio.","ui.widget.blankOption":"Por favor seleccione ...","ui.widget.showPassword":"Show password","ui.widget.hidePassword":"Hide password","ui.error.title":"O pedido HTTP de \\"{method} {url}\\" falhou.","ui.error.server500":"Parece que ocorreu um erro inesperado no seu servidor. Por favor verifique os ficheiros de registo do seu servidor web (Apache/Nginx) e os registos do Contao Manager em \\"Contao-manager/logs\\".","ui.error.response":"O servidor devolveu uma resposta com o código de estado {status}.","ui.error.moreLink":"Mais informação ","ui.error.support":"Contao Support","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Ajuda","ui.footer.reportProblem":"Reportar um Problema","ui.navigation.discover":"Descubra","ui.navigation.packages":"Pacotes","ui.navigation.tools":"Ferramentas","ui.navigation.installTool":"Ferramenta de Instalação","ui.navigation.backend":"Backend Contao","ui.navigation.debug":"Depuração Contao","ui.navigation.logViewer":"Log Viewer","ui.navigation.phpinfo":"Informação PHP","ui.navigation.phpinfoLoading":"Carregamento de informação PHP","ui.navigation.maintenance":"Manutenção","ui.navigation.rebuildCache":"Reconstruir Cache","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"Verificar Sistema","ui.navigation.advanced":"Avançado","ui.navigation.logout":"Terminar Sessão","ui.maintenance.database.title":"Database Migrations and Backups","ui.maintenance.database.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.database.migrations":"One pending database migration | {count} pending database migrations","ui.maintenance.database.schemaUpdates":"One pending schema update | {count} pending schema updates","ui.maintenance.database.error":"Database problem found.","ui.maintenance.database.warning":"Database warnings found.","ui.maintenance.database.button":"Check database","ui.maintenance.database.migrationOnly":"Check migrations only","ui.maintenance.database.schemaOnly":"Check schema only","ui.maintenance.database.installTool":"Open Install Tool","ui.maintenance.database.createBackup":"Create Backup","ui.maintenance.database.backupUnsupported":"Database backups are not supported by your Contao version.","ui.maintenance.database.backupList":"You have one database backup, created on {date}. | You have {count} database backups, the latest one was created on {date}.","ui.maintenance.database.backupEmpty":"You currently have no database backups.","ui.maintenance.rebuildCache.title":"Cache de Aplicação","ui.maintenance.rebuildCache.description":"Reconstruir a cache da aplicação é necessário após modificar quaisquer dos ficheiros de configuração.","ui.maintenance.rebuildCache.rebuildProd":"Reconstruir Cache de Produção","ui.maintenance.rebuildCache.rebuildDev":"Reconstruir Cache Desenvolvimento","ui.maintenance.rebuildCache.clearProd":"Limpar Cache Produção","ui.maintenance.rebuildCache.clearDev":"Limpar Cache Desenvolvimento","ui.maintenance.installTool.title":"Ferramenta de Instalação do Contao","ui.maintenance.installTool.description":"A Ferramenta de Instalação do Contao bloqueia automaticamente caso a senha seja introduzida erradamente três vezes.","ui.maintenance.installTool.unlock":"Desbloquear ferramenta de instalação","ui.maintenance.installTool.lock":"Bloquear ferramenta de instalação","ui.maintenance.dumpAutoload.title":"Carregador de Classes Composer","ui.maintenance.dumpAutoload.description":"O Composer autoloader é responsável por carregar classes PHP. O autoloader tem que ser \\"dumped\\" após adicionar namespaces personalizados ao root compser.json .","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Dependências Composer ","ui.maintenance.composerInstall.description":"As dependências dos Composer estão localizadas na pasta {vendor} na raiz da sua aplicação. A reinstalação das dependências pode ser necessária após manipulação ou carregamento manual do ficheiro {composerLock}.","ui.maintenance.composerInstall.button":"Executar Instalador","ui.maintenance.composerInstall.update":"Executar Actualizador Composer","ui.maintenance.composerCache.title":"Cache Composer","ui.maintenance.composerCache.description":"O Composer guarda cache de pacotes provenientes de download para melhor performance. Caso tenha problemas com ficheiros não funcionais, apagar a Composer cache para forçar um novo download poderá resolver o problema.","ui.maintenance.composerCache.button":"Apagar Cache","ui.maintenance.maintenanceMode.title":"Modo Manutenção","ui.maintenance.maintenanceMode.description":"Colocar o Contao em modo de manutenção exibirá um modelo \\"503 Serviço Indisponível\\" para o website.","ui.maintenance.maintenanceMode.enable":"Activar","ui.maintenance.maintenanceMode.disable":"Desactivar","ui.maintenance.debugMode.title":"Modo Depuração","ui.maintenance.debugMode.description":"Activar o modo de depuração definindo um utilizador e uma palavra-passe para o ponto de entrada {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Active o modo de depuração ao definir o cookie de depuração para o domínio corrente.","ui.maintenance.debugMode.activate":"Activar","ui.maintenance.debugMode.deactivate":"Desactivar","ui.maintenance.debugMode.credentials":"Credenciais","ui.maintenance.debugMode.user":"Por favor introduza um nome de utilizador para o modo de depuração.","ui.maintenance.debugMode.password":"Por favor introduza uma senha para o modo de depuração.","ui.maintenance.opcodeCache.title":"Cache Opcode","ui.maintenance.opcodeCache.description":"O Opcode efectua cache de ficheiros PHP no processo web para mais rápida execução. Deverá ser apagado dentro de certas circunstâncias caso ficheiros não sejam reconhecidos após edição.","ui.maintenance.opcodeCache.button":"Truncar Cache","ui.maintenance.safeMode":"Nao disponível em Modo Segurança","ui.maintenance.unsupported":"Não suportado pela sua versão Contao","ui.packages.updateButton":"Actualizar Pacotes","ui.packages.searchButton":"Procurar Pacotes","ui.packages.searchPlaceholder":"Procurar Pacotes ...","ui.packages.uploadOverlay":"Arrastar e largar ficheiros para upload","ui.packages.uploadButton":"Carregar Packages","ui.packages.uploadMessage":"Tem um carregamento não confirmado. | Tem {count} uploads não confirmados.","ui.packages.uploadApply":"Confirmar Uploads","ui.packages.uploadReset":"Apagar Uploads","ui.packages.uploadIncomplete":"Este ficheiro não foi uploaded completamente. Por favor remova-o e tente novamente.","ui.packages.uploadDuplicate":"Este ficheiro aparenta ter sido uploaded várias vezes. Por favor remova os duplicados.","ui.packages.uploadInstalled":"Este ficheiro já se encontra instalado. Por favor remova os duplicados.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure that the PHP ZIP extension is installed and update your dependencies.","ui.packages.changesMessage":"Tem uma alteração não confirmada. | Tem {count} alterações não confirmadas.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Aplicar Alterações","ui.packages.changesApplyAll":"Actualizar todos os pacotes","ui.packages.changesDryrunAll":"Funcionamento a seco todos os pacotes","ui.packages.changesReset":"Reverter Alterações","ui.packages.changesReview":"Rever Alterações","ui.packagelist.loading":"A Carregar ...","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"Novos pacotes","ui.packagelist.installed":"Pacotes instalados","ui.package.hintRevert":"Reverter Alterações","ui.package.hintNoupdate":"Não actualizar","ui.package.hintConstraint":" Este pacote será instalado com limitações de entrada {constraint} quando aplicar alterações.","ui.package.hintConstraintBest":"Este pacote será instalado com a melhor versão disponível quando aplicar alterações.","ui.package.hintConstraintChange":"As limitações de entrada para este pacote serão alteradas de \\"{from}\\" para \\"{to}\\" quando aplicar alterações.","ui.package.hintConstraintUpdate":"Este pacote será actualizado quando aplicar alterações. ","ui.package.hintAdded":"Este pacote vai ser instalado quando aplicar as alterações.","ui.package.hintRemoved":"Este pacote será removido quando aplicar alterações.","ui.package.requiredTitle":"manualmente adicionado","ui.package.requiredText":"Este pacote é requerido pelo seu composer.json mas não está instalado.","ui.package.removedTitle":"manualmente removido","ui.package.removedText":"Este pacote vai ser removido do seu composer.json.","ui.package.installed":"Actualmente instalado:","ui.package.version":"Versão {version}","ui.package.additionalDownloads":"{count} Descarregar | {count} Descarregar","ui.package.additionalStars":"{count} Estrela | {count} Estrelas","ui.package.editConstraint":"Editar","ui.package.uploadConstraint":"Esta restrição está definida pelo pacote que foi uploaded.","ui.package.updateButton":"Actualizar","ui.package.removeButton":"Remover","ui.package.installButton":"Adicionar Pacote","ui.package.installButtonShort":"Adicionar","ui.package.detailsButton":"Detalhes","ui.package.latestConstraint":"versão mais recente","ui.package.update":"Actualização disponível","ui.package.updateLatest":"versão mais recente","ui.package.updateAvailable":"{version} disponível","ui.package.updateUnknown":"versão desconhecida","ui.package.updateConstraint":"A newer version outside your version constraint is available.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Versão {version}","ui.cloudStatus.waitingTime":"Tempo de Espera","ui.cloudStatus.jobs":"Tarefas Actuais","ui.cloudStatus.workers":"Trabalhadores","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"nenhum","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} seg","ui.cloudStatus.error":"Incapaz de obter o estatuto de Composer Resolver Cloud. Pode ser para questões de manutenção ou de experiência.","ui.cloudStatus.button":"Estado das nuvens","ui.cloudStatus.refresh":"Actualizar o estado das nuvens","ui.log-viewer.loading":"A Carregar ...","ui.log-viewer.empty":"There are no log files on your server.","ui.log-viewer.reload":"Reload","ui.log-viewer.file":"Log file","ui.log-viewer.channel":"Channel","ui.log-viewer.channelTitle":"The channel this message was logged to.","ui.log-viewer.level":"Level","ui.log-viewer.levelTitle":"Severity of the log message.","ui.log-viewer.timeHeader":"Time","ui.log-viewer.messageHeader":"Message","ui.log-viewer.showContext":"Show Context","ui.log-viewer.hideContext":"Hide Context","ui.log-viewer.showExtra":"Show Extra","ui.log-viewer.hideExtra":"Hide Extra","ui.log-viewer.more":"Load more …","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download file \\"{file}\\"","ui.log-viewer.prodEnvironment":"Production Environment","ui.log-viewer.devEnvironment":"Development Environment (Debug Mode)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Change Password","ui.user-manager.setupTotp":"Setup Two-Factor Authentication","ui.user-manager.disableTotp":"Disable Two-Factor Authentication","ui.user-manager.invite":"Invite User","ui.user-manager.delete":"Delete","ui.user-manager.deleteConfirm":"Do you really want to delete user \\"{username}\\"?","ui.user-manager.deleted":"User {username} deleted successfully","ui.user-manager.passwordHeadline":"Change Password","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Current password","ui.user-manager.newPassword":"New password","ui.user-manager.passwordPlaceholder":"min. 8 caracteres","ui.user-manager.submitPassword":"Submit","ui.user-manager.passwordChanged":"Your password has been changed successfully.","ui.user-manager.passwordError":"This password is incorrect.","ui.user-manager.inviteHeadline":"Invite User","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Create Invitation Link","ui.user-manager.clipboard":"Copy to clipboard","ui.user-manager.permissions":"Learn about permissions","ui.user-manager.cancel":"Cancelar","ui.user-manager.close":"Fechar","ui.user-manager.you":"You","ui.totp.headline":"Two-Factor Authentication","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verification code","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"The verification code is invalid.","ui.totp.enable":"Activar","ui.totp.disable":"Desactivar","ui.totp.cancel":"Cancelar","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Setup Two-Factor Authentication","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[504],{33:function(e,t,n){"use strict"; /** * @vue/shared v3.5.13 * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT **/ /*! #__NO_SIDE_EFFECTS__ */ function r(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return e=>e in t}n.d(t,{$3:function(){return p},$H:function(){return $},BH:function(){return X},BX:function(){return re},Bm:function(){return E},C4:function(){return Q},CE:function(){return m},CP:function(){return c},DY:function(){return F},Gv:function(){return w},J$:function(){return ee},Kg:function(){return _},MZ:function(){return o},Mp:function(){return l},NO:function(){return a},Oj:function(){return i},PT:function(){return I},Qd:function(){return T},Ro:function(){return B},SU:function(){return A},TF:function(){return d},Tg:function(){return x},Tn:function(){return b},Tr:function(){return G},We:function(){return H},X$:function(){return u},Y2:function(){return te},ZH:function(){return M},Zf:function(){return O},_B:function(){return J},bB:function(){return U},cy:function(){return h},gd:function(){return y},pD:function(){return r},rU:function(){return D},tE:function(){return s},u3:function(){return oe},vM:function(){return v},v_:function(){return se},yI:function(){return R},yL:function(){return S},yQ:function(){return j}});const o={},i=[],s=()=>{},a=()=>!1,l=e=>111===e.charCodeAt(0)&&110===e.charCodeAt(1)&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),c=e=>e.startsWith("onUpdate:"),u=Object.assign,d=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},f=Object.prototype.hasOwnProperty,p=(e,t)=>f.call(e,t),h=Array.isArray,m=e=>"[object Map]"===C(e),v=e=>"[object Set]"===C(e),g=e=>"[object Date]"===C(e),y=e=>"[object RegExp]"===C(e),b=e=>"function"===typeof e,_=e=>"string"===typeof e,E=e=>"symbol"===typeof e,w=e=>null!==e&&"object"===typeof e,S=e=>(w(e)||b(e))&&b(e.then)&&b(e.catch),k=Object.prototype.toString,C=e=>k.call(e),O=e=>C(e).slice(8,-1),T=e=>"[object Object]"===C(e),R=e=>_(e)&&"NaN"!==e&&"-"!==e[0]&&""+parseInt(e,10)===e,A=r(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),N=e=>{const t=Object.create(null);return n=>{const r=t[n];return r||(t[n]=e(n))}},L=/-(\w)/g,I=N((e=>e.replace(L,((e,t)=>t?t.toUpperCase():"")))),P=/\B([A-Z])/g,x=N((e=>e.replace(P,"-$1").toLowerCase())),M=N((e=>e.charAt(0).toUpperCase()+e.slice(1))),D=N((e=>{const t=e?`on${M(e)}`:"";return t})),$=(e,t)=>!Object.is(e,t),F=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},U=e=>{const t=parseFloat(e);return isNaN(t)?e:t},B=e=>{const t=_(e)?Number(e):NaN;return isNaN(t)?e:t};let V;const H=()=>V||(V="undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:"undefined"!==typeof n.g?n.g:{});const W="Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol",X=r(W);function G(e){if(h(e)){const t={};for(let n=0;n{if(e){const n=e.split(z);n.length>1&&(t[n[0].trim()]=n[1].trim())}})),t}function Q(e){let t="";if(_(e))t=e;else if(h(e))for(let n=0;nre(e,t)))}const ie=e=>!(!e||!0!==e["__v_isRef"]),se=e=>_(e)?e:null==e?"":h(e)||w(e)&&(e.toString===k||!b(e.toString))?ie(e)?se(e.value):JSON.stringify(e,ae,2):String(e),ae=(e,t)=>ie(t)?ae(e,t.value):m(t)?{[`Map(${t.size})`]:[...t.entries()].reduce(((e,[t,n],r)=>(e[le(t,r)+" =>"]=n,e)),{})}:v(t)?{[`Set(${t.size})`]:[...t.values()].map((e=>le(e)))}:E(t)?le(t):!w(t)||h(t)||T(t)?t:String(t),le=(e,t="")=>{var n;return E(e)?`Symbol(${null!=(n=e.description)?n:t})`:e}},34:function(e,t,n){"use strict";var r=n(4901);e.exports=function(e){return"object"==typeof e?null!==e:r(e)}},81:function(e,t,n){"use strict";var r=n(9565),o=n(9306),i=n(8551),s=n(6823),a=n(851),l=TypeError;e.exports=function(e,t){var n=arguments.length<2?a(e):t;if(o(n))return i(r(n,e));throw new l(s(e)+" is not iterable")}},116:function(e,t,n){"use strict";var r=n(6518),o=n(2652),i=n(9306),s=n(8551),a=n(1767);r({target:"Iterator",proto:!0,real:!0},{find:function(e){s(this),i(e);var t=a(this),n=0;return o(t,(function(t,r){if(e(t,n++))return r(t)}),{IS_RECORD:!0,INTERRUPTED:!0}).result}})},144:function(e,t,n){const r=n(3908),o=(e,t,n=!1)=>{if(e instanceof r)return e;try{return new r(e,t)}catch(o){if(!n)return null;throw o}};e.exports=o},156:function(e,t,n){"use strict";var r=n(953);t.A={namespaced:!0,state:{modals:{}},getters:{hasModal:e=>Object.values(e.modals).reduce(((e,t)=>e+Object.values(t).length),0)>0,currentModal(e){const t=Object.keys(e.modals).sort(((e,t)=>t-e));for(const n of t){const t=Object.values(e.modals[n]);if(t.length>0)return t.find((()=>!0))}}},mutations:{open(e,{id:t,component:n,priority:o=0}){const i=Object.assign({},e.modals);i[o]||(i[o]={}),i[o][t]=(0,r.IG)(n),e.modals=i},close(e,t){const n=Object.assign({},e.modals);Object.keys(n).forEach((e=>{n[e]&&n[e][t]&&delete n[e][t]})),e.modals=n}}}},266:function(e,t){"use strict";t.A=e=>e?Intl&&Intl.NumberFormat?(new Intl.NumberFormat).format(e):e:""},270:function(e,t,n){const r=n(3908),o=n(8311),i=(e,t,n)=>{let i=null,s=null,a=null;try{a=new o(t,n)}catch(l){return null}return e.forEach((e=>{a.test(e)&&(i&&1!==s.compare(e)||(i=e,s=new r(i,n)))})),i};e.exports=i},283:function(e,t,n){"use strict";var r=n(9504),o=n(9039),i=n(4901),s=n(9297),a=n(3724),l=n(350).CONFIGURABLE,c=n(3706),u=n(1181),d=u.enforce,f=u.get,p=String,h=Object.defineProperty,m=r("".slice),v=r("".replace),g=r([].join),y=a&&!o((function(){return 8!==h((function(){}),"length",{value:8}).length})),b=String(String).split("String"),_=e.exports=function(e,t,n){"Symbol("===m(p(t),0,7)&&(t="["+v(p(t),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),n&&n.getter&&(t="get "+t),n&&n.setter&&(t="set "+t),(!s(e,"name")||l&&e.name!==t)&&(a?h(e,"name",{value:t,configurable:!0}):e.name=t),y&&n&&s(n,"arity")&&e.length!==n.arity&&h(e,"length",{value:n.arity});try{n&&s(n,"constructor")&&n.constructor?a&&h(e,"prototype",{writable:!1}):e.prototype&&(e.prototype=void 0)}catch(o){}var r=d(e);return s(r,"source")||(r.source=g(b,"string"==typeof t?t:"")),e};Function.prototype.toString=_((function(){return i(this)&&f(this).source||c(this)}),"toString")},350:function(e,t,n){"use strict";var r=n(3724),o=n(9297),i=Function.prototype,s=r&&Object.getOwnPropertyDescriptor,a=o(i,"name"),l=a&&"something"===function(){}.name,c=a&&(!r||r&&s(i,"name").configurable);e.exports={EXISTS:a,PROPER:l,CONFIGURABLE:c}},397:function(e,t,n){"use strict";var r=n(7751);e.exports=r("document","documentElement")},416:function(e,t){"use strict";t.A={data:()=>({metadata:{}}),methods:{async loadMetadata(){if(!this.data)return void(this.metadata=null);this.metadata={};const e=await this.$store.dispatch("packages/metadata",this.data);this.metadata=e?Object.assign({},this.data,e):null}},watch:{data(){this.loadMetadata()}},created(){this.loadMetadata(),this.$watch(this.$i18n.locale,this.loadMetadata)}}},421:function(e){"use strict";e.exports={}},560:function(e,t,n){const r=n(3908),o=(e,t,n)=>new r(e,n).compare(new r(t,n));e.exports=o},616:function(e,t,n){"use strict";var r=n(9039);e.exports=!r((function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")}))},641:function(e,t,n){"use strict";n.d(t,{$V:function(){return Ve},$u:function(){return it},$y:function(){return vt},BA:function(){return r.BA},Bi:function(){return be},Bs:function(){return Io},C4:function(){return o.C4},CE:function(){return $r},Df:function(){return ge},Dl:function(){return O},E:function(){return Wt},E3:function(){return zr},EW:function(){return Ro},EY:function(){return Or},FK:function(){return Cr},Fv:function(){return Yr},Fw:function(){return Wn},GM:function(){return Pt},Gc:function(){return r.Gc},Gt:function(){return dn},Gw:function(){return jo},Gy:function(){return ie},H4:function(){return p},HF:function(){return Bt},Ht:function(){return $t},IG:function(){return r.IG},IJ:function(){return r.IJ},Ic:function(){return ot},Im:function(){return ee},K9:function(){return xn},KC:function(){return nt},KR:function(){return r.KR},Kf:function(){return o.rU},Kh:function(){return r.Kh},LJ:function(){return Uo},LM:function(){return Xn},Lk:function(){return Wr},Lu:function(){return xt},MZ:function(){return ve},Mw:function(){return Tr},NP:function(){return Mt},Ng:function(){return Kr},OA:function(){return Ft},OW:function(){return pe},PP:function(){return r.PP},PR:function(){return Ge},PS:function(){return pn},PT:function(){return o.PT},Pn:function(){return $e},Pr:function(){return r.Pr},Q3:function(){return Qr},QP:function(){return ae},QW:function(){return r.QW},QZ:function(){return r.QZ},Qi:function(){return F},R1:function(){return r.R1},R8:function(){return xo},RG:function(){return wt},SS:function(){return lt},Tb:function(){return kt},Tm:function(){return r.Tm},Tq:function(){return je},Tr:function(){return o.Tr},U4:function(){return l},U_:function(){return zn},Ul:function(){return r.Ul},Vq:function(){return Mr},WQ:function(){return fn},Wv:function(){return Fr},X2:function(){return r.X2},Y4:function(){return qe},Y5:function(){return Bo},YY:function(){return U},Yj:function(){return Nt},Yv:function(){return r.Yv},ZH:function(){return o.ZH},ZQ:function(){return Mo},_B:function(){return o._B},aT:function(){return Vo},bF:function(){return Xr},bU:function(){return Lo},bj:function(){return ct},bn:function(){return Ht},bo:function(){return V},ch:function(){return r.ch},ci:function(){return Mn},dA:function(){return Fe},dY:function(){return w},ds:function(){return r.ds},eW:function(){return qr},eX:function(){return Et},fE:function(){return r.fE},fn:function(){return Zn},g2:function(){return ht},g8:function(){return r.g8},gN:function(){return gt},gW:function(){return Br},gh:function(){return d},h:function(){return Ao},hi:function(){return at},i9:function(){return r.i9},iD:function(){return $o},jC:function(){return Rr},jr:function(){return r.jr},jt:function(){return j},ju:function(){return r.ju},k6:function(){return B},lW:function(){return r.lW},lt:function(){return Do},mu:function(){return r.mu},n:function(){return ze},nD:function(){return r.nD},nI:function(){return ao},nT:function(){return Gn},o5:function(){return r.o5},p9:function(){return Kn},pI:function(){return _t},pM:function(){return ye},pR:function(){return de},qG:function(){return dt},qL:function(){return f},qP:function(){return Lt},qR:function(){return ut},rE:function(){return Po},rO:function(){return Dt},rU:function(){return Me},rY:function(){return r.rY},rk:function(){return Ee},sV:function(){return rt},tB:function(){return r.tB},tC:function(){return _o},tG:function(){return c},tY:function(){return hr},uX:function(){return Lr},uY:function(){return r.uY},ux:function(){return r.ux},v6:function(){return to},v_:function(){return o.v_},vv:function(){return jr},wB:function(){return qn},wX:function(){return Eo},wk:function(){return It},xo:function(){return st},y$:function(){return No},yC:function(){return r.yC},zz:function(){return Vt}});var r=n(953),o=n(33); /** * @vue/runtime-core v3.5.13 * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT **/ const i=[];function s(e){i.push(e)}function a(){i.pop()}function l(e,t){}const c={SETUP_FUNCTION:0,0:"SETUP_FUNCTION",RENDER_FUNCTION:1,1:"RENDER_FUNCTION",NATIVE_EVENT_HANDLER:5,5:"NATIVE_EVENT_HANDLER",COMPONENT_EVENT_HANDLER:6,6:"COMPONENT_EVENT_HANDLER",VNODE_HOOK:7,7:"VNODE_HOOK",DIRECTIVE_HOOK:8,8:"DIRECTIVE_HOOK",TRANSITION_HOOK:9,9:"TRANSITION_HOOK",APP_ERROR_HANDLER:10,10:"APP_ERROR_HANDLER",APP_WARN_HANDLER:11,11:"APP_WARN_HANDLER",FUNCTION_REF:12,12:"FUNCTION_REF",ASYNC_COMPONENT_LOADER:13,13:"ASYNC_COMPONENT_LOADER",SCHEDULER:14,14:"SCHEDULER",COMPONENT_UPDATE:15,15:"COMPONENT_UPDATE",APP_UNMOUNT_CLEANUP:16,16:"APP_UNMOUNT_CLEANUP"},u={["sp"]:"serverPrefetch hook",["bc"]:"beforeCreate hook",["c"]:"created hook",["bm"]:"beforeMount hook",["m"]:"mounted hook",["bu"]:"beforeUpdate hook",["u"]:"updated",["bum"]:"beforeUnmount hook",["um"]:"unmounted hook",["a"]:"activated hook",["da"]:"deactivated hook",["ec"]:"errorCaptured hook",["rtc"]:"renderTracked hook",["rtg"]:"renderTriggered hook",[0]:"setup function",[1]:"render function",[2]:"watcher getter",[3]:"watcher callback",[4]:"watcher cleanup function",[5]:"native event handler",[6]:"component event handler",[7]:"vnode hook",[8]:"directive hook",[9]:"transition hook",[10]:"app errorHandler",[11]:"app warnHandler",[12]:"ref function",[13]:"async component loader",[14]:"scheduler flush",[15]:"component update",[16]:"app unmount cleanup function"};function d(e,t,n,r){try{return r?e(...r):e()}catch(o){p(o,t,n)}}function f(e,t,n,r){if((0,o.Tn)(e)){const i=d(e,t,n,r);return i&&(0,o.yL)(i)&&i.catch((e=>{p(e,t,n)})),i}if((0,o.cy)(e)){const o=[];for(let i=0;i>>1,o=m[r],i=A(o);i=A(n)?m.push(e):m.splice(S(t),0,e),e.flags|=1,C()}}function C(){E||(E=_.then(N))}function O(e){(0,o.cy)(e)?g.push(...e):y&&-1===e.id?y.splice(b+1,0,e):1&e.flags||(g.push(e),e.flags|=1),C()}function T(e,t,n=v+1){for(0;nA(e)-A(t)));if(g.length=0,y)return void y.push(...e);for(y=e,b=0;bnull==e.id?2&e.flags?-1:1/0:e.id;function N(e){o.tE;try{for(v=0;vL.emit(e,...t))),I=[];else if("undefined"!==typeof window&&window.HTMLElement&&!(null==(r=null==(n=window.navigator)?void 0:n.userAgent)?void 0:r.includes("jsdom"))){const e=t.__VUE_DEVTOOLS_HOOK_REPLAY__=t.__VUE_DEVTOOLS_HOOK_REPLAY__||[];e.push((e=>{x(e,t)})),setTimeout((()=>{L||(t.__VUE_DEVTOOLS_HOOK_REPLAY__=null,P=!0,I=[])}),3e3)}else P=!0,I=[]}let M=null,D=null;function $(e){const t=M;return M=e,D=e&&e.type.__scopeId||null,t}function F(e){D=e}function j(){D=null}const U=e=>B;function B(e,t=M,n){if(!t)return e;if(e._n)return e;const r=(...n)=>{r._d&&Mr(-1);const o=$(t);let i;try{i=e(...n)}finally{$(o),r._d&&Mr(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function V(e,t){if(null===M)return e;const n=Co(M),i=e.dirs||(e.dirs=[]);for(let s=0;se.__isTeleport,G=e=>e&&(e.disabled||""===e.disabled),K=e=>e&&(e.defer||""===e.defer),z=e=>"undefined"!==typeof SVGElement&&e instanceof SVGElement,q=e=>"function"===typeof MathMLElement&&e instanceof MathMLElement,Y=(e,t)=>{const n=e&&e.to;if((0,o.Kg)(n)){if(t){const e=t(n);return e}return null}return n},Q={name:"Teleport",__isTeleport:!0,process(e,t,n,r,o,i,s,a,l,c){const{mc:u,pc:d,pbc:f,o:{insert:p,querySelector:h,createText:m,createComment:v}}=c,g=G(t.props);let{shapeFlag:y,children:b,dynamicChildren:_}=t;if(null==e){const e=t.el=m(""),c=t.anchor=m("");p(e,n,r),p(c,n,r);const d=(e,t)=>{16&y&&(o&&o.isCE&&(o.ce._teleportTarget=e),u(b,e,t,o,i,s,a,l))},f=()=>{const e=t.target=Y(t.props,h),n=ne(e,t,m,p);e&&("svg"!==s&&z(e)?s="svg":"mathml"!==s&&q(e)&&(s="mathml"),g||(d(e,n),te(t,!1)))};g&&(d(n,c),te(t,!0)),K(t.props)?Pn((()=>{f(),t.el.__isMounted=!0}),i):f()}else{if(K(t.props)&&!e.el.__isMounted)return void Pn((()=>{Q.process(e,t,n,r,o,i,s,a,l,c),delete e.el.__isMounted}),i);t.el=e.el,t.targetStart=e.targetStart;const u=t.anchor=e.anchor,p=t.target=e.target,m=t.targetAnchor=e.targetAnchor,v=G(e.props),y=v?n:p,b=v?u:m;if("svg"===s||z(p)?s="svg":("mathml"===s||q(p))&&(s="mathml"),_?(f(e.dynamicChildren,_,y,o,i,s,a),Un(e,t,!0)):l||d(e,t,y,b,o,i,s,a,!1),g)v?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):J(t,n,u,c,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const e=t.target=Y(t.props,h);e&&J(t,e,null,c,0)}else v&&J(t,p,m,c,1);te(t,g)}},remove(e,t,n,{um:r,o:{remove:o}},i){const{shapeFlag:s,children:a,anchor:l,targetStart:c,targetAnchor:u,target:d,props:f}=e;if(d&&(o(c),o(u)),i&&o(l),16&s){const e=i||!G(f);for(let o=0;o{e.isMounted=!0})),st((()=>{e.isUnmounting=!0})),e}const se=[Function,Array],ae={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:se,onEnter:se,onAfterEnter:se,onEnterCancelled:se,onBeforeLeave:se,onLeave:se,onAfterLeave:se,onLeaveCancelled:se,onBeforeAppear:se,onAppear:se,onAfterAppear:se,onAppearCancelled:se},le=e=>{const t=e.subTree;return t.component?le(t.component):t},ce={name:"BaseTransition",props:ae,setup(e,{slots:t}){const n=ao(),o=ie();return()=>{const i=t.default&&ge(t.default(),!0);if(!i||!i.length)return;const s=ue(i),a=(0,r.ux)(e),{mode:l}=a;if(o.isLeaving)return he(s);const c=me(s);if(!c)return he(s);let u=pe(c,a,o,n,(e=>u=e));c.type!==Tr&&ve(c,u);let d=n.subTree&&me(n.subTree);if(d&&d.type!==Tr&&!Ur(c,d)&&le(n).type!==Tr){let e=pe(d,a,o,n);if(ve(d,e),"out-in"===l&&c.type!==Tr)return o.isLeaving=!0,e.afterLeave=()=>{o.isLeaving=!1,8&n.job.flags||n.update(),delete e.afterLeave,d=void 0},he(s);"in-out"===l&&c.type!==Tr?e.delayLeave=(e,t,n)=>{const r=fe(o,d);r[String(d.key)]=d,e[re]=()=>{t(),e[re]=void 0,delete u.delayedLeave,d=void 0},u.delayedLeave=()=>{n(),delete u.delayedLeave,d=void 0}}:d=void 0}else d&&(d=void 0);return s}}};function ue(e){let t=e[0];if(e.length>1){let n=!1;for(const r of e)if(r.type!==Tr){0,t=r,n=!0;break}}return t}const de=ce;function fe(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function pe(e,t,n,r,i){const{appear:s,mode:a,persisted:l=!1,onBeforeEnter:c,onEnter:u,onAfterEnter:d,onEnterCancelled:p,onBeforeLeave:h,onLeave:m,onAfterLeave:v,onLeaveCancelled:g,onBeforeAppear:y,onAppear:b,onAfterAppear:_,onAppearCancelled:E}=t,w=String(e.key),S=fe(n,e),k=(e,t)=>{e&&f(e,r,9,t)},C=(e,t)=>{const n=t[1];k(e,t),(0,o.cy)(e)?e.every((e=>e.length<=1))&&n():e.length<=1&&n()},O={mode:a,persisted:l,beforeEnter(t){let r=c;if(!n.isMounted){if(!s)return;r=y||c}t[re]&&t[re](!0);const o=S[w];o&&Ur(e,o)&&o.el[re]&&o.el[re](),k(r,[t])},enter(e){let t=u,r=d,o=p;if(!n.isMounted){if(!s)return;t=b||u,r=_||d,o=E||p}let i=!1;const a=e[oe]=t=>{i||(i=!0,k(t?o:r,[e]),O.delayedLeave&&O.delayedLeave(),e[oe]=void 0)};t?C(t,[e,a]):a()},leave(t,r){const o=String(e.key);if(t[oe]&&t[oe](!0),n.isUnmounting)return r();k(h,[t]);let i=!1;const s=t[re]=n=>{i||(i=!0,r(),k(n?g:v,[t]),t[re]=void 0,S[o]===e&&delete S[o])};S[o]=e,m?C(m,[t,s]):s()},clone(e){const o=pe(e,t,n,r,i);return i&&i(o),o}};return O}function he(e){if(We(e))return e=zr(e),e.children=null,e}function me(e){if(!We(e))return X(e.type)&&e.children?ue(e.children):e;const{shapeFlag:t,children:n}=e;if(n){if(16&t)return n[0];if(32&t&&(0,o.Tn)(n.default))return n.default()}}function ve(e,t){6&e.shapeFlag&&e.component?(e.transition=t,ve(e.component.subTree,t)):128&e.shapeFlag?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function ge(e,t=!1,n){let r=[],o=0;for(let i=0;i1)for(let i=0;i(0,o.X$)({name:e.name},t,{setup:e}))():e}function be(){const e=ao();return e?(e.appContext.config.idPrefix||"v")+"-"+e.ids[0]+e.ids[1]++:""}function _e(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function Ee(e){const t=ao(),n=(0,r.IJ)(null);if(t){const r=t.refs===o.MZ?t.refs={}:t.refs;Object.defineProperty(r,e,{enumerable:!0,get:()=>n.value,set:e=>n.value=e})}else 0;const i=n;return i}function we(e,t,n,i,s=!1){if((0,o.cy)(e))return void e.forEach(((e,r)=>we(e,t&&((0,o.cy)(t)?t[r]:t),n,i,s)));if(Be(i)&&!s)return void(512&i.shapeFlag&&i.type.__asyncResolved&&i.component.subTree.component&&we(e,t,n,i.component.subTree));const a=4&i.shapeFlag?Co(i.component):i.el,l=s?null:a,{i:c,r:u}=e;const f=t&&t.r,p=c.refs===o.MZ?c.refs={}:c.refs,h=c.setupState,m=(0,r.ux)(h),v=h===o.MZ?()=>!1:e=>(0,o.$3)(m,e);if(null!=f&&f!==u&&((0,o.Kg)(f)?(p[f]=null,v(f)&&(h[f]=null)):(0,r.i9)(f)&&(f.value=null)),(0,o.Tn)(u))d(u,c,12,[l,p]);else{const t=(0,o.Kg)(u),i=(0,r.i9)(u);if(t||i){const r=()=>{if(e.f){const n=t?v(u)?h[u]:p[u]:u.value;s?(0,o.cy)(n)&&(0,o.TF)(n,a):(0,o.cy)(n)?n.includes(a)||n.push(a):t?(p[u]=[a],v(u)&&(h[u]=p[u])):(u.value=[a],e.k&&(p[e.k]=u.value))}else t?(p[u]=l,v(u)&&(h[u]=l)):i&&(u.value=l,e.k&&(p[e.k]=l))};l?(r.id=-1,Pn(r,n)):r()}else 0}}let Se=!1;const ke=()=>{Se||(console.error("Hydration completed but contains mismatches."),Se=!0)},Ce=e=>e.namespaceURI.includes("svg")&&"foreignObject"!==e.tagName,Oe=e=>e.namespaceURI.includes("MathML"),Te=e=>{if(1===e.nodeType)return Ce(e)?"svg":Oe(e)?"mathml":void 0},Re=e=>8===e.nodeType;function Ae(e){const{mt:t,p:n,o:{patchProp:i,createText:s,nextSibling:a,parentNode:l,remove:c,insert:u,createComment:d}}=e,f=(e,t)=>{if(!t.hasChildNodes())return n(null,e,t),R(),void(t._vnode=e);p(t.firstChild,e,null,null,null),R(),t._vnode=e},p=(n,r,o,i,c,d=!1)=>{d=d||!!r.dynamicChildren;const f=Re(n)&&"["===n.data,E=()=>g(n,r,o,i,c,f),{type:w,ref:S,shapeFlag:k,patchFlag:C}=r;let O=n.nodeType;r.el=n,-2===C&&(d=!1,r.dynamicChildren=null);let T=null;switch(w){case Or:3!==O?""===r.children?(u(r.el=s(""),l(n),n),T=n):T=E():(n.data!==r.children&&(ke(),n.data=r.children),T=a(n));break;case Tr:_(n)?(T=a(n),b(r.el=n.content.firstChild,n,o)):T=8!==O||f?E():a(n);break;case Rr:if(f&&(n=a(n),O=n.nodeType),1===O||3===O){T=n;const e=!r.children.length;for(let t=0;t{l=l||!!t.dynamicChildren;const{type:u,props:d,patchFlag:f,shapeFlag:p,dirs:h,transition:v}=t,g="input"===u||"option"===u;if(g||-1!==f){h&&H(t,null,n,"created");let u,y=!1;if(_(e)){y=jn(null,v)&&n&&n.vnode.props&&n.vnode.props.appear;const r=e.content.firstChild;y&&v.beforeEnter(r),b(r,e,n),t.el=e=r}if(16&p&&(!d||!d.innerHTML&&!d.textContent)){let r=m(e.firstChild,t,e,n,s,a,l);while(r){Ie(e,1)||ke();const t=r;r=r.nextSibling,c(t)}}else if(8&p){let n=t.children;"\n"!==n[0]||"PRE"!==e.tagName&&"TEXTAREA"!==e.tagName||(n=n.slice(1)),e.textContent!==n&&(Ie(e,0)||ke(),e.textContent=t.children)}if(d)if(g||!l||48&f){const t=e.tagName.includes("-");for(const r in d)(g&&(r.endsWith("value")||"indeterminate"===r)||(0,o.Mp)(r)&&!(0,o.SU)(r)||"."===r[0]||t)&&i(e,r,null,d[r],void 0,n)}else if(d.onClick)i(e,"onClick",null,d.onClick,void 0,n);else if(4&f&&(0,r.g8)(d.style))for(const e in d.style)d.style[e];(u=d&&d.onVnodeBeforeMount)&&no(u,n,t),h&&H(t,null,n,"beforeMount"),((u=d&&d.onVnodeMounted)||h||y)&&wr((()=>{u&&no(u,n,t),y&&v.enter(e),h&&H(t,null,n,"mounted")}),s)}return e.nextSibling},m=(e,t,r,o,i,l,c)=>{c=c||!!t.dynamicChildren;const d=t.children,f=d.length;for(let h=0;h{const{slotScopeIds:s}=t;s&&(o=o?o.concat(s):s);const c=l(e),f=m(a(e),t,c,n,r,o,i);return f&&Re(f)&&"]"===f.data?a(t.anchor=f):(ke(),u(t.anchor=d("]"),c,f),f)},g=(e,t,r,o,i,s)=>{if(Ie(e.parentElement,1)||ke(),t.el=null,s){const t=y(e);while(1){const n=a(e);if(!n||n===t)break;c(n)}}const u=a(e),d=l(e);return c(e),n(null,t,d,u,r,o,Te(d),i),r&&(r.vnode.el=t.el,ur(r,t.el)),u},y=(e,t="[",n="]")=>{let r=0;while(e)if(e=a(e),e&&Re(e)&&(e.data===t&&r++,e.data===n)){if(0===r)return a(e);r--}return e},b=(e,t,n)=>{const r=t.parentNode;r&&r.replaceChild(e,t);let o=n;while(o)o.vnode.el===t&&(o.vnode.el=o.subTree.el=e),o=o.parent},_=e=>1===e.nodeType&&"TEMPLATE"===e.tagName;return[f,p]}const Ne="data-allow-mismatch",Le={[0]:"text",[1]:"children",[2]:"class",[3]:"style",[4]:"attribute"};function Ie(e,t){if(0===t||1===t)while(e&&!e.hasAttribute(Ne))e=e.parentElement;const n=e&&e.getAttribute(Ne);if(null==n)return!1;if(""===n)return!0;{const e=n.split(",");return!(0!==t||!e.includes("children"))||n.split(",").includes(Le[t])}}const Pe=(0,o.We)().requestIdleCallback||(e=>setTimeout(e,1)),xe=(0,o.We)().cancelIdleCallback||(e=>clearTimeout(e)),Me=(e=1e4)=>t=>{const n=Pe(t,{timeout:e});return()=>xe(n)};function De(e){const{top:t,left:n,bottom:r,right:o}=e.getBoundingClientRect(),{innerHeight:i,innerWidth:s}=window;return(t>0&&t0&&r0&&n0&&o(t,n)=>{const r=new IntersectionObserver((e=>{for(const n of e)if(n.isIntersecting){r.disconnect(),t();break}}),e);return n((e=>{if(e instanceof Element)return De(e)?(t(),r.disconnect(),!1):void r.observe(e)})),()=>r.disconnect()},Fe=e=>t=>{if(e){const n=matchMedia(e);if(!n.matches)return n.addEventListener("change",t,{once:!0}),()=>n.removeEventListener("change",t);t()}},je=(e=[])=>(t,n)=>{(0,o.Kg)(e)&&(e=[e]);let r=!1;const i=e=>{r||(r=!0,s(),t(),e.target.dispatchEvent(new e.constructor(e.type,e)))},s=()=>{n((t=>{for(const n of e)t.removeEventListener(n,i)}))};return n((t=>{for(const n of e)t.addEventListener(n,i,{once:!0})})),s};function Ue(e,t){if(Re(e)&&"["===e.data){let n=1,r=e.nextSibling;while(r){if(1===r.nodeType){const e=t(r);if(!1===e)break}else if(Re(r))if("]"===r.data){if(0===--n)break}else"["===r.data&&n++;r=r.nextSibling}}else t(e)}const Be=e=>!!e.type.__asyncLoader /*! #__NO_SIDE_EFFECTS__ */;function Ve(e){(0,o.Tn)(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:i,delay:s=200,hydrate:a,timeout:l,suspensible:c=!0,onError:u}=e;let d,f=null,h=0;const m=()=>(h++,f=null,v()),v=()=>{let e;return f||(e=f=t().catch((e=>{if(e=e instanceof Error?e:new Error(String(e)),u)return new Promise(((t,n)=>{const r=()=>t(m()),o=()=>n(e);u(e,r,o,h+1)}));throw e})).then((t=>e!==f&&f?f:(t&&(t.__esModule||"Module"===t[Symbol.toStringTag])&&(t=t.default),d=t,t))))};return ye({name:"AsyncComponentWrapper",__asyncLoader:v,__asyncHydrate(e,t,n){const r=a?()=>{const r=a(n,(t=>Ue(e,t)));r&&(t.bum||(t.bum=[])).push(r)}:n;d?r():v().then((()=>!t.isUnmounted&&r()))},get __asyncResolved(){return d},setup(){const e=so;if(_e(e),d)return()=>He(d,e);const t=t=>{f=null,p(t,e,13,!i)};if(c&&e.suspense||vo)return v().then((t=>()=>He(t,e))).catch((e=>(t(e),()=>i?Xr(i,{error:e}):null)));const o=(0,r.KR)(!1),a=(0,r.KR)(),u=(0,r.KR)(!!s);return s&&setTimeout((()=>{u.value=!1}),s),null!=l&&setTimeout((()=>{if(!o.value&&!a.value){const e=new Error(`Async component timed out after ${l}ms.`);t(e),a.value=e}}),l),v().then((()=>{o.value=!0,e.parent&&We(e.parent.vnode)&&e.parent.update()})).catch((e=>{t(e),a.value=e})),()=>o.value&&d?He(d,e):a.value&&i?Xr(i,{error:a.value}):n&&!u.value?Xr(n):void 0}})}function He(e,t){const{ref:n,props:r,children:o,ce:i}=t.vnode,s=Xr(e,r,o);return s.ref=n,s.ce=i,delete t.vnode.ce,s}const We=e=>e.type.__isKeepAlive,Xe={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(e,{slots:t}){const n=ao(),r=n.ctx;if(!r.renderer)return()=>{const e=t.default&&t.default();return e&&1===e.length?e[0]:e};const i=new Map,s=new Set;let a=null;const l=n.suspense,{renderer:{p:c,m:u,um:d,o:{createElement:f}}}=r,p=f("div");function h(e){Je(e),d(e,n,l,!0)}function m(e){i.forEach(((t,n)=>{const r=Oo(t.type);r&&!e(r)&&v(n)}))}function v(e){const t=i.get(e);!t||a&&Ur(t,a)?a&&Je(a):h(t),i.delete(e),s.delete(e)}r.activate=(e,t,n,r,i)=>{const s=e.component;u(e,t,n,0,l),c(s.vnode,e,t,n,s,l,r,e.slotScopeIds,i),Pn((()=>{s.isDeactivated=!1,s.a&&(0,o.DY)(s.a);const t=e.props&&e.props.onVnodeMounted;t&&no(t,s.parent,e)}),l)},r.deactivate=e=>{const t=e.component;Hn(t.m),Hn(t.a),u(e,p,null,1,l),Pn((()=>{t.da&&(0,o.DY)(t.da);const n=e.props&&e.props.onVnodeUnmounted;n&&no(n,t.parent,e),t.isDeactivated=!0}),l)},qn((()=>[e.include,e.exclude]),(([e,t])=>{e&&m((t=>Ke(e,t))),t&&m((e=>!Ke(t,e)))}),{flush:"post",deep:!0});let g=null;const y=()=>{null!=g&&(dr(n.subTree.type)?Pn((()=>{i.set(g,Ze(n.subTree))}),n.subTree.suspense):i.set(g,Ze(n.subTree)))};return rt(y),it(y),st((()=>{i.forEach((e=>{const{subTree:t,suspense:r}=n,o=Ze(t);if(e.type!==o.type||e.key!==o.key)h(e);else{Je(o);const e=o.component.da;e&&Pn(e,r)}}))})),()=>{if(g=null,!t.default)return a=null;const n=t.default(),r=n[0];if(n.length>1)return a=null,n;if(!jr(r)||!(4&r.shapeFlag)&&!(128&r.shapeFlag))return a=null,r;let o=Ze(r);if(o.type===Tr)return a=null,o;const l=o.type,c=Oo(Be(o)?o.type.__asyncResolved||{}:l),{include:u,exclude:d,max:f}=e;if(u&&(!c||!Ke(u,c))||d&&c&&Ke(d,c))return o.shapeFlag&=-257,a=o,r;const p=null==o.key?l:o.key,h=i.get(p);return o.el&&(o=zr(o),128&r.shapeFlag&&(r.ssContent=o)),g=p,h?(o.el=h.el,o.component=h.component,o.transition&&ve(o,o.transition),o.shapeFlag|=512,s.delete(p),s.add(p)):(s.add(p),f&&s.size>parseInt(f,10)&&v(s.values().next().value)),o.shapeFlag|=256,a=o,dr(r.type)?r:o}}},Ge=Xe;function Ke(e,t){return(0,o.cy)(e)?e.some((e=>Ke(e,t))):(0,o.Kg)(e)?e.split(",").includes(t):!!(0,o.gd)(e)&&(e.lastIndex=0,e.test(t))}function ze(e,t){Ye(e,"a",t)}function qe(e,t){Ye(e,"da",t)}function Ye(e,t,n=so){const r=e.__wdc||(e.__wdc=()=>{let t=n;while(t){if(t.isDeactivated)return;t=t.parent}return e()});if(et(t,r,n),n){let e=n.parent;while(e&&e.parent)We(e.parent.vnode)&&Qe(r,t,n,e),e=e.parent}}function Qe(e,t,n,r){const i=et(t,e,r,!0);at((()=>{(0,o.TF)(r[t],i)}),n)}function Je(e){e.shapeFlag&=-257,e.shapeFlag&=-513}function Ze(e){return 128&e.shapeFlag?e.ssContent:e}function et(e,t,n=so,o=!1){if(n){const i=n[e]||(n[e]=[]),s=t.__weh||(t.__weh=(...o)=>{(0,r.C4)();const i=uo(n),s=f(t,n,e,o);return i(),(0,r.bl)(),s});return o?i.unshift(s):i.push(s),s}}const tt=e=>(t,n=so)=>{vo&&"sp"!==e||et(e,((...e)=>t(...e)),n)},nt=tt("bm"),rt=tt("m"),ot=tt("bu"),it=tt("u"),st=tt("bum"),at=tt("um"),lt=tt("sp"),ct=tt("rtg"),ut=tt("rtc");function dt(e,t=so){et("ec",e,t)}const ft="components",pt="directives";function ht(e,t){return yt(ft,e,!0,t)||e}const mt=Symbol.for("v-ndc");function vt(e){return(0,o.Kg)(e)?yt(ft,e,!1)||e:e||mt}function gt(e){return yt(pt,e)}function yt(e,t,n=!0,r=!1){const i=M||so;if(i){const n=i.type;if(e===ft){const e=Oo(n,!1);if(e&&(e===t||e===(0,o.PT)(t)||e===(0,o.ZH)((0,o.PT)(t))))return n}const s=bt(i[e]||n[e],t)||bt(i.appContext[e],t);return!s&&r?n:s}}function bt(e,t){return e&&(e[t]||e[(0,o.PT)(t)]||e[(0,o.ZH)((0,o.PT)(t))])}function _t(e,t,n,i){let s;const a=n&&n[i],l=(0,o.cy)(e);if(l||(0,o.Kg)(e)){const n=l&&(0,r.g8)(e);let o=!1;n&&(o=!(0,r.fE)(e),e=(0,r.qA)(e)),s=new Array(e.length);for(let i=0,l=e.length;it(e,n,void 0,a&&a[n])));else{const n=Object.keys(e);s=new Array(n.length);for(let r=0,o=n.length;r{const t=r.fn(...e);return t&&(t.key=r.key),t}:r.fn)}return e}function wt(e,t,n={},r,i){if(M.ce||M.parent&&Be(M.parent)&&M.parent.ce)return"default"!==t&&(n.name=t),Lr(),Fr(Cr,null,[Xr("slot",n,r&&r())],64);let s=e[t];s&&s._c&&(s._d=!1),Lr();const a=s&&St(s(n)),l=n.key||a&&a.key,c=Fr(Cr,{key:(l&&!(0,o.Bm)(l)?l:`_${t}`)+(!a&&r?"_fb":"")},a||(r?r():[]),a&&1===e._?64:-2);return!i&&c.scopeId&&(c.slotScopeIds=[c.scopeId+"-s"]),s&&s._c&&(s._d=!0),c}function St(e){return e.some((e=>!jr(e)||e.type!==Tr&&!(e.type===Cr&&!St(e.children))))?e:null}function kt(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:(0,o.rU)(r)]=e[r];return n}const Ct=e=>e?po(e)?Co(e):Ct(e.parent):null,Ot=(0,o.X$)(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Ct(e.parent),$root:e=>Ct(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Yt(e),$forceUpdate:e=>e.f||(e.f=()=>{k(e.update)}),$nextTick:e=>e.n||(e.n=w.bind(e.proxy)),$watch:e=>Qn.bind(e)}),Tt=(e,t)=>e!==o.MZ&&!e.__isScriptSetup&&(0,o.$3)(e,t),Rt={get({_:e},t){if("__v_skip"===t)return!0;const{ctx:n,setupState:i,data:s,props:a,accessCache:l,type:c,appContext:u}=e;let d;if("$"!==t[0]){const r=l[t];if(void 0!==r)switch(r){case 1:return i[t];case 2:return s[t];case 4:return n[t];case 3:return a[t]}else{if(Tt(i,t))return l[t]=1,i[t];if(s!==o.MZ&&(0,o.$3)(s,t))return l[t]=2,s[t];if((d=e.propsOptions[0])&&(0,o.$3)(d,t))return l[t]=3,a[t];if(n!==o.MZ&&(0,o.$3)(n,t))return l[t]=4,n[t];Xt&&(l[t]=0)}}const f=Ot[t];let p,h;return f?("$attrs"===t&&(0,r.u4)(e.attrs,"get",""),f(e)):(p=c.__cssModules)&&(p=p[t])?p:n!==o.MZ&&(0,o.$3)(n,t)?(l[t]=4,n[t]):(h=u.config.globalProperties,(0,o.$3)(h,t)?h[t]:void 0)},set({_:e},t,n){const{data:r,setupState:i,ctx:s}=e;return Tt(i,t)?(i[t]=n,!0):r!==o.MZ&&(0,o.$3)(r,t)?(r[t]=n,!0):!(0,o.$3)(e.props,t)&&(("$"!==t[0]||!(t.slice(1)in e))&&(s[t]=n,!0))},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:i,propsOptions:s}},a){let l;return!!n[a]||e!==o.MZ&&(0,o.$3)(e,a)||Tt(t,a)||(l=s[0])&&(0,o.$3)(l,a)||(0,o.$3)(r,a)||(0,o.$3)(Ot,a)||(0,o.$3)(i.config.globalProperties,a)},defineProperty(e,t,n){return null!=n.get?e._.accessCache[t]=0:(0,o.$3)(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};const At=(0,o.X$)({},Rt,{get(e,t){if(t!==Symbol.unscopables)return Rt.get(e,t,e)},has(e,t){const n="_"!==t[0]&&!(0,o.BH)(t);return n}});function Nt(){return null}function Lt(){return null}function It(e){0}function Pt(e){0}function xt(){return null}function Mt(){0}function Dt(e,t){return null}function $t(){return jt().slots}function Ft(){return jt().attrs}function jt(){const e=ao();return e.setupContext||(e.setupContext=ko(e))}function Ut(e){return(0,o.cy)(e)?e.reduce(((e,t)=>(e[t]=null,e)),{}):e}function Bt(e,t){const n=Ut(e);for(const r in t){if(r.startsWith("__skip"))continue;let e=n[r];e?(0,o.cy)(e)||(0,o.Tn)(e)?e=n[r]={type:e,default:t[r]}:e.default=t[r]:null===e&&(e=n[r]={default:t[r]}),e&&t[`__skip_${r}`]&&(e.skipFactory=!0)}return n}function Vt(e,t){return e&&t?(0,o.cy)(e)&&(0,o.cy)(t)?e.concat(t):(0,o.X$)({},Ut(e),Ut(t)):e||t}function Ht(e,t){const n={};for(const r in e)t.includes(r)||Object.defineProperty(n,r,{enumerable:!0,get:()=>e[r]});return n}function Wt(e){const t=ao();let n=e();return fo(),(0,o.yL)(n)&&(n=n.catch((e=>{throw uo(t),e}))),[n,()=>uo(t)]}let Xt=!0;function Gt(e){const t=Yt(e),n=e.proxy,i=e.ctx;Xt=!1,t.beforeCreate&&zt(t.beforeCreate,e,"bc");const{data:s,computed:a,methods:l,watch:c,provide:u,inject:d,created:f,beforeMount:p,mounted:h,beforeUpdate:m,updated:v,activated:g,deactivated:y,beforeDestroy:b,beforeUnmount:_,destroyed:E,unmounted:w,render:S,renderTracked:k,renderTriggered:C,errorCaptured:O,serverPrefetch:T,expose:R,inheritAttrs:A,components:N,directives:L,filters:I}=t,P=null;if(d&&Kt(d,i,P),l)for(const r in l){const e=l[r];(0,o.Tn)(e)&&(i[r]=e.bind(n))}if(s){0;const t=s.call(n,n);0,(0,o.Gv)(t)&&(e.data=(0,r.Kh)(t))}if(Xt=!0,a)for(const r in a){const e=a[r],t=(0,o.Tn)(e)?e.bind(n,n):(0,o.Tn)(e.get)?e.get.bind(n,n):o.tE;0;const s=!(0,o.Tn)(e)&&(0,o.Tn)(e.set)?e.set.bind(n):o.tE,l=Ro({get:t,set:s});Object.defineProperty(i,r,{enumerable:!0,configurable:!0,get:()=>l.value,set:e=>l.value=e})}if(c)for(const r in c)qt(c[r],i,n,r);if(u){const e=(0,o.Tn)(u)?u.call(n):u;Reflect.ownKeys(e).forEach((t=>{dn(t,e[t])}))}function x(e,t){(0,o.cy)(t)?t.forEach((t=>e(t.bind(n)))):t&&e(t.bind(n))}if(f&&zt(f,e,"c"),x(nt,p),x(rt,h),x(ot,m),x(it,v),x(ze,g),x(qe,y),x(dt,O),x(ut,k),x(ct,C),x(st,_),x(at,w),x(lt,T),(0,o.cy)(R))if(R.length){const t=e.exposed||(e.exposed={});R.forEach((e=>{Object.defineProperty(t,e,{get:()=>n[e],set:t=>n[e]=t})}))}else e.exposed||(e.exposed={});S&&e.render===o.tE&&(e.render=S),null!=A&&(e.inheritAttrs=A),N&&(e.components=N),L&&(e.directives=L),T&&_e(e)}function Kt(e,t,n=o.tE){(0,o.cy)(e)&&(e=tn(e));for(const i in e){const n=e[i];let s;s=(0,o.Gv)(n)?"default"in n?fn(n.from||i,n.default,!0):fn(n.from||i):fn(n),(0,r.i9)(s)?Object.defineProperty(t,i,{enumerable:!0,configurable:!0,get:()=>s.value,set:e=>s.value=e}):t[i]=s}}function zt(e,t,n){f((0,o.cy)(e)?e.map((e=>e.bind(t.proxy))):e.bind(t.proxy),t,n)}function qt(e,t,n,r){let i=r.includes(".")?Jn(n,r):()=>n[r];if((0,o.Kg)(e)){const n=t[e];(0,o.Tn)(n)&&qn(i,n)}else if((0,o.Tn)(e))qn(i,e.bind(n));else if((0,o.Gv)(e))if((0,o.cy)(e))e.forEach((e=>qt(e,t,n,r)));else{const r=(0,o.Tn)(e.handler)?e.handler.bind(n):t[e.handler];(0,o.Tn)(r)&&qn(i,r,e)}else 0}function Yt(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:i,optionsCache:s,config:{optionMergeStrategies:a}}=e.appContext,l=s.get(t);let c;return l?c=l:i.length||n||r?(c={},i.length&&i.forEach((e=>Qt(c,e,a,!0))),Qt(c,t,a)):c=t,(0,o.Gv)(t)&&s.set(t,c),c}function Qt(e,t,n,r=!1){const{mixins:o,extends:i}=t;i&&Qt(e,i,n,!0),o&&o.forEach((t=>Qt(e,t,n,!0)));for(const s in t)if(r&&"expose"===s);else{const r=Jt[s]||n&&n[s];e[s]=r?r(e[s],t[s]):t[s]}return e}const Jt={data:Zt,props:on,emits:on,methods:rn,computed:rn,beforeCreate:nn,created:nn,beforeMount:nn,mounted:nn,beforeUpdate:nn,updated:nn,beforeDestroy:nn,beforeUnmount:nn,destroyed:nn,unmounted:nn,activated:nn,deactivated:nn,errorCaptured:nn,serverPrefetch:nn,components:rn,directives:rn,watch:sn,provide:Zt,inject:en};function Zt(e,t){return t?e?function(){return(0,o.X$)((0,o.Tn)(e)?e.call(this,this):e,(0,o.Tn)(t)?t.call(this,this):t)}:t:e}function en(e,t){return rn(tn(e),tn(t))}function tn(e){if((0,o.cy)(e)){const t={};for(let n=0;n1)return n&&(0,o.Tn)(t)?t.call(r&&r.proxy):t}else 0}function pn(){return!!(so||M||un)}const hn={},mn=()=>Object.create(hn),vn=e=>Object.getPrototypeOf(e)===hn;function gn(e,t,n,o=!1){const i={},s=mn();e.propsDefaults=Object.create(null),bn(e,t,i,s);for(const r in e.propsOptions[0])r in i||(i[r]=void 0);n?e.props=o?i:(0,r.Gc)(i):e.type.props?e.props=i:e.props=s,e.attrs=s}function yn(e,t,n,i){const{props:s,attrs:a,vnode:{patchFlag:l}}=e,c=(0,r.ux)(s),[u]=e.propsOptions;let d=!1;if(!(i||l>0)||16&l){let r;bn(e,t,s,a)&&(d=!0);for(const i in c)t&&((0,o.$3)(t,i)||(r=(0,o.Tg)(i))!==i&&(0,o.$3)(t,r))||(u?!n||void 0===n[i]&&void 0===n[r]||(s[i]=_n(u,c,i,void 0,e,!0)):delete s[i]);if(a!==c)for(const e in a)t&&(0,o.$3)(t,e)||(delete a[e],d=!0)}else if(8&l){const n=e.vnode.dynamicProps;for(let r=0;r{c=!0;const[n,r]=wn(e,t,!0);(0,o.X$)(a,n),r&&l.push(...r)};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}if(!s&&!c)return(0,o.Gv)(e)&&r.set(e,o.Oj),o.Oj;if((0,o.cy)(s))for(let d=0;d"_"===e[0]||"$stable"===e,Cn=e=>(0,o.cy)(e)?e.map(Jr):[Jr(e)],On=(e,t,n)=>{if(t._n)return t;const r=B(((...e)=>Cn(t(...e))),n);return r._c=!1,r},Tn=(e,t,n)=>{const r=e._ctx;for(const i in e){if(kn(i))continue;const n=e[i];if((0,o.Tn)(n))t[i]=On(i,n,r);else if(null!=n){0;const e=Cn(n);t[i]=()=>e}}},Rn=(e,t)=>{const n=Cn(t);e.slots.default=()=>n},An=(e,t,n)=>{for(const r in t)(n||"_"!==r)&&(e[r]=t[r])},Nn=(e,t,n)=>{const r=e.slots=mn();if(32&e.vnode.shapeFlag){const e=t._;e?(An(r,t,n),n&&(0,o.yQ)(r,"_",e,!0)):Tn(t,r)}else t&&Rn(e,t)},Ln=(e,t,n)=>{const{vnode:r,slots:i}=e;let s=!0,a=o.MZ;if(32&r.shapeFlag){const e=t._;e?n&&1===e?s=!1:An(i,t,n):(s=!t.$stable,Tn(t,i)),a=t}else t&&(Rn(e,t),a={default:1});if(s)for(const o in i)kn(o)||null!=a[o]||delete i[o]};function In(){}const Pn=wr;function xn(e){return Dn(e)}function Mn(e){return Dn(e,Ae)}function Dn(e,t){In();const n=(0,o.We)();n.__VUE__=!0;const{insert:i,remove:s,patchProp:a,createElement:l,createText:c,createComment:u,setText:d,setElementText:f,parentNode:p,nextSibling:h,setScopeId:m=o.tE,insertStaticContent:v}=e,g=(e,t,n,r=null,o=null,i=null,s=void 0,a=null,l=!!t.dynamicChildren)=>{if(e===t)return;e&&!Ur(e,t)&&(r=Y(e),X(e,o,i,!0),e=null),-2===t.patchFlag&&(l=!1,t.dynamicChildren=null);const{type:c,ref:u,shapeFlag:d}=t;switch(c){case Or:y(e,t,n,r);break;case Tr:b(e,t,n,r);break;case Rr:null==e&&_(t,n,r,s);break;case Cr:P(e,t,n,r,o,i,s,a,l);break;default:1&d?S(e,t,n,r,o,i,s,a,l):6&d?x(e,t,n,r,o,i,s,a,l):(64&d||128&d)&&c.process(e,t,n,r,o,i,s,a,l,Z)}null!=u&&o&&we(u,e&&e.ref,i,t||e,!t)},y=(e,t,n,r)=>{if(null==e)i(t.el=c(t.children),n,r);else{const n=t.el=e.el;t.children!==e.children&&d(n,t.children)}},b=(e,t,n,r)=>{null==e?i(t.el=u(t.children||""),n,r):t.el=e.el},_=(e,t,n,r)=>{[e.el,e.anchor]=v(e.children,t,n,r,e.el,e.anchor)},E=({el:e,anchor:t},n,r)=>{let o;while(e&&e!==t)o=h(e),i(e,n,r),e=o;i(t,n,r)},w=({el:e,anchor:t})=>{let n;while(e&&e!==t)n=h(e),s(e),e=n;s(t)},S=(e,t,n,r,o,i,s,a,l)=>{"svg"===t.type?s="svg":"math"===t.type&&(s="mathml"),null==e?C(t,n,r,o,i,s,a,l):N(e,t,o,i,s,a,l)},C=(e,t,n,r,s,c,u,d)=>{let p,h;const{props:m,shapeFlag:v,transition:g,dirs:y}=e;if(p=e.el=l(e.type,c,m&&m.is,m),8&v?f(p,e.children):16&v&&A(e.children,p,null,r,s,$n(e,c),u,d),y&&H(e,null,r,"created"),O(p,e,e.scopeId,u,r),m){for(const e in m)"value"===e||(0,o.SU)(e)||a(p,e,null,m[e],c,r);"value"in m&&a(p,"value",null,m.value,c),(h=m.onVnodeBeforeMount)&&no(h,r,e)}y&&H(e,null,r,"beforeMount");const b=jn(s,g);b&&g.beforeEnter(p),i(p,t,n),((h=m&&m.onVnodeMounted)||b||y)&&Pn((()=>{h&&no(h,r,e),b&&g.enter(p),y&&H(e,null,r,"mounted")}),s)},O=(e,t,n,r,o)=>{if(n&&m(e,n),r)for(let i=0;i{for(let c=l;c{const c=t.el=e.el;let{patchFlag:u,dynamicChildren:d,dirs:p}=t;u|=16&e.patchFlag;const h=e.props||o.MZ,m=t.props||o.MZ;let v;if(n&&Fn(n,!1),(v=m.onVnodeBeforeUpdate)&&no(v,n,t,e),p&&H(t,e,n,"beforeUpdate"),n&&Fn(n,!0),(h.innerHTML&&null==m.innerHTML||h.textContent&&null==m.textContent)&&f(c,""),d?L(e.dynamicChildren,d,c,n,r,$n(t,i),s):l||j(e,t,c,null,n,r,$n(t,i),s,!1),u>0){if(16&u)I(c,h,m,n,i);else if(2&u&&h.class!==m.class&&a(c,"class",null,m.class,i),4&u&&a(c,"style",h.style,m.style,i),8&u){const e=t.dynamicProps;for(let t=0;t{v&&no(v,n,t,e),p&&H(t,e,n,"updated")}),r)},L=(e,t,n,r,o,i,s)=>{for(let a=0;a{if(t!==n){if(t!==o.MZ)for(const s in t)(0,o.SU)(s)||s in n||a(e,s,t[s],null,i,r);for(const s in n){if((0,o.SU)(s))continue;const l=n[s],c=t[s];l!==c&&"value"!==s&&a(e,s,c,l,i,r)}"value"in n&&a(e,"value",t.value,n.value,i)}},P=(e,t,n,r,o,s,a,l,u)=>{const d=t.el=e?e.el:c(""),f=t.anchor=e?e.anchor:c("");let{patchFlag:p,dynamicChildren:h,slotScopeIds:m}=t;m&&(l=l?l.concat(m):m),null==e?(i(d,n,r),i(f,n,r),A(t.children||[],n,f,o,s,a,l,u)):p>0&&64&p&&h&&e.dynamicChildren?(L(e.dynamicChildren,h,n,o,s,a,l),(null!=t.key||o&&t===o.subTree)&&Un(e,t,!0)):j(e,t,n,f,o,s,a,l,u)},x=(e,t,n,r,o,i,s,a,l)=>{t.slotScopeIds=a,null==e?512&t.shapeFlag?o.ctx.activate(t,n,r,s,l):M(t,n,r,o,i,s,l):D(e,t,l)},M=(e,t,n,r,o,i,s)=>{const a=e.component=io(e,r,o);if(We(e)&&(a.ctx.renderer=Z),go(a,!1,s),a.asyncDep){if(o&&o.registerDep(a,$,s),!e.el){const e=a.subTree=Xr(Tr);b(null,e,t,n)}}else $(a,e,t,n,o,i,s)},D=(e,t,n)=>{const r=t.component=e.component;if(lr(e,t,n)){if(r.asyncDep&&!r.asyncResolved)return void F(r,t,n);r.next=t,r.update()}else t.el=e.el,r.vnode=t},$=(e,t,n,i,s,a,l)=>{const c=()=>{if(e.isMounted){let{next:t,bu:n,u:r,parent:i,vnode:u}=e;{const n=Vn(e);if(n)return t&&(t.el=u.el,F(e,t,l)),void n.asyncDep.then((()=>{e.isUnmounted||c()}))}let d,f=t;0,Fn(e,!1),t?(t.el=u.el,F(e,t,l)):t=u,n&&(0,o.DY)(n),(d=t.props&&t.props.onVnodeBeforeUpdate)&&no(d,i,t,u),Fn(e,!0);const h=or(e);0;const m=e.subTree;e.subTree=h,g(m,h,p(m.el),Y(m),e,s,a),t.el=h.el,null===f&&ur(e,h.el),r&&Pn(r,s),(d=t.props&&t.props.onVnodeUpdated)&&Pn((()=>no(d,i,t,u)),s)}else{let r;const{el:l,props:c}=t,{bm:u,m:d,parent:f,root:p,type:h}=e,m=Be(t);if(Fn(e,!1),u&&(0,o.DY)(u),!m&&(r=c&&c.onVnodeBeforeMount)&&no(r,f,t),Fn(e,!0),l&&te){const t=()=>{e.subTree=or(e),te(l,e.subTree,e,s,null)};m&&h.__asyncHydrate?h.__asyncHydrate(l,e,t):t()}else{p.ce&&p.ce._injectChildStyle(h);const r=e.subTree=or(e);0,g(null,r,n,i,e,s,a),t.el=r.el}if(d&&Pn(d,s),!m&&(r=c&&c.onVnodeMounted)){const e=t;Pn((()=>no(r,f,e)),s)}(256&t.shapeFlag||f&&Be(f.vnode)&&256&f.vnode.shapeFlag)&&e.a&&Pn(e.a,s),e.isMounted=!0,t=n=i=null}};e.scope.on();const u=e.effect=new r.X2(c);e.scope.off();const d=e.update=u.run.bind(u),f=e.job=u.runIfDirty.bind(u);f.i=e,f.id=e.uid,u.scheduler=()=>k(f),Fn(e,!0),d()},F=(e,t,n)=>{t.component=e;const o=e.vnode.props;e.vnode=t,e.next=null,yn(e,t.props,o,n),Ln(e,t.children,n),(0,r.C4)(),T(e),(0,r.bl)()},j=(e,t,n,r,o,i,s,a,l=!1)=>{const c=e&&e.children,u=e?e.shapeFlag:0,d=t.children,{patchFlag:p,shapeFlag:h}=t;if(p>0){if(128&p)return void B(c,d,n,r,o,i,s,a,l);if(256&p)return void U(c,d,n,r,o,i,s,a,l)}8&h?(16&u&&q(c,o,i),d!==c&&f(n,d)):16&u?16&h?B(c,d,n,r,o,i,s,a,l):q(c,o,i,!0):(8&u&&f(n,""),16&h&&A(d,n,r,o,i,s,a,l))},U=(e,t,n,r,i,s,a,l,c)=>{e=e||o.Oj,t=t||o.Oj;const u=e.length,d=t.length,f=Math.min(u,d);let p;for(p=0;pd?q(e,i,s,!0,!1,f):A(t,n,r,i,s,a,l,c,f)},B=(e,t,n,r,i,s,a,l,c)=>{let u=0;const d=t.length;let f=e.length-1,p=d-1;while(u<=f&&u<=p){const r=e[u],o=t[u]=c?Zr(t[u]):Jr(t[u]);if(!Ur(r,o))break;g(r,o,n,null,i,s,a,l,c),u++}while(u<=f&&u<=p){const r=e[f],o=t[p]=c?Zr(t[p]):Jr(t[p]);if(!Ur(r,o))break;g(r,o,n,null,i,s,a,l,c),f--,p--}if(u>f){if(u<=p){const e=p+1,o=ep)while(u<=f)X(e[u],i,s,!0),u++;else{const h=u,m=u,v=new Map;for(u=m;u<=p;u++){const e=t[u]=c?Zr(t[u]):Jr(t[u]);null!=e.key&&v.set(e.key,u)}let y,b=0;const _=p-m+1;let E=!1,w=0;const S=new Array(_);for(u=0;u<_;u++)S[u]=0;for(u=h;u<=f;u++){const r=e[u];if(b>=_){X(r,i,s,!0);continue}let o;if(null!=r.key)o=v.get(r.key);else for(y=m;y<=p;y++)if(0===S[y-m]&&Ur(r,t[y])){o=y;break}void 0===o?X(r,i,s,!0):(S[o-m]=u+1,o>=w?w=o:E=!0,g(r,t[o],n,null,i,s,a,l,c),b++)}const k=E?Bn(S):o.Oj;for(y=k.length-1,u=_-1;u>=0;u--){const e=m+u,o=t[e],f=e+1{const{el:s,type:a,transition:l,children:c,shapeFlag:u}=e;if(6&u)return void V(e.component.subTree,t,n,r);if(128&u)return void e.suspense.move(t,n,r);if(64&u)return void a.move(e,t,n,Z);if(a===Cr){i(s,t,n);for(let e=0;el.enter(s)),o);else{const{leave:e,delayLeave:r,afterLeave:o}=l,a=()=>i(s,t,n),c=()=>{e(s,(()=>{a(),o&&o()}))};r?r(s,a,c):c()}else i(s,t,n)},X=(e,t,n,r=!1,o=!1)=>{const{type:i,props:s,ref:a,children:l,dynamicChildren:c,shapeFlag:u,patchFlag:d,dirs:f,cacheIndex:p}=e;if(-2===d&&(o=!1),null!=a&&we(a,null,n,e,!0),null!=p&&(t.renderCache[p]=void 0),256&u)return void t.ctx.deactivate(e);const h=1&u&&f,m=!Be(e);let v;if(m&&(v=s&&s.onVnodeBeforeUnmount)&&no(v,t,e),6&u)z(e.component,n,r);else{if(128&u)return void e.suspense.unmount(n,r);h&&H(e,null,t,"beforeUnmount"),64&u?e.type.remove(e,t,n,Z,r):c&&!c.hasOnce&&(i!==Cr||d>0&&64&d)?q(c,t,n,!1,!0):(i===Cr&&384&d||!o&&16&u)&&q(l,t,n),r&&G(e)}(m&&(v=s&&s.onVnodeUnmounted)||h)&&Pn((()=>{v&&no(v,t,e),h&&H(e,null,t,"unmounted")}),n)},G=e=>{const{type:t,el:n,anchor:r,transition:o}=e;if(t===Cr)return void K(n,r);if(t===Rr)return void w(e);const i=()=>{s(n),o&&!o.persisted&&o.afterLeave&&o.afterLeave()};if(1&e.shapeFlag&&o&&!o.persisted){const{leave:t,delayLeave:r}=o,s=()=>t(n,i);r?r(e.el,i,s):s()}else i()},K=(e,t)=>{let n;while(e!==t)n=h(e),s(e),e=n;s(t)},z=(e,t,n)=>{const{bum:r,scope:i,job:s,subTree:a,um:l,m:c,a:u}=e;Hn(c),Hn(u),r&&(0,o.DY)(r),i.stop(),s&&(s.flags|=8,X(a,e,t,n)),l&&Pn(l,t),Pn((()=>{e.isUnmounted=!0}),t),t&&t.pendingBranch&&!t.isUnmounted&&e.asyncDep&&!e.asyncResolved&&e.suspenseId===t.pendingId&&(t.deps--,0===t.deps&&t.resolve())},q=(e,t,n,r=!1,o=!1,i=0)=>{for(let s=i;s{if(6&e.shapeFlag)return Y(e.component.subTree);if(128&e.shapeFlag)return e.suspense.next();const t=h(e.anchor||e.el),n=t&&t[W];return n?h(n):t};let Q=!1;const J=(e,t,n)=>{null==e?t._vnode&&X(t._vnode,null,null,!0):g(t._vnode||null,e,t,null,null,null,n),t._vnode=e,Q||(Q=!0,T(),R(),Q=!1)},Z={p:g,um:X,m:V,r:G,mt:M,mc:A,pc:j,pbc:L,n:Y,o:e};let ee,te;return t&&([ee,te]=t(Z)),{render:J,hydrate:ee,createApp:cn(J,ee)}}function $n({type:e,props:t},n){return"svg"===n&&"foreignObject"===e||"mathml"===n&&"annotation-xml"===e&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Fn({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function jn(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Un(e,t,n=!1){const r=e.children,i=t.children;if((0,o.cy)(r)&&(0,o.cy)(i))for(let o=0;o>1,e[n[a]]0&&(t[r]=n[i-1]),n[i]=r)}}i=n.length,s=n[i-1];while(i-- >0)n[i]=s,s=t[s];return n}function Vn(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Vn(t)}function Hn(e){if(e)for(let t=0;t{{const e=fn(Wn);return e}};function Gn(e,t){return Yn(e,null,t)}function Kn(e,t){return Yn(e,null,{flush:"post"})}function zn(e,t){return Yn(e,null,{flush:"sync"})}function qn(e,t,n){return Yn(e,t,n)}function Yn(e,t,n=o.MZ){const{immediate:i,deep:s,flush:a,once:l}=n;const c=(0,o.X$)({},n);const u=t&&i||!t&&"post"!==a;let d;if(vo)if("sync"===a){const e=Xn();d=e.__watcherHandles||(e.__watcherHandles=[])}else if(!u){const e=()=>{};return e.stop=o.tE,e.resume=o.tE,e.pause=o.tE,e}const p=so;c.call=(e,t,n)=>f(e,p,t,n);let h=!1;"post"===a?c.scheduler=e=>{Pn(e,p&&p.suspense)}:"sync"!==a&&(h=!0,c.scheduler=(e,t)=>{t?e():k(e)}),c.augmentJob=e=>{t&&(e.flags|=4),h&&(e.flags|=2,p&&(e.id=p.uid,e.i=p))};const m=(0,r.wB)(e,t,c);return vo&&(d?d.push(m):u&&m()),m}function Qn(e,t,n){const r=this.proxy,i=(0,o.Kg)(e)?e.includes(".")?Jn(r,e):()=>r[e]:e.bind(r,r);let s;(0,o.Tn)(t)?s=t:(s=t.handler,n=t);const a=uo(this),l=Yn(i,s.bind(r),n);return a(),l}function Jn(e,t){const n=t.split(".");return()=>{let t=e;for(let e=0;e{let c,u,d=o.MZ;return zn((()=>{const t=e[s];(0,o.$H)(c,t)&&(c=t,l())})),{get(){return r(),n.get?n.get(c):c},set(e){const r=n.set?n.set(e):e;if(!(0,o.$H)(r,c)&&(d===o.MZ||!(0,o.$H)(e,d)))return;const f=i.vnode.props;f&&(t in f||s in f||a in f)&&(`onUpdate:${t}`in f||`onUpdate:${s}`in f||`onUpdate:${a}`in f)||(c=e,l()),i.emit(`update:${t}`,r),(0,o.$H)(e,r)&&(0,o.$H)(e,d)&&!(0,o.$H)(r,u)&&l(),d=e,u=r}}}));return c[Symbol.iterator]=()=>{let e=0;return{next(){return e<2?{value:e++?l||o.MZ:c,done:!1}:{done:!0}}}},c}const er=(e,t)=>"modelValue"===t||"model-value"===t?e.modelModifiers:e[`${t}Modifiers`]||e[`${(0,o.PT)(t)}Modifiers`]||e[`${(0,o.Tg)(t)}Modifiers`];function tr(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||o.MZ;let i=n;const s=t.startsWith("update:"),a=s&&er(r,t.slice(7));let l;a&&(a.trim&&(i=n.map((e=>(0,o.Kg)(e)?e.trim():e))),a.number&&(i=n.map(o.bB)));let c=r[l=(0,o.rU)(t)]||r[l=(0,o.rU)((0,o.PT)(t))];!c&&s&&(c=r[l=(0,o.rU)((0,o.Tg)(t))]),c&&f(c,e,6,i);const u=r[l+"Once"];if(u){if(e.emitted){if(e.emitted[l])return}else e.emitted={};e.emitted[l]=!0,f(u,e,6,i)}}function nr(e,t,n=!1){const r=t.emitsCache,i=r.get(e);if(void 0!==i)return i;const s=e.emits;let a={},l=!1;if(!(0,o.Tn)(e)){const r=e=>{const n=nr(e,t,!0);n&&(l=!0,(0,o.X$)(a,n))};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}return s||l?((0,o.cy)(s)?s.forEach((e=>a[e]=null)):(0,o.X$)(a,s),(0,o.Gv)(e)&&r.set(e,a),a):((0,o.Gv)(e)&&r.set(e,null),null)}function rr(e,t){return!(!e||!(0,o.Mp)(t))&&(t=t.slice(2).replace(/Once$/,""),(0,o.$3)(e,t[0].toLowerCase()+t.slice(1))||(0,o.$3)(e,(0,o.Tg)(t))||(0,o.$3)(e,t))}function or(e){const{type:t,vnode:n,proxy:r,withProxy:i,propsOptions:[s],slots:a,attrs:l,emit:c,render:u,renderCache:d,props:f,data:h,setupState:m,ctx:v,inheritAttrs:g}=e,y=$(e);let b,_;try{if(4&n.shapeFlag){const e=i||r,t=e;b=Jr(u.call(t,e,d,f,m,h,v)),_=l}else{const e=t;0,b=Jr(e.length>1?e(f,{attrs:l,slots:a,emit:c}):e(f,null)),_=t.props?l:sr(l)}}catch(w){Ar.length=0,p(w,e,1),b=Xr(Tr)}let E=b;if(_&&!1!==g){const e=Object.keys(_),{shapeFlag:t}=E;e.length&&7&t&&(s&&e.some(o.CP)&&(_=ar(_,s)),E=zr(E,_,!1,!0))}return n.dirs&&(E=zr(E,null,!1,!0),E.dirs=E.dirs?E.dirs.concat(n.dirs):n.dirs),n.transition&&ve(E,n.transition),b=E,$(y),b}function ir(e,t=!0){let n;for(let r=0;r{let t;for(const n in e)("class"===n||"style"===n||(0,o.Mp)(n))&&((t||(t={}))[n]=e[n]);return t},ar=(e,t)=>{const n={};for(const r in e)(0,o.CP)(r)&&r.slice(9)in t||(n[r]=e[r]);return n};function lr(e,t,n){const{props:r,children:o,component:i}=e,{props:s,children:a,patchFlag:l}=t,c=i.emitsOptions;if(t.dirs||t.transition)return!0;if(!(n&&l>=0))return!(!o&&!a||a&&a.$stable)||r!==s&&(r?!s||cr(r,s,c):!!s);if(1024&l)return!0;if(16&l)return r?cr(r,s,c):!!s;if(8&l){const e=t.dynamicProps;for(let t=0;te.__isSuspense;let fr=0;const pr={name:"Suspense",__isSuspense:!0,process(e,t,n,r,o,i,s,a,l,c){if(null==e)vr(t,n,r,o,i,s,a,l,c);else{if(i&&i.deps>0&&!e.suspense.isInFallback)return t.suspense=e.suspense,t.suspense.vnode=t,void(t.el=e.el);gr(e,t,n,r,o,s,a,l,c)}},hydrate:br,normalize:_r},hr=pr;function mr(e,t){const n=e.props&&e.props[t];(0,o.Tn)(n)&&n()}function vr(e,t,n,r,o,i,s,a,l){const{p:c,o:{createElement:u}}=l,d=u("div"),f=e.suspense=yr(e,o,r,t,d,n,i,s,a,l);c(null,f.pendingBranch=e.ssContent,d,null,r,f,i,s),f.deps>0?(mr(e,"onPending"),mr(e,"onFallback"),c(null,e.ssFallback,t,n,r,null,i,s),Sr(f,e.ssFallback)):f.resolve(!1,!0)}function gr(e,t,n,r,o,i,s,a,{p:l,um:c,o:{createElement:u}}){const d=t.suspense=e.suspense;d.vnode=t,t.el=e.el;const f=t.ssContent,p=t.ssFallback,{activeBranch:h,pendingBranch:m,isInFallback:v,isHydrating:g}=d;if(m)d.pendingBranch=f,Ur(f,m)?(l(m,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0?d.resolve():v&&(g||(l(h,p,n,r,o,null,i,s,a),Sr(d,p)))):(d.pendingId=fr++,g?(d.isHydrating=!1,d.activeBranch=m):c(m,o,d),d.deps=0,d.effects.length=0,d.hiddenContainer=u("div"),v?(l(null,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0?d.resolve():(l(h,p,n,r,o,null,i,s,a),Sr(d,p))):h&&Ur(f,h)?(l(h,f,n,r,o,d,i,s,a),d.resolve(!0)):(l(null,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0&&d.resolve()));else if(h&&Ur(f,h))l(h,f,n,r,o,d,i,s,a),Sr(d,f);else if(mr(t,"onPending"),d.pendingBranch=f,512&f.shapeFlag?d.pendingId=f.component.suspenseId:d.pendingId=fr++,l(null,f,d.hiddenContainer,null,o,d,i,s,a),d.deps<=0)d.resolve();else{const{timeout:e,pendingId:t}=d;e>0?setTimeout((()=>{d.pendingId===t&&d.fallback(p)}),e):0===e&&d.fallback(p)}}function yr(e,t,n,r,i,s,a,l,c,u,d=!1){const{p:f,m:h,um:m,n:v,o:{parentNode:g,remove:y}}=u;let b;const _=kr(e);_&&t&&t.pendingBranch&&(b=t.pendingId,t.deps++);const E=e.props?(0,o.Ro)(e.props.timeout):void 0;const w=s,S={vnode:e,parent:t,parentComponent:n,namespace:a,container:r,hiddenContainer:i,deps:0,pendingId:fr++,timeout:"number"===typeof E?E:-1,activeBranch:null,pendingBranch:null,isInFallback:!d,isHydrating:d,isUnmounted:!1,effects:[],resolve(e=!1,n=!1){const{vnode:r,activeBranch:o,pendingBranch:i,pendingId:a,effects:l,parentComponent:c,container:u}=S;let d=!1;S.isHydrating?S.isHydrating=!1:e||(d=o&&i.transition&&"out-in"===i.transition.mode,d&&(o.transition.afterLeave=()=>{a===S.pendingId&&(h(i,u,s===w?v(o):s,0),O(l))}),o&&(g(o.el)===u&&(s=v(o)),m(o,c,S,!0)),d||h(i,u,s,0)),Sr(S,i),S.pendingBranch=null,S.isInFallback=!1;let f=S.parent,p=!1;while(f){if(f.pendingBranch){f.effects.push(...l),p=!0;break}f=f.parent}p||d||O(l),S.effects=[],_&&t&&t.pendingBranch&&b===t.pendingId&&(t.deps--,0!==t.deps||n||t.resolve()),mr(r,"onResolve")},fallback(e){if(!S.pendingBranch)return;const{vnode:t,activeBranch:n,parentComponent:r,container:o,namespace:i}=S;mr(t,"onFallback");const s=v(n),a=()=>{S.isInFallback&&(f(null,e,o,s,r,null,i,l,c),Sr(S,e))},u=e.transition&&"out-in"===e.transition.mode;u&&(n.transition.afterLeave=a),S.isInFallback=!0,m(n,r,null,!0),u||a()},move(e,t,n){S.activeBranch&&h(S.activeBranch,e,t,n),S.container=e},next(){return S.activeBranch&&v(S.activeBranch)},registerDep(e,t,n){const r=!!S.pendingBranch;r&&S.deps++;const o=e.vnode.el;e.asyncDep.catch((t=>{p(t,e,0)})).then((i=>{if(e.isUnmounted||S.isUnmounted||S.pendingId!==e.suspenseId)return;e.asyncResolved=!0;const{vnode:s}=e;bo(e,i,!1),o&&(s.el=o);const l=!o&&e.subTree.el;t(e,s,g(o||e.subTree.el),o?null:v(e.subTree),S,a,n),l&&y(l),ur(e,s.el),r&&0===--S.deps&&S.resolve()}))},unmount(e,t){S.isUnmounted=!0,S.activeBranch&&m(S.activeBranch,n,e,t),S.pendingBranch&&m(S.pendingBranch,n,e,t)}};return S}function br(e,t,n,r,o,i,s,a,l){const c=t.suspense=yr(t,r,n,e.parentNode,document.createElement("div"),null,o,i,s,a,!0),u=l(e,c.pendingBranch=t.ssContent,n,c,i,s);return 0===c.deps&&c.resolve(!1,!0),u}function _r(e){const{shapeFlag:t,children:n}=e,r=32&t;e.ssContent=Er(r?n.default:n),e.ssFallback=r?Er(n.fallback):Xr(Tr)}function Er(e){let t;if((0,o.Tn)(e)){const n=xr&&e._c;n&&(e._d=!1,Lr()),e=e(),n&&(e._d=!0,t=Nr,Ir())}if((0,o.cy)(e)){const t=ir(e);0,e=t}return e=Jr(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter((t=>t!==e))),e}function wr(e,t){t&&t.pendingBranch?(0,o.cy)(e)?t.effects.push(...e):t.effects.push(e):O(e)}function Sr(e,t){e.activeBranch=t;const{vnode:n,parentComponent:r}=e;let o=t.el;while(!o&&t.component)t=t.component.subTree,o=t.el;n.el=o,r&&r.subTree===n&&(r.vnode.el=o,ur(r,o))}function kr(e){const t=e.props&&e.props.suspensible;return null!=t&&!1!==t}const Cr=Symbol.for("v-fgt"),Or=Symbol.for("v-txt"),Tr=Symbol.for("v-cmt"),Rr=Symbol.for("v-stc"),Ar=[];let Nr=null;function Lr(e=!1){Ar.push(Nr=e?null:[])}function Ir(){Ar.pop(),Nr=Ar[Ar.length-1]||null}let Pr,xr=1;function Mr(e,t=!1){xr+=e,e<0&&Nr&&t&&(Nr.hasOnce=!0)}function Dr(e){return e.dynamicChildren=xr>0?Nr||o.Oj:null,Ir(),xr>0&&Nr&&Nr.push(e),e}function $r(e,t,n,r,o,i){return Dr(Wr(e,t,n,r,o,i,!0))}function Fr(e,t,n,r,o){return Dr(Xr(e,t,n,r,o,!0))}function jr(e){return!!e&&!0===e.__v_isVNode}function Ur(e,t){return e.type===t.type&&e.key===t.key}function Br(e){Pr=e}const Vr=({key:e})=>null!=e?e:null,Hr=({ref:e,ref_key:t,ref_for:n})=>("number"===typeof e&&(e=""+e),null!=e?(0,o.Kg)(e)||(0,r.i9)(e)||(0,o.Tn)(e)?{i:M,r:e,k:t,f:!!n}:e:null);function Wr(e,t=null,n=null,r=0,i=null,s=(e===Cr?0:1),a=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Vr(t),ref:t&&Hr(t),scopeId:D,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:s,patchFlag:r,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:M};return l?(eo(c,n),128&s&&e.normalize(c)):n&&(c.shapeFlag|=(0,o.Kg)(n)?8:16),xr>0&&!a&&Nr&&(c.patchFlag>0||6&s)&&32!==c.patchFlag&&Nr.push(c),c}const Xr=Gr;function Gr(e,t=null,n=null,i=0,s=null,a=!1){if(e&&e!==mt||(e=Tr),jr(e)){const r=zr(e,t,!0);return n&&eo(r,n),xr>0&&!a&&Nr&&(6&r.shapeFlag?Nr[Nr.indexOf(e)]=r:Nr.push(r)),r.patchFlag=-2,r}if(To(e)&&(e=e.__vccOpts),t){t=Kr(t);let{class:e,style:n}=t;e&&!(0,o.Kg)(e)&&(t.class=(0,o.C4)(e)),(0,o.Gv)(n)&&((0,r.ju)(n)&&!(0,o.cy)(n)&&(n=(0,o.X$)({},n)),t.style=(0,o.Tr)(n))}const l=(0,o.Kg)(e)?1:dr(e)?128:X(e)?64:(0,o.Gv)(e)?4:(0,o.Tn)(e)?2:0;return Wr(e,t,n,i,s,l,a,!0)}function Kr(e){return e?(0,r.ju)(e)||vn(e)?(0,o.X$)({},e):e:null}function zr(e,t,n=!1,r=!1){const{props:i,ref:s,patchFlag:a,children:l,transition:c}=e,u=t?to(i||{},t):i,d={__v_isVNode:!0,__v_skip:!0,type:e.type,props:u,key:u&&Vr(u),ref:t&&t.ref?n&&s?(0,o.cy)(s)?s.concat(Hr(t)):[s,Hr(t)]:Hr(t):s,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Cr?-1===a?16:16|a:a,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&zr(e.ssContent),ssFallback:e.ssFallback&&zr(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&r&&ve(d,c.clone(d)),d}function qr(e=" ",t=0){return Xr(Or,null,e,t)}function Yr(e,t){const n=Xr(Rr,null,e);return n.staticCount=t,n}function Qr(e="",t=!1){return t?(Lr(),Fr(Tr,null,e)):Xr(Tr,null,e)}function Jr(e){return null==e||"boolean"===typeof e?Xr(Tr):(0,o.cy)(e)?Xr(Cr,null,e.slice()):jr(e)?Zr(e):Xr(Or,null,String(e))}function Zr(e){return null===e.el&&-1!==e.patchFlag||e.memo?e:zr(e)}function eo(e,t){let n=0;const{shapeFlag:r}=e;if(null==t)t=null;else if((0,o.cy)(t))n=16;else if("object"===typeof t){if(65&r){const n=t.default;return void(n&&(n._c&&(n._d=!1),eo(e,n()),n._c&&(n._d=!0)))}{n=32;const r=t._;r||vn(t)?3===r&&M&&(1===M.slots._?t._=1:(t._=2,e.patchFlag|=1024)):t._ctx=M}}else(0,o.Tn)(t)?(t={default:t,_ctx:M},n=32):(t=String(t),64&r?(n=16,t=[qr(t)]):n=8);e.children=t,e.shapeFlag|=n}function to(...e){const t={};for(let n=0;nso||M;let lo,co;{const e=(0,o.We)(),t=(t,n)=>{let r;return(r=e[t])||(r=e[t]=[]),r.push(n),e=>{r.length>1?r.forEach((t=>t(e))):r[0](e)}};lo=t("__VUE_INSTANCE_SETTERS__",(e=>so=e)),co=t("__VUE_SSR_SETTERS__",(e=>vo=e))}const uo=e=>{const t=so;return lo(e),e.scope.on(),()=>{e.scope.off(),lo(t)}},fo=()=>{so&&so.scope.off(),lo(null)};function po(e){return 4&e.vnode.shapeFlag}let ho,mo,vo=!1;function go(e,t=!1,n=!1){t&&co(t);const{props:r,children:o}=e.vnode,i=po(e);gn(e,r,i,t),Nn(e,o,n);const s=i?yo(e,t):void 0;return t&&co(!1),s}function yo(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Rt);const{setup:i}=n;if(i){(0,r.C4)();const n=e.setupContext=i.length>1?ko(e):null,s=uo(e),a=d(i,e,0,[e.props,n]),l=(0,o.yL)(a);if((0,r.bl)(),s(),!l&&!e.sp||Be(e)||_e(e),l){if(a.then(fo,fo),t)return a.then((n=>{bo(e,n,t)})).catch((t=>{p(t,e,0)}));e.asyncDep=a}else bo(e,a,t)}else wo(e,t)}function bo(e,t,n){(0,o.Tn)(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:(0,o.Gv)(t)&&(e.setupState=(0,r.Pr)(t)),wo(e,n)}function _o(e){ho=e,mo=e=>{e.render._rc&&(e.withProxy=new Proxy(e.ctx,At))}}const Eo=()=>!ho;function wo(e,t,n){const i=e.type;if(!e.render){if(!t&&ho&&!i.render){const t=i.template||Yt(e).template;if(t){0;const{isCustomElement:n,compilerOptions:r}=e.appContext.config,{delimiters:s,compilerOptions:a}=i,l=(0,o.X$)((0,o.X$)({isCustomElement:n,delimiters:s},r),a);i.render=ho(t,l)}}e.render=i.render||o.tE,mo&&mo(e)}{const t=uo(e);(0,r.C4)();try{Gt(e)}finally{(0,r.bl)(),t()}}}const So={get(e,t){return(0,r.u4)(e,"get",""),e[t]}};function ko(e){const t=t=>{e.exposed=t||{}};return{attrs:new Proxy(e.attrs,So),slots:e.slots,emit:e.emit,expose:t}}function Co(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy((0,r.Pr)((0,r.IG)(e.exposed)),{get(t,n){return n in t?t[n]:n in Ot?Ot[n](e):void 0},has(e,t){return t in e||t in Ot}})):e.proxy}function Oo(e,t=!0){return(0,o.Tn)(e)?e.displayName||e.name:e.name||t&&e.__name}function To(e){return(0,o.Tn)(e)&&"__vccOpts"in e}const Ro=(e,t)=>{const n=(0,r.EW)(e,t,vo);return n};function Ao(e,t,n){const r=arguments.length;return 2===r?(0,o.Gv)(t)&&!(0,o.cy)(t)?jr(t)?Xr(e,null,[t]):Xr(e,t):Xr(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):3===r&&jr(n)&&(n=[n]),Xr(e,t,n))}function No(){return void 0}function Lo(e,t,n,r){const o=n[r];if(o&&Io(o,e))return o;const i=t();return i.memo=e.slice(),i.cacheIndex=r,n[r]=i}function Io(e,t){const n=e.memo;if(n.length!=t.length)return!1;for(let r=0;r0&&Nr&&Nr.push(e),!0}const Po="3.5.13",xo=o.tE,Mo=u,Do=L,$o=x,Fo={createComponentInstance:io,setupComponent:go,renderComponentRoot:or,setCurrentRenderingInstance:$,isVNode:jr,normalizeVNode:Jr,getComponentPublicInstance:Co,ensureValidVNode:St,pushWarningContext:s,popWarningContext:a},jo=Fo,Uo=null,Bo=null,Vo=null},655:function(e,t,n){"use strict";var r=n(6955),o=String;e.exports=function(e){if("Symbol"===r(e))throw new TypeError("Cannot convert a Symbol value to a string");return o(e)}},679:function(e,t,n){"use strict";var r=n(1625),o=TypeError;e.exports=function(e,t){if(r(t,e))return e;throw new o("Incorrect invocation")}},713:function(e,t,n){"use strict";var r=n(9565),o=n(9306),i=n(8551),s=n(1767),a=n(9462),l=n(6319),c=a((function(){var e=this.iterator,t=i(r(this.next,e)),n=this.done=!!t.done;if(!n)return l(e,this.mapper,[t.value,this.counter++],!0)}));e.exports=function(e){return i(this),o(e),new c(s(this),{mapper:e})}},741:function(e){"use strict";var t=Math.ceil,n=Math.floor;e.exports=Math.trunc||function(e){var r=+e;return(r>0?n:t)(r)}},757:function(e,t,n){"use strict";var r=n(7751),o=n(4901),i=n(1625),s=n(7040),a=Object;e.exports=s?function(e){return"symbol"==typeof e}:function(e){var t=r("Symbol");return o(t)&&i(t.prototype,a(e))}},851:function(e,t,n){"use strict";var r=n(6955),o=n(5966),i=n(4117),s=n(6269),a=n(8227),l=a("iterator");e.exports=function(e){if(!i(e))return o(e,l)||o(e,"@@iterator")||s[r(e)]}},909:function(e,t,n){const r=n(3908),o=(e,t,n)=>{const o=new r(e,n),i=new r(t,n);return o.compare(i)||o.compareBuild(i)};e.exports=o},950:function(e,t){"use strict";let n=null,r=null;t.A={namespaced:!0,mutations:{setCurrent(e,t){r.$router.push({query:Object.assign({},r.$router.currentRoute.value.query,{p:t}),append:!0})},clearCurrent(){const e=Object.assign({},r.$router.currentRoute.value.query);delete e.p,r.$router.push({query:e,append:!0})},trackPackage(e,t){t?r.$store.commit("modals/open",{id:"package-details",component:n}):r.$store.commit("modals/close","package-details")}},actions:{init({commit:e},{vue:t,component:o}){r=t,n=o,r.$watch("$route.query.p",(t=>e("trackPackage",t))),e("trackPackage",r.$route.query.p)}}}},953:function(e,t,n){"use strict";n.d(t,{BA:function(){return He},C4:function(){return R},EW:function(){return et},Gc:function(){return ke},IG:function(){return Pe},IJ:function(){return Fe},KR:function(){return $e},Kh:function(){return Se},PP:function(){return nt},Pr:function(){return Xe},QW:function(){return ze},QZ:function(){return k},R1:function(){return Ve},Tm:function(){return Ae},Ul:function(){return tt},X2:function(){return d},Yv:function(){return st},bl:function(){return A},ch:function(){return at},ds:function(){return C},fE:function(){return Ne},g8:function(){return Re},hV:function(){return ct},hZ:function(){return U},i9:function(){return De},jr:function(){return c},ju:function(){return Le},lJ:function(){return xe},lW:function(){return Qe},mu:function(){return Be},nD:function(){return Oe},o5:function(){return l},qA:function(){return H},rY:function(){return Ke},tB:function(){return Ce},u4:function(){return j},uY:function(){return a},ux:function(){return Ie},wB:function(){return lt},yC:function(){return s}});var r=n(33); /** * @vue/reactivity v3.5.13 * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT **/let o,i;class s{constructor(e=!1){this.detached=e,this._active=!0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=o,!e&&o&&(this.index=(o.scopes||(o.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){let e,t;if(this._isPaused=!0,this.scopes)for(e=0,t=this.scopes.length;e0)return;if(p){let e=p;p=void 0;while(e){const t=e.next;e.next=void 0,e.flags&=-9,e=t}}let e;while(f){let n=f;f=void 0;while(n){const r=n.next;if(n.next=void 0,n.flags&=-9,1&n.flags)try{n.trigger()}catch(t){e||(e=t)}n=r}}if(e)throw e}function y(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function b(e){let t,n=e.depsTail,r=n;while(r){const e=r.prevDep;-1===r.version?(r===n&&(n=e),w(r),S(r)):t=r,r.dep.activeLink=r.prevActiveLink,r.prevActiveLink=void 0,r=e}e.deps=t,e.depsTail=n}function _(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(E(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function E(e){if(4&e.flags&&!(16&e.flags))return;if(e.flags&=-17,e.globalVersion===L)return;e.globalVersion=L;const t=e.dep;if(e.flags|=2,t.version>0&&!e.isSSR&&e.deps&&!_(e))return void(e.flags&=-3);const n=i,o=O;i=e,O=!0;try{y(e);const n=e.fn(e._value);(0===t.version||(0,r.$H)(n,e._value))&&(e._value=n,t.version++)}catch(s){throw t.version++,s}finally{i=n,O=o,b(e),e.flags&=-3}}function w(e,t=!1){const{dep:n,prevSub:r,nextSub:o}=e;if(r&&(r.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=r,e.nextSub=void 0),n.subs===e&&(n.subs=r,!r&&n.computed)){n.computed.flags&=-5;for(let e=n.computed.deps;e;e=e.nextDep)w(e,!0)}t||--n.sc||!n.map||n.map.delete(n.key)}function S(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}function k(e,t){e.effect instanceof d&&(e=e.effect.fn);const n=new d(e);t&&(0,r.X$)(n,t);try{n.run()}catch(i){throw n.stop(),i}const o=n.run.bind(n);return o.effect=n,o}function C(e){e.effect.stop()}let O=!0;const T=[];function R(){T.push(O),O=!1}function A(){const e=T.pop();O=void 0===e||e}function N(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const e=i;i=void 0;try{t()}finally{i=e}}}let L=0;class I{constructor(e,t){this.sub=e,this.dep=t,this.version=t.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class P{constructor(e){this.computed=e,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0}track(e){if(!i||!O||i===this.computed)return;let t=this.activeLink;if(void 0===t||t.sub!==i)t=this.activeLink=new I(i,this),i.deps?(t.prevDep=i.depsTail,i.depsTail.nextDep=t,i.depsTail=t):i.deps=i.depsTail=t,x(t);else if(-1===t.version&&(t.version=this.version,t.nextDep)){const e=t.nextDep;e.prevDep=t.prevDep,t.prevDep&&(t.prevDep.nextDep=e),t.prevDep=i.depsTail,t.nextDep=void 0,i.depsTail.nextDep=t,i.depsTail=t,i.deps===t&&(i.deps=e)}return t}trigger(e){this.version++,L++,this.notify(e)}notify(e){v();try{0;for(let e=this.subs;e;e=e.prevSub)e.sub.notify()&&e.sub.dep.notify()}finally{g()}}}function x(e){if(e.dep.sc++,4&e.sub.flags){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let e=t.deps;e;e=e.nextDep)x(e)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const M=new WeakMap,D=Symbol(""),$=Symbol(""),F=Symbol("");function j(e,t,n){if(O&&i){let t=M.get(e);t||M.set(e,t=new Map);let r=t.get(n);r||(t.set(n,r=new P),r.map=t,r.key=n),r.track()}}function U(e,t,n,o,i,s){const a=M.get(e);if(!a)return void L++;const l=e=>{e&&e.trigger()};if(v(),"clear"===t)a.forEach(l);else{const i=(0,r.cy)(e),s=i&&(0,r.yI)(n);if(i&&"length"===n){const e=Number(o);a.forEach(((t,n)=>{("length"===n||n===F||!(0,r.Bm)(n)&&n>=e)&&l(t)}))}else switch((void 0!==n||a.has(void 0))&&l(a.get(n)),s&&l(a.get(F)),t){case"add":i?s&&l(a.get("length")):(l(a.get(D)),(0,r.CE)(e)&&l(a.get($)));break;case"delete":i||(l(a.get(D)),(0,r.CE)(e)&&l(a.get($)));break;case"set":(0,r.CE)(e)&&l(a.get(D));break}}g()}function B(e,t){const n=M.get(e);return n&&n.get(t)}function V(e){const t=Ie(e);return t===e?t:(j(t,"iterate",F),Ne(e)?t:t.map(xe))}function H(e){return j(e=Ie(e),"iterate",F),e}const W={__proto__:null,[Symbol.iterator](){return X(this,Symbol.iterator,xe)},concat(...e){return V(this).concat(...e.map((e=>(0,r.cy)(e)?V(e):e)))},entries(){return X(this,"entries",(e=>(e[1]=xe(e[1]),e)))},every(e,t){return K(this,"every",e,t,void 0,arguments)},filter(e,t){return K(this,"filter",e,t,(e=>e.map(xe)),arguments)},find(e,t){return K(this,"find",e,t,xe,arguments)},findIndex(e,t){return K(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return K(this,"findLast",e,t,xe,arguments)},findLastIndex(e,t){return K(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return K(this,"forEach",e,t,void 0,arguments)},includes(...e){return q(this,"includes",e)},indexOf(...e){return q(this,"indexOf",e)},join(e){return V(this).join(e)},lastIndexOf(...e){return q(this,"lastIndexOf",e)},map(e,t){return K(this,"map",e,t,void 0,arguments)},pop(){return Y(this,"pop")},push(...e){return Y(this,"push",e)},reduce(e,...t){return z(this,"reduce",e,t)},reduceRight(e,...t){return z(this,"reduceRight",e,t)},shift(){return Y(this,"shift")},some(e,t){return K(this,"some",e,t,void 0,arguments)},splice(...e){return Y(this,"splice",e)},toReversed(){return V(this).toReversed()},toSorted(e){return V(this).toSorted(e)},toSpliced(...e){return V(this).toSpliced(...e)},unshift(...e){return Y(this,"unshift",e)},values(){return X(this,"values",xe)}};function X(e,t,n){const r=H(e),o=r[t]();return r===e||Ne(e)||(o._next=o.next,o.next=()=>{const e=o._next();return e.value&&(e.value=n(e.value)),e}),o}const G=Array.prototype;function K(e,t,n,r,o,i){const s=H(e),a=s!==e&&!Ne(e),l=s[t];if(l!==G[t]){const t=l.apply(e,i);return a?xe(t):t}let c=n;s!==e&&(a?c=function(t,r){return n.call(this,xe(t),r,e)}:n.length>2&&(c=function(t,r){return n.call(this,t,r,e)}));const u=l.call(s,c,r);return a&&o?o(u):u}function z(e,t,n,r){const o=H(e);let i=n;return o!==e&&(Ne(e)?n.length>3&&(i=function(t,r,o){return n.call(this,t,r,o,e)}):i=function(t,r,o){return n.call(this,t,xe(r),o,e)}),o[t](i,...r)}function q(e,t,n){const r=Ie(e);j(r,"iterate",F);const o=r[t](...n);return-1!==o&&!1!==o||!Le(n[0])?o:(n[0]=Ie(n[0]),r[t](...n))}function Y(e,t,n=[]){R(),v();const r=Ie(e)[t].apply(e,n);return g(),A(),r}const Q=(0,r.pD)("__proto__,__v_isRef,__isVue"),J=new Set(Object.getOwnPropertyNames(Symbol).filter((e=>"arguments"!==e&&"caller"!==e)).map((e=>Symbol[e])).filter(r.Bm));function Z(e){(0,r.Bm)(e)||(e=String(e));const t=Ie(this);return j(t,"has",e),t.hasOwnProperty(e)}class ee{constructor(e=!1,t=!1){this._isReadonly=e,this._isShallow=t}get(e,t,n){if("__v_skip"===t)return e["__v_skip"];const o=this._isReadonly,i=this._isShallow;if("__v_isReactive"===t)return!o;if("__v_isReadonly"===t)return o;if("__v_isShallow"===t)return i;if("__v_raw"===t)return n===(o?i?_e:be:i?ye:ge).get(e)||Object.getPrototypeOf(e)===Object.getPrototypeOf(n)?e:void 0;const s=(0,r.cy)(e);if(!o){let e;if(s&&(e=W[t]))return e;if("hasOwnProperty"===t)return Z}const a=Reflect.get(e,t,De(e)?e:n);return((0,r.Bm)(t)?J.has(t):Q(t))?a:(o||j(e,"get",t),i?a:De(a)?s&&(0,r.yI)(t)?a:a.value:(0,r.Gv)(a)?o?Ce(a):Se(a):a)}}class te extends ee{constructor(e=!1){super(!1,e)}set(e,t,n,o){let i=e[t];if(!this._isShallow){const t=Ae(i);if(Ne(n)||Ae(n)||(i=Ie(i),n=Ie(n)),!(0,r.cy)(e)&&De(i)&&!De(n))return!t&&(i.value=n,!0)}const s=(0,r.cy)(e)&&(0,r.yI)(t)?Number(t)e,le=e=>Reflect.getPrototypeOf(e);function ce(e,t,n){return function(...o){const i=this["__v_raw"],s=Ie(i),a=(0,r.CE)(s),l="entries"===e||e===Symbol.iterator&&a,c="keys"===e&&a,u=i[e](...o),d=n?ae:t?Me:xe;return!t&&j(s,"iterate",c?$:D),{next(){const{value:e,done:t}=u.next();return t?{value:e,done:t}:{value:l?[d(e[0]),d(e[1])]:d(e),done:t}},[Symbol.iterator](){return this}}}}function ue(e){return function(...t){return"delete"!==e&&("clear"===e?void 0:this)}}function de(e,t){const n={get(n){const o=this["__v_raw"],i=Ie(o),s=Ie(n);e||((0,r.$H)(n,s)&&j(i,"get",n),j(i,"get",s));const{has:a}=le(i),l=t?ae:e?Me:xe;return a.call(i,n)?l(o.get(n)):a.call(i,s)?l(o.get(s)):void(o!==i&&o.get(n))},get size(){const t=this["__v_raw"];return!e&&j(Ie(t),"iterate",D),Reflect.get(t,"size",t)},has(t){const n=this["__v_raw"],o=Ie(n),i=Ie(t);return e||((0,r.$H)(t,i)&&j(o,"has",t),j(o,"has",i)),t===i?n.has(t):n.has(t)||n.has(i)},forEach(n,r){const o=this,i=o["__v_raw"],s=Ie(i),a=t?ae:e?Me:xe;return!e&&j(s,"iterate",D),i.forEach(((e,t)=>n.call(r,a(e),a(t),o)))}};(0,r.X$)(n,e?{add:ue("add"),set:ue("set"),delete:ue("delete"),clear:ue("clear")}:{add(e){t||Ne(e)||Ae(e)||(e=Ie(e));const n=Ie(this),r=le(n),o=r.has.call(n,e);return o||(n.add(e),U(n,"add",e,e)),this},set(e,n){t||Ne(n)||Ae(n)||(n=Ie(n));const o=Ie(this),{has:i,get:s}=le(o);let a=i.call(o,e);a||(e=Ie(e),a=i.call(o,e));const l=s.call(o,e);return o.set(e,n),a?(0,r.$H)(n,l)&&U(o,"set",e,n,l):U(o,"add",e,n),this},delete(e){const t=Ie(this),{has:n,get:r}=le(t);let o=n.call(t,e);o||(e=Ie(e),o=n.call(t,e));const i=r?r.call(t,e):void 0,s=t.delete(e);return o&&U(t,"delete",e,void 0,i),s},clear(){const e=Ie(this),t=0!==e.size,n=void 0,r=e.clear();return t&&U(e,"clear",void 0,void 0,n),r}});const o=["keys","values","entries",Symbol.iterator];return o.forEach((r=>{n[r]=ce(r,e,t)})),n}function fe(e,t){const n=de(e,t);return(t,o,i)=>"__v_isReactive"===o?!e:"__v_isReadonly"===o?e:"__v_raw"===o?t:Reflect.get((0,r.$3)(n,o)&&o in t?n:t,o,i)}const pe={get:fe(!1,!1)},he={get:fe(!1,!0)},me={get:fe(!0,!1)},ve={get:fe(!0,!0)};const ge=new WeakMap,ye=new WeakMap,be=new WeakMap,_e=new WeakMap;function Ee(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function we(e){return e["__v_skip"]||!Object.isExtensible(e)?0:Ee((0,r.Zf)(e))}function Se(e){return Ae(e)?e:Te(e,!1,re,pe,ge)}function ke(e){return Te(e,!1,ie,he,ye)}function Ce(e){return Te(e,!0,oe,me,be)}function Oe(e){return Te(e,!0,se,ve,_e)}function Te(e,t,n,o,i){if(!(0,r.Gv)(e))return e;if(e["__v_raw"]&&(!t||!e["__v_isReactive"]))return e;const s=i.get(e);if(s)return s;const a=we(e);if(0===a)return e;const l=new Proxy(e,2===a?o:n);return i.set(e,l),l}function Re(e){return Ae(e)?Re(e["__v_raw"]):!(!e||!e["__v_isReactive"])}function Ae(e){return!(!e||!e["__v_isReadonly"])}function Ne(e){return!(!e||!e["__v_isShallow"])}function Le(e){return!!e&&!!e["__v_raw"]}function Ie(e){const t=e&&e["__v_raw"];return t?Ie(t):e}function Pe(e){return!(0,r.$3)(e,"__v_skip")&&Object.isExtensible(e)&&(0,r.yQ)(e,"__v_skip",!0),e}const xe=e=>(0,r.Gv)(e)?Se(e):e,Me=e=>(0,r.Gv)(e)?Ce(e):e;function De(e){return!!e&&!0===e["__v_isRef"]}function $e(e){return je(e,!1)}function Fe(e){return je(e,!0)}function je(e,t){return De(e)?e:new Ue(e,t)}class Ue{constructor(e,t){this.dep=new P,this["__v_isRef"]=!0,this["__v_isShallow"]=!1,this._rawValue=t?e:Ie(e),this._value=t?e:xe(e),this["__v_isShallow"]=t}get value(){return this.dep.track(),this._value}set value(e){const t=this._rawValue,n=this["__v_isShallow"]||Ne(e)||Ae(e);e=n?e:Ie(e),(0,r.$H)(e,t)&&(this._rawValue=e,this._value=n?e:xe(e),this.dep.trigger())}}function Be(e){e.dep&&e.dep.trigger()}function Ve(e){return De(e)?e.value:e}function He(e){return(0,r.Tn)(e)?e():Ve(e)}const We={get:(e,t,n)=>"__v_raw"===t?e:Ve(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const o=e[t];return De(o)&&!De(n)?(o.value=n,!0):Reflect.set(e,t,n,r)}};function Xe(e){return Re(e)?e:new Proxy(e,We)}class Ge{constructor(e){this["__v_isRef"]=!0,this._value=void 0;const t=this.dep=new P,{get:n,set:r}=e(t.track.bind(t),t.trigger.bind(t));this._get=n,this._set=r}get value(){return this._value=this._get()}set value(e){this._set(e)}}function Ke(e){return new Ge(e)}function ze(e){const t=(0,r.cy)(e)?new Array(e.length):{};for(const n in e)t[n]=Je(e,n);return t}class qe{constructor(e,t,n){this._object=e,this._key=t,this._defaultValue=n,this["__v_isRef"]=!0,this._value=void 0}get value(){const e=this._object[this._key];return this._value=void 0===e?this._defaultValue:e}set value(e){this._object[this._key]=e}get dep(){return B(Ie(this._object),this._key)}}class Ye{constructor(e){this._getter=e,this["__v_isRef"]=!0,this["__v_isReadonly"]=!0,this._value=void 0}get value(){return this._value=this._getter()}}function Qe(e,t,n){return De(e)?e:(0,r.Tn)(e)?new Ye(e):(0,r.Gv)(e)&&arguments.length>1?Je(e,t,n):$e(e)}function Je(e,t,n){const r=e[t];return De(r)?r:new qe(e,t,n)}class Ze{constructor(e,t,n){this.fn=e,this.setter=t,this._value=void 0,this.dep=new P(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=L-1,this.next=void 0,this.effect=this,this["__v_isReadonly"]=!t,this.isSSR=n}notify(){if(this.flags|=16,!(8&this.flags||i===this))return m(this,!0),!0}get value(){const e=this.dep.track();return E(this),e&&(e.version=this.dep.version),this._value}set value(e){this.setter&&this.setter(e)}}function et(e,t,n=!1){let o,i;(0,r.Tn)(e)?o=e:(o=e.get,i=e.set);const s=new Ze(o,i,n);return s}const tt={GET:"get",HAS:"has",ITERATE:"iterate"},nt={SET:"set",ADD:"add",DELETE:"delete",CLEAR:"clear"},rt={},ot=new WeakMap;let it;function st(){return it}function at(e,t=!1,n=it){if(n){let t=ot.get(n);t||ot.set(n,t=[]),t.push(e)}else 0}function lt(e,t,n=r.MZ){const{immediate:o,deep:i,once:s,scheduler:a,augmentJob:c,call:u}=n,f=e=>i?e:Ne(e)||!1===i||0===i?ct(e,1):ct(e);let p,h,m,v,g=!1,y=!1;if(De(e)?(h=()=>e.value,g=Ne(e)):Re(e)?(h=()=>f(e),g=!0):(0,r.cy)(e)?(y=!0,g=e.some((e=>Re(e)||Ne(e))),h=()=>e.map((e=>De(e)?e.value:Re(e)?f(e):(0,r.Tn)(e)?u?u(e,2):e():void 0))):h=(0,r.Tn)(e)?t?u?()=>u(e,2):e:()=>{if(m){R();try{m()}finally{A()}}const t=it;it=p;try{return u?u(e,3,[v]):e(v)}finally{it=t}}:r.tE,t&&i){const e=h,t=!0===i?1/0:i;h=()=>ct(e(),t)}const b=l(),_=()=>{p.stop(),b&&b.active&&(0,r.TF)(b.effects,p)};if(s&&t){const e=t;t=(...t)=>{e(...t),_()}}let E=y?new Array(e.length).fill(rt):rt;const w=e=>{if(1&p.flags&&(p.dirty||e))if(t){const e=p.run();if(i||g||(y?e.some(((e,t)=>(0,r.$H)(e,E[t]))):(0,r.$H)(e,E))){m&&m();const n=it;it=p;try{const n=[e,E===rt?void 0:y&&E[0]===rt?[]:E,v];u?u(t,3,n):t(...n),E=e}finally{it=n}}}else p.run()};return c&&c(w),p=new d(h),p.scheduler=a?()=>a(w,!1):w,v=e=>at(e,!1,p),m=p.onStop=()=>{const e=ot.get(p);if(e){if(u)u(e,4);else for(const t of e)t();ot.delete(p)}},t?o?w(!0):E=p.run():a?a(w.bind(null,!0),!0):p.run(),_.pause=p.pause.bind(p),_.resume=p.resume.bind(p),_.stop=_,_}function ct(e,t=1/0,n){if(t<=0||!(0,r.Gv)(e)||e["__v_skip"])return e;if(n=n||new Set,n.has(e))return e;if(n.add(e),t--,De(e))ct(e.value,t,n);else if((0,r.cy)(e))for(let r=0;r{ct(e,t,n)}));else if((0,r.Qd)(e)){for(const r in e)ct(e[r],t,n);for(const r of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,r)&&ct(e[r],t,n)}return e}},1072:function(e,t,n){"use strict";var r=n(1828),o=n(8727);e.exports=Object.keys||function(e){return r(e,o)}},1123:function(e){const t=/^[0-9]+$/,n=(e,n)=>{const r=t.test(e),o=t.test(n);return r&&o&&(e=+e,n=+n),e===n?0:r&&!o?-1:o&&!r?1:en(t,e);e.exports={compareIdentifiers:n,rcompareIdentifiers:r}},1181:function(e,t,n){"use strict";var r,o,i,s=n(8622),a=n(4576),l=n(34),c=n(6699),u=n(9297),d=n(7629),f=n(6119),p=n(421),h="Object already initialized",m=a.TypeError,v=a.WeakMap,g=function(e){return i(e)?o(e):r(e,{})},y=function(e){return function(t){var n;if(!l(t)||(n=o(t)).type!==e)throw new m("Incompatible receiver, "+e+" required");return n}};if(s||d.state){var b=d.state||(d.state=new v);b.get=b.get,b.has=b.has,b.set=b.set,r=function(e,t){if(b.has(e))throw new m(h);return t.facade=e,b.set(e,t),t},o=function(e){return b.get(e)||{}},i=function(e){return b.has(e)}}else{var _=f("state");p[_]=!0,r=function(e,t){if(u(e,_))throw new m(h);return t.facade=e,c(e,_,t),t},o=function(e){return u(e,_)?e[_]:{}},i=function(e){return u(e,_)}}e.exports={set:r,get:o,has:i,enforce:g,getterFor:y}},1261:function(e,t,n){const r=n(3908),o=n(8311),i=n(5580),s=(e,t)=>{e=new o(e,t);let n=new r("0.0.0");if(e.test(n))return n;if(n=new r("0.0.0-0"),e.test(n))return n;n=null;for(let o=0;o{const t=new r(e.semver.version);switch(e.operator){case">":0===t.prerelease.length?t.patch++:t.prerelease.push(0),t.raw=t.format();case"":case">=":s&&!i(t,s)||(s=t);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${e.operator}`)}})),!s||n&&!i(n,s)||(n=s)}return n&&e.test(n)?n:null};e.exports=s},1291:function(e,t,n){"use strict";var r=n(741);e.exports=function(e){var t=+e;return t!==t||0===t?0:r(t)}},1625:function(e,t,n){"use strict";var r=n(9504);e.exports=r({}.isPrototypeOf)},1701:function(e,t,n){"use strict";var r=n(6518),o=n(713),i=n(6395);r({target:"Iterator",proto:!0,real:!0,forced:i},{map:o})},1729:function(e,t,n){const r=n(144),o=(e,t)=>{const n=r(e,t);return n&&n.prerelease.length?n.prerelease:null};e.exports=o},1763:function(e,t,n){const r=n(560),o=(e,t)=>r(e,t,!0);e.exports=o},1767:function(e){"use strict";e.exports=function(e){return{iterator:e,next:e.next,done:!1}}},1828:function(e,t,n){"use strict";var r=n(9504),o=n(9297),i=n(5397),s=n(9617).indexOf,a=n(421),l=r([].push);e.exports=function(e,t){var n,r=i(e),c=0,u=[];for(n in r)!o(a,n)&&o(r,n)&&l(u,n);while(t.length>c)o(r,n=t[c++])&&(~s(u,n)||l(u,n));return u}},1832:function(e,t,n){const r=n(144),o=(e,t)=>{const n=r(e,null,!0),o=r(t,null,!0),i=n.compare(o);if(0===i)return null;const s=i>0,a=s?n:o,l=s?o:n,c=!!a.prerelease.length,u=!!l.prerelease.length;if(u&&!c){if(!l.patch&&!l.minor)return"major";if(0===l.compareMain(a))return l.minor&&!l.patch?"minor":"patch"}const d=c?"pre":"";return n.major!==o.major?d+"major":n.minor!==o.minor?d+"minor":n.patch!==o.patch?d+"patch":"prerelease"};e.exports=o},1881:function(e,t){"use strict";t.A={computed:{query:e=>e.$route.query.q,pages:e=>Number(e.$route.query.pages)||1,sorting:e=>e.$route.query.sort||"",isSearching:e=>e.query||e.pages>1||e.sorting},methods:{startSearch(e,t=1){const n={q:e};t&&(n.pages=t),this.sorting&&this.query===e&&(n.sort=this.sorting),this.$router.push({query:n,append:!0}).catch((()=>{}))},stopSearch(e){const t=Object.assign({},this.$route);delete t.query,this.$router.push(t).catch((()=>{})),e&&e.target&&e.target.blur()},sortBy(e){this.$router.push({query:Object.assign({},this.$route.query,{sort:e})}).catch((()=>{}))},loadMore(e){this.startSearch(this.query,this.pages+1),e&&e.target&&e.target.blur()}}}},2106:function(e,t,n){"use strict";var r=n(283),o=n(4913);e.exports=function(e,t,n){return n.get&&r(n.get,t,{getter:!0}),n.set&&r(n.set,t,{setter:!0}),o.f(e,t,n)}},2111:function(e,t,n){const r=n(4641),o=n(3999),i=n(5580),s=n(4089),a=n(7059),l=n(5200),c=(e,t,n,c)=>{switch(t){case"===":return"object"===typeof e&&(e=e.version),"object"===typeof n&&(n=n.version),e===n;case"!==":return"object"===typeof e&&(e=e.version),"object"===typeof n&&(n=n.version),e!==n;case"":case"=":case"==":return r(e,n,c);case"!=":return o(e,n,c);case">":return i(e,n,c);case">=":return s(e,n,c);case"<":return a(e,n,c);case"<=":return l(e,n,c);default:throw new TypeError(`Invalid operator: ${t}`)}};e.exports=c},2140:function(e,t,n){"use strict";var r=n(8227),o=r("toStringTag"),i={};i[o]="z",e.exports="[object z]"===String(i)},2195:function(e,t,n){"use strict";var r=n(9504),o=r({}.toString),i=r("".slice);e.exports=function(e){return i(o(e),8,-1)}},2211:function(e,t,n){"use strict";var r=n(9039);e.exports=!r((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},2360:function(e,t,n){"use strict";var r,o=n(8551),i=n(6801),s=n(8727),a=n(421),l=n(397),c=n(4055),u=n(6119),d=">",f="<",p="prototype",h="script",m=u("IE_PROTO"),v=function(){},g=function(e){return f+h+d+e+f+"/"+h+d},y=function(e){e.write(g("")),e.close();var t=e.parentWindow.Object;return e=null,t},b=function(){var e,t=c("iframe"),n="java"+h+":";return t.style.display="none",l.appendChild(t),t.src=String(n),e=t.contentWindow.document,e.open(),e.write(g("document.F=Object")),e.close(),e.F},_=function(){try{r=new ActiveXObject("htmlfile")}catch(t){}_="undefined"!=typeof document?document.domain&&r?y(r):b():y(r);var e=s.length;while(e--)delete _[p][s[e]];return _()};a[m]=!0,e.exports=Object.create||function(e,t){var n;return null!==e?(v[p]=o(e),n=new v,v[p]=null,n[m]=e):n=_(),void 0===t?n:i.f(n,t)}},2361:function(e,t,n){"use strict";n.d(t,{A:function(){return f}});var r=n(641),o=n(3751);const i={class:"search-bar"},s=["placeholder","disabled","value"];function a(e,t,n,a,l,c){return(0,r.uX)(),(0,r.CE)("section",i,[(0,r.Lk)("input",{class:"search-bar__input",ref:"search",id:"search",type:"text",placeholder:n.placeholder,disabled:n.disabled,autocomplete:"off",value:e.query,onInput:t[0]||(t[0]=(...e)=>c.searchInput&&c.searchInput(...e)),onKeypress:t[1]||(t[1]=(0,o.jR)((0,o.D$)(((...t)=>e.stopSearch&&e.stopSearch(...t)),["prevent"]),["esc"]))},null,40,s),e.query?((0,r.uX)(),(0,r.CE)("button",{key:0,class:"search-bar__button search-bar__button--stop",onClick:t[2]||(t[2]=(...t)=>e.stopSearch&&e.stopSearch(...t))},t[4]||(t[4]=[(0,r.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",fill:"#737373",xmlns:"http://www.w3.org/2000/svg"},[(0,r.Lk)("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"}),(0,r.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)]))):((0,r.uX)(),(0,r.CE)("button",{key:1,class:"search-bar__button search-bar__button--start",onClick:t[3]||(t[3]=t=>e.$refs.search.focus())},t[5]||(t[5]=[(0,r.Lk)("svg",{fill:"#737373",height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,r.Lk)("path",{d:"M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),(0,r.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)])))])}var l=n(1881),c={mixins:[l.A],props:{placeholder:String,disabled:Boolean},methods:{searchInput(e){this.startSearch(e.target.value)}}},u=n(6262);const d=(0,u.A)(c,[["render",a]]);var f=d},2489:function(e,t,n){"use strict";var r=n(6518),o=n(9565),i=n(9306),s=n(8551),a=n(1767),l=n(9462),c=n(6319),u=n(6395),d=l((function(){var e,t,n,r=this.iterator,i=this.predicate,a=this.next;while(1){if(e=s(o(a,r)),t=this.done=!!e.done,t)return;if(n=e.value,c(r,i,[n,this.counter++],!0))return n}}));r({target:"Iterator",proto:!0,real:!0,forced:u},{filter:function(e){return s(this),i(e),new d(a(this),{predicate:e})}})},2525:function(e,t,n){const r=n(7638),o=n(560);e.exports=(e,t,n)=>{const i=[];let s=null,a=null;const l=e.sort(((e,t)=>o(e,t,n)));for(const o of l){const e=r(o,t,n);e?(a=o,s||(s=o)):(a&&i.push([s,a]),a=null,s=null)}s&&i.push([s,null]);const c=[];for(const[r,o]of i)r===o?c.push(r):o||r!==l[0]?o?r===l[0]?c.push(`<=${o}`):c.push(`${r} - ${o}`):c.push(`>=${r}`):c.push("*");const u=c.join(" || "),d="string"===typeof t.raw?t.raw:String(t);return u.lengthy;y++)if(_=N(e[y]),_&&c(m,_))return _;return new h(!1)}v=u(e,g)}E=C?e.next:v.next;while(!(w=o(E,v)).done){try{_=N(w.value)}catch(L){f(v,"throw",L)}if("object"==typeof _&&_&&c(m,_))return _}return new h(!1)}},2777:function(e,t,n){"use strict";var r=n(9565),o=n(34),i=n(757),s=n(5966),a=n(4270),l=n(8227),c=TypeError,u=l("toPrimitive");e.exports=function(e,t){if(!o(e)||i(e))return e;var n,l=s(e,u);if(l){if(void 0===t&&(t="default"),n=r(l,e,t),!o(n)||i(n))return n;throw new c("Can't convert object to primitive value")}return void 0===t&&(t="number"),a(e,t)}},2787:function(e,t,n){"use strict";var r=n(9297),o=n(4901),i=n(8981),s=n(6119),a=n(2211),l=s("IE_PROTO"),c=Object,u=c.prototype;e.exports=a?c.getPrototypeOf:function(e){var t=i(e);if(r(t,l))return t[l];var n=t.constructor;return o(n)&&t instanceof n?n.prototype:t instanceof c?u:null}},2796:function(e,t,n){"use strict";var r=n(9039),o=n(4901),i=/#|\.prototype\./,s=function(e,t){var n=l[a(e)];return n===u||n!==c&&(o(t)?r(t):!!t)},a=s.normalize=function(e){return String(e).replace(i,".").toLowerCase()},l=s.data={},c=s.NATIVE="N",u=s.POLYFILL="P";e.exports=s},2812:function(e){"use strict";var t=TypeError;e.exports=function(e,n){if(enew r(e,t).major;e.exports=o},3007:function(e,t,n){const r=n(3908),o=(e,t,n,o,i)=>{"string"===typeof n&&(i=o,o=n,n=void 0);try{return new r(e instanceof r?e.version:e,n).inc(t,o,i).version}catch(s){return null}};e.exports=o},3170:function(e,t,n){"use strict";n.d(t,{A:function(){return f}});var r=n(641),o=n(33),i=n(3751);const s={class:"popup-overlay__content"},a={key:1,class:"popup-overlay__actions"};function l(e,t,n,l,c,u){return(0,r.uX)(),(0,r.CE)("div",{class:"popup-overlay",onClick:t[1]||(t[1]=(...e)=>u.clearCurrent&&u.clearCurrent(...e))},[(0,r.Lk)("div",{ref:"popup",class:(0,o.C4)(`popup-overlay__popup ${n.popupClass}`)},[(0,r.RG)(e.$slots,"content",{},(()=>[(0,r.Lk)("form",{onSubmit:t[0]||(t[0]=(0,i.D$)((t=>e.$emit("submit")),["prevent"]))},[n.headline||e.$slots.headline?(0,r.RG)(e.$slots,"headline",{key:0},(()=>[(0,r.Lk)("h1",{class:(0,o.C4)(["popup-overlay__headline",{[`popup-overlay__headline--${n.headlineType}`]:!!n.headlineType}])},(0,o.v_)(n.headline),3)])):(0,r.Q3)("",!0),(0,r.Lk)("div",s,[(0,r.RG)(e.$slots,"default")]),e.$slots.actions?((0,r.uX)(),(0,r.CE)("div",a,[(0,r.RG)(e.$slots,"actions")])):(0,r.Q3)("",!0)],32)]))],2)])}var c={emits:["submit"],props:{fixed:Boolean,popupClass:[String,Object],headline:String,headlineType:String},methods:{clearCurrent(e){this.$refs.popup&&!this.$refs.popup.contains(e.target)&&document.body.contains(e.target)&&this.$emit("clear")}}},u=n(6262);const d=(0,u.A)(c,[["render",l]]);var f=d},3192:function(e,t,n){"use strict";n.d(t,{A:function(){return o}});var r=n(3751);async function o(e,t,n,o=()=>{}){if(await t.init(),void 0!==URLSearchParams){const e=new URLSearchParams(location.search);if(e.has("_locale")){await t.switch(e.get("_locale")),e.delete("_locale");const n=new URL(location.pathname,location);n.search=e.toString(),history.replaceState(history.state,"",n.toString())}}const i=(0,r.Ef)({...e});i.use(t.plugin),n.forEach((e=>{i.use(e)})),o(i),i.mount("body")}},3382:function(e,t,n){"use strict";e.exports=n.p+"img/funding.cf78a0a0.svg"},3392:function(e,t,n){"use strict";var r=n(9504),o=0,i=Math.random(),s=r(1..toString);e.exports=function(e){return"Symbol("+(void 0===e?"":e)+")_"+s(++o+i,36)}},3609:function(e,t,n){"use strict";var r=n(6518),o=n(8981),i=n(6198),s=n(4527),a=n(4606),l=n(6837),c=1!==[].unshift(0),u=function(){try{Object.defineProperty([],"length",{writable:!1}).unshift()}catch(e){return e instanceof TypeError}},d=c||!u();r({target:"Array",proto:!0,arity:1,forced:d},{unshift:function(e){var t=o(this),n=i(t),r=arguments.length;if(r){l(n+r);var c=n;while(c--){var u=c+r;c in t?t[u]=t[c]:a(t,u)}for(var d=0;de})}catch(ht){}const l=s?e=>s.createHTML(e):e=>e,c="http://www.w3.org/2000/svg",u="http://www.w3.org/1998/Math/MathML",d="undefined"!==typeof document?document:null,f=d&&d.createElement("template"),p={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const o="svg"===t?d.createElementNS(c,e):"mathml"===t?d.createElementNS(u,e):n?d.createElement(e,{is:n}):d.createElement(e);return"select"===e&&r&&null!=r.multiple&&o.setAttribute("multiple",r.multiple),o},createText:e=>d.createTextNode(e),createComment:e=>d.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>d.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,o,i){const s=n?n.previousSibling:t.lastChild;if(o&&(o===i||o.nextSibling)){while(1)if(t.insertBefore(o.cloneNode(!0),n),o===i||!(o=o.nextSibling))break}else{f.innerHTML=l("svg"===r?`${e}`:"mathml"===r?`${e}`:e);const o=f.content;if("svg"===r||"mathml"===r){const e=o.firstChild;while(e.firstChild)o.appendChild(e.firstChild);o.removeChild(e)}t.insertBefore(o,n)}return[s?s.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},h="transition",m="animation",v=Symbol("_vtc"),g={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},y=(0,o.X$)({},r.QP,g),b=e=>(e.displayName="Transition",e.props=y,e),_=b(((e,{slots:t})=>(0,r.h)(r.pR,S(e),t))),E=(e,t=[])=>{(0,o.cy)(e)?e.forEach((e=>e(...t))):e&&e(...t)},w=e=>!!e&&((0,o.cy)(e)?e.some((e=>e.length>1)):e.length>1);function S(e){const t={};for(const o in e)o in g||(t[o]=e[o]);if(!1===e.css)return t;const{name:n="v",type:r,duration:i,enterFromClass:s=`${n}-enter-from`,enterActiveClass:a=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=s,appearActiveClass:u=a,appearToClass:d=l,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:h=`${n}-leave-to`}=e,m=k(i),v=m&&m[0],y=m&&m[1],{onBeforeEnter:b,onEnter:_,onEnterCancelled:S,onLeave:C,onLeaveCancelled:A,onBeforeAppear:L=b,onAppear:I=_,onAppearCancelled:P=S}=t,M=(e,t,n,r)=>{e._enterCancelled=r,T(e,t?d:l),T(e,t?u:a),n&&n()},D=(e,t)=>{e._isLeaving=!1,T(e,f),T(e,h),T(e,p),t&&t()},$=e=>(t,n)=>{const o=e?I:_,i=()=>M(t,e,n);E(o,[t,i]),R((()=>{T(t,e?c:s),O(t,e?d:l),w(o)||N(t,r,v,i)}))};return(0,o.X$)(t,{onBeforeEnter(e){E(b,[e]),O(e,s),O(e,a)},onBeforeAppear(e){E(L,[e]),O(e,c),O(e,u)},onEnter:$(!1),onAppear:$(!0),onLeave(e,t){e._isLeaving=!0;const n=()=>D(e,t);O(e,f),e._enterCancelled?(O(e,p),x()):(x(),O(e,p)),R((()=>{e._isLeaving&&(T(e,f),O(e,h),w(C)||N(e,r,y,n))})),E(C,[e,n])},onEnterCancelled(e){M(e,!1,void 0,!0),E(S,[e])},onAppearCancelled(e){M(e,!0,void 0,!0),E(P,[e])},onLeaveCancelled(e){D(e),E(A,[e])}})}function k(e){if(null==e)return null;if((0,o.Gv)(e))return[C(e.enter),C(e.leave)];{const t=C(e);return[t,t]}}function C(e){const t=(0,o.Ro)(e);return t}function O(e,t){t.split(/\s+/).forEach((t=>t&&e.classList.add(t))),(e[v]||(e[v]=new Set)).add(t)}function T(e,t){t.split(/\s+/).forEach((t=>t&&e.classList.remove(t)));const n=e[v];n&&(n.delete(t),n.size||(e[v]=void 0))}function R(e){requestAnimationFrame((()=>{requestAnimationFrame(e)}))}let A=0;function N(e,t,n,r){const o=e._endId=++A,i=()=>{o===e._endId&&r()};if(null!=n)return setTimeout(i,n);const{type:s,timeout:a,propCount:l}=L(e,t);if(!s)return r();const c=s+"end";let u=0;const d=()=>{e.removeEventListener(c,f),i()},f=t=>{t.target===e&&++u>=l&&d()};setTimeout((()=>{u(n[e]||"").split(", "),o=r(`${h}Delay`),i=r(`${h}Duration`),s=I(o,i),a=r(`${m}Delay`),l=r(`${m}Duration`),c=I(a,l);let u=null,d=0,f=0;t===h?s>0&&(u=h,d=s,f=i.length):t===m?c>0&&(u=m,d=c,f=l.length):(d=Math.max(s,c),u=d>0?s>c?h:m:null,f=u?u===h?i.length:l.length:0);const p=u===h&&/\b(transform|all)(,|$)/.test(r(`${h}Property`).toString());return{type:u,timeout:d,propCount:f,hasTransform:p}}function I(e,t){while(e.lengthP(t)+P(e[n]))))}function P(e){return"auto"===e?0:1e3*Number(e.slice(0,-1).replace(",","."))}function x(){return document.body.offsetHeight}function M(e,t,n){const r=e[v];r&&(t=(t?[t,...r]:[...r]).join(" ")),null==t?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const D=Symbol("_vod"),$=Symbol("_vsh"),F={beforeMount(e,{value:t},{transition:n}){e[D]="none"===e.style.display?"":e.style.display,n&&t?n.beforeEnter(e):j(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!==!n&&(r?t?(r.beforeEnter(e),j(e,!0),r.enter(e)):r.leave(e,(()=>{j(e,!1)})):j(e,t))},beforeUnmount(e,{value:t}){j(e,t)}};function j(e,t){e.style.display=t?e[D]:"none",e[$]=!t}function U(){F.getSSRProps=({value:e})=>{if(!e)return{style:{display:"none"}}}}const B=Symbol("");function V(e){const t=(0,r.nI)();if(!t)return;const n=t.ut=(n=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach((e=>W(e,n)))};const i=()=>{const r=e(t.proxy);t.ce?W(t.ce,r):H(t.subTree,r),n(r)};(0,r.Ic)((()=>{(0,r.Dl)(i)})),(0,r.sV)((()=>{(0,r.wB)(i,o.tE,{flush:"post"});const e=new MutationObserver(i);e.observe(t.subTree.el.parentNode,{childList:!0}),(0,r.hi)((()=>e.disconnect()))}))}function H(e,t){if(128&e.shapeFlag){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push((()=>{H(n.activeBranch,t)}))}while(e.component)e=e.component.subTree;if(1&e.shapeFlag&&e.el)W(e.el,t);else if(e.type===r.FK)e.children.forEach((e=>H(e,t)));else if(e.type===r.jC){let{el:n,anchor:r}=e;while(n){if(W(n,t),n===r)break;n=n.nextSibling}}}function W(e,t){if(1===e.nodeType){const n=e.style;let r="";for(const e in t)n.setProperty(`--${e}`,t[e]),r+=`--${e}: ${t[e]};`;n[B]=r}}const X=/(^|;)\s*display\s*:/;function G(e,t,n){const r=e.style,i=(0,o.Kg)(n);let s=!1;if(n&&!i){if(t)if((0,o.Kg)(t))for(const e of t.split(";")){const t=e.slice(0,e.indexOf(":")).trim();null==n[t]&&z(r,t,"")}else for(const e in t)null==n[e]&&z(r,e,"");for(const e in n)"display"===e&&(s=!0),z(r,e,n[e])}else if(i){if(t!==n){const e=r[B];e&&(n+=";"+e),r.cssText=n,s=X.test(n)}}else t&&e.removeAttribute("style");D in e&&(e[D]=s?r.display:"",e[$]&&(r.display="none"))}const K=/\s*!important$/;function z(e,t,n){if((0,o.cy)(n))n.forEach((n=>z(e,t,n)));else if(null==n&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Q(e,t);K.test(n)?e.setProperty((0,o.Tg)(r),n.replace(K,""),"important"):e[r]=n}}const q=["Webkit","Moz","ms"],Y={};function Q(e,t){const n=Y[t];if(n)return n;let r=(0,o.PT)(t);if("filter"!==r&&r in e)return Y[t]=r;r=(0,o.ZH)(r);for(let o=0;oae||(le.then((()=>ae=0)),ae=Date.now());function ue(e,t){const n=e=>{if(e._vts){if(e._vts<=n.attached)return}else e._vts=Date.now();(0,r.qL)(de(e,n.value),t,5,[e])};return n.value=e,n.attached=ce(),n}function de(e,t){if((0,o.cy)(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map((e=>t=>!t._stopped&&e&&e(t)))}return t}const fe=e=>111===e.charCodeAt(0)&&110===e.charCodeAt(1)&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,pe=(e,t,n,r,i,s)=>{const a="svg"===i;"class"===t?M(e,r,a):"style"===t?G(e,n,r):(0,o.Mp)(t)?(0,o.CP)(t)||oe(e,t,n,r,s):("."===t[0]?(t=t.slice(1),1):"^"===t[0]?(t=t.slice(1),0):he(e,t,r,a))?(ee(e,t,r),e.tagName.includes("-")||"value"!==t&&"checked"!==t&&"selected"!==t||Z(e,t,r,a,s,"value"!==t)):!e._isVueCE||!/[A-Z]/.test(t)&&(0,o.Kg)(r)?("true-value"===t?e._trueValue=r:"false-value"===t&&(e._falseValue=r),Z(e,t,r,a)):ee(e,(0,o.PT)(t),r,s,t)};function he(e,t,n,r){if(r)return"innerHTML"===t||"textContent"===t||!!(t in e&&fe(t)&&(0,o.Tn)(n));if("spellcheck"===t||"draggable"===t||"translate"===t)return!1;if("form"===t)return!1;if("list"===t&&"INPUT"===e.tagName)return!1;if("type"===t&&"TEXTAREA"===e.tagName)return!1;if("width"===t||"height"===t){const t=e.tagName;if("IMG"===t||"VIDEO"===t||"CANVAS"===t||"SOURCE"===t)return!1}return(!fe(t)||!(0,o.Kg)(n))&&t in e}const me={}; /*! #__NO_SIDE_EFFECTS__ */function ve(e,t,n){const i=(0,r.pM)(e,t);(0,o.Qd)(i)&&(0,o.X$)(i,t);class s extends be{constructor(e){super(i,e,n)}}return s.def=i,s} /*! #__NO_SIDE_EFFECTS__ */const ge=(e,t)=>ve(e,t,ct),ye="undefined"!==typeof HTMLElement?HTMLElement:class{};class be extends ye{constructor(e,t={},n=lt){super(),this._def=e,this._props=t,this._createApp=n,this._isVueCE=!0,this._instance=null,this._app=null,this._nonce=this._def.nonce,this._connected=!1,this._resolved=!1,this._numberProps=null,this._styleChildren=new WeakSet,this._ob=null,this.shadowRoot&&n!==lt?this._root=this.shadowRoot:!1!==e.shadowRoot?(this.attachShadow({mode:"open"}),this._root=this.shadowRoot):this._root=this,this._def.__asyncLoader||this._resolveProps(this._def)}connectedCallback(){if(!this.isConnected)return;this.shadowRoot||this._parseSlots(),this._connected=!0;let e=this;while(e=e&&(e.parentNode||e.host))if(e instanceof be){this._parent=e;break}this._instance||(this._resolved?(this._setParent(),this._update()):e&&e._pendingResolve?this._pendingResolve=e._pendingResolve.then((()=>{this._pendingResolve=void 0,this._resolveDef()})):this._resolveDef())}_setParent(e=this._parent){e&&(this._instance.parent=e._instance,this._instance.provides=e._instance.provides)}disconnectedCallback(){this._connected=!1,(0,r.dY)((()=>{this._connected||(this._ob&&(this._ob.disconnect(),this._ob=null),this._app&&this._app.unmount(),this._instance&&(this._instance.ce=void 0),this._app=this._instance=null)}))}_resolveDef(){if(this._pendingResolve)return;for(let n=0;n{for(const t of e)this._setAttr(t.attributeName)})),this._ob.observe(this,{attributes:!0});const e=(e,t=!1)=>{this._resolved=!0,this._pendingResolve=void 0;const{props:n,styles:r}=e;let i;if(n&&!(0,o.cy)(n))for(const s in n){const e=n[s];(e===Number||e&&e.type===Number)&&(s in this._props&&(this._props[s]=(0,o.Ro)(this._props[s])),(i||(i=Object.create(null)))[(0,o.PT)(s)]=!0)}this._numberProps=i,t&&this._resolveProps(e),this.shadowRoot&&this._applyStyles(r),this._mount(e)},t=this._def.__asyncLoader;t?this._pendingResolve=t().then((t=>e(this._def=t,!0))):e(this._def)}_mount(e){this._app=this._createApp(e),e.configureApp&&e.configureApp(this._app),this._app._ceVNode=this._createVNode(),this._app.mount(this._root);const t=this._instance&&this._instance.exposed;if(t)for(const n in t)(0,o.$3)(this,n)||Object.defineProperty(this,n,{get:()=>(0,i.R1)(t[n])})}_resolveProps(e){const{props:t}=e,n=(0,o.cy)(t)?t:Object.keys(t||{});for(const r of Object.keys(this))"_"!==r[0]&&n.includes(r)&&this._setProp(r,this[r]);for(const r of n.map(o.PT))Object.defineProperty(this,r,{get(){return this._getProp(r)},set(e){this._setProp(r,e,!0,!0)}})}_setAttr(e){if(e.startsWith("data-v-"))return;const t=this.hasAttribute(e);let n=t?this.getAttribute(e):me;const r=(0,o.PT)(e);t&&this._numberProps&&this._numberProps[r]&&(n=(0,o.Ro)(n)),this._setProp(r,n,!1,!0)}_getProp(e){return this._props[e]}_setProp(e,t,n=!0,r=!1){if(t!==this._props[e]&&(t===me?delete this._props[e]:(this._props[e]=t,"key"===e&&this._app&&(this._app._ceVNode.key=t)),r&&this._instance&&this._update(),n)){const n=this._ob;n&&n.disconnect(),!0===t?this.setAttribute((0,o.Tg)(e),""):"string"===typeof t||"number"===typeof t?this.setAttribute((0,o.Tg)(e),t+""):t||this.removeAttribute((0,o.Tg)(e)),n&&n.observe(this,{attributes:!0})}}_update(){st(this._createVNode(),this._root)}_createVNode(){const e={};this.shadowRoot||(e.onVnodeMounted=e.onVnodeUpdated=this._renderSlots.bind(this));const t=(0,r.bF)(this._def,(0,o.X$)(e,this._props));return this._instance||(t.ce=e=>{this._instance=e,e.ce=this,e.isCE=!0;const t=(e,t)=>{this.dispatchEvent(new CustomEvent(e,(0,o.Qd)(t[0])?(0,o.X$)({detail:t},t[0]):{detail:t}))};e.emit=(e,...n)=>{t(e,n),(0,o.Tg)(e)!==e&&t((0,o.Tg)(e),n)},this._setParent()}),t}_applyStyles(e,t){if(!e)return;if(t){if(t===this._def||this._styleChildren.has(t))return;this._styleChildren.add(t)}const n=this._nonce;for(let r=e.length-1;r>=0;r--){const t=document.createElement("style");n&&t.setAttribute("nonce",n),t.textContent=e[r],this.shadowRoot.prepend(t)}}_parseSlots(){const e=this._slots={};let t;while(t=this.firstChild){const n=1===t.nodeType&&t.getAttribute("slot")||"default";(e[n]||(e[n]=[])).push(t),this.removeChild(t)}}_renderSlots(){const e=(this._teleportTarget||this).querySelectorAll("slot"),t=this._instance.type.__scopeId;for(let n=0;n(delete e.props.mode,e),Re=Te({name:"TransitionGroup",props:(0,o.X$)({},y,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=(0,r.nI)(),o=(0,r.Gy)();let s,a;return(0,r.$u)((()=>{if(!s.length)return;const t=e.moveClass||`${e.name||"v"}-move`;if(!Pe(s[0].el,n.vnode.el,t))return;s.forEach(Ne),s.forEach(Le);const r=s.filter(Ie);x(),r.forEach((e=>{const n=e.el,r=n.style;O(n,t),r.transform=r.webkitTransform=r.transitionDuration="";const o=n[Ce]=e=>{e&&e.target!==n||e&&!/transform$/.test(e.propertyName)||(n.removeEventListener("transitionend",o),n[Ce]=null,T(n,t))};n.addEventListener("transitionend",o)}))})),()=>{const l=(0,i.ux)(e),c=S(l);let u=l.tag||r.FK;if(s=[],a)for(let e=0;e{e.split(/\s+/).forEach((e=>e&&r.classList.remove(e)))})),n.split(/\s+/).forEach((e=>e&&r.classList.add(e))),r.style.display="none";const i=1===t.nodeType?t:t.parentNode;i.appendChild(r);const{hasTransform:s}=L(r);return i.removeChild(r),s}const xe=e=>{const t=e.props["onUpdate:modelValue"]||!1;return(0,o.cy)(t)?e=>(0,o.DY)(t,e):t};function Me(e){e.target.composing=!0}function De(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const $e=Symbol("_assign"),Fe={created(e,{modifiers:{lazy:t,trim:n,number:r}},i){e[$e]=xe(i);const s=r||i.props&&"number"===i.props.type;te(e,t?"change":"input",(t=>{if(t.target.composing)return;let r=e.value;n&&(r=r.trim()),s&&(r=(0,o.bB)(r)),e[$e](r)})),n&&te(e,"change",(()=>{e.value=e.value.trim()})),t||(te(e,"compositionstart",Me),te(e,"compositionend",De),te(e,"change",De))},mounted(e,{value:t}){e.value=null==t?"":t},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:r,trim:i,number:s}},a){if(e[$e]=xe(a),e.composing)return;const l=!s&&"number"!==e.type||/^0\d/.test(e.value)?e.value:(0,o.bB)(e.value),c=null==t?"":t;if(l!==c){if(document.activeElement===e&&"range"!==e.type){if(r&&t===n)return;if(i&&e.value.trim()===c)return}e.value=c}}},je={deep:!0,created(e,t,n){e[$e]=xe(n),te(e,"change",(()=>{const t=e._modelValue,n=We(e),r=e.checked,i=e[$e];if((0,o.cy)(t)){const e=(0,o.u3)(t,n),s=-1!==e;if(r&&!s)i(t.concat(n));else if(!r&&s){const n=[...t];n.splice(e,1),i(n)}}else if((0,o.vM)(t)){const e=new Set(t);r?e.add(n):e.delete(n),i(e)}else i(Xe(e,r))}))},mounted:Ue,beforeUpdate(e,t,n){e[$e]=xe(n),Ue(e,t,n)}};function Ue(e,{value:t,oldValue:n},r){let i;if(e._modelValue=t,(0,o.cy)(t))i=(0,o.u3)(t,r.props.value)>-1;else if((0,o.vM)(t))i=t.has(r.props.value);else{if(t===n)return;i=(0,o.BX)(t,Xe(e,!0))}e.checked!==i&&(e.checked=i)}const Be={created(e,{value:t},n){e.checked=(0,o.BX)(t,n.props.value),e[$e]=xe(n),te(e,"change",(()=>{e[$e](We(e))}))},beforeUpdate(e,{value:t,oldValue:n},r){e[$e]=xe(r),t!==n&&(e.checked=(0,o.BX)(t,r.props.value))}},Ve={deep:!0,created(e,{value:t,modifiers:{number:n}},i){const s=(0,o.vM)(t);te(e,"change",(()=>{const t=Array.prototype.filter.call(e.options,(e=>e.selected)).map((e=>n?(0,o.bB)(We(e)):We(e)));e[$e](e.multiple?s?new Set(t):t:t[0]),e._assigning=!0,(0,r.dY)((()=>{e._assigning=!1}))})),e[$e]=xe(i)},mounted(e,{value:t}){He(e,t)},beforeUpdate(e,t,n){e[$e]=xe(n)},updated(e,{value:t}){e._assigning||He(e,t)}};function He(e,t){const n=e.multiple,r=(0,o.cy)(t);if(!n||r||(0,o.vM)(t)){for(let i=0,s=e.options.length;iString(e)===String(a))):(0,o.u3)(t,a)>-1}else s.selected=t.has(a);else if((0,o.BX)(We(s),t))return void(e.selectedIndex!==i&&(e.selectedIndex=i))}n||-1===e.selectedIndex||(e.selectedIndex=-1)}}function We(e){return"_value"in e?e._value:e.value}function Xe(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const Ge={created(e,t,n){ze(e,t,n,null,"created")},mounted(e,t,n){ze(e,t,n,null,"mounted")},beforeUpdate(e,t,n,r){ze(e,t,n,r,"beforeUpdate")},updated(e,t,n,r){ze(e,t,n,r,"updated")}};function Ke(e,t){switch(e){case"SELECT":return Ve;case"TEXTAREA":return Fe;default:switch(t){case"checkbox":return je;case"radio":return Be;default:return Fe}}}function ze(e,t,n,r,o){const i=Ke(e.tagName,n.props&&n.props.type),s=i[o];s&&s(e,t,n,r)}function qe(){Fe.getSSRProps=({value:e})=>({value:e}),Be.getSSRProps=({value:e},t)=>{if(t.props&&(0,o.BX)(t.props.value,e))return{checked:!0}},je.getSSRProps=({value:e},t)=>{if((0,o.cy)(e)){if(t.props&&(0,o.u3)(e,t.props.value)>-1)return{checked:!0}}else if((0,o.vM)(e)){if(t.props&&e.has(t.props.value))return{checked:!0}}else if(e)return{checked:!0}},Ge.getSSRProps=(e,t)=>{if("string"!==typeof t.type)return;const n=Ke(t.type.toUpperCase(),t.props&&t.props.type);return n.getSSRProps?n.getSSRProps(e,t):void 0}}const Ye=["ctrl","shift","alt","meta"],Qe={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&0!==e.button,middle:e=>"button"in e&&1!==e.button,right:e=>"button"in e&&2!==e.button,exact:(e,t)=>Ye.some((n=>e[`${n}Key`]&&!t.includes(n)))},Je=(e,t)=>{const n=e._withMods||(e._withMods={}),r=t.join(".");return n[r]||(n[r]=(n,...r)=>{for(let e=0;e{const n=e._withKeys||(e._withKeys={}),r=t.join(".");return n[r]||(n[r]=n=>{if(!("key"in n))return;const r=(0,o.Tg)(n.key);return t.some((e=>e===r||Ze[e]===r))?e(n):void 0})},tt=(0,o.X$)({patchProp:pe},p);let nt,rt=!1;function ot(){return nt||(nt=(0,r.K9)(tt))}function it(){return nt=rt?nt:(0,r.ci)(tt),rt=!0,nt}const st=(...e)=>{ot().render(...e)},at=(...e)=>{it().hydrate(...e)},lt=(...e)=>{const t=ot().createApp(...e);const{mount:n}=t;return t.mount=e=>{const r=dt(e);if(!r)return;const i=t._component;(0,o.Tn)(i)||i.render||i.template||(i.template=r.innerHTML),1===r.nodeType&&(r.textContent="");const s=n(r,!1,ut(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),s},t},ct=(...e)=>{const t=it().createApp(...e);const{mount:n}=t;return t.mount=e=>{const t=dt(e);if(t)return n(t,!0,ut(t))},t};function ut(e){return e instanceof SVGElement?"svg":"function"===typeof MathMLElement&&e instanceof MathMLElement?"mathml":void 0}function dt(e){if((0,o.Kg)(e)){const t=document.querySelector(e);return t}return e}let ft=!1;const pt=()=>{ft||(ft=!0,qe(),U())}},3874:function(e,t,n){const r=n(8311),o=(e,t)=>{try{return new r(e,t).range||"*"}catch(n){return null}};e.exports=o},3904:function(e,t,n){const r=Symbol("SemVer ANY");class o{static get ANY(){return r}constructor(e,t){if(t=i(t),e instanceof o){if(e.loose===!!t.loose)return e;e=e.value}e=e.trim().split(/\s+/).join(" "),c("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===r?this.value="":this.value=this.operator+this.semver.version,c("comp",this)}parse(e){const t=this.options.loose?s[a.COMPARATORLOOSE]:s[a.COMPARATOR],n=e.match(t);if(!n)throw new TypeError(`Invalid comparator: ${e}`);this.operator=void 0!==n[1]?n[1]:"","="===this.operator&&(this.operator=""),n[2]?this.semver=new u(n[2],this.options.loose):this.semver=r}toString(){return this.value}test(e){if(c("Comparator.test",e,this.options.loose),this.semver===r||e===r)return!0;if("string"===typeof e)try{e=new u(e,this.options)}catch(t){return!1}return l(e,this.operator,this.semver,this.options)}intersects(e,t){if(!(e instanceof o))throw new TypeError("a Comparator is required");return""===this.operator?""===this.value||new d(e.value,t).test(this.value):""===e.operator?""===e.value||new d(this.value,t).test(e.semver):(t=i(t),(!t.includePrerelease||"<0.0.0-0"!==this.value&&"<0.0.0-0"!==e.value)&&(!(!t.includePrerelease&&(this.value.startsWith("<0.0.0")||e.value.startsWith("<0.0.0")))&&(!(!this.operator.startsWith(">")||!e.operator.startsWith(">"))||(!(!this.operator.startsWith("<")||!e.operator.startsWith("<"))||(!(this.semver.version!==e.semver.version||!this.operator.includes("=")||!e.operator.includes("="))||(!!(l(this.semver,"<",e.semver,t)&&this.operator.startsWith(">")&&e.operator.startsWith("<"))||!!(l(this.semver,">",e.semver,t)&&this.operator.startsWith("<")&&e.operator.startsWith(">"))))))))}}e.exports=o;const i=n(8587),{safeRe:s,t:a}=n(9718),l=n(2111),c=n(7272),u=n(3908),d=n(8311)},3908:function(e,t,n){const r=n(7272),{MAX_LENGTH:o,MAX_SAFE_INTEGER:i}=n(6874),{safeRe:s,safeSrc:a,t:l}=n(9718),c=n(8587),{compareIdentifiers:u}=n(1123);class d{constructor(e,t){if(t=c(t),e instanceof d){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if("string"!==typeof e)throw new TypeError(`Invalid version. Must be a string. Got type "${typeof e}".`);if(e.length>o)throw new TypeError(`version is longer than ${o} characters`);r("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;const n=e.trim().match(t.loose?s[l.LOOSE]:s[l.FULL]);if(!n)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+n[1],this.minor=+n[2],this.patch=+n[3],this.major>i||this.major<0)throw new TypeError("Invalid major version");if(this.minor>i||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>i||this.patch<0)throw new TypeError("Invalid patch version");n[4]?this.prerelease=n[4].split(".").map((e=>{if(/^[0-9]+$/.test(e)){const t=+e;if(t>=0&&t=0)"number"===typeof this.prerelease[r]&&(this.prerelease[r]++,r=-2);if(-1===r){if(t===this.prerelease.join(".")&&!1===n)throw new Error("invalid increment argument: identifier already exists");this.prerelease.push(e)}}if(t){let r=[t,e];!1===n&&(r=[t]),0===u(this.prerelease[0],t)?isNaN(this.prerelease[1])&&(this.prerelease=r):this.prerelease=r}break}default:throw new Error(`invalid increment argument: ${e}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(".")}`),this}}e.exports=d},3927:function(e,t,n){const r=n(909),o=(e,t)=>e.sort(((e,n)=>r(e,n,t)));e.exports=o},3999:function(e,t,n){const r=n(560),o=(e,t,n)=>0!==r(e,t,n);e.exports=o},4055:function(e,t,n){"use strict";var r=n(4576),o=n(34),i=r.document,s=o(i)&&o(i.createElement);e.exports=function(e){return s?i.createElement(e):{}}},4089:function(e,t,n){const r=n(560),o=(e,t,n)=>r(e,t,n)>=0;e.exports=o},4114:function(e,t,n){"use strict";var r=n(6518),o=n(8981),i=n(6198),s=n(4527),a=n(6837),l=n(9039),c=l((function(){return 4294967297!==[].push.call({length:4294967296},1)})),u=function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(e){return e instanceof TypeError}},d=c||!u();r({target:"Array",proto:!0,arity:1,forced:d},{push:function(e){var t=o(this),n=i(t),r=arguments.length;a(n+r);for(var l=0;l{for(var n in t)i.o(t,n)&&!i.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},s={};function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);nR});const d=(m={computed:()=>r.EW,createTextVNode:()=>r.eW,createVNode:()=>r.bF,defineComponent:()=>r.pM,reactive:()=>o.Kh,ref:()=>o.KR,watch:()=>r.wB,watchEffect:()=>r.nT},v={},i.d(v,m),v),f=(0,d.defineComponent)({props:{data:{required:!0,type:String},onClick:Function},render:function(){var e=this.data,t=this.onClick;return(0,d.createVNode)("span",{class:"vjs-tree-brackets",onClick:t},[e])}}),p=(0,d.defineComponent)({emits:["change","update:modelValue"],props:{checked:{type:Boolean,default:!1},isMultiple:Boolean,onChange:Function},setup:function(e,t){var n=t.emit;return{uiType:(0,d.computed)((function(){return e.isMultiple?"checkbox":"radio"})),model:(0,d.computed)({get:function(){return e.checked},set:function(e){return n("update:modelValue",e)}})}},render:function(){var e=this.uiType,t=this.model,n=this.$emit;return(0,d.createVNode)("label",{class:["vjs-check-controller",t?"is-checked":""],onClick:function(e){return e.stopPropagation()}},[(0,d.createVNode)("span",{class:"vjs-check-controller-inner is-".concat(e)},null),(0,d.createVNode)("input",{checked:t,class:"vjs-check-controller-original is-".concat(e),type:e,onChange:function(){return n("change",t)}},null)])}}),h=(0,d.defineComponent)({props:{nodeType:{required:!0,type:String},onClick:Function},render:function(){var e=this.nodeType,t=this.onClick,n="objectStart"===e||"arrayStart"===e;return n||"objectCollapsed"===e||"arrayCollapsed"===e?(0,d.createVNode)("span",{class:"vjs-carets vjs-carets-".concat(n?"open":"close"),onClick:t},[(0,d.createVNode)("svg",{viewBox:"0 0 1024 1024",focusable:"false","data-icon":"caret-down",width:"1em",height:"1em",fill:"currentColor","aria-hidden":"true"},[(0,d.createVNode)("path",{d:"M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"},null)])]):null}});var m,v;function g(e){return g="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},g(e)}function y(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}function b(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"root",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=arguments.length>3?arguments[3]:void 0,o=r||{},i=o.key,s=o.index,a=o.type,l=void 0===a?"content":a,c=o.showComma,u=void 0!==c&&c,d=o.length,f=void 0===d?1:d,p=y(e);if("array"===p){var h=_(e.map((function(e,r,o){return b(e,"".concat(t,"[").concat(r,"]"),n+1,{index:r,showComma:r!==o.length-1,length:f,type:l})})));return[b("[",t,n,{showComma:!1,key:i,length:e.length,type:"arrayStart"})[0]].concat(h,b("]",t,n,{showComma:u,length:e.length,type:"arrayEnd"})[0])}if("object"===p){var m=Object.keys(e),v=_(m.map((function(r,o,i){return b(e[r],/^[a-zA-Z_]\w*$/.test(r)?"".concat(t,".").concat(r):"".concat(t,'["').concat(r,'"]'),n+1,{key:r,showComma:o!==i.length-1,length:f,type:l})})));return[b("{",t,n,{showComma:!1,key:i,index:s,length:m.length,type:"objectStart"})[0]].concat(v,b("}",t,n,{showComma:u,length:m.length,type:"objectEnd"})[0])}return[{content:e,level:n,key:i,index:s,path:t,showComma:u,length:f,type:l}]}function _(e){if("function"==typeof Array.prototype.flat)return e.flat();for(var t=c(e),n=[];t.length;){var r=t.shift();Array.isArray(r)?t.unshift.apply(t,c(r)):n.push(r)}return n}function E(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:new WeakMap;if(null==e)return e;if(e instanceof Date)return new Date(e);if(e instanceof RegExp)return new RegExp(e);if("object"!==g(e))return e;if(t.get(e))return t.get(e);if(Array.isArray(e)){var n=e.map((function(e){return E(e,t)}));return t.set(e,n),n}var r={};for(var o in e)r[o]=E(e[o],t);return t.set(e,r),r}function w(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function S(e){for(var t=1;t=t||o.length>=n,a=null===(i=e.pathCollapsible)||void 0===i?void 0:i.call(e,o);return"objectStart"!==o.type&&"arrayStart"!==o.type||!s&&!a?r:T(T({},r),{},u({},o.path,1))}),{})},a=(0,d.reactive)({translateY:0,visibleData:null,hiddenPaths:s(e.deep,e.collapsedNodeLength)}),f=(0,d.computed)((function(){for(var e=null,t=[],n=i.value.length,r=0;rt.length?t.length-r:s;l<0&&(l=0);var c=l+r;a.translateY=l*e.itemHeight,a.visibleData=t.filter((function(e,t){return t>=l&&t{if(!e)return"";const o=new Date(e);return isNaN(o.getTime())?e:t?n?o.toLocaleString(r,{dateStyle:n,timeStyle:t}):o.toLocaleTimeString(r,{timeStyle:t}):o.toLocaleDateString(r,{dateStyle:n})}},4270:function(e,t,n){"use strict";var r=n(9565),o=n(4901),i=n(34),s=TypeError;e.exports=function(e,t){var n,a;if("string"===t&&o(n=e.toString)&&!i(a=r(n,e)))return a;if(o(n=e.valueOf)&&!i(a=r(n,e)))return a;if("string"!==t&&o(n=e.toString)&&!i(a=r(n,e)))return a;throw new s("Can't convert object to primitive value")}},4277:function(e,t,n){const r=n(909),o=(e,t)=>e.sort(((e,n)=>r(n,e,t)));e.exports=o},4335:function(e,t,n){"use strict";n.d(t,{A:function(){return bn}});var r={};function o(e,t){return function(){return e.apply(t,arguments)}}n.r(r),n.d(r,{hasBrowserEnv:function(){return Fe},hasStandardBrowserEnv:function(){return Ue},hasStandardBrowserWebWorkerEnv:function(){return Be},navigator:function(){return je},origin:function(){return Ve}});const{toString:i}=Object.prototype,{getPrototypeOf:s}=Object,a=(e=>t=>{const n=i.call(t);return e[n]||(e[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),l=e=>(e=e.toLowerCase(),t=>a(t)===e),c=e=>t=>typeof t===e,{isArray:u}=Array,d=c("undefined");function f(e){return null!==e&&!d(e)&&null!==e.constructor&&!d(e.constructor)&&v(e.constructor.isBuffer)&&e.constructor.isBuffer(e)}const p=l("ArrayBuffer");function h(e){let t;return t="undefined"!==typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&p(e.buffer),t}const m=c("string"),v=c("function"),g=c("number"),y=e=>null!==e&&"object"===typeof e,b=e=>!0===e||!1===e,_=e=>{if("object"!==a(e))return!1;const t=s(e);return(null===t||t===Object.prototype||null===Object.getPrototypeOf(t))&&!(Symbol.toStringTag in e)&&!(Symbol.iterator in e)},E=l("Date"),w=l("File"),S=l("Blob"),k=l("FileList"),C=e=>y(e)&&v(e.pipe),O=e=>{let t;return e&&("function"===typeof FormData&&e instanceof FormData||v(e.append)&&("formdata"===(t=a(e))||"object"===t&&v(e.toString)&&"[object FormData]"===e.toString()))},T=l("URLSearchParams"),[R,A,N,L]=["ReadableStream","Request","Response","Headers"].map(l),I=e=>e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function P(e,t,{allOwnKeys:n=!1}={}){if(null===e||"undefined"===typeof e)return;let r,o;if("object"!==typeof e&&(e=[e]),u(e))for(r=0,o=e.length;r0)if(r=n[o],t===r.toLowerCase())return r;return null}const M=(()=>"undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:global)(),D=e=>!d(e)&&e!==M;function $(){const{caseless:e}=D(this)&&this||{},t={},n=(n,r)=>{const o=e&&x(t,r)||r;_(t[o])&&_(n)?t[o]=$(t[o],n):_(n)?t[o]=$({},n):u(n)?t[o]=n.slice():t[o]=n};for(let r=0,o=arguments.length;r(P(t,((t,r)=>{n&&v(t)?e[r]=o(t,n):e[r]=t}),{allOwnKeys:r}),e),j=e=>(65279===e.charCodeAt(0)&&(e=e.slice(1)),e),U=(e,t,n,r)=>{e.prototype=Object.create(t.prototype,r),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),n&&Object.assign(e.prototype,n)},B=(e,t,n,r)=>{let o,i,a;const l={};if(t=t||{},null==e)return t;do{o=Object.getOwnPropertyNames(e),i=o.length;while(i-- >0)a=o[i],r&&!r(a,e,t)||l[a]||(t[a]=e[a],l[a]=!0);e=!1!==n&&s(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},V=(e,t,n)=>{e=String(e),(void 0===n||n>e.length)&&(n=e.length),n-=t.length;const r=e.indexOf(t,n);return-1!==r&&r===n},H=e=>{if(!e)return null;if(u(e))return e;let t=e.length;if(!g(t))return null;const n=new Array(t);while(t-- >0)n[t]=e[t];return n},W=(e=>t=>e&&t instanceof e)("undefined"!==typeof Uint8Array&&s(Uint8Array)),X=(e,t)=>{const n=e&&e[Symbol.iterator],r=n.call(e);let o;while((o=r.next())&&!o.done){const n=o.value;t.call(e,n[0],n[1])}},G=(e,t)=>{let n;const r=[];while(null!==(n=e.exec(t)))r.push(n);return r},K=l("HTMLFormElement"),z=e=>e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(e,t,n){return t.toUpperCase()+n})),q=(({hasOwnProperty:e})=>(t,n)=>e.call(t,n))(Object.prototype),Y=l("RegExp"),Q=(e,t)=>{const n=Object.getOwnPropertyDescriptors(e),r={};P(n,((n,o)=>{let i;!1!==(i=t(n,o,e))&&(r[o]=i||n)})),Object.defineProperties(e,r)},J=e=>{Q(e,((t,n)=>{if(v(e)&&-1!==["arguments","caller","callee"].indexOf(n))return!1;const r=e[n];v(r)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")}))}))},Z=(e,t)=>{const n={},r=e=>{e.forEach((e=>{n[e]=!0}))};return u(e)?r(e):r(String(e).split(t)),n},ee=()=>{},te=(e,t)=>null!=e&&Number.isFinite(e=+e)?e:t,ne="abcdefghijklmnopqrstuvwxyz",re="0123456789",oe={DIGIT:re,ALPHA:ne,ALPHA_DIGIT:ne+ne.toUpperCase()+re},ie=(e=16,t=oe.ALPHA_DIGIT)=>{let n="";const{length:r}=t;while(e--)n+=t[Math.random()*r|0];return n};function se(e){return!!(e&&v(e.append)&&"FormData"===e[Symbol.toStringTag]&&e[Symbol.iterator])}const ae=e=>{const t=new Array(10),n=(e,r)=>{if(y(e)){if(t.indexOf(e)>=0)return;if(!("toJSON"in e)){t[r]=e;const o=u(e)?[]:{};return P(e,((e,t)=>{const i=n(e,r+1);!d(i)&&(o[t]=i)})),t[r]=void 0,o}}return e};return n(e,0)},le=l("AsyncFunction"),ce=e=>e&&(y(e)||v(e))&&v(e.then)&&v(e.catch),ue=((e,t)=>e?setImmediate:t?((e,t)=>(M.addEventListener("message",(({source:n,data:r})=>{n===M&&r===e&&t.length&&t.shift()()}),!1),n=>{t.push(n),M.postMessage(e,"*")}))(`axios@${Math.random()}`,[]):e=>setTimeout(e))("function"===typeof setImmediate,v(M.postMessage)),de="undefined"!==typeof queueMicrotask?queueMicrotask.bind(M):"undefined"!==typeof process&&process.nextTick||ue;var fe={isArray:u,isArrayBuffer:p,isBuffer:f,isFormData:O,isArrayBufferView:h,isString:m,isNumber:g,isBoolean:b,isObject:y,isPlainObject:_,isReadableStream:R,isRequest:A,isResponse:N,isHeaders:L,isUndefined:d,isDate:E,isFile:w,isBlob:S,isRegExp:Y,isFunction:v,isStream:C,isURLSearchParams:T,isTypedArray:W,isFileList:k,forEach:P,merge:$,extend:F,trim:I,stripBOM:j,inherits:U,toFlatObject:B,kindOf:a,kindOfTest:l,endsWith:V,toArray:H,forEachEntry:X,matchAll:G,isHTMLForm:K,hasOwnProperty:q,hasOwnProp:q,reduceDescriptors:Q,freezeMethods:J,toObjectSet:Z,toCamelCase:z,noop:ee,toFiniteNumber:te,findKey:x,global:M,isContextDefined:D,ALPHABET:oe,generateString:ie,isSpecCompliantForm:se,toJSONObject:ae,isAsyncFn:le,isThenable:ce,setImmediate:ue,asap:de};function pe(e,t,n,r,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name="AxiosError",t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),o&&(this.response=o,this.status=o.status?o.status:null)}fe.inherits(pe,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:fe.toJSONObject(this.config),code:this.code,status:this.status}}});const he=pe.prototype,me={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((e=>{me[e]={value:e}})),Object.defineProperties(pe,me),Object.defineProperty(he,"isAxiosError",{value:!0}),pe.from=(e,t,n,r,o,i)=>{const s=Object.create(he);return fe.toFlatObject(e,s,(function(e){return e!==Error.prototype}),(e=>"isAxiosError"!==e)),pe.call(s,e.message,t,n,r,o),s.cause=e,s.name=e.name,i&&Object.assign(s,i),s};var ve=pe,ge=null;function ye(e){return fe.isPlainObject(e)||fe.isArray(e)}function be(e){return fe.endsWith(e,"[]")?e.slice(0,-2):e}function _e(e,t,n){return e?e.concat(t).map((function(e,t){return e=be(e),!n&&t?"["+e+"]":e})).join(n?".":""):t}function Ee(e){return fe.isArray(e)&&!e.some(ye)}const we=fe.toFlatObject(fe,{},null,(function(e){return/^is[A-Z]/.test(e)}));function Se(e,t,n){if(!fe.isObject(e))throw new TypeError("target must be an object");t=t||new(ge||FormData),n=fe.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!fe.isUndefined(t[e])}));const r=n.metaTokens,o=n.visitor||u,i=n.dots,s=n.indexes,a=n.Blob||"undefined"!==typeof Blob&&Blob,l=a&&fe.isSpecCompliantForm(t);if(!fe.isFunction(o))throw new TypeError("visitor must be a function");function c(e){if(null===e)return"";if(fe.isDate(e))return e.toISOString();if(!l&&fe.isBlob(e))throw new ve("Blob is not supported. Use a Buffer instead.");return fe.isArrayBuffer(e)||fe.isTypedArray(e)?l&&"function"===typeof Blob?new Blob([e]):Buffer.from(e):e}function u(e,n,o){let a=e;if(e&&!o&&"object"===typeof e)if(fe.endsWith(n,"{}"))n=r?n:n.slice(0,-2),e=JSON.stringify(e);else if(fe.isArray(e)&&Ee(e)||(fe.isFileList(e)||fe.endsWith(n,"[]"))&&(a=fe.toArray(e)))return n=be(n),a.forEach((function(e,r){!fe.isUndefined(e)&&null!==e&&t.append(!0===s?_e([n],r,i):null===s?n:n+"[]",c(e))})),!1;return!!ye(e)||(t.append(_e(o,n,i),c(e)),!1)}const d=[],f=Object.assign(we,{defaultVisitor:u,convertValue:c,isVisitable:ye});function p(e,n){if(!fe.isUndefined(e)){if(-1!==d.indexOf(e))throw Error("Circular reference detected in "+n.join("."));d.push(e),fe.forEach(e,(function(e,r){const i=!(fe.isUndefined(e)||null===e)&&o.call(t,e,fe.isString(r)?r.trim():r,n,f);!0===i&&p(e,n?n.concat(r):[r])})),d.pop()}}if(!fe.isObject(e))throw new TypeError("data must be an object");return p(e),t}var ke=Se;function Ce(e){const t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function Oe(e,t){this._pairs=[],e&&ke(e,this,t)}const Te=Oe.prototype;Te.append=function(e,t){this._pairs.push([e,t])},Te.toString=function(e){const t=e?function(t){return e.call(this,t,Ce)}:Ce;return this._pairs.map((function(e){return t(e[0])+"="+t(e[1])}),"").join("&")};var Re=Oe;function Ae(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function Ne(e,t,n){if(!t)return e;const r=n&&n.encode||Ae;fe.isFunction(n)&&(n={serialize:n});const o=n&&n.serialize;let i;if(i=o?o(t,n):fe.isURLSearchParams(t)?t.toString():new Re(t,n).toString(r),i){const t=e.indexOf("#");-1!==t&&(e=e.slice(0,t)),e+=(-1===e.indexOf("?")?"?":"&")+i}return e}class Le{constructor(){this.handlers=[]}use(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){fe.forEach(this.handlers,(function(t){null!==t&&e(t)}))}}var Ie=Le,Pe={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},xe="undefined"!==typeof URLSearchParams?URLSearchParams:Re,Me="undefined"!==typeof FormData?FormData:null,De="undefined"!==typeof Blob?Blob:null,$e={isBrowser:!0,classes:{URLSearchParams:xe,FormData:Me,Blob:De},protocols:["http","https","file","blob","url","data"]};const Fe="undefined"!==typeof window&&"undefined"!==typeof document,je="object"===typeof navigator&&navigator||void 0,Ue=Fe&&(!je||["ReactNative","NativeScript","NS"].indexOf(je.product)<0),Be=(()=>"undefined"!==typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"===typeof self.importScripts)(),Ve=Fe&&window.location.href||"http://localhost";var He={...r,...$e};function We(e,t){return ke(e,new He.classes.URLSearchParams,Object.assign({visitor:function(e,t,n,r){return He.isNode&&fe.isBuffer(e)?(this.append(t,e.toString("base64")),!1):r.defaultVisitor.apply(this,arguments)}},t))}function Xe(e){return fe.matchAll(/\w+|\[(\w*)]/g,e).map((e=>"[]"===e[0]?"":e[1]||e[0]))}function Ge(e){const t={},n=Object.keys(e);let r;const o=n.length;let i;for(r=0;r=e.length;if(i=!i&&fe.isArray(r)?r.length:i,a)return fe.hasOwnProp(r,i)?r[i]=[r[i],n]:r[i]=n,!s;r[i]&&fe.isObject(r[i])||(r[i]=[]);const l=t(e,n,r[i],o);return l&&fe.isArray(r[i])&&(r[i]=Ge(r[i])),!s}if(fe.isFormData(e)&&fe.isFunction(e.entries)){const n={};return fe.forEachEntry(e,((e,r)=>{t(Xe(e),r,n,0)})),n}return null}var ze=Ke;function qe(e,t,n){if(fe.isString(e))try{return(t||JSON.parse)(e),fe.trim(e)}catch(r){if("SyntaxError"!==r.name)throw r}return(n||JSON.stringify)(e)}const Ye={transitional:Pe,adapter:["xhr","http","fetch"],transformRequest:[function(e,t){const n=t.getContentType()||"",r=n.indexOf("application/json")>-1,o=fe.isObject(e);o&&fe.isHTMLForm(e)&&(e=new FormData(e));const i=fe.isFormData(e);if(i)return r?JSON.stringify(ze(e)):e;if(fe.isArrayBuffer(e)||fe.isBuffer(e)||fe.isStream(e)||fe.isFile(e)||fe.isBlob(e)||fe.isReadableStream(e))return e;if(fe.isArrayBufferView(e))return e.buffer;if(fe.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let s;if(o){if(n.indexOf("application/x-www-form-urlencoded")>-1)return We(e,this.formSerializer).toString();if((s=fe.isFileList(e))||n.indexOf("multipart/form-data")>-1){const t=this.env&&this.env.FormData;return ke(s?{"files[]":e}:e,t&&new t,this.formSerializer)}}return o||r?(t.setContentType("application/json",!1),qe(e)):e}],transformResponse:[function(e){const t=this.transitional||Ye.transitional,n=t&&t.forcedJSONParsing,r="json"===this.responseType;if(fe.isResponse(e)||fe.isReadableStream(e))return e;if(e&&fe.isString(e)&&(n&&!this.responseType||r)){const n=t&&t.silentJSONParsing,i=!n&&r;try{return JSON.parse(e)}catch(o){if(i){if("SyntaxError"===o.name)throw ve.from(o,ve.ERR_BAD_RESPONSE,this,null,this.response);throw o}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:He.classes.FormData,Blob:He.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};fe.forEach(["delete","get","head","post","put","patch"],(e=>{Ye.headers[e]={}}));var Qe=Ye;const Je=fe.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]);var Ze=e=>{const t={};let n,r,o;return e&&e.split("\n").forEach((function(e){o=e.indexOf(":"),n=e.substring(0,o).trim().toLowerCase(),r=e.substring(o+1).trim(),!n||t[n]&&Je[n]||("set-cookie"===n?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)})),t};const et=Symbol("internals");function tt(e){return e&&String(e).trim().toLowerCase()}function nt(e){return!1===e||null==e?e:fe.isArray(e)?e.map(nt):String(e)}function rt(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;while(r=n.exec(e))t[r[1]]=r[2];return t}const ot=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function it(e,t,n,r,o){return fe.isFunction(r)?r.call(this,t,n):(o&&(t=n),fe.isString(t)?fe.isString(r)?-1!==t.indexOf(r):fe.isRegExp(r)?r.test(t):void 0:void 0)}function st(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,((e,t,n)=>t.toUpperCase()+n))}function at(e,t){const n=fe.toCamelCase(" "+t);["get","set","has"].forEach((r=>{Object.defineProperty(e,r+n,{value:function(e,n,o){return this[r].call(this,t,e,n,o)},configurable:!0})}))}class lt{constructor(e){e&&this.set(e)}set(e,t,n){const r=this;function o(e,t,n){const o=tt(t);if(!o)throw new Error("header name must be a non-empty string");const i=fe.findKey(r,o);(!i||void 0===r[i]||!0===n||void 0===n&&!1!==r[i])&&(r[i||t]=nt(e))}const i=(e,t)=>fe.forEach(e,((e,n)=>o(e,n,t)));if(fe.isPlainObject(e)||e instanceof this.constructor)i(e,t);else if(fe.isString(e)&&(e=e.trim())&&!ot(e))i(Ze(e),t);else if(fe.isHeaders(e))for(const[s,a]of e.entries())o(a,s,n);else null!=e&&o(t,e,n);return this}get(e,t){if(e=tt(e),e){const n=fe.findKey(this,e);if(n){const e=this[n];if(!t)return e;if(!0===t)return rt(e);if(fe.isFunction(t))return t.call(this,e,n);if(fe.isRegExp(t))return t.exec(e);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,t){if(e=tt(e),e){const n=fe.findKey(this,e);return!(!n||void 0===this[n]||t&&!it(this,this[n],n,t))}return!1}delete(e,t){const n=this;let r=!1;function o(e){if(e=tt(e),e){const o=fe.findKey(n,e);!o||t&&!it(n,n[o],o,t)||(delete n[o],r=!0)}}return fe.isArray(e)?e.forEach(o):o(e),r}clear(e){const t=Object.keys(this);let n=t.length,r=!1;while(n--){const o=t[n];e&&!it(this,this[o],o,e,!0)||(delete this[o],r=!0)}return r}normalize(e){const t=this,n={};return fe.forEach(this,((r,o)=>{const i=fe.findKey(n,o);if(i)return t[i]=nt(r),void delete t[o];const s=e?st(o):String(o).trim();s!==o&&delete t[o],t[s]=nt(r),n[s]=!0})),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const t=Object.create(null);return fe.forEach(this,((n,r)=>{null!=n&&!1!==n&&(t[r]=e&&fe.isArray(n)?n.join(", "):n)})),t}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map((([e,t])=>e+": "+t)).join("\n")}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(e){return e instanceof this?e:new this(e)}static concat(e,...t){const n=new this(e);return t.forEach((e=>n.set(e))),n}static accessor(e){const t=this[et]=this[et]={accessors:{}},n=t.accessors,r=this.prototype;function o(e){const t=tt(e);n[t]||(at(r,e),n[t]=!0)}return fe.isArray(e)?e.forEach(o):o(e),this}}lt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),fe.reduceDescriptors(lt.prototype,(({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(e){this[n]=e}}})),fe.freezeMethods(lt);var ct=lt;function ut(e,t){const n=this||Qe,r=t||n,o=ct.from(r.headers);let i=r.data;return fe.forEach(e,(function(e){i=e.call(n,i,o.normalize(),t?t.status:void 0)})),o.normalize(),i}function dt(e){return!(!e||!e.__CANCEL__)}function ft(e,t,n){ve.call(this,null==e?"canceled":e,ve.ERR_CANCELED,t,n),this.name="CanceledError"}fe.inherits(ft,ve,{__CANCEL__:!0});var pt=ft;function ht(e,t,n){const r=n.config.validateStatus;n.status&&r&&!r(n.status)?t(new ve("Request failed with status code "+n.status,[ve.ERR_BAD_REQUEST,ve.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n)):e(n)}function mt(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function vt(e,t){e=e||10;const n=new Array(e),r=new Array(e);let o,i=0,s=0;return t=void 0!==t?t:1e3,function(a){const l=Date.now(),c=r[s];o||(o=l),n[i]=a,r[i]=l;let u=s,d=0;while(u!==i)d+=n[u++],u%=e;if(i=(i+1)%e,i===s&&(s=(s+1)%e),l-o{o=i,n=null,r&&(clearTimeout(r),r=null),e.apply(null,t)},a=(...e)=>{const t=Date.now(),a=t-o;a>=i?s(e,t):(n=e,r||(r=setTimeout((()=>{r=null,s(n)}),i-a)))},l=()=>n&&s(n);return[a,l]}var bt=yt;const _t=(e,t,n=3)=>{let r=0;const o=gt(50,250);return bt((n=>{const i=n.loaded,s=n.lengthComputable?n.total:void 0,a=i-r,l=o(a),c=i<=s;r=i;const u={loaded:i,total:s,progress:s?i/s:void 0,bytes:a,rate:l||void 0,estimated:l&&s&&c?(s-i)/l:void 0,event:n,lengthComputable:null!=s,[t?"download":"upload"]:!0};e(u)}),n)},Et=(e,t)=>{const n=null!=e;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},wt=e=>(...t)=>fe.asap((()=>e(...t)));var St=He.hasStandardBrowserEnv?((e,t)=>n=>(n=new URL(n,He.origin),e.protocol===n.protocol&&e.host===n.host&&(t||e.port===n.port)))(new URL(He.origin),He.navigator&&/(msie|trident)/i.test(He.navigator.userAgent)):()=>!0,kt=He.hasStandardBrowserEnv?{write(e,t,n,r,o,i){const s=[e+"="+encodeURIComponent(t)];fe.isNumber(n)&&s.push("expires="+new Date(n).toGMTString()),fe.isString(r)&&s.push("path="+r),fe.isString(o)&&s.push("domain="+o),!0===i&&s.push("secure"),document.cookie=s.join("; ")},read(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove(e){this.write(e,"",Date.now()-864e5)}}:{write(){},read(){return null},remove(){}};function Ct(e){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function Ot(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function Tt(e,t){return e&&!Ct(t)?Ot(e,t):t}const Rt=e=>e instanceof ct?{...e}:e;function At(e,t){t=t||{};const n={};function r(e,t,n,r){return fe.isPlainObject(e)&&fe.isPlainObject(t)?fe.merge.call({caseless:r},e,t):fe.isPlainObject(t)?fe.merge({},t):fe.isArray(t)?t.slice():t}function o(e,t,n,o){return fe.isUndefined(t)?fe.isUndefined(e)?void 0:r(void 0,e,n,o):r(e,t,n,o)}function i(e,t){if(!fe.isUndefined(t))return r(void 0,t)}function s(e,t){return fe.isUndefined(t)?fe.isUndefined(e)?void 0:r(void 0,e):r(void 0,t)}function a(n,o,i){return i in t?r(n,o):i in e?r(void 0,n):void 0}const l={url:i,method:i,data:i,baseURL:s,transformRequest:s,transformResponse:s,paramsSerializer:s,timeout:s,timeoutMessage:s,withCredentials:s,withXSRFToken:s,adapter:s,responseType:s,xsrfCookieName:s,xsrfHeaderName:s,onUploadProgress:s,onDownloadProgress:s,decompress:s,maxContentLength:s,maxBodyLength:s,beforeRedirect:s,transport:s,httpAgent:s,httpsAgent:s,cancelToken:s,socketPath:s,responseEncoding:s,validateStatus:a,headers:(e,t,n)=>o(Rt(e),Rt(t),n,!0)};return fe.forEach(Object.keys(Object.assign({},e,t)),(function(r){const i=l[r]||o,s=i(e[r],t[r],r);fe.isUndefined(s)&&i!==a||(n[r]=s)})),n}var Nt=e=>{const t=At({},e);let n,{data:r,withXSRFToken:o,xsrfHeaderName:i,xsrfCookieName:s,headers:a,auth:l}=t;if(t.headers=a=ct.from(a),t.url=Ne(Tt(t.baseURL,t.url),e.params,e.paramsSerializer),l&&a.set("Authorization","Basic "+btoa((l.username||"")+":"+(l.password?unescape(encodeURIComponent(l.password)):""))),fe.isFormData(r))if(He.hasStandardBrowserEnv||He.hasStandardBrowserWebWorkerEnv)a.setContentType(void 0);else if(!1!==(n=a.getContentType())){const[e,...t]=n?n.split(";").map((e=>e.trim())).filter(Boolean):[];a.setContentType([e||"multipart/form-data",...t].join("; "))}if(He.hasStandardBrowserEnv&&(o&&fe.isFunction(o)&&(o=o(t)),o||!1!==o&&St(t.url))){const e=i&&s&&kt.read(s);e&&a.set(i,e)}return t};const Lt="undefined"!==typeof XMLHttpRequest;var It=Lt&&function(e){return new Promise((function(t,n){const r=Nt(e);let o=r.data;const i=ct.from(r.headers).normalize();let s,a,l,c,u,{responseType:d,onUploadProgress:f,onDownloadProgress:p}=r;function h(){c&&c(),u&&u(),r.cancelToken&&r.cancelToken.unsubscribe(s),r.signal&&r.signal.removeEventListener("abort",s)}let m=new XMLHttpRequest;function v(){if(!m)return;const r=ct.from("getAllResponseHeaders"in m&&m.getAllResponseHeaders()),o=d&&"text"!==d&&"json"!==d?m.response:m.responseText,i={data:o,status:m.status,statusText:m.statusText,headers:r,config:e,request:m};ht((function(e){t(e),h()}),(function(e){n(e),h()}),i),m=null}m.open(r.method.toUpperCase(),r.url,!0),m.timeout=r.timeout,"onloadend"in m?m.onloadend=v:m.onreadystatechange=function(){m&&4===m.readyState&&(0!==m.status||m.responseURL&&0===m.responseURL.indexOf("file:"))&&setTimeout(v)},m.onabort=function(){m&&(n(new ve("Request aborted",ve.ECONNABORTED,e,m)),m=null)},m.onerror=function(){n(new ve("Network Error",ve.ERR_NETWORK,e,m)),m=null},m.ontimeout=function(){let t=r.timeout?"timeout of "+r.timeout+"ms exceeded":"timeout exceeded";const o=r.transitional||Pe;r.timeoutErrorMessage&&(t=r.timeoutErrorMessage),n(new ve(t,o.clarifyTimeoutError?ve.ETIMEDOUT:ve.ECONNABORTED,e,m)),m=null},void 0===o&&i.setContentType(null),"setRequestHeader"in m&&fe.forEach(i.toJSON(),(function(e,t){m.setRequestHeader(t,e)})),fe.isUndefined(r.withCredentials)||(m.withCredentials=!!r.withCredentials),d&&"json"!==d&&(m.responseType=r.responseType),p&&([l,u]=_t(p,!0),m.addEventListener("progress",l)),f&&m.upload&&([a,c]=_t(f),m.upload.addEventListener("progress",a),m.upload.addEventListener("loadend",c)),(r.cancelToken||r.signal)&&(s=t=>{m&&(n(!t||t.type?new pt(null,e,m):t),m.abort(),m=null)},r.cancelToken&&r.cancelToken.subscribe(s),r.signal&&(r.signal.aborted?s():r.signal.addEventListener("abort",s)));const g=mt(r.url);g&&-1===He.protocols.indexOf(g)?n(new ve("Unsupported protocol "+g+":",ve.ERR_BAD_REQUEST,e)):m.send(o||null)}))};const Pt=(e,t)=>{const{length:n}=e=e?e.filter(Boolean):[];if(t||n){let n,r=new AbortController;const o=function(e){if(!n){n=!0,s();const t=e instanceof Error?e:this.reason;r.abort(t instanceof ve?t:new pt(t instanceof Error?t.message:t))}};let i=t&&setTimeout((()=>{i=null,o(new ve(`timeout ${t} of ms exceeded`,ve.ETIMEDOUT))}),t);const s=()=>{e&&(i&&clearTimeout(i),i=null,e.forEach((e=>{e.unsubscribe?e.unsubscribe(o):e.removeEventListener("abort",o)})),e=null)};e.forEach((e=>e.addEventListener("abort",o)));const{signal:a}=r;return a.unsubscribe=()=>fe.asap(s),a}};var xt=Pt;const Mt=function*(e,t){let n=e.byteLength;if(!t||n{const o=Dt(e,t);let i,s=0,a=e=>{i||(i=!0,r&&r(e))};return new ReadableStream({async pull(e){try{const{done:t,value:r}=await o.next();if(t)return a(),void e.close();let i=r.byteLength;if(n){let e=s+=i;n(e)}e.enqueue(new Uint8Array(r))}catch(t){throw a(t),t}},cancel(e){return a(e),o.return()}},{highWaterMark:2})},jt="function"===typeof fetch&&"function"===typeof Request&&"function"===typeof Response,Ut=jt&&"function"===typeof ReadableStream,Bt=jt&&("function"===typeof TextEncoder?(e=>t=>e.encode(t))(new TextEncoder):async e=>new Uint8Array(await new Response(e).arrayBuffer())),Vt=(e,...t)=>{try{return!!e(...t)}catch(n){return!1}},Ht=Ut&&Vt((()=>{let e=!1;const t=new Request(He.origin,{body:new ReadableStream,method:"POST",get duplex(){return e=!0,"half"}}).headers.has("Content-Type");return e&&!t})),Wt=65536,Xt=Ut&&Vt((()=>fe.isReadableStream(new Response("").body))),Gt={stream:Xt&&(e=>e.body)};jt&&(e=>{["text","arrayBuffer","blob","formData","stream"].forEach((t=>{!Gt[t]&&(Gt[t]=fe.isFunction(e[t])?e=>e[t]():(e,n)=>{throw new ve(`Response type '${t}' is not supported`,ve.ERR_NOT_SUPPORT,n)})}))})(new Response);const Kt=async e=>{if(null==e)return 0;if(fe.isBlob(e))return e.size;if(fe.isSpecCompliantForm(e)){const t=new Request(He.origin,{method:"POST",body:e});return(await t.arrayBuffer()).byteLength}return fe.isArrayBufferView(e)||fe.isArrayBuffer(e)?e.byteLength:(fe.isURLSearchParams(e)&&(e+=""),fe.isString(e)?(await Bt(e)).byteLength:void 0)},zt=async(e,t)=>{const n=fe.toFiniteNumber(e.getContentLength());return null==n?Kt(t):n};var qt=jt&&(async e=>{let{url:t,method:n,data:r,signal:o,cancelToken:i,timeout:s,onDownloadProgress:a,onUploadProgress:l,responseType:c,headers:u,withCredentials:d="same-origin",fetchOptions:f}=Nt(e);c=c?(c+"").toLowerCase():"text";let p,h=xt([o,i&&i.toAbortSignal()],s);const m=h&&h.unsubscribe&&(()=>{h.unsubscribe()});let v;try{if(l&&Ht&&"get"!==n&&"head"!==n&&0!==(v=await zt(u,r))){let e,n=new Request(t,{method:"POST",body:r,duplex:"half"});if(fe.isFormData(r)&&(e=n.headers.get("content-type"))&&u.setContentType(e),n.body){const[e,t]=Et(v,_t(wt(l)));r=Ft(n.body,Wt,e,t)}}fe.isString(d)||(d=d?"include":"omit");const o="credentials"in Request.prototype;p=new Request(t,{...f,signal:h,method:n.toUpperCase(),headers:u.normalize().toJSON(),body:r,duplex:"half",credentials:o?d:void 0});let i=await fetch(p);const s=Xt&&("stream"===c||"response"===c);if(Xt&&(a||s&&m)){const e={};["status","statusText","headers"].forEach((t=>{e[t]=i[t]}));const t=fe.toFiniteNumber(i.headers.get("content-length")),[n,r]=a&&Et(t,_t(wt(a),!0))||[];i=new Response(Ft(i.body,Wt,n,(()=>{r&&r(),m&&m()})),e)}c=c||"text";let g=await Gt[fe.findKey(Gt,c)||"text"](i,e);return!s&&m&&m(),await new Promise(((t,n)=>{ht(t,n,{data:g,headers:ct.from(i.headers),status:i.status,statusText:i.statusText,config:e,request:p})}))}catch(g){if(m&&m(),g&&"TypeError"===g.name&&/fetch/i.test(g.message))throw Object.assign(new ve("Network Error",ve.ERR_NETWORK,e,p),{cause:g.cause||g});throw ve.from(g,g&&g.code,e,p)}});const Yt={http:ge,xhr:It,fetch:qt};fe.forEach(Yt,((e,t)=>{if(e){try{Object.defineProperty(e,"name",{value:t})}catch(n){}Object.defineProperty(e,"adapterName",{value:t})}}));const Qt=e=>`- ${e}`,Jt=e=>fe.isFunction(e)||null===e||!1===e;var Zt={getAdapter:e=>{e=fe.isArray(e)?e:[e];const{length:t}=e;let n,r;const o={};for(let i=0;i`adapter ${e} `+(!1===t?"is not supported by the environment":"is not available in the build")));let n=t?e.length>1?"since :\n"+e.map(Qt).join("\n"):" "+Qt(e[0]):"as no adapter specified";throw new ve("There is no suitable adapter to dispatch the request "+n,"ERR_NOT_SUPPORT")}return r},adapters:Yt};function en(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new pt(null,e)}function tn(e){en(e),e.headers=ct.from(e.headers),e.data=ut.call(e,e.transformRequest),-1!==["post","put","patch"].indexOf(e.method)&&e.headers.setContentType("application/x-www-form-urlencoded",!1);const t=Zt.getAdapter(e.adapter||Qe.adapter);return t(e).then((function(t){return en(e),t.data=ut.call(e,e.transformResponse,t),t.headers=ct.from(t.headers),t}),(function(t){return dt(t)||(en(e),t&&t.response&&(t.response.data=ut.call(e,e.transformResponse,t.response),t.response.headers=ct.from(t.response.headers))),Promise.reject(t)}))}const nn="1.7.9",rn={};["object","boolean","number","function","string","symbol"].forEach(((e,t)=>{rn[e]=function(n){return typeof n===e||"a"+(t<1?"n ":" ")+e}}));const on={};function sn(e,t,n){if("object"!==typeof e)throw new ve("options must be an object",ve.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let o=r.length;while(o-- >0){const i=r[o],s=t[i];if(s){const t=e[i],n=void 0===t||s(t,i,e);if(!0!==n)throw new ve("option "+i+" must be "+n,ve.ERR_BAD_OPTION_VALUE)}else if(!0!==n)throw new ve("Unknown option "+i,ve.ERR_BAD_OPTION)}}rn.transitional=function(e,t,n){function r(e,t){return"[Axios v"+nn+"] Transitional option '"+e+"'"+t+(n?". "+n:"")}return(n,o,i)=>{if(!1===e)throw new ve(r(o," has been removed"+(t?" in "+t:"")),ve.ERR_DEPRECATED);return t&&!on[o]&&(on[o]=!0,console.warn(r(o," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(n,o,i)}},rn.spelling=function(e){return(t,n)=>(console.warn(`${n} is likely a misspelling of ${e}`),!0)};var an={assertOptions:sn,validators:rn};const ln=an.validators;class cn{constructor(e){this.defaults=e,this.interceptors={request:new Ie,response:new Ie}}async request(e,t){try{return await this._request(e,t)}catch(n){if(n instanceof Error){let e={};Error.captureStackTrace?Error.captureStackTrace(e):e=new Error;const t=e.stack?e.stack.replace(/^.+\n/,""):"";try{n.stack?t&&!String(n.stack).endsWith(t.replace(/^.+\n.+\n/,""))&&(n.stack+="\n"+t):n.stack=t}catch(r){}}throw n}}_request(e,t){"string"===typeof e?(t=t||{},t.url=e):t=e||{},t=At(this.defaults,t);const{transitional:n,paramsSerializer:r,headers:o}=t;void 0!==n&&an.assertOptions(n,{silentJSONParsing:ln.transitional(ln.boolean),forcedJSONParsing:ln.transitional(ln.boolean),clarifyTimeoutError:ln.transitional(ln.boolean)},!1),null!=r&&(fe.isFunction(r)?t.paramsSerializer={serialize:r}:an.assertOptions(r,{encode:ln.function,serialize:ln.function},!0)),an.assertOptions(t,{baseUrl:ln.spelling("baseURL"),withXsrfToken:ln.spelling("withXSRFToken")},!0),t.method=(t.method||this.defaults.method||"get").toLowerCase();let i=o&&fe.merge(o.common,o[t.method]);o&&fe.forEach(["delete","get","head","post","put","patch","common"],(e=>{delete o[e]})),t.headers=ct.concat(i,o);const s=[];let a=!0;this.interceptors.request.forEach((function(e){"function"===typeof e.runWhen&&!1===e.runWhen(t)||(a=a&&e.synchronous,s.unshift(e.fulfilled,e.rejected))}));const l=[];let c;this.interceptors.response.forEach((function(e){l.push(e.fulfilled,e.rejected)}));let u,d=0;if(!a){const e=[tn.bind(this),void 0];e.unshift.apply(e,s),e.push.apply(e,l),u=e.length,c=Promise.resolve(t);while(d{if(!n._listeners)return;let t=n._listeners.length;while(t-- >0)n._listeners[t](e);n._listeners=null})),this.promise.then=e=>{let t;const r=new Promise((e=>{n.subscribe(e),t=e})).then(e);return r.cancel=function(){n.unsubscribe(t)},r},e((function(e,r,o){n.reason||(n.reason=new pt(e,r,o),t(n.reason))}))}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}toAbortSignal(){const e=new AbortController,t=t=>{e.abort(t)};return this.subscribe(t),e.signal.unsubscribe=()=>this.unsubscribe(t),e.signal}static source(){let e;const t=new dn((function(t){e=t}));return{token:t,cancel:e}}}var fn=dn;function pn(e){return function(t){return e.apply(null,t)}}function hn(e){return fe.isObject(e)&&!0===e.isAxiosError}const mn={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(mn).forEach((([e,t])=>{mn[t]=e}));var vn=mn;function gn(e){const t=new un(e),n=o(un.prototype.request,t);return fe.extend(n,un.prototype,t,{allOwnKeys:!0}),fe.extend(n,t,null,{allOwnKeys:!0}),n.create=function(t){return gn(At(e,t))},n}const yn=gn(Qe);yn.Axios=un,yn.CanceledError=pt,yn.CancelToken=fn,yn.isCancel=dt,yn.VERSION=nn,yn.toFormData=ke,yn.AxiosError=ve,yn.Cancel=yn.CanceledError,yn.all=function(e){return Promise.all(e)},yn.spread=pn,yn.isAxiosError=hn,yn.mergeConfig=At,yn.AxiosHeaders=ct,yn.formToJSON=e=>ze(fe.isHTMLForm(e)?new FormData(e):e),yn.getAdapter=Zt.getAdapter,yn.HttpStatusCode=vn,yn.default=yn;var bn=yn},4376:function(e,t,n){"use strict";var r=n(2195);e.exports=Array.isArray||function(e){return"Array"===r(e)}},4405:function(e,t,n){"use strict";n.d(t,{A:function(){return p}});var r=Object.defineProperty,o=(e,t,n)=>t in e?r(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,i=(e,t,n)=>(o(e,"symbol"!=typeof t?t+"":t,n),n);class s{constructor(){i(this,"seed",0),i(this,"data",new Map)}id(){return Date.now().toString(26)+this.seed++}add(e,t=this.id()){return this.data.set(t,e),t}get(e){return this.data.get(e)}delete(e){this.delete(e)}}const a="Failed to copy value to clipboard. Unknown type.",l={asString(e){if(null==e)return console.warn("Clipboard input is empty"),"";if("string"!=typeof e)try{return JSON.stringify(e)}catch(t){return console.warn(a,t),""}return e}},c="position:fixed; pointer-events:none; z-index:-9999; opacity:0;",u={createTextarea(e){const t=document.createElement("textarea");return t.addEventListener("focusin",(e=>{e.stopPropagation()})),t.value=e,t.setAttribute("readonly",""),t.style.cssText=c,t}},d={async requestClipboardPermission(){return navigator.permissions.query({name:"clipboard-write"})},async writeClipboard(e){return"granted"===(await d.requestClipboardPermission()).state&&(await navigator.clipboard.writeText(e),!0)},writeClipboardExecCommand(e){const t=u.createTextarea(e);if(document.body.appendChild(t),navigator.userAgent.match(/ipad|ipod|iphone/i)){t.contentEditable="true",t.readOnly=!0;const e=document.createRange();e.selectNodeContents(t);const n=window.getSelection();n&&(n.removeAllRanges(),n.addRange(e),t.setSelectionRange(0,999999))}else t.select();const n=document.execCommand("copy");return document.body.removeChild(t),n},async copy(e){const t="function"==typeof e?e():e,n=l.asString(t);if(d.writeClipboardExecCommand(n))return!0;await d.writeClipboard(n)}},f=new s,p={install(e){const t="3"===e.version[0]?e.config.globalProperties:e.prototype;t.$clipboard=d.copy,e.directive("clipboard",{beforeMount(e,t){const n=t.arg,r=t.value,o="function"==typeof r;if("error"===n&&o)return void(e.dataset.clipboardError=f.add(r));if("error"===n&&o)return void(e.dataset.clipboardSuccess=f.add(r));const i=async t=>{var n;const o=await d.copy(r)?e.dataset.clipboardSuccess:e.dataset.clipboardError;null==(n=f.get(o))||n({value:r,event:t})};e.dataset.clipboardClick=f.add(i),e.addEventListener("click",i)},unmounted(e){const{clipboardSuccessHandler:t,clipboardErrorHandler:n,clipboardClickHandler:r}=e.dataset;if(t&&f.delete(t),n&&f.delete(n),r){const t=f.get(r);t&&(e.removeEventListener("click",t),f.delete(r))}},get bind(){return this.beforeMount},get unbind(){return this.unmounted}})}}},4493:function(e,t,n){const r=n(3908),o=(e,t)=>new r(e,t).patch;e.exports=o},4495:function(e,t,n){"use strict";var r=n(9519),o=n(9039),i=n(4576),s=i.String;e.exports=!!Object.getOwnPropertySymbols&&!o((function(){var e=Symbol("symbol detection");return!s(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},4527:function(e,t,n){"use strict";var r=n(3724),o=n(4376),i=TypeError,s=Object.getOwnPropertyDescriptor,a=r&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(e){return e instanceof TypeError}}();e.exports=a?function(e,t){if(o(e)&&!s(e,"length").writable)throw new i("Cannot set read only .length");return e.length=t}:function(e,t){return e.length=t}},4576:function(e,t,n){"use strict";var r=function(e){return e&&e.Math===Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||r("object"==typeof this&&this)||function(){return this}()||Function("return this")()},4603:function(e,t,n){"use strict";var r=n(6840),o=n(9504),i=n(655),s=n(2812),a=URLSearchParams,l=a.prototype,c=o(l.append),u=o(l["delete"]),d=o(l.forEach),f=o([].push),p=new a("a=1&a=2&b=3");p["delete"]("a",1),p["delete"]("b",void 0),p+""!=="a=2"&&r(l,"delete",(function(e){var t=arguments.length,n=t<2?void 0:arguments[1];if(t&&void 0===n)return u(this,e);var r=[];d(this,(function(e,t){f(r,{key:t,value:e})})),s(t,1);var o,a=i(e),l=i(n),p=0,h=0,m=!1,v=r.length;while(p0===r(e,t,n);e.exports=o},4659:function(e,t,n){"use strict";var r=n(3724),o=n(4913),i=n(6980);e.exports=function(e,t,n){r?o.f(e,t,i(0,n)):e[t]=n}},4901:function(e){"use strict";var t="object"==typeof document&&document.all;e.exports="undefined"==typeof t&&void 0!==t?function(e){return"function"==typeof e||e===t}:function(e){return"function"==typeof e}},4913:function(e,t,n){"use strict";var r=n(3724),o=n(5917),i=n(8686),s=n(8551),a=n(6969),l=TypeError,c=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d="enumerable",f="configurable",p="writable";t.f=r?i?function(e,t,n){if(s(e),t=a(t),s(n),"function"===typeof e&&"prototype"===t&&"value"in n&&p in n&&!n[p]){var r=u(e,t);r&&r[p]&&(e[t]=n.value,n={configurable:f in n?n[f]:r[f],enumerable:d in n?n[d]:r[d],writable:!1})}return c(e,t,n)}:c:function(e,t,n){if(s(e),t=a(t),s(n),o)try{return c(e,t,n)}catch(r){}if("get"in n||"set"in n)throw new l("Accessors not supported");return"value"in n&&(e[t]=n.value),e}},4999:function(e,t,n){"use strict";n.d(t,{A:function(){return c}});var r=n(641),o=n(3751);function i(e,t,n,i,s,a){return n.horizontal?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"loader",onTransitionend:t[0]||(t[0]=(0,o.D$)((()=>{}),["stop"]))},[t[2]||(t[2]=(0,r.Fv)('
',5)),(0,r.RG)(e.$slots,"default")],32)):((0,r.uX)(),(0,r.CE)("div",{key:1,class:"loader",onTransitionend:t[1]||(t[1]=(0,o.D$)((()=>{}),["stop"]))},[t[3]||(t[3]=(0,r.Fv)('
',1)),(0,r.RG)(e.$slots,"default")],32))}var s={props:{horizontal:Boolean}},a=n(6262);const l=(0,a.A)(s,[["render",i]]);var c=l},5031:function(e,t,n){"use strict";var r=n(7751),o=n(9504),i=n(8480),s=n(3717),a=n(8551),l=o([].concat);e.exports=r("Reflect","ownKeys")||function(e){var t=i.f(a(e)),n=s.f;return n?l(t,n(e)):t}},5032:function(e,t,n){const r=n(8311),o=n(3904),{ANY:i}=o,s=n(7638),a=n(560),l=(e,t,n={})=>{if(e===t)return!0;e=new r(e,n),t=new r(t,n);let o=!1;e:for(const r of e.set){for(const e of t.set){const t=d(r,e,n);if(o=o||null!==t,t)continue e}if(o)return!1}return!0},c=[new o(">=0.0.0-0")],u=[new o(">=0.0.0")],d=(e,t,n)=>{if(e===t)return!0;if(1===e.length&&e[0].semver===i){if(1===t.length&&t[0].semver===i)return!0;e=n.includePrerelease?c:u}if(1===t.length&&t[0].semver===i){if(n.includePrerelease)return!0;t=u}const r=new Set;let o,l,d,h,m,v,g;for(const i of e)">"===i.operator||">="===i.operator?o=f(o,i,n):"<"===i.operator||"<="===i.operator?l=p(l,i,n):r.add(i.semver);if(r.size>1)return null;if(o&&l){if(d=a(o.semver,l.semver,n),d>0)return null;if(0===d&&(">="!==o.operator||"<="!==l.operator))return null}for(const i of r){if(o&&!s(i,String(o),n))return null;if(l&&!s(i,String(l),n))return null;for(const e of t)if(!s(i,String(e),n))return!1;return!0}let y=!(!l||n.includePrerelease||!l.semver.prerelease.length)&&l.semver,b=!(!o||n.includePrerelease||!o.semver.prerelease.length)&&o.semver;y&&1===y.prerelease.length&&"<"===l.operator&&0===y.prerelease[0]&&(y=!1);for(const i of t){if(g=g||">"===i.operator||">="===i.operator,v=v||"<"===i.operator||"<="===i.operator,o)if(b&&i.semver.prerelease&&i.semver.prerelease.length&&i.semver.major===b.major&&i.semver.minor===b.minor&&i.semver.patch===b.patch&&(b=!1),">"===i.operator||">="===i.operator){if(h=f(o,i,n),h===i&&h!==o)return!1}else if(">="===o.operator&&!s(o.semver,String(i),n))return!1;if(l)if(y&&i.semver.prerelease&&i.semver.prerelease.length&&i.semver.major===y.major&&i.semver.minor===y.minor&&i.semver.patch===y.patch&&(y=!1),"<"===i.operator||"<="===i.operator){if(m=p(l,i,n),m===i&&m!==l)return!1}else if("<="===l.operator&&!s(l.semver,String(i),n))return!1;if(!i.operator&&(l||o)&&0!==d)return!1}return!(o&&v&&!l&&0!==d)&&(!(l&&g&&!o&&0!==d)&&(!b&&!y))},f=(e,t,n)=>{if(!e)return t;const r=a(e.semver,t.semver,n);return r>0?e:r<0||">"===t.operator&&">="===e.operator?t:e},p=(e,t,n)=>{if(!e)return t;const r=a(e.semver,t.semver,n);return r<0?e:r>0||"<"===t.operator&&"<="===e.operator?t:e};e.exports=l},5039:function(e,t,n){"use strict";n.d(t,{A:function(){return Fe}});var r=n(641),o=n(33),i=n.p+"img/search-by-algolia.72f0ac9a.svg";const s={class:"package-search__title"},a={key:1,class:"package-search__status package-search__status--offline"},l={class:"package-search__title"},c={class:"package-search__explain"},u={key:2,class:"package-search__status package-search__status--empty"},d={class:"package-search__results"},f={class:"package-search__more"},p={key:4},h={class:"package-search__headline"},m={class:"package-search__results"},v={class:"package-search__more"},g={class:"package-search__headline"},y={class:"package-search__results"},b={class:"package-search__more"},_={class:"package-search__headline"},E={class:"package-search__results"},w={class:"package-search__more"};function S(e,t,n,S,k,C){const O=(0,r.g2)("search-input"),T=(0,r.g2)("loading-spinner"),R=(0,r.g2)("i18n-t"),A=(0,r.g2)("search-sorting"),N=(0,r.g2)("discover-package"),L=(0,r.g2)("loading-button"),I=(0,r.g2)("ad-banner");return(0,r.uX)(),(0,r.Wv)((0,r.$y)(n.wrapper),null,{search:(0,r.k6)((()=>[(0,r.bF)(O,{placeholder:e.$tc("ui.discover.searchPlaceholder",e.extensionCount),class:"package-search__input"},null,8,["placeholder"])])),default:(0,r.k6)((()=>[e.searching&&!e.results?((0,r.uX)(),(0,r.Wv)(T,{key:0,class:"package-search__status package-search__status--loader"},{default:(0,r.k6)((()=>[(0,r.Lk)("p",s,(0,o.v_)(e.$t("ui.discover.loading")),1)])),_:1})):e.offline||null===e.discover?((0,r.uX)(),(0,r.CE)("div",a,[(0,r.Lk)("p",l,(0,o.v_)(e.$t("ui.discover.offline")),1),(0,r.Lk)("p",c,(0,o.v_)(e.$t("ui.discover.offlineExplain")),1),(0,r.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",onClick:t[0]||(t[0]=(...e)=>C.getOnline&&C.getOnline(...e))},(0,o.v_)(e.$t("ui.discover.offlineButton")),1)])):e.isSearching&&e.results&&!Object.keys(e.results).length?((0,r.uX)(),(0,r.CE)("div",u,[(0,r.bF)(R,{keypath:"ui.discover.empty",tag:"p",class:"package-search__title"},{query:(0,r.k6)((()=>[(0,r.Lk)("i",null,(0,o.v_)(e.query),1)])),_:1})])):e.isSearching?((0,r.uX)(),(0,r.CE)(r.FK,{key:3},[e.query?(0,r.Q3)("",!0):((0,r.uX)(),(0,r.Wv)(A,{key:0})),(0,r.Lk)("div",d,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.results,(t=>((0,r.uX)(),(0,r.Wv)(N,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})])),actions:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})])),_:2},1032,["data"])))),128))]),(0,r.Lk)("div",f,[e.hasMore?((0,r.uX)(),(0,r.Wv)(L,{key:0,inline:"",icon:"search",loading:e.searching,onClick:e.loadMore},{default:(0,r.k6)((()=>[(0,r.eW)((0,o.v_)(e.$t("ui.discover.more")),1)])),_:1},8,["loading","onClick"])):(0,r.Q3)("",!0)])],64)):((0,r.uX)(),(0,r.CE)("div",p,[e.discover.ads.length?((0,r.uX)(),(0,r.Wv)(I,{key:0})):(0,r.Q3)("",!0),(0,r.Lk)("h2",h,(0,o.v_)(e.$t("ui.discover.latestPackages")),1),(0,r.Lk)("div",m,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.discover.latest,(t=>((0,r.uX)(),(0,r.Wv)(N,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})])),actions:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})])),_:2},1032,["data"])))),128))]),(0,r.Lk)("div",v,[(0,r.Lk)("button",{class:"package-search__more-button",onClick:t[1]||(t[1]=e=>C.openSearch("latest"))},(0,o.v_)(e.$t("ui.discover.more")),1)]),(0,r.Lk)("h2",g,(0,o.v_)(e.$t("ui.discover.faversPackages")),1),(0,r.Lk)("div",y,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.discover.favers,(t=>((0,r.uX)(),(0,r.Wv)(N,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})])),actions:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})])),_:2},1032,["data"])))),128))]),(0,r.Lk)("div",b,[(0,r.Lk)("button",{class:"package-search__more-button",onClick:t[2]||(t[2]=e=>C.openSearch("favers"))},(0,o.v_)(e.$t("ui.discover.more")),1)]),(0,r.Lk)("h2",_,(0,o.v_)(e.$t("ui.discover.downloadsPackages")),1),(0,r.Lk)("div",E,[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.discover.downloads,(t=>((0,r.uX)(),(0,r.Wv)(N,{class:"package-search__item",data:t,key:t.name},{hint:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-hint",{data:t})])),actions:(0,r.k6)((()=>[(0,r.RG)(e.$slots,"package-actions",{data:t})])),_:2},1032,["data"])))),128))]),(0,r.Lk)("div",w,[(0,r.Lk)("button",{class:"package-search__more-button",onClick:t[3]||(t[3]=e=>C.openSearch("downloads"))},(0,o.v_)(e.$t("ui.discover.more")),1)])])),t[4]||(t[4]=(0,r.Lk)("a",{href:"https://www.algolia.com/",target:"_blank",class:"package-search__algolia"},[(0,r.Lk)("img",{src:i,alt:"Algolia | Fast, Reliable and Modern Search and Discovery",width:"200"})],-1))])),_:3})}var k=n(6278),C=n(1881),O=n(6077),T=n(4999),R=n(3751);const A={class:"ads"},N={key:0,class:"container"},L=["title","onClick"],I=["src"],P=["href","title"],x=["src"],M={key:1,class:"link"},D={href:"https://contao.org/de/anzeigen-erweiterungsliste.html",target:"_blank"},$={key:2,class:"link"},F={href:"https://contao.org/en/extension-ads.html",target:"_blank"};function j(e,t,n,i,s,a){const l=(0,r.g2)("vueper-slide"),c=(0,r.g2)("vueper-slides");return(0,r.uX)(),(0,r.CE)("div",A,[e.ads&&e.ads.length>1?((0,r.uX)(),(0,r.CE)("div",N,[(0,r.bF)(c,{class:"no-shadow",autoplay:"",infinite:"",duration:1e4,"slide-ratio":1/4,"visible-slides":2,breakpoints:{630:{slideRatio:.5,visibleSlides:1}},bullets:!1,touchable:!1,"arrows-outside":!1},{default:(0,r.k6)((()=>[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.ads,(t=>((0,r.uX)(),(0,r.Wv)(l,{key:t.objectID},{content:(0,r.k6)((()=>[t.package?((0,r.uX)(),(0,r.CE)("a",{key:0,href:"#",title:t.title,onClick:(0,R.D$)((n=>e.setCurrent(t.package)),["stop"])},[(0,r.Lk)("img",{src:t.image,alt:""},null,8,I)],8,L)):((0,r.uX)(),(0,r.CE)("a",{key:1,href:t.url,title:t.title,target:"_blank",rel:"noreferrer noopener"},[(0,r.Lk)("img",{src:t.image,alt:""},null,8,x)],8,P))])),_:2},1024)))),128))])),_:1})])):(0,r.Q3)("",!0),"de"===e.$i18n.locale?((0,r.uX)(),(0,r.CE)("div",M,[(0,r.Lk)("a",D,(0,o.v_)(e.$t("ui.discover.advertisement")),1)])):((0,r.uX)(),(0,r.CE)("div",$,[(0,r.Lk)("a",F,(0,o.v_)(e.$t("ui.discover.advertisement")),1)]))])}const U=["src"],B=["src"],V=["src"],H=["src"],W=["src"],X={key:2},G={class:"vueperslide__content-wrapper"},K=["innerHTML"],z=["innerHTML"],q={class:"vueperslide__content-wrapper"},Y=["innerHTML"],Q=["innerHTML"],J={key:4,class:"vueperslide__loader"};function Z(e,t,n,i,s,a){return(0,r.uX)(),(0,r.Wv)((0,r.$y)(n.link?"a":"div"),{class:(0,o.C4)(["vueperslide",a.slideClasses]),href:!(!n.link||a.justDragged)&&n.link,target:n.link&&n.openInNew?"boolean"==typeof n.openInNew?"_blank":n.openInNew:"_self",face:a.slideFace3d,style:(0,o.Tr)(a.slideStyles),"aria-hidden":a.slides.activeId===e._.uid||a.isSlideVisible?"false":"true",onMouseenter:t[0]||(t[0]=t=>e.$emit("mouse-enter",{slideIndex:a.slideIndex,title:n.title,content:n.content,image:n.image,link:n.link},e.$el)),onMouseleave:t[1]||(t[1]=t=>e.$emit("mouse-leave"))},{default:(0,r.k6)((()=>[a.videoObj?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[a.videoObj.webm||a.videoObj.mp4?((0,r.uX)(),(0,r.CE)("video",(0,r.v6)({key:0,class:"vueperslide__video",width:"100%",height:"100%"},a.videoObj.props||{}),[a.videoObj.webm?((0,r.uX)(),(0,r.CE)("source",{key:0,src:a.videoObj.webm,type:"video/webm"},null,8,U)):(0,r.Q3)("",!0),a.videoObj.mp4?((0,r.uX)(),(0,r.CE)("source",{key:1,src:a.videoObj.mp4,type:"video/mp4"},null,8,B)):(0,r.Q3)("",!0),a.videoObj.ogv?((0,r.uX)(),(0,r.CE)("source",{key:2,src:a.videoObj.ogv,type:"video/ogg"},null,8,V)):(0,r.Q3)("",!0),a.videoObj.avi?((0,r.uX)(),(0,r.CE)("source",{key:3,src:a.videoObj.avi,type:"video/avi"},null,8,H)):(0,r.Q3)("",!0),(0,r.eW)((0,o.v_)(a.videoObj.alt||"Sorry, your browser doesn't support embedded videos."),1)],16)):a.videoObj.url?((0,r.uX)(),(0,r.CE)("iframe",(0,r.v6)({key:1,class:"vueperslide__video",src:a.videoObj.url,type:"text/html",frameborder:"0",width:"100%",height:"100%"},a.videoObj.props||{}),null,16,W)):(0,r.Q3)("",!0)],64)):(0,r.Q3)("",!0),e.imageSrc&&a.conf.slideImageInside?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__image",style:(0,o.Tr)(a.imageStyles)},null,4)):(0,r.Q3)("",!0),a.conf.slideContentOutside?(0,r.bo)(((0,r.uX)(),(0,r.CE)("div",X,[(0,r.RG)(e.$slots,"content",{},(()=>[(0,r.Lk)("div",G,[n.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:n.title},null,8,K)):(0,r.Q3)("",!0),n.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:n.content},null,8,z)):(0,r.Q3)("",!0)])]))],512)),[[R.aG,!1]]):(0,r.RG)(e.$slots,"content",{key:3},(()=>[(0,r.Lk)("div",q,[n.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:n.title},null,8,Y)):(0,r.Q3)("",!0),n.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:n.content},null,8,Q)):(0,r.Q3)("",!0)])])),a.conf.lazy&&!e.loaded?((0,r.uX)(),(0,r.CE)("div",J,[(0,r.RG)(e.$slots,"loader")])):(0,r.Q3)("",!0)])),_:3},40,["href","target","class","face","style","aria-hidden"])}const ee=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n},te={inject:["slides","touch","updateSlide","addClone","addSlide","removeSlide"],props:{clone:{type:Boolean},image:{type:String,default:""},video:{type:[String,Object],default:""},title:{type:String,default:""},content:{type:String,default:""},link:{type:String,default:""},duration:{type:Number,default:0},lazyloaded:{type:Boolean},openInNew:{type:[Boolean,String]}},emits:["mouse-enter","mouse-leave"],data:()=>({imageSrc:"",loading:!1,loaded:!1}),computed:{conf(){return this.$parent.conf},slideClasses(){return{"vueperslide--active":this.slides.activeId===this._.uid,"vueperslide--previous-slide":this.isPreviousSlide,"vueperslide--next-slide":this.isNextSlide,"vueperslide--visible":this.isSlideVisible,"vueperslide--loading":this.conf.lazy&&!this.loaded,"vueperslide--has-video":this.videoObj,"vueperslide--has-image-inside":this.conf.slideImageInside,"vueperslide--no-pointer-events":this.videoObj&&!1===this.videoObj.pointerEvents}},slideStyles(){const{visibleSlides:e,fade:t,slideImageInside:n,gap:r,gapPx:o}=this.conf;return{...!n&&this.imageSrc&&{backgroundImage:`url("${this.imageSrc}")`},...e>1&&{width:(100-(r?r*(e-1):0))/e+"%"},...e>1&&t&&{[this.conf.rtl?"right":"left"]:this.slideIndex%e/e*100+"%"},...r&&{[this.conf.rtl?"marginLeft":"marginRight"]:r+(o?"px":"%")}}},videoObj(){if(!this.video)return null;let e={url:"",alt:"",props:{controls:!0}};return"object"==typeof this.video?e=Object.assign(e,this.video):"string"==typeof this.video&&(e.url=this.video),e},youtubeVideo(){return/youtube\.|youtu\.be/.test(this.videoObj.url)},imageStyles(){return{...this.conf.slideImageInside&&this.imageSrc&&{backgroundImage:`url("${this.imageSrc}")`}}},slideFace3d(){if(!this.conf["3d"])return!1;const e=["front","right","back","left"],t=(this.slides.current-1+this.slidesCount)%this.slidesCount,n=(this.slides.current+1)%this.slidesCount;let r="front";return this.slideIndex===t?r=e[(4+this.slides.current-1)%4]:this.slideIndex===n&&(r=e[(this.slides.current+1)%4]),r=e[this.slideIndex%4],this.conf.rtl&&"left"===r?r="right":this.conf.rtl&&"right"===r&&(r="left"),r},isPreviousSlide(){if(!this.conf["3d"])return!1;const e=(this.slides.current-1+this.slidesCount)%this.slidesCount;return this._.uid===this.slides.list[e].id},isNextSlide(){if(!this.conf["3d"])return!1;const e=(this.slides.current+1)%this.slidesCount;return this._.uid===this.slides.list[e].id},isSlideVisible(){return this.slideIndex>=this.slides.firstVisible&&this.slideIndexe.id))},slidesCount(){return this.slidesList.length},slideIndex(){return this.slidesList.indexOf(this._.uid)},justDragged(){return this.touch.justDragged}},methods:{updateThisSlide(e){this.updateSlide(this._.uid,e)},loadImage(){if(!this.loading&&!this.loaded)return this.loading=!0,new Promise(((e,t)=>{const n=document.createElement("img");n.onload=()=>{this.imageSrc=this.image,this.loading=!1,this.loaded=!0,this.$nextTick((()=>{e({image:this.imageSrc,style:((this.$el.attributes||{}).style||{}).value})}))},n.onerror=(this.loading=!1)||t,n.src=this.image}))},playVideo(){this.videoObj&&(this.videoObj.url?this.$el.querySelector("iframe").contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}',"*"):this.$el.querySelector("video").play())},pauseVideo(){this.videoObj&&(this.videoObj.url?this.$el.querySelector("iframe").contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}',"*"):this.$el.querySelector("video").pause())}},created(){if(this.imageSrc=this.conf.lazy?"":this.image,this.clone)return this.addClone();this.addSlide({id:this._.uid,image:this.imageSrc,video:this.videoObj&&{...this.videoObj,play:this.playVideo,pause:this.pauseVideo},title:this.title,content:this.content,contentSlot:this.$slots.content,loaderSlot:this.$slots.loader,link:this.link,style:"",loadImage:this.loadImage,duration:this.duration})},mounted(){this.clone||this.updateThisSlide({contentSlot:this.$slots.content,loaderSlot:this.$slots.loader,style:((this.$el.attributes||{}).style||{}).value})},beforeUnmount(){this.clone||this.removeSlide(this._.uid)},watch:{image(){this.imageSrc=this.conf.lazy&&!this.isSlideVisible?"":this.image,this.clone||this.updateThisSlide({image:this.imageSrc,...!this.conf.slideImageInside&&{style:this.slideStyles}})},title(){this.clone||this.updateThisSlide({title:this.title})},content(){this.clone||this.updateThisSlide({content:this.content})},link(){this.clone||this.updateThisSlide({link:this.link})},lazyloaded(){this.clone&&(this.loaded=this.lazyloaded)}}},ne=ee(te,[["render",Z]]),re=["innerHTML"],oe=["innerHTML"],ie={class:"vueperslides__inner"},se={key:0,class:"vueperslides__paused"},ae={key:1,class:"vueperslides__progress"},le={key:2,class:"vueperslides__fractions"},ce={viewBox:"0 0 9 18"},ue=["d"],de={viewBox:"0 0 9 18"},fe=["d"],pe={key:4,class:"vueperslides__bullets",ref:"bullets",role:"tablist","aria-label":"Slideshow navigation"},he=["aria-label","onClick"],me={class:"default"},ve={key:1,class:"vueperslides__bullets vueperslides__bullets--outside",ref:"bullets",role:"tablist","aria-label":"Slideshow navigation"},ge=["aria-label","onClick"],ye={class:"default"},be=["innerHTML"],_e=["innerHTML"];function Ee(e,t,n,i,s,a){const l=(0,r.g2)("vnodes"),c=(0,r.g2)("vueper-slide");return(0,r.uX)(),(0,r.CE)("div",{class:(0,o.C4)(["vueperslides",a.vueperslidesClasses]),ref:"vueperslides","aria-label":"Slideshow",style:(0,o.Tr)(a.vueperslidesStyles)},[a.slidesCount&&"top"===a.conf.slideContentOutside?((0,r.uX)(),(0,r.CE)("div",{key:0,class:(0,o.C4)(["vueperslide__content-wrapper vueperslide__content-wrapper--outside-top",a.conf.slideContentOutsideClass])},[a.currentSlide.contentSlot?((0,r.uX)(),(0,r.Wv)(l,{key:0,vnodes:a.currentSlide.contentSlot()},null,8,["vnodes"])):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[a.currentSlide.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:a.currentSlide.title},null,8,re)):(0,r.Q3)("",!0),a.currentSlide.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:a.currentSlide.content},null,8,oe)):(0,r.Q3)("",!0)],64))],2)):(0,r.Q3)("",!0),(0,r.Lk)("div",ie,[(0,r.Lk)("div",{class:"vueperslides__parallax-wrapper",style:(0,o.Tr)(`padding-bottom: ${100*a.conf.slideRatio}%`),"aria-live":"polite"},[(0,r.Lk)("div",{class:(0,o.C4)(["vueperslides__track",{"vueperslides__track--dragging":e.touch.dragging,"vueperslides__track--mousedown":e.mouseDown}]),ref:"track",style:(0,o.Tr)(a.trackStyles)},[(0,r.Lk)("div",{class:"vueperslides__track-inner",style:(0,o.Tr)(a.trackInnerStyles)},[(0,r.RG)(e.$slots,"default"),e.isReady&&a.conf.infinite&&a.canSlide&&a.lastSlide?((0,r.uX)(),(0,r.Wv)(c,{key:0,class:"vueperslide--clone vueperslide--clone-1",clone:"",title:a.lastSlide.title,content:a.lastSlide.content,image:a.lastSlide.image,link:a.lastSlide.link,style:(0,o.Tr)(a.lastSlide.style),lazyloaded:a.lastSlide.loaded,"aria-hidden":"true"},(0,r.eX)({_:2},[a.lastSlide.contentSlot?{name:"content",fn:(0,r.k6)((()=>[(0,r.bF)(l,{vnodes:a.lastSlide.contentSlot()},null,8,["vnodes"])])),key:"0"}:void 0,a.conf.lazy&&!a.lastSlide.loaded&&a.lastSlide.loaderSlot?{name:"loader",fn:(0,r.k6)((()=>[(0,r.bF)(l,{vnodes:a.lastSlide.loaderSlot()},null,8,["vnodes"])])),key:"1"}:void 0]),1032,["title","content","image","link","style","lazyloaded"])):(0,r.Q3)("",!0),e.isReady&&a.conf.infinite&&a.canSlide&&a.firstSlide?((0,r.uX)(),(0,r.Wv)(c,{key:1,class:"vueperslide--clone vueperslide--clone-2",clone:"",title:a.firstSlide.title,content:a.firstSlide.content,image:a.firstSlide.image,link:a.firstSlide.link,style:(0,o.Tr)(a.firstSlide.style),lazyloaded:a.firstSlide.loaded,"aria-hidden":"true"},(0,r.eX)({_:2},[a.firstSlide.contentSlot?{name:"content",fn:(0,r.k6)((()=>[(0,r.bF)(l,{vnodes:a.firstSlide.contentSlot()},null,8,["vnodes"])])),key:"0"}:void 0,a.conf.lazy&&!a.firstSlide.loaded&&a.firstSlide.loaderSlot?{name:"loader",fn:(0,r.k6)((()=>[(0,r.bF)(l,{vnodes:a.firstSlide.loaderSlot()},null,8,["vnodes"])])),key:"1"}:void 0]),1032,["title","content","image","link","style","lazyloaded"])):(0,r.Q3)("",!0)],4)],6)],4),(a.conf.pauseOnHover||a.conf.pauseOnTouch)&&e.$slots.pause?((0,r.uX)(),(0,r.CE)("div",se,[(0,r.RG)(e.$slots,"pause")])):(0,r.Q3)("",!0),a.conf.progress?((0,r.uX)(),(0,r.CE)("div",ae,[(0,r.RG)(e.$slots,"progress",{current:e.slides.current+1,total:a.slidesCount},(()=>[(0,r.Lk)("div",{style:(0,o.Tr)(`width: ${100*(e.slides.current+1)/a.slidesCount}%`)},null,4)]))])):(0,r.Q3)("",!0),a.conf.fractions?((0,r.uX)(),(0,r.CE)("div",le,[(0,r.RG)(e.$slots,"fraction",{current:e.slides.current+1,total:a.slidesCount},(()=>[(0,r.eW)((0,o.v_)(`${e.slides.current+1} / ${a.slidesCount}`),1)]))])):(0,r.Q3)("",!0),a.conf.arrows&&a.canSlide&&!n.disable?((0,r.uX)(),(0,r.CE)("div",{key:3,class:(0,o.C4)(["vueperslides__arrows",{"vueperslides__arrows--outside":a.conf.arrowsOutside}])},[(0,r.bo)((0,r.Lk)("button",{class:"vueperslides__arrow vueperslides__arrow--prev",type:"button",onClick:t[0]||(t[0]=e=>a.previous()),"aria-label":"Previous",onKeyup:[t[1]||(t[1]=(0,R.jR)((e=>a.conf.rtl?a.next():a.previous()),["left"])),t[2]||(t[2]=(0,R.jR)((e=>a.conf.rtl?a.previous():a.next()),["right"]))]},[(0,r.RG)(e.$slots,"arrow-"+(a.conf.rtl?"right":"left"),{},(()=>[((0,r.uX)(),(0,r.CE)("svg",ce,[(0,r.Lk)("path",{"stroke-linecap":"round",d:a.conf.rtl?"m1 1 l7 8 -7 8":"m8 1 l-7 8 7 8"},null,8,ue)]))]))],544),[[R.aG,!a.arrowPrevDisabled]]),(0,r.bo)((0,r.Lk)("button",{class:"vueperslides__arrow vueperslides__arrow--next",type:"button",onClick:t[3]||(t[3]=e=>a.next()),"aria-label":"Next",onKeyup:[t[4]||(t[4]=(0,R.jR)((e=>a.conf.rtl?a.next():a.previous()),["left"])),t[5]||(t[5]=(0,R.jR)((e=>a.conf.rtl?a.previous():a.next()),["right"]))]},[(0,r.RG)(e.$slots,"arrow-"+(a.conf.rtl?"left":"right"),{},(()=>[((0,r.uX)(),(0,r.CE)("svg",de,[(0,r.Lk)("path",{"stroke-linecap":"round",d:a.conf.rtl?"m8 1 l-7 8 7 8":"m1 1 l7 8 -7 8"},null,8,fe)]))]))],544),[[R.aG,!a.arrowNextDisabled]])],2)):(0,r.Q3)("",!0),a.conf.bullets&&a.canSlide&&!n.disable&&!a.conf.bulletsOutside?((0,r.uX)(),(0,r.CE)("div",pe,[(0,r.RG)(e.$slots,"bullets",{currentSlide:e.slides.current,bulletIndexes:a.bulletIndexes,goToSlide:a.goToSlide,previous:a.previous,next:a.next},(()=>[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(a.bulletIndexes,((n,i)=>((0,r.uX)(),(0,r.CE)("button",{class:(0,o.C4)(["vueperslides__bullet",{"vueperslides__bullet--active":e.slides.current===n}]),type:"button",key:i,role:"tab","aria-label":`Slide ${i+1}`,onClick:e=>a.goToSlide(n),onKeyup:[t[6]||(t[6]=(0,R.jR)((e=>a.conf.rtl?a.next():a.previous()),["left"])),t[7]||(t[7]=(0,R.jR)((e=>a.conf.rtl?a.previous():a.next()),["right"]))]},[(0,r.RG)(e.$slots,"bullet",{active:e.slides.current===n,slideIndex:n,index:i+1},(()=>[(0,r.Lk)("div",me,[(0,r.Lk)("span",null,(0,o.v_)(i+1),1)])]))],42,he)))),128))]))],512)):(0,r.Q3)("",!0)]),a.conf.bullets&&a.canSlide&&!n.disable&&a.conf.bulletsOutside?((0,r.uX)(),(0,r.CE)("div",ve,[(0,r.RG)(e.$slots,"bullets",{currentSlide:e.slides.current,bulletIndexes:a.bulletIndexes,goToSlide:a.goToSlide,previous:a.previous,next:a.next},(()=>[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(a.bulletIndexes,((n,i)=>((0,r.uX)(),(0,r.CE)("button",{class:(0,o.C4)(["vueperslides__bullet",{"vueperslides__bullet--active":e.slides.current===n}]),type:"button",key:i,role:"tab","aria-label":`Slide ${i+1}`,onClick:e=>a.goToSlide(n),onKeyup:[t[8]||(t[8]=(0,R.jR)((e=>a.conf.rtl?a.next():a.previous()),["left"])),t[9]||(t[9]=(0,R.jR)((e=>a.conf.rtl?a.previous():a.next()),["right"]))]},[(0,r.RG)(e.$slots,"bullet",{active:e.slides.current===n,slideIndex:n,index:i+1},(()=>[(0,r.Lk)("div",ye,[(0,r.Lk)("span",null,(0,o.v_)(i+1),1)])]))],42,ge)))),128))]))],512)):(0,r.Q3)("",!0),a.slidesCount&&"bottom"===a.conf.slideContentOutside?((0,r.uX)(),(0,r.CE)("div",{key:2,class:(0,o.C4)(["vueperslide__content-wrapper vueperslide__content-wrapper--outside-bottom",a.conf.slideContentOutsideClass])},[a.currentSlide.contentSlot?((0,r.uX)(),(0,r.Wv)(l,{key:0,vnodes:a.currentSlide.contentSlot()},null,8,["vnodes"])):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[a.currentSlide.title?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"vueperslide__title",innerHTML:a.currentSlide.title},null,8,be)):(0,r.Q3)("",!0),a.currentSlide.content?((0,r.uX)(),(0,r.CE)("div",{key:1,class:"vueperslide__content",innerHTML:a.currentSlide.content},null,8,_e)):(0,r.Q3)("",!0)],64))],2)):(0,r.Q3)("",!0)],6)}const we={name:"vueper-slides",components:{VueperSlide:ne,vnodes:{render(){return this.$attrs.vnodes}}},provide(){return{conf:this.conf,slides:this.slides,touch:this.touch,updateSlide:this.updateSlide,addClone:this.addClone,addSlide:this.addSlide,removeSlide:this.removeSlide}},props:{alwaysRefreshClones:{type:Boolean,default:!1},arrows:{type:Boolean,default:!0},arrowsOutside:{type:Boolean,default:null},autoplay:{type:Boolean,default:!1},breakpoints:{type:Object,default:()=>({})},bullets:{type:Boolean,default:!0},bulletsOutside:{type:Boolean,default:null},disable:{type:Boolean,default:!1},disableArrowsOnEdges:{type:[Boolean,String],default:!1},draggingDistance:{type:Number,default:null},duration:{type:[Number,String],default:4e3},infinite:{type:Boolean,default:!0},fade:{type:Boolean,default:!1},fixedHeight:{type:[Boolean,String],default:!1},fractions:{type:Boolean,default:!1},gap:{type:Number,default:0},initSlide:{type:Number,default:1},lazy:{type:Boolean,default:!1},lazyLoadOnDrag:{type:Boolean,default:!1},pauseOnHover:{type:Boolean,default:!0},pauseOnTouch:{type:Boolean,default:!0},parallax:{type:[Boolean,Number],default:!1},pageScrollingElement:{type:String,default:""},parallaxFixedContent:{type:Boolean,default:!1},preventYScroll:{type:Boolean,default:!1},progress:{type:Boolean,default:!1},rtl:{type:Boolean,default:!1},slideContentOutside:{type:[Boolean,String],default:!1},slideContentOutsideClass:{type:String,default:""},slideImageInside:{type:Boolean,default:!1},slideMultiple:{type:[Boolean,Number],default:!1},slideRatio:{type:Number,default:1/3},touchable:{type:Boolean,default:!0},transitionSpeed:{type:[Number,String],default:600},visibleSlides:{type:Number,default:1},"3d":{type:Boolean,default:!1}},emits:["ready","next","previous","autoplay-pause","autoplay-resume","before-slide","slide","image-loaded","image-failed"],data:()=>({isReady:!1,isPaused:!1,container:null,slides:{list:[],activeId:null,current:0,focus:0,firstVisible:0},mouseDown:!1,mouseOver:!1,touch:{enabled:!0,dragging:!1,lazyloadTriggered:!1,justDragged:!1,dragStartX:0,dragNowX:0,dragAmount:0},transition:{currentTranslation:0,speed:0,animated:!1},autoplayTimer:null,nextSlideIsClone:!1,breakpointsData:{list:[],current:null},parallaxData:{translation:0,slideshowOffsetTop:null,isVisible:!1}}),computed:{conf(){const e={...this.$props,...this.$props.breakpoints&&this.$props.breakpoints[this.breakpointsData.current]||{}};return e.slideMultiple=e.slideMultiple?e.visibleSlides:1,e.gap=this.gap&&parseInt(this.gap)||0,e.visibleSlides>1&&(e["3d"]=!1),(e.fade||e.disableArrowsOnEdges||e.visibleSlides>1||e["3d"])&&(e.infinite=!1),e.visibleSlides>1&&null===e.arrowsOutside&&(e.arrowsOutside=!0),e.visibleSlides>1&&null===e.bulletsOutside&&(e.bulletsOutside=!0),this.touch.enabled!==e.touchable&&this.toggleTouchableOption(e.touchable),e.parallax&&e.parallaxFixedContent&&(e.slideContentOutside="top",e.slideContentOutsideClass="parallax-fixed-content"),e},slidesCount(){return this.slides.list.length},gapsCount(){const{fade:e,"3d":t,slideMultiple:n,gap:r}=this.conf;if(!r||e||t||this.multipleSlides1by1&&this.slides.current0&&(o-=this.slidePosAfterPreferred),o},slidesAfterCurrent(){return this.slidesCount-(this.slides.current+1)},preferredPosition(){return this.multipleSlides1by1?Math.ceil(this.conf.visibleSlides/2)-1:0},slidePosAfterPreferred(){return this.conf.visibleSlides-this.preferredPosition-this.slidesAfterCurrent-1},multipleSlides1by1(){return this.conf.visibleSlides>1&&1===this.conf.slideMultiple},touchEnabled:{get(){return this.slidesCount>1&&this.touch.enabled},set(e){this.touch.enabled=e}},canSlide(){return this.slidesCount/this.conf.visibleSlides>1},firstSlide(){const e=this.slidesCount?this.slides.list[0]:{};return e.style&&"string"==typeof e.style&&(e.style=e.style.replace(/width: ?\d+.*?;?/,"")),e},lastSlide(){const e=this.slidesCount?this.slides.list[this.slidesCount-1]:{};return e.style&&"string"==typeof e.style&&(e.style=e.style.replace(/width: ?\d+.*?;?/,"")),e},currentSlide(){const e=this.slidesCount&&this.slides.list[this.slides.current]||{};return this.slides.current1,"vueperslides--bullets-outside":this.conf.bulletsOutside,"vueperslides--animated":this.transition.animated,"vueperslides--no-animation":!this.isReady}},vueperslidesStyles(){return/^-?\d/.test(this.conf.fixedHeight)?`height: ${this.conf.fixedHeight}`:null},trackStyles(){const e={};return this.conf.parallax&&(e.transform=`translate3d(0, ${this.parallaxData.translation}%, 0)`,e.willChange=this.parallaxData.isVisible?"transform":"auto"),e},trackInnerStyles(){const e={},{fade:t,"3d":n}=this.conf;if(e.transitionDuration=`${this.transition.speed}ms`,n){const t=90*this.transition.currentTranslation/100;e.transform=`rotateY(-90deg) translateX(-50%) rotateY(90deg) rotateY(${t}deg)`}else t||(e.transform=`translate3d(${this.transition.currentTranslation}%, 0, 0)`,e.willChange=this.touch.dragging||this.transition.animated?"transform":"auto");return e},bulletIndexes(){return Array(Math.ceil(this.slidesCount/this.conf.slideMultiple)).fill().map(((e,t)=>t*this.conf.slideMultiple))},arrowPrevDisabled(){return!this.slides.current&&this.conf.disableArrowsOnEdges},arrowNextDisabled(){const{disableArrowsOnEdges:e,visibleSlides:t,slideMultiple:n}=this.conf;return this.slides.current+(n>1&&t>1?t-1:0)===this.slidesCount-1&&e}},methods:{init(){this.container=this.$refs.vueperslides,this.touchEnabled=this.conf.touchable,this.transition.speed=this.conf.transitionSpeed,Object.keys(this.breakpoints).length&&(this.setBreakpointsList(),this.setBreakpointConfig(this.getCurrentBreakpoint()));const e={animation:!1,autoPlaying:this.conf.autoplay};this.goToSlide(this.conf.initSlide-1,e),this.bindEvents(),this.$nextTick((()=>{this.isReady=!0,this.emit("ready")}))},emit(e,t=!0,n=!1){let r=null;if((t||"number"==typeof n)&&(r={},t&&this.slides.activeId&&this.slidesCount&&(r.currentSlide=this.getSlideData(this.slides.current)),"number"==typeof n&&this.slidesCount)){const{nextSlide:e}=this.getSlideInRange(n);r.nextSlide=this.getSlideData(e)}this.$emit(...r?[e,r]:[e])},getSlideData(e){const t=this.slides.list[e];let n={};return t&&(n={index:e,title:t.title,content:t.content,contentSlot:t.contentSlot,image:t.image,link:t.link}),n},setBreakpointsList(){this.breakpointsData.list=[99999,...Object.keys(this.breakpoints)].map((e=>parseInt(e))).sort(((e,t)=>parseInt(t)-parseInt(e)))},getCurrentBreakpoint(){const e=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,t=[e,...this.breakpointsData.list].sort(((e,t)=>parseInt(t)-parseInt(e)));return this.breakpointsData.list[t.indexOf(e)-1]},hasBreakpointChanged(e){return this.breakpointsData.current!==parseInt(e)},setBreakpointConfig(e){const t=this.breakpoints&&this.breakpoints[e]||{},n=t.slideMultiple&&t.slideMultiple!==this.conf.slideMultiple,r=t.visibleSlides&&t.visibleSlides!==this.conf.visibleSlides;this.breakpointsData.current=e,this.slides.current=this.getFirstVisibleSlide(this.slides.focus),n||r?this.goToSlide(this.slides.current,{breakpointChange:!0}):this.updateTrackTranslation()},bindEvents(){const e="ontouchstart"in window;this.touchEnabled&&this.toggleTouchableOption(!0),this.conf.autoplay&&(this.conf.pauseOnHover&&!e?(this.container.addEventListener("mouseenter",this.onMouseEnter),this.container.addEventListener("mouseleave",this.onMouseLeave)):this.conf.pauseOnTouch&&e&&document.addEventListener("touchstart",(e=>{this[this.$el.contains(e.target)?"onSlideshowTouch":"onOustideTouch"]()}))),(this.breakpointsData.list.length||this.conf.parallax)&&window.addEventListener("resize",this.onResize),this.conf.parallax&&this.enableParallax()},getSlideshowOffsetTop(e=!1){if(null===this.parallaxData.slideshowOffsetTop||e){let e=this.container,t=e.offsetTop;for(;e=e.offsetParent;)t+=e.offsetTop;this.parallaxData.slideshowOffsetTop=t}return this.parallaxData.slideshowOffsetTop},enableParallax(){this.refreshParallax(),this.pageScrollingElement?(this.parallaxData.scrollingEl=document.querySelector(this.pageScrollingElement),this.parallaxData.scrollingEl.addEventListener("scroll",this.onScroll)):document.addEventListener("scroll",this.onScroll)},disableParallax(){(this.pageScrollingElement?document.querySelector(this.pageScrollingElement):document).removeEventListener("scroll",this.onScroll),this.parallaxData.scrollingEl=null,this.parallaxData.isVisible=!1,this.parallaxData.translation=0,this.parallaxData.slideshowOffsetTop=null},onScroll(){const{scrollingEl:e}=this.parallaxData,t=document.documentElement;let n=0;n=e?e.scrollTop:(window.pageYOffset||t.scrollTop)-(t.clientTop||0);const r=window.innerHeight||t.clientHeight||document.body.clientHeight,o=this.container.clientHeight,i=this.getSlideshowOffsetTop(),s=i+o-n,a=r+n-i;if(this.parallaxData.isVisible=s>0&&a>0,this.parallaxData.isVisible){const e=r+o,t=100*s/e,n=-1===this.conf.parallax?100-t:t;this.parallaxData.translation=-n/2}},onResize(){if(this.breakpointsData.list.length){const e=this.getCurrentBreakpoint();this.hasBreakpointChanged(e)&&this.setBreakpointConfig(e)}this.conf.parallax&&this.getSlideshowOffsetTop(!0)},onMouseEnter(){this.mouseOver=!0,this.conf.pauseOnHover&&this.conf.autoplay&&(this.isPaused=!0)},onMouseLeave(){this.mouseOver=!1,this.conf.pauseOnHover&&this.conf.autoplay&&(this.isPaused=!1)},onMouseDown(e){!this.touchEnabled||this.disable||(!e.touches&&this.preventYScroll&&e.preventDefault(),this.mouseDown=!0,this.touch.dragStartX=this.getCurrentMouseX(e),this.conf.draggingDistance||this.updateTrackTranslation(this.touch.dragStartX))},onMouseMove(e){if(this.mouseDown||this.touch.dragging)if(this.conf.autoplay&&(this.isPaused=!0),this.preventYScroll&&e.preventDefault(),this.mouseDown=!1,this.touch.dragging=!0,this.touch.dragNowX=this.getCurrentMouseX(e),this.conf.draggingDistance){this.touch.dragAmount=this.touch.dragNowX-this.touch.dragStartX;const e=this.touch.dragAmount/this.container.clientWidth;this.updateTrackTranslation(),this.transition.currentTranslation+=100*e}else this.updateTrackTranslation(this.touch.dragNowX)},onMouseUp(e){if(this.mouseDown=!1,!this.touch.dragging)return this.cancelSlideChange();this.conf.autoplay&&(("ontouchstart"in window||this.mouseOver)&&this.conf.pauseOnTouch||(this.isPaused=!1)),this.touch.dragging=!1;const t=this.conf.draggingDistance?-this.touch.dragAmount:0,n=(this.touch.dragStartX-this.container.offsetLeft)/this.container.clientWidth,r=(this.touch.dragNowX-this.container.offsetLeft)/this.container.clientWidth,o=100*((n<.5?0:1)-r);let i=(t||o)>0;if(this.conf.rtl&&(i=!i),[Math.abs(t)this.touch.justDragged=!1),50),this.touch.lazyloadTriggered=!1},onSlideshowTouch(){this.isPaused=!0},onOustideTouch(){this.isPaused=!1},justDragged(){return this.touch.justDragged},cancelSlideChange(){this.conf.fade||this.updateTrackTranslation()},getCurrentMouseX(e){return"ontouchstart"in window?e.touches[0].clientX:e.clientX},getBasicTranslation(){return this.slides.current/this.conf.visibleSlides},updateTrackTranslation(e=null){let t=this.getBasicTranslation();const{infinite:n,visibleSlides:r,slideMultiple:o,gap:i,"3d":s,lazy:a,lazyLoadOnDrag:l}=this.conf;if(n&&!1!==this.nextSlideIsClone&&(t=(this.nextSlideIsClone?this.slidesCount:-1)/r),i&&(t+=this.gapsCount/(r/o)*i/100),this.touch.dragStartX&&e&&(!n||!1===this.nextSlideIsClone)){let o=0;const i=(this.touch.dragStartX-this.container.offsetLeft)/this.container.clientWidth;let c=(e-this.container.offsetLeft)/this.container.clientWidth;if(s){const e=Math.round(i)?[0,2]:[-1,1];c=Math.min(Math.max(c,e[0]),e[1])}if(o=(i<.5?0:1)-c,t+=o*(this.conf.rtl?-1:1),a&&l&&!this.touch.lazyloadTriggered){this.touch.lazyloadTriggered=!0;let e=this.slides.current+(o>0?1:-1)*r;n&&-1===e?e=this.slidesCount-1:n&&e===this.slidesCount&&(e=0);for(let t=0;t0;let n=Math.min(this.preferredPosition,this.slides.current);e&&(n+=this.slidePosAfterPreferred),t-=n/r}this.transition.currentTranslation=100*-t*(this.conf.rtl?-1:1)},pauseAutoplay(){this.isPaused=!0,clearTimeout(this.autoplayTimer),this.autoplayTimer=0,this.emit("autoplay-pause")},resumeAutoplay(){this.isPaused=!1,this.doAutoplay(),this.emit("autoplay-resume")},doAutoplay(){clearTimeout(this.autoplayTimer),this.autoplayTimer=setTimeout((()=>{this.goToSlide(this.slides.current+this.conf.slideMultiple,{autoPlaying:!0})}),this.currentSlide.duration||this.conf.duration)},previous(e=!0){e&&this.emit("previous"),this.goToSlide(this.slides.current-this.conf.slideMultiple)},next(e=!0){e&&this.emit("next"),this.goToSlide(this.slides.current+this.conf.slideMultiple)},refreshParallax(){setTimeout((()=>{this.onResize(),this.onScroll()}),100)},getFirstVisibleSlide(e){const{slideMultiple:t,visibleSlides:n}=this.conf;let r=this.slides.current;return n>1&&t===n?r=Math.floor(e/n)*n:this.multipleSlides1by1&&(r=e-Math.min(e,this.preferredPosition)-Math.max(this.slidePosAfterPreferred,0)),r},getSlideInRange(e,t){let n=!1;this.conf.infinite&&-1===e?n=0:this.conf.infinite&&e===this.slidesCount&&(n=1);let r=(e+this.slidesCount)%this.slidesCount;if(this.conf.slideMultiple>1){const t=this.slidesCount%this.conf.slideMultiple||this.conf.slideMultiple,n=this.conf.slideMultiple-t;r+=e<0?n:0,r=this.getFirstVisibleSlide(r)}return this.conf.disableArrowsOnEdges&&(e<0||e>this.slidesCount-1)&&!t&&(r=this.slides.current),{nextSlide:r,clone:n}},goToSlide(e,{animation:t=!0,autoPlaying:n=!1,jumping:r=!1,breakpointChange:o=!1,emit:i=!0}={}){if(!this.slidesCount||this.disable)return;this.conf.autoplay&&!n&&!this.isPaused&&(this.isPaused=!0,this.$nextTick((()=>this.isPaused=!1))),this.transition.animated=t,setTimeout((()=>this.transition.animated=!1),this.transitionSpeed);const{nextSlide:s,clone:a}=this.getSlideInRange(e,n);if(this.nextSlideIsClone=a,!this.slides.list[s])return;if(this.conf.lazy)for(let c=0;c{const t=-1===e&&this.slides.current!==this.slidesCount-1,n=e===this.slidesCount&&0!==this.slides.current;t||n||(this.transition.speed=0,this.goToSlide(a?0:this.slidesCount-1,{animation:!1,jumping:!0}),setTimeout((()=>this.transition.speed=this.conf.transitionSpeed),50))}),this.transition.speed-50),this.slides.current=s,this.slides.firstVisible=this.getFirstVisibleSlide(s),o||(this.slides.focus=s),this.conf.fade||this.updateTrackTranslation(),this.slides.activeId=this.slides.list[this.slides.current].id,this.conf.autoplay&&n&&!this.isPaused&&this.doAutoplay(),this.slidesCount&&(this.isReady&&!r&&i&&this.emit("slide"),this.isReady&&this.conf.bullets&&!n&&!r&&this.$refs.bullets)){const e=this.$refs.bullets.children,t=e&&e[this.slides.current/this.conf.slideMultiple];if(t&&"button"===t.nodeName.toLowerCase()){let e=document.documentElement;this.pageScrollingElement&&(e=document.querySelector(this.pageScrollingElement));const n=e.scrollTop;t.focus({preventScroll:!0}),e.scrollTop=n}}},addSlide(e){return this.slides.list.push(e),this.isReady&&1===this.slidesCount&&this.conf.autoplay&&this.isPaused&&(this.isPaused=!1),this.slidesCount},addClone(){return this.updateTrackTranslation(),this.slidesCount},updateSlide(e,t){let n=this.slides.list.find((t=>t.id===e));n&&(n=Object.assign(n,t))},removeSlide(e){const t=this.slides.list.findIndex((t=>t.id===e));t>-1&&(this.slides.list.splice(t,1),this.slidesCount&&e===this.slides.activeId&&this.goToSlide(t-1,{autoPlaying:!0})),this.slides.current>=this.slidesCount&&this.goToSlide(0,{autoPlaying:!0})},loadSlide(e,t){e.loadImage().then((n=>{const{image:r,style:o}=n;e.loaded=!0,e.image=r,e.style=o,this.$emit("image-loaded",this.getSlideData(t))}),(()=>{e.loaded=!1,this.$emit("image-failed",this.getSlideData(t))}))},toggleTouchableOption(e){const{track:t}=this.$refs;if(!t)return;this.touchEnabled=e;const n="ontouchstart"in window;e?(this.$refs.track.addEventListener(n?"touchstart":"mousedown",this.onMouseDown,{passive:!this.preventYScroll}),document.addEventListener(n?"touchmove":"mousemove",this.onMouseMove,{passive:!this.preventYScroll}),document.addEventListener(n?"touchend":"mouseup",this.onMouseUp,{passive:!0})):this.removeEventListeners()},removeEventListeners(){const e="ontouchstart"in window;this.$refs.track.removeEventListener(e?"touchstart":"mousedown",this.onMouseDown,{passive:!this.preventYScroll}),document.removeEventListener(e?"touchmove":"mousemove",this.onMouseMove,{passive:!this.preventYScroll}),document.removeEventListener(e?"touchend":"mouseup",this.onMouseUp,{passive:!0})}},watch:{isPaused(e){this[e?"pauseAutoplay":"resumeAutoplay"]()},parallax(e){this[e?"enableParallax":"disableParallax"]()}},mounted(){this.init()},beforeUnmount(){this.removeEventListeners(),this.conf.parallax&&this.disableParallax(),window.removeEventListener("resize",this.onResize),document.removeEventListener("touchstart",(e=>{this[this.$el.contains(e.target)?"onSlideshowTouch":"onOustideTouch"]()})),this.container.removeEventListener("mouseenter",this.onMouseEnter),this.container.removeEventListener("mouseleave",this.onMouseLeave)}},Se=ee(we,[["render",Ee]]);var ke={components:{VueperSlides:Se,VueperSlide:ne},computed:{...(0,k.aH)("algolia",["ads"])},methods:{...(0,k.PY)("packages/details",["setCurrent"])}},Ce=n(6262);const Oe=(0,Ce.A)(ke,[["render",j],["__scopeId","data-v-8007fa0a"]]);var Te=Oe;const Re={class:"package-sorting__label"},Ae=["title","onClick"];function Ne(e,t,n,i,s,a){return(0,r.uX)(),(0,r.CE)("section",{class:"package-sorting",onClick:t[0]||(t[0]=t=>e.open=!e.open)},[(0,r.Lk)("label",Re,(0,o.v_)(e.$t("ui.discover.sortBy")),1),(0,r.Lk)("ul",{class:(0,o.C4)(["package-sorting__group",{"package-sorting__group--open":e.open}])},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(e.sortOptions,((t,n)=>((0,r.uX)(),(0,r.CE)("li",{key:t,class:(0,o.C4)(["package-sorting__item",{"package-sorting__item--active":e.sorting===t,"package-sorting__item--open":e.open}]),title:e.$t(`ui.discover.sort${n}Title`),onClick:n=>e.sortBy(t)},(0,o.v_)(e.$t(`ui.discover.sort${n}`)),11,Ae)))),128))],2)])}var Le={mixins:[C.A],data:()=>({open:!1,sortOptions:{Released:"released",Latest:"latest",Favers:"favers",Downloads:"downloads"}})};const Ie=(0,Ce.A)(Le,[["render",Ne]]);var Pe=Ie,xe=n(2361),Me=n(6966),De={mixins:[C.A],components:{LoadingButton:Me.A,SearchInput:xe.A,SearchSorting:Pe,AdBanner:Te,LoadingSpinner:T.A,DiscoverPackage:O.A},props:{wrapper:{required:!0},hideThemes:{type:Boolean,default:!1}},data:()=>({offline:!1,searching:!1,extensionCount:0,results:null,hasMore:!1}),computed:{...(0,k.aH)("algolia",["discover"])},methods:{...(0,k.PY)("packages/details",["setCurrent"]),async searchPackages(){this.searching=!0,this.offline=!1;try{const e={hitsPerPage:10*this.pages};this.hideThemes&&(e.facetFilters=["type:-contao-theme"]),this.query?e.query=this.query:this.sorting&&(e.sorting=this.sorting);const t=await this.$store.dispatch("algolia/findPackages",e);if(this.hasMore=t.nbPages>1,0===t.nbHits)return void(this.results={});const n={};t.hits.forEach((e=>{n[e.name]=e})),this.results=n}catch(e){this.offline=!0}this.searching=!1},async getOnline(){this.searching=!0,this.offline=!1,await this.$store.dispatch("algolia/discover"),this.searching=!1},async openSearch(e){this.results=null,await this.sortBy(e)}},watch:{sorting(){this.searchPackages()},query(){this.results=null,this.searchPackages()},pages(){this.searchPackages()}},created(){this.$watch(this.$i18n.locale,(()=>{this.isSearching&&this.searchPackages()}))},async mounted(){const e={hitsPerPage:0,attributesToRetrieve:null,attributesToHighlight:null,analytics:!1};this.hideThemes&&(e.facetFilters=["type:-contao-theme"]),this.$store.dispatch("algolia/findPackages",e).then((e=>{this.extensionCount=e.nbHits}),(()=>{})),this.isSearching&&this.searchPackages()}};const $e=(0,Ce.A)(De,[["render",S]]);var Fe=$e},5200:function(e,t,n){const r=n(560),o=(e,t,n)=>r(e,t,n)<=0;e.exports=o},5220:function(e,t,n){"use strict";n.d(t,{Bt:function(){return ce},aE:function(){return it}});var r=n(641),o=n(953); /*! * vue-router v4.5.0 * (c) 2024 Eduardo San Martin Morote * @license MIT */ const i="undefined"!==typeof document;function s(e){return"object"===typeof e||"displayName"in e||"props"in e||"__vccOpts"in e}function a(e){return e.__esModule||"Module"===e[Symbol.toStringTag]||e.default&&s(e.default)}const l=Object.assign;function c(e,t){const n={};for(const r in t){const o=t[r];n[r]=d(o)?o.map(e):e(o)}return n}const u=()=>{},d=Array.isArray;const f=/#/g,p=/&/g,h=/\//g,m=/=/g,v=/\?/g,g=/\+/g,y=/%5B/g,b=/%5D/g,_=/%5E/g,E=/%60/g,w=/%7B/g,S=/%7C/g,k=/%7D/g,C=/%20/g;function O(e){return encodeURI(""+e).replace(S,"|").replace(y,"[").replace(b,"]")}function T(e){return O(e).replace(w,"{").replace(k,"}").replace(_,"^")}function R(e){return O(e).replace(g,"%2B").replace(C,"+").replace(f,"%23").replace(p,"%26").replace(E,"`").replace(w,"{").replace(k,"}").replace(_,"^")}function A(e){return R(e).replace(m,"%3D")}function N(e){return O(e).replace(f,"%23").replace(v,"%3F")}function L(e){return null==e?"":N(e).replace(h,"%2F")}function I(e){try{return decodeURIComponent(""+e)}catch(t){}return""+e}const P=/\/$/,x=e=>e.replace(P,"");function M(e,t,n="/"){let r,o={},i="",s="";const a=t.indexOf("#");let l=t.indexOf("?");return a=0&&(l=-1),l>-1&&(r=t.slice(0,l),i=t.slice(l+1,a>-1?a:t.length),o=e(i)),a>-1&&(r=r||t.slice(0,a),s=t.slice(a,t.length)),r=H(null!=r?r:t,n),{fullPath:r+(i&&"?")+i+s,path:r,query:o,hash:I(s)}}function D(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function $(e,t){return t&&e.toLowerCase().startsWith(t.toLowerCase())?e.slice(t.length)||"/":e}function F(e,t,n){const r=t.matched.length-1,o=n.matched.length-1;return r>-1&&r===o&&j(t.matched[r],n.matched[o])&&U(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function j(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function U(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!B(e[n],t[n]))return!1;return!0}function B(e,t){return d(e)?V(e,t):d(t)?V(t,e):e===t}function V(e,t){return d(t)?e.length===t.length&&e.every(((e,n)=>e===t[n])):1===e.length&&e[0]===t}function H(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),o=r[r.length-1];".."!==o&&"."!==o||r.push("");let i,s,a=n.length-1;for(i=0;i1&&a--}return n.slice(0,a).join("/")+"/"+r.slice(i).join("/")}const W={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var X,G;(function(e){e["pop"]="pop",e["push"]="push"})(X||(X={})),function(e){e["back"]="back",e["forward"]="forward",e["unknown"]=""}(G||(G={}));function K(e){if(!e)if(i){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return"/"!==e[0]&&"#"!==e[0]&&(e="/"+e),x(e)}const z=/^[^#]+#/;function q(e,t){return e.replace(z,"#")+t}function Y(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const Q=()=>({left:window.scrollX,top:window.scrollY});function J(e){let t;if("el"in e){const n=e.el,r="string"===typeof n&&n.startsWith("#");0;const o="string"===typeof n?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=Y(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(null!=t.left?t.left:window.scrollX,null!=t.top?t.top:window.scrollY)}function Z(e,t){const n=history.state?history.state.position-t:-1;return n+e}const ee=new Map;function te(e,t){ee.set(e,t)}function ne(e){const t=ee.get(e);return ee.delete(e),t}let re=()=>location.protocol+"//"+location.host;function oe(e,t){const{pathname:n,search:r,hash:o}=t,i=e.indexOf("#");if(i>-1){let t=o.includes(e.slice(i))?e.slice(i).length:1,n=o.slice(t);return"/"!==n[0]&&(n="/"+n),$(n,"")}const s=$(n,e);return s+r+o}function ie(e,t,n,r){let o=[],i=[],s=null;const a=({state:i})=>{const a=oe(e,location),l=n.value,c=t.value;let u=0;if(i){if(n.value=a,t.value=i,s&&s===l)return void(s=null);u=c?i.position-c.position:0}else r(a);o.forEach((e=>{e(n.value,l,{delta:u,type:X.pop,direction:u?u>0?G.forward:G.back:G.unknown})}))};function c(){s=n.value}function u(e){o.push(e);const t=()=>{const t=o.indexOf(e);t>-1&&o.splice(t,1)};return i.push(t),t}function d(){const{history:e}=window;e.state&&e.replaceState(l({},e.state,{scroll:Q()}),"")}function f(){for(const e of i)e();i=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",d)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",d,{passive:!0}),{pauseListeners:c,listen:u,destroy:f}}function se(e,t,n,r=!1,o=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:o?Q():null}}function ae(e){const{history:t,location:n}=window,r={value:oe(e,n)},o={value:t.state};function i(r,i,s){const a=e.indexOf("#"),l=a>-1?(n.host&&document.querySelector("base")?e:e.slice(a))+r:re()+e+r;try{t[s?"replaceState":"pushState"](i,"",l),o.value=i}catch(c){console.error(c),n[s?"replace":"assign"](l)}}function s(e,n){const s=l({},t.state,se(o.value.back,e,o.value.forward,!0),n,{position:o.value.position});i(e,s,!0),r.value=e}function a(e,n){const s=l({},o.value,t.state,{forward:e,scroll:Q()});i(s.current,s,!0);const a=l({},se(r.value,e,null),{position:s.position+1},n);i(e,a,!1),r.value=e}return o.value||i(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0),{location:r,state:o,push:a,replace:s}}function le(e){e=K(e);const t=ae(e),n=ie(e,t.state,t.location,t.replace);function r(e,t=!0){t||n.pauseListeners(),history.go(e)}const o=l({location:"",base:e,go:r,createHref:q.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function ce(e){return e=location.host?e||location.pathname+location.search:"",e.includes("#")||(e+="#"),le(e)}function ue(e){return"string"===typeof e||e&&"object"===typeof e}function de(e){return"string"===typeof e||"symbol"===typeof e}const fe=Symbol("");var pe;(function(e){e[e["aborted"]=4]="aborted",e[e["cancelled"]=8]="cancelled",e[e["duplicated"]=16]="duplicated"})(pe||(pe={}));function he(e,t){return l(new Error,{type:e,[fe]:!0},t)}function me(e,t){return e instanceof Error&&fe in e&&(null==t||!!(e.type&t))}const ve="[^/]+?",ge={sensitive:!1,strict:!1,start:!0,end:!0},ye=/[.+*?^${}()[\]/\\]/g;function be(e,t){const n=l({},ge,t),r=[];let o=n.start?"^":"";const i=[];for(const l of e){const e=l.length?[]:[90];n.strict&&!l.length&&(o+="/");for(let t=0;tt.length?1===t.length&&80===t[0]?1:-1:0}function Ee(e,t){let n=0;const r=e.score,o=t.score;while(n0&&t[t.length-1]<0}const Se={type:0,value:""},ke=/[a-zA-Z0-9_]/;function Ce(e){if(!e)return[[]];if("/"===e)return[[Se]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(e){throw new Error(`ERR (${n})/"${c}": ${e}`)}let n=0,r=n;const o=[];let i;function s(){i&&o.push(i),i=[]}let a,l=0,c="",u="";function d(){c&&(0===n?i.push({type:0,value:c}):1===n||2===n||3===n?(i.length>1&&("*"===a||"+"===a)&&t(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),i.push({type:1,value:c,regexp:u,repeatable:"*"===a||"+"===a,optional:"*"===a||"?"===a})):t("Invalid state to consume buffer"),c="")}function f(){c+=a}while(l{s(h)}:u}function s(e){if(de(e)){const t=r.get(e);t&&(r.delete(e),n.splice(n.indexOf(t),1),t.children.forEach(s),t.alias.forEach(s))}else{const t=n.indexOf(e);t>-1&&(n.splice(t,1),e.record.name&&r.delete(e.record.name),e.children.forEach(s),e.alias.forEach(s))}}function a(){return n}function c(e){const t=xe(e,n);n.splice(t,0,e),e.record.name&&!Le(e)&&r.set(e.record.name,e)}function d(e,t){let o,i,s,a={};if("name"in e&&e.name){if(o=r.get(e.name),!o)throw he(1,{location:e});0,s=o.record.name,a=l(Re(t.params,o.keys.filter((e=>!e.optional)).concat(o.parent?o.parent.keys.filter((e=>e.optional)):[]).map((e=>e.name))),e.params&&Re(e.params,o.keys.map((e=>e.name)))),i=o.stringify(a)}else if(null!=e.path)i=e.path,o=n.find((e=>e.re.test(i))),o&&(a=o.parse(i),s=o.record.name);else{if(o=t.name?r.get(t.name):n.find((e=>e.re.test(t.path))),!o)throw he(1,{location:e,currentLocation:t});s=o.record.name,a=l({},t.params,e.params),i=o.stringify(a)}const c=[];let u=o;while(u)c.unshift(u.record),u=u.parent;return{name:s,path:i,params:a,matched:c,meta:Ie(c)}}function f(){n.length=0,r.clear()}return t=Pe({strict:!1,end:!0,sensitive:!1},t),e.forEach((e=>i(e))),{addRoute:i,resolve:d,removeRoute:s,clearRoutes:f,getRoutes:a,getRecordMatcher:o}}function Re(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function Ae(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:Ne(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function Ne(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const r in e.components)t[r]="object"===typeof n?n[r]:n;return t}function Le(e){while(e){if(e.record.aliasOf)return!0;e=e.parent}return!1}function Ie(e){return e.reduce(((e,t)=>l(e,t.meta)),{})}function Pe(e,t){const n={};for(const r in e)n[r]=r in t?t[r]:e[r];return n}function xe(e,t){let n=0,r=t.length;while(n!==r){const o=n+r>>1,i=Ee(e,t[o]);i<0?r=o:n=o+1}const o=Me(e);return o&&(r=t.lastIndexOf(o,r-1)),r}function Me(e){let t=e;while(t=t.parent)if(De(t)&&0===Ee(e,t))return t}function De({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function $e(e){const t={};if(""===e||"?"===e)return t;const n="?"===e[0],r=(n?e.slice(1):e).split("&");for(let o=0;oe&&R(e))):[r&&R(r)];o.forEach((e=>{void 0!==e&&(t+=(t.length?"&":"")+n,null!=e&&(t+="="+e))}))}return t}function je(e){const t={};for(const n in e){const r=e[n];void 0!==r&&(t[n]=d(r)?r.map((e=>null==e?null:""+e)):null==r?r:""+r)}return t}const Ue=Symbol(""),Be=Symbol(""),Ve=Symbol(""),He=Symbol(""),We=Symbol("");function Xe(){let e=[];function t(t){return e.push(t),()=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Ge(e,t,n,r,o,i=e=>e()){const s=r&&(r.enterCallbacks[o]=r.enterCallbacks[o]||[]);return()=>new Promise(((a,l)=>{const c=e=>{!1===e?l(he(4,{from:n,to:t})):e instanceof Error?l(e):ue(e)?l(he(2,{from:t,to:e})):(s&&r.enterCallbacks[o]===s&&"function"===typeof e&&s.push(e),a())},u=i((()=>e.call(r&&r.instances[o],t,n,c)));let d=Promise.resolve(u);e.length<3&&(d=d.then(c)),d.catch((e=>l(e)))}))}function Ke(e,t,n,r,o=e=>e()){const i=[];for(const l of e){0;for(const e in l.components){let c=l.components[e];if("beforeRouteEnter"===t||l.instances[e])if(s(c)){const s=c.__vccOpts||c,a=s[t];a&&i.push(Ge(a,n,r,l,e,o))}else{let s=c();0,i.push((()=>s.then((i=>{if(!i)throw new Error(`Couldn't resolve component "${e}" at "${l.path}"`);const s=a(i)?i.default:i;l.mods[e]=i,l.components[e]=s;const c=s.__vccOpts||s,u=c[t];return u&&Ge(u,n,r,l,e,o)()}))))}}}return i}function ze(e){const t=(0,r.WQ)(Ve),n=(0,r.WQ)(He);const i=(0,r.EW)((()=>{const n=(0,o.R1)(e.to);return t.resolve(n)})),s=(0,r.EW)((()=>{const{matched:e}=i.value,{length:t}=e,r=e[t-1],o=n.matched;if(!r||!o.length)return-1;const s=o.findIndex(j.bind(null,r));if(s>-1)return s;const a=et(e[t-2]);return t>1&&et(r)===a&&o[o.length-1].path!==a?o.findIndex(j.bind(null,e[t-2])):s})),a=(0,r.EW)((()=>s.value>-1&&Ze(n.params,i.value.params))),l=(0,r.EW)((()=>s.value>-1&&s.value===n.matched.length-1&&U(n.params,i.value.params)));function c(n={}){if(Je(n)){const n=t[(0,o.R1)(e.replace)?"replace":"push"]((0,o.R1)(e.to)).catch(u);return e.viewTransition&&"undefined"!==typeof document&&"startViewTransition"in document&&document.startViewTransition((()=>n)),n}return Promise.resolve()}return{route:i,href:(0,r.EW)((()=>i.value.href)),isActive:a,isExactActive:l,navigate:c}}function qe(e){return 1===e.length?e[0]:e}const Ye=(0,r.pM)({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:ze,setup(e,{slots:t}){const n=(0,o.Kh)(ze(e)),{options:i}=(0,r.WQ)(Ve),s=(0,r.EW)((()=>({[tt(e.activeClass,i.linkActiveClass,"router-link-active")]:n.isActive,[tt(e.exactActiveClass,i.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive})));return()=>{const o=t.default&&qe(t.default(n));return e.custom?o:(0,r.h)("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:s.value},o)}}}),Qe=Ye;function Je(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&(void 0===e.button||0===e.button)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function Ze(e,t){for(const n in t){const r=t[n],o=e[n];if("string"===typeof r){if(r!==o)return!1}else if(!d(o)||o.length!==r.length||r.some(((e,t)=>e!==o[t])))return!1}return!0}function et(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const tt=(e,t,n)=>null!=e?e:null!=t?t:n,nt=(0,r.pM)({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const i=(0,r.WQ)(We),s=(0,r.EW)((()=>e.route||i.value)),a=(0,r.WQ)(Be,0),c=(0,r.EW)((()=>{let e=(0,o.R1)(a);const{matched:t}=s.value;let n;while((n=t[e])&&!n.components)e++;return e})),u=(0,r.EW)((()=>s.value.matched[c.value]));(0,r.Gt)(Be,(0,r.EW)((()=>c.value+1))),(0,r.Gt)(Ue,u),(0,r.Gt)(We,s);const d=(0,o.KR)();return(0,r.wB)((()=>[d.value,u.value,e.name]),(([e,t,n],[r,o,i])=>{t&&(t.instances[n]=e,o&&o!==t&&e&&e===r&&(t.leaveGuards.size||(t.leaveGuards=o.leaveGuards),t.updateGuards.size||(t.updateGuards=o.updateGuards))),!e||!t||o&&j(t,o)&&r||(t.enterCallbacks[n]||[]).forEach((t=>t(e)))}),{flush:"post"}),()=>{const o=s.value,i=e.name,a=u.value,c=a&&a.components[i];if(!c)return rt(n.default,{Component:c,route:o});const f=a.props[i],p=f?!0===f?o.params:"function"===typeof f?f(o):f:null,h=e=>{e.component.isUnmounted&&(a.instances[i]=null)},m=(0,r.h)(c,l({},p,t,{onVnodeUnmounted:h,ref:d}));return rt(n.default,{Component:m,route:o})||m}}});function rt(e,t){if(!e)return null;const n=e(t);return 1===n.length?n[0]:n}const ot=nt;function it(e){const t=Te(e.routes,e),n=e.parseQuery||$e,s=e.stringifyQuery||Fe,a=e.history;const f=Xe(),p=Xe(),h=Xe(),m=(0,o.IJ)(W);let v=W;i&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const g=c.bind(null,(e=>""+e)),y=c.bind(null,L),b=c.bind(null,I);function _(e,n){let r,o;return de(e)?(r=t.getRecordMatcher(e),o=n):o=e,t.addRoute(o,r)}function E(e){const n=t.getRecordMatcher(e);n&&t.removeRoute(n)}function w(){return t.getRoutes().map((e=>e.record))}function S(e){return!!t.getRecordMatcher(e)}function k(e,r){if(r=l({},r||m.value),"string"===typeof e){const o=M(n,e,r.path),i=t.resolve({path:o.path},r),s=a.createHref(o.fullPath);return l(o,i,{params:b(i.params),hash:I(o.hash),redirectedFrom:void 0,href:s})}let o;if(null!=e.path)o=l({},e,{path:M(n,e.path,r.path).path});else{const t=l({},e.params);for(const e in t)null==t[e]&&delete t[e];o=l({},e,{params:y(t)}),r.params=y(r.params)}const i=t.resolve(o,r),c=e.hash||"";i.params=g(b(i.params));const u=D(s,l({},e,{hash:T(c),path:i.path})),d=a.createHref(u);return l({fullPath:u,hash:c,query:s===Fe?je(e.query):e.query||{}},i,{redirectedFrom:void 0,href:d})}function C(e){return"string"===typeof e?M(n,e,m.value.path):l({},e)}function O(e,t){if(v!==e)return he(8,{from:t,to:e})}function R(e){return P(e)}function A(e){return R(l(C(e),{replace:!0}))}function N(e){const t=e.matched[e.matched.length-1];if(t&&t.redirect){const{redirect:n}=t;let r="function"===typeof n?n(e):n;return"string"===typeof r&&(r=r.includes("?")||r.includes("#")?r=C(r):{path:r},r.params={}),l({query:e.query,hash:e.hash,params:null!=r.path?{}:e.params},r)}}function P(e,t){const n=v=k(e),r=m.value,o=e.state,i=e.force,a=!0===e.replace,c=N(n);if(c)return P(l(C(c),{state:"object"===typeof c?l({},o,c.state):o,force:i,replace:a}),t||n);const u=n;let d;return u.redirectedFrom=t,!i&&F(s,r,n)&&(d=he(16,{to:u,from:r}),re(r,r,!0,!1)),(d?Promise.resolve(d):j(u,r)).catch((e=>me(e)?me(e,2)?e:ee(e):q(e,u,r))).then((e=>{if(e){if(me(e,2))return P(l({replace:a},C(e.to),{state:"object"===typeof e.to?l({},o,e.to.state):o,force:i}),t||u)}else e=B(u,r,!0,a,o);return U(u,r,e),e}))}function x(e,t){const n=O(e,t);return n?Promise.reject(n):Promise.resolve()}function $(e){const t=se.values().next().value;return t&&"function"===typeof t.runWithContext?t.runWithContext(e):e()}function j(e,t){let n;const[r,o,i]=st(e,t);n=Ke(r.reverse(),"beforeRouteLeave",e,t);for(const a of r)a.leaveGuards.forEach((r=>{n.push(Ge(r,e,t))}));const s=x.bind(null,e,t);return n.push(s),le(n).then((()=>{n=[];for(const r of f.list())n.push(Ge(r,e,t));return n.push(s),le(n)})).then((()=>{n=Ke(o,"beforeRouteUpdate",e,t);for(const r of o)r.updateGuards.forEach((r=>{n.push(Ge(r,e,t))}));return n.push(s),le(n)})).then((()=>{n=[];for(const r of i)if(r.beforeEnter)if(d(r.beforeEnter))for(const o of r.beforeEnter)n.push(Ge(o,e,t));else n.push(Ge(r.beforeEnter,e,t));return n.push(s),le(n)})).then((()=>(e.matched.forEach((e=>e.enterCallbacks={})),n=Ke(i,"beforeRouteEnter",e,t,$),n.push(s),le(n)))).then((()=>{n=[];for(const r of p.list())n.push(Ge(r,e,t));return n.push(s),le(n)})).catch((e=>me(e,8)?e:Promise.reject(e)))}function U(e,t,n){h.list().forEach((r=>$((()=>r(e,t,n)))))}function B(e,t,n,r,o){const s=O(e,t);if(s)return s;const c=t===W,u=i?history.state:{};n&&(r||c?a.replace(e.fullPath,l({scroll:c&&u&&u.scroll},o)):a.push(e.fullPath,o)),m.value=e,re(e,t,n,c),ee()}let V;function H(){V||(V=a.listen(((e,t,n)=>{if(!ae.listening)return;const r=k(e),o=N(r);if(o)return void P(l(o,{replace:!0,force:!0}),r).catch(u);v=r;const s=m.value;i&&te(Z(s.fullPath,n.delta),Q()),j(r,s).catch((e=>me(e,12)?e:me(e,2)?(P(l(C(e.to),{force:!0}),r).then((e=>{me(e,20)&&!n.delta&&n.type===X.pop&&a.go(-1,!1)})).catch(u),Promise.reject()):(n.delta&&a.go(-n.delta,!1),q(e,r,s)))).then((e=>{e=e||B(r,s,!1),e&&(n.delta&&!me(e,8)?a.go(-n.delta,!1):n.type===X.pop&&me(e,20)&&a.go(-1,!1)),U(r,s,e)})).catch(u)})))}let G,K=Xe(),z=Xe();function q(e,t,n){ee(e);const r=z.list();return r.length?r.forEach((r=>r(e,t,n))):console.error(e),Promise.reject(e)}function Y(){return G&&m.value!==W?Promise.resolve():new Promise(((e,t)=>{K.add([e,t])}))}function ee(e){return G||(G=!e,H(),K.list().forEach((([t,n])=>e?n(e):t())),K.reset()),e}function re(t,n,o,s){const{scrollBehavior:a}=e;if(!i||!a)return Promise.resolve();const l=!o&&ne(Z(t.fullPath,0))||(s||!o)&&history.state&&history.state.scroll||null;return(0,r.dY)().then((()=>a(t,n,l))).then((e=>e&&J(e))).catch((e=>q(e,t,n)))}const oe=e=>a.go(e);let ie;const se=new Set,ae={currentRoute:m,listening:!0,addRoute:_,removeRoute:E,clearRoutes:t.clearRoutes,hasRoute:S,getRoutes:w,resolve:k,options:e,push:R,replace:A,go:oe,back:()=>oe(-1),forward:()=>oe(1),beforeEach:f.add,beforeResolve:p.add,afterEach:h.add,onError:z.add,isReady:Y,install(e){const t=this;e.component("RouterLink",Qe),e.component("RouterView",ot),e.config.globalProperties.$router=t,Object.defineProperty(e.config.globalProperties,"$route",{enumerable:!0,get:()=>(0,o.R1)(m)}),i&&!ie&&m.value===W&&(ie=!0,R(a.location).catch((e=>{0})));const n={};for(const o in W)Object.defineProperty(n,o,{get:()=>m.value[o],enumerable:!0});e.provide(Ve,t),e.provide(He,(0,o.Gc)(n)),e.provide(We,m);const r=e.unmount;se.add(e),e.unmount=function(){se.delete(e),se.size<1&&(v=W,V&&V(),V=null,m.value=W,ie=!1,G=!1),r()}}};function le(e){return e.reduce(((e,t)=>e.then((()=>$(t)))),Promise.resolve())}return ae}function st(e,t){const n=[],r=[],o=[],i=Math.max(t.matched.length,e.matched.length);for(let s=0;sj(e,i)))?r.push(i):n.push(i));const a=e.matched[s];a&&(t.matched.find((e=>j(e,a)))||o.push(a))}return[n,r,o]}},5342:function(e,t,n){const r=n(7075),o=(e,t,n)=>r(e,t,"<",n);e.exports=o},5397:function(e,t,n){"use strict";var r=n(7055),o=n(7750);e.exports=function(e){return r(o(e))}},5529:function(e,t,n){"use strict";n.d(t,{A:function(){return u}});var r=n(641),o=n(33);const i=["href","target","onClick"];function s(e,t,n,s,a,l){return(0,r.uX)(),(0,r.CE)("ul",{class:(0,o.C4)(l.cssClass)},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.items,((e,t)=>((0,r.uX)(),(0,r.CE)("li",{key:t,class:"link-menu__item"},[(0,r.Lk)("a",{class:"link-menu__action",href:e.href,target:e.target,onClick:t=>l.click(t,e)},(0,o.v_)(e.label),9,i)])))),128))],2)}var a={props:{items:{type:Array,required:!0},color:String,align:String,valign:String},computed:{cssClass:e=>({"link-menu":!0,[`link-menu--${e.color}`]:!!e.color,[`link-menu--align-${e.align}`]:!!e.align,[`link-menu--valign-${e.valign}`]:!!e.valign})},methods:{click(e,t){t.action&&(e.preventDefault(),t.action(t))}}},l=n(6262);const c=(0,l.A)(a,[["render",s]]);var u=c},5571:function(e,t,n){const r=n(7075),o=(e,t,n)=>r(e,t,">",n);e.exports=o},5580:function(e,t,n){const r=n(560),o=(e,t,n)=>r(e,t,n)>0;e.exports=o},5610:function(e,t,n){"use strict";var r=n(1291),o=Math.max,i=Math.min;e.exports=function(e,t){var n=r(e);return n<0?o(n+t,0):i(n,t)}},5633:function(e,t,n){"use strict";n.d(t,{Bx:function(){return Ae},Eg:function(){return Rt},FD:function(){return ne},VC:function(){return T}});var r=n(953),o=n(641),i=n(33),s=n(3751),a=Object.defineProperty,l=Object.defineProperties,c=Object.getOwnPropertyDescriptors,u=Object.getOwnPropertySymbols,d=Object.prototype.hasOwnProperty,f=Object.prototype.propertyIsEnumerable,p=(e,t,n)=>t in e?a(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,h=(e,t)=>{for(var n in t||(t={}))d.call(t,n)&&p(e,n,t[n]);if(u)for(var n of u(t))f.call(t,n)&&p(e,n,t[n]);return e},m=(e,t)=>l(e,c(t)),v=(e,t)=>{var n={};for(var r in e)d.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&u)for(var r of u(e))t.indexOf(r)<0&&f.call(e,r)&&(n[r]=e[r]);return n};const g="Notivue__",y=6e3,b={SUCCESS:"success",ERROR:"error",WARNING:"warning",INFO:"info",PROMISE:"promise",PROMISE_RESOLVE:"promise-resolve",PROMISE_REJECT:"promise-reject"},_={title:"",message:"",duration:y,ariaLive:"polite",ariaRole:"status"},E=m(h({},_),{ariaLive:"assertive",ariaRole:"alert"}),w=m(h({},_),{duration:1/0}),S=m(h({},E),{ariaLive:"polite"}),k=h({},_),C={[b.SUCCESS]:_,[b.ERROR]:E,[b.WARNING]:S,[b.INFO]:k,[b.PROMISE]:w,[b.PROMISE_RESOLVE]:_,[b.PROMISE_REJECT]:E},O={pauseOnHover:!0,pauseOnTouch:!0,pauseOnTabChange:!0,enqueue:!1,position:"top-center",teleportTo:"body",notifications:C,limit:1/0,avoidDuplicates:!1,transition:"transform 0.35s cubic-bezier(0.5, 1, 0.25, 1)",animations:{enter:g+"enter",leave:g+"leave",clearAll:g+"clearAll"}},T=N();function R(e){Object.assign(T,e)}function A(e){let t=0;function n(n,o,i=""+t++){return"string"===typeof(0,r.R1)(n)&&(n={message:n}),e.push(m(h({},n),{id:i,type:o})),{id:i,clear:()=>e.clear(i),destroy:()=>e.clear(i,{isDestroy:!0})}}return{success:e=>n(e,b.SUCCESS),error:e=>n(e,b.ERROR),warning:e=>n(e,b.WARNING),info:e=>n(e,b.INFO),promise:e=>{const{id:t,clear:r,destroy:o}=n(e,b.PROMISE);return{resolve:e=>n(e,b.PROMISE_RESOLVE,t),reject:e=>n(e,b.PROMISE_REJECT,t),success:e=>n(e,b.PROMISE_RESOLVE,t),error:e=>n(e,b.PROMISE_REJECT,t),clear:r,destroy:o}},load(e){return this.promise(e)},clearAll:()=>e.clearAll(),destroyAll:()=>e.destroyAll()}}function N(){const e=new Proxy({},{get:()=>()=>{}});return A(e)}const L="undefined"===typeof window;function I(e,t){const n=h({},e);for(const r in t)t.hasOwnProperty(r)&&(x(t[r])?n[r]=I(e[r],t[r]):n[r]=t[r]);return n}function P(e,t){return t.props||(t.props={}),h(h(h(h({},e[t.type]),e.global),t),"promise"===t.type?{duration:1/0}:{})}function x(e){if("[object Object]"!==Object.prototype.toString.call(e))return!1;const t=Object.getPrototypeOf(e);return null===t||null===Object.getPrototypeOf(t)}function M(e,t,n){const o=I(e,t);function i(e){return(0,r.rY)(((t,r)=>({get(){return t(),e},set(t){n.value&&(e=t,r())}})))}for(const r in o)o[r]=i(o[r]);return o}function D(e){return Object.entries(e).reduce(((e,[t,{value:n}])=>m(h({},e),{[t]:(0,r.ux)(n)})),{})}const $=e=>e===b.SUCCESS||e===b.ERROR||e===b.WARNING||e===b.INFO,F=["timeout","resumedAt","remaining","animationAttrs","positionStyles"];function j(e){return Object.fromEntries(Object.entries(e).filter((([e])=>!F.includes(e))))}let U=()=>{};function B(e,t){const n=V(e,t),r=H(),o=W(n,r),i=X(),s=G(n,o,r,i),a=K(o,s);return{config:n,queue:r,items:o,elements:i,animations:s,timeouts:a}}function V(e,t){const n=M(O,e,t);function r(e){if(t.value){"function"===typeof e&&(e=e(D(n)));for(const t in e)"object"===typeof n[t].value?n[t].value=I(n[t].value,e[t]):n[t].value=e[t]}}return U=r,m(h({},n),{update:r})}function H(){return{entries:(0,r.IJ)([]),get length(){return this.entries.value.length},add(e){this.entries.value.push(e),this.triggerRef()},get(e){return this.entries.value.find((t=>t.id===e))},update(e,t){const n=this.get(e);n&&Object.assign(n,t)},remove(e){this.entries.value=this.entries.value.filter((t=>t.id!==e))},triggerRef(){(0,r.mu)(this.entries)},clear(){this.entries.value=[]}}}function W(e,t){return{entries:(0,r.IJ)([]),get length(){return this.entries.value.length},lifecycleEventsCount:(0,r.KR)(0),addLifecycleEvent(){this.lifecycleEventsCount.value++},clearLifecycleEvents(){this.lifecycleEventsCount.value=0},add(e){this.entries.value.unshift(e),this.triggerRef(),this.addLifecycleEvent()},addFromQueue(){const e=m(h({},t.entries.value[0]),{timeout:t.entries.value[0].timeout(),createdAt:Date.now()});t.remove(e.id),this.add(e)},findDupe(e){return this.entries.value.find((t=>(0,r.R1)(t.message).replace(/\uFEFF/g,"")===(0,r.R1)(e.message).replace(/\uFEFF/g,"")&&(0,r.R1)(t.title)===(0,r.R1)(e.title)&&t.type===e.type))},get(e){return this.entries.value.find((t=>t.id===e))},update(e,t){const n=this.get(e);n&&Object.assign(n,t)},triggerRef(){(0,r.mu)(this.entries)},updateAll(e){this.entries.value=this.entries.value.map(e)},remove(n){this.entries.value=this.entries.value.filter((e=>e.id!==n));const r=t.length>0&&this.length+t.dataset.notivueItem-+e.dataset.notivueItem))},containers:(0,r.KR)([])}}function G(e,t,n,o){return{isReducedMotion:(0,r.KR)(!1),setReducedMotion(e){this.isReducedMotion.value=e},playLeave(n,{isDestroy:r=!1,isUserTriggered:o=!1}={}){const{leave:i=""}=e.animations.value,s=t.get(n);window.clearTimeout(null==s?void 0:s.timeout);const a=e=>{var r;e&&e.currentTarget!==e.target||(null==(r=null==s?void 0:s[o?"onManualClear":"onAutoClear"])||r.call(s,j(s)),t.remove(n))};if(!s||!i||r||this.isReducedMotion.value)return t.addLifecycleEvent(),a();t.update(n,{positionStyles:m(h({},s.positionStyles),{zIndex:-1}),animationAttrs:{class:i,onAnimationend:a}}),t.addLifecycleEvent()},playClearAll(){t.entries.value.forEach((e=>window.clearTimeout(e.timeout)));const{clearAll:r=""}=e.animations.value,i=()=>{n.clear(),t.clear()};if(!r||this.isReducedMotion.value)return i();o.setRootAttrs({class:r,onAnimationend:i})},updatePositions({isImmediate:n=!1}={}){const r=this.isReducedMotion.value||n,i=0===e.position.value.indexOf("top"),s=e.animations.value.leave;let a=0;for(const l of o.getSortedItems()){const n=l.dataset.notivueItem,o=t.get(n);l&&o&&o.animationAttrs.class!==s&&(t.update(n,{positionStyles:{transform:`translate3d(0, ${a}px, 0)`,transition:r?"none":e.transition.value}}),a+=(i?1:-1)*l.clientHeight)}t.triggerRef()}}}function K(e,t){return{isStreamPaused:(0,r.KR)(!1),isStreamFocused:(0,r.KR)(!1),debounceTimeout:void 0,setStreamPause(e=!0){this.isStreamPaused.value=e},setStreamFocus(e=!0){this.isStreamFocused.value=e},clearDebounceTimeout(){window.clearTimeout(this.debounceTimeout)},reset(){this.clearDebounceTimeout(),this.setStreamPause(!1),this.setStreamFocus(!1)},create(e,n){if(!this.isStreamPaused.value)return Number.isFinite(n)&&n>0?window.setTimeout((()=>t.playLeave(e)),n):void 0},pause(){0===e.length||this.isStreamPaused.value||(this.setStreamPause(),e.updateAll((e=>{var t;if(window.clearTimeout(e.timeout),e.duration===1/0)return e;let n=0;return n=null==e.remaining?e.duration-(Date.now()-(null!=(t=e.resumedAt)?t:e.createdAt)):e.remaining-(Date.now()-e.resumedAt),m(h({},e),{remaining:n})})))},resume(){0!==e.length&&this.isStreamPaused.value&&(this.setStreamPause(!1),e.updateAll((e=>{var t;return window.clearTimeout(e.timeout),e.duration===1/0?e:m(h({},e),{timeout:this.create(e.id,null!=(t=e.remaining)?t:e.duration),resumedAt:Date.now()})})))},resumeWithDebounce(e){this.debounceTimeout=window.setTimeout((()=>{this.resume()}),e)}}}function z({config:e,items:t,queue:n,animations:o,timeouts:i}){return{destroyAll(){n.clear(),t.clear()},clearAll(){o.playClearAll()},clear(e,{isDestroy:n=!1}={}){var r;const s=(null==(r=t.entries.value[t.entries.value.length-1])?void 0:r.id)===e;s&&i.resume(),o.playLeave(e,{isUserTriggered:!0,isDestroy:n})},push(s){const a=P(e.notifications.value,s),l=Date.now();if(e.avoidDuplicates.value&&$(a.type)){const e=t.findDupe(a);e&&(window.clearTimeout(e.timeout),t.update(e.id,{createdAt:l,duration:a.duration,remaining:void 0,timeout:i.create(e.id,a.duration),duplicateCount:e.duplicateCount+1}),(0,r.i9)(e.message)?e.message.value+="\ufeff":e.message+="\ufeff",t.triggerRef());const o=t.findDupe.call(n,a);if(o&&(n.update(o.id,{duration:a.duration,createdAt:l,duplicateCount:o.duplicateCount+1}),n.triggerRef()),o||e)return}const c=()=>i.create(a.id,a.duration);if(s.type===b.PROMISE_RESOLVE||s.type===b.PROMISE_REJECT)n.get(a.id)?(n.update(a.id,m(h({},a),{createdAt:l,timeout:c})),n.triggerRef()):(t.update(a.id,m(h({},a),{createdAt:l,timeout:c()})),t.triggerRef());else{const r=e.enqueue.value,u=t.length>=e.limit.value,d=!r&&u,f=r&&!s.skipQueue&&u;d&&t.entries.value.slice(e.limit.value-1).forEach((e=>i.create(e.id,1)));const p=m(h({},a),{createdAt:l,duplicateCount:0,animationAttrs:{class:o.isReducedMotion.value?"":e.animations.value.enter,onAnimationend(){p.animationAttrs.class===e.animations.value.enter&&t.update(a.id,{animationAttrs:{class:"",onAnimationend:()=>{}}})}},timeout:f?c:c(),clear:()=>this.clear(a.id),destroy:()=>this.clear(a.id,{isDestroy:!0})});f?n.add(p):t.add(p)}}}}const q=Symbol(),Y=Symbol();function Q(e){return[(0,o.wB)(e.items.lifecycleEventsCount,(()=>{e.animations.updatePositions()}),{flush:"post"}),(0,o.wB)(e.config.position,(()=>{e.animations.updatePositions({isImmediate:!0})}),{flush:"post"}),(0,o.wB)((()=>0===e.items.length&&0===e.queue.length),(t=>{t&&(e.timeouts.reset(),e.elements.setRootAttrs({}))}),{flush:"post"})]}let J=()=>{},Z=()=>{};function ee(e){const t=(0,r.KR)(e),n=(0,r.tB)(t);function o(r,o){const i=()=>Q(r);e&&R(o);let s=e?i():[()=>{}];const a={isRunning:n,startInstance(){t.value||(R(o),s=i(),t.value=!0)},stopInstance(){t.value&&(r.items.clear(),r.queue.clear(),r.items.clearLifecycleEvents(),R(N()),s.forEach((e=>e())),t.value=!1)}};return J=()=>a.startInstance(),Z=()=>a.stopInstance(),a}return{isRunning:n,setupInstance:o}}function te(e,t){const{setupInstance:n,isRunning:r}=ee(e),o=B(t,r),i=z(o),s=Object.freeze(A(i)),a=n(o,s);return{store:o,instance:a,push:s}}function ne(e={}){return{install(t){var n;const r=e,{startOnCreation:o=!0}=r,i=v(r,["startOnCreation"]),{store:s,instance:a,push:l}=te(o,i);t.provide(q,a),t.provide(Y,s),(n=t.config.globalProperties).$push||(n.$push=l)}}}function re(){return(0,o.WQ)(Y)}function oe(){return L?{isRunning:(0,r.KR)(!0),startInstance:()=>{},stopInstance:()=>{}}:(0,o.WQ)(q)}function ie(){if(L)return m(h({},(0,r.QW)((0,r.Kh)(O))),{update:()=>{},isTopAlign:(0,o.EW)((()=>!0)),isStreamPaused:(0,r.KR)(!1)});const e=re();return m(h({},e.config),{isStreamPaused:(0,r.tB)(e.timeouts.isStreamPaused),isTopAlign:(0,o.EW)((()=>0===e.config.position.value.indexOf("top")))})}const se=Symbol(""),ae='a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]',le={comboKey:"n",handleClicks:!0,leaveMessage:"You're leaving the notifications stream. Press Control + N to navigate it again.",emptyMessage:"No notifications to navigate",renderAnnouncement:!0,maxAnnouncements:2};const ce={listAriaLabel:"Notifications"},ue=(0,o.pM)({setup(e,{slots:t,attrs:n}){const i=(0,r.KR)(!1);return(0,o.sV)((()=>i.value=!0)),()=>{var e;return i.value?null==(e=t.default)?void 0:e.call(t):(0,o.CE)("span",n,"")}}}),de=e=>"mouse"===e.pointerType;function fe(e){return`${e.title?`${e.title}: `:""}${e.message}`}const pe=["role","aria-live"],he=(0,o.pM)({__name:"AriaLive",props:{item:{}},setup(e){const t=e,n={position:"absolute",width:"1px",height:"1px",padding:"0",margin:"-1px",overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",border:"0"};return(e,s)=>((0,o.uX)(),(0,o.CE)("div",{style:n,role:t.item.ariaRole,"aria-live":t.item.ariaLive,key:`${e.item.id}_${e.item.type}`,"aria-atomic":"true"},(0,i.v_)((0,r.R1)(fe)(t.item)),9,pe))}});function me(){const{timeouts:e,config:t}=re();function n(t){de(t)&&e.pause()}function r(t){de(t)&&e.resume()}return(0,o.EW)((()=>t.pauseOnHover.value&&!e.isStreamFocused.value?{onPointerenter:n,onPointerleave:r}:{}))}function ve(){const{timeouts:e,config:t}=re();function n(t){de(t)||(e.clearDebounceTimeout(),e.pause(),e.resumeWithDebounce(2e3))}return(0,o.xo)((()=>{e.clearDebounceTimeout()})),(0,o.EW)((()=>t.pauseOnTouch.value&&!e.isStreamFocused.value?{onPointerdown:n}:{}))}const ge={boxSizing:"border-box"},ye={list:m(h({},ge),{display:"flex",justifyContent:"center",listStyle:"none",margin:"0 auto",maxWidth:"var(--nv-root-width, 100%)",padding:"0",pointerEvents:"none",position:"fixed",zIndex:"var(--nv-z, 500)"}),listItem:m(h({},ge),{display:"flex",margin:"0",position:"absolute",transitionProperty:"transform",width:"100%"}),itemContainer:m(h({},ge),{maxWidth:"100%",padding:"0 0 var(--nv-gap, 0.75rem) 0",pointerEvents:"auto"})};function be(){const{isTopAlign:e,position:t}=ie(),n=(0,o.EW)((()=>{const t=e.value,n=[`var(--nv-root-top, ${t?"1.25rem":"0px"})`,"var(--nv-root-right, 1.25rem)",`var(--nv-root-bottom, ${t?"0px":"1.25rem"})`,"var(--nv-root-left, 1.25rem)"],r=n.map((e=>`calc(-1 * ${e})`));return t?r.splice(2,1,"0px"):r.splice(0,1,"0px"),{inset:n.join(" "),clipPath:`inset(${r.join(" ")})`}})),r=(0,o.EW)((()=>({[e.value?"top":"bottom"]:"0",justifyContent:`var(--nv-root-x-align, ${t.value.endsWith("left")?"flex-start":t.value.endsWith("right")?"flex-end":"center"})`})));return(0,o.EW)((()=>({list:h(h({},ye.list),n.value),listItem:h(h({},ye.listItem),r.value),itemContainer:ye.itemContainer})))}function _e(e){function t(){window.matchMedia("(max-width: 1100px)").matches&&e()}(0,o.sV)((()=>{window.addEventListener("resize",t)})),(0,o.xo)((()=>{window.removeEventListener("resize",t)}))}function Ee(e,t){let n;const r=new WeakSet;(0,o.sV)((()=>{n=new ResizeObserver(((e,n)=>{for(const o of e)r.has(o.target)?Object.values(o.contentRect.toJSON()).every((e=>0===e))?(r.delete(o.target),n.unobserve(o.target)):(t(),r.delete(o.target),n.unobserve(o.target)):r.add(o.target)}))})),(0,o.wB)(e,(e=>{e.length>0&&e.forEach((e=>null==n?void 0:n.observe(e)))}),{flush:"post"}),(0,o.xo)((()=>{null==n||n.disconnect()}))}function we(){const{elements:e,animations:t}=re();_e((()=>t.updatePositions({isImmediate:!0}))),Ee(e.items.value,(()=>t.updatePositions()))}function Se(){const{config:e,timeouts:t}=re();function n(){t.isStreamFocused.value||e.pauseOnTabChange.value&&t.resume()}function r(){t.isStreamFocused.value||e.pauseOnTabChange.value&&t.pause()}(0,o.sV)((()=>{window.addEventListener("focus",n),window.addEventListener("blur",r)})),(0,o.xo)((()=>{window.removeEventListener("focus",n),window.removeEventListener("blur",r)}))}function ke(){const{animations:e}=re(),t=window.matchMedia("(prefers-reduced-motion: reduce)"),n=()=>e.setReducedMotion(t.matches);(0,o.sV)((()=>{var e;n(),null==(e=t.addEventListener)||e.call(t,"change",n)})),(0,o.xo)((()=>{var e;null==(e=t.removeEventListener)||e.call(t,"change",n)}))}const Ce=["data-notivue-align","aria-label"],Oe=["data-notivue-item","aria-setsize","aria-posinset"],Te=["aria-label","tabindex","data-notivue-container"],Re=(0,o.pM)({__name:"NotivueImpl",props:(0,o.HF)({class:{},containersTabIndex:{},listAriaLabel:{},styles:{}},ce),setup(e){const t=e,{config:n,items:s,elements:a}=re(),l=be(),c=me(),u=ve();return ke(),Se(),we(),(e,d)=>{var f;return(0,o.uX)(),(0,o.Wv)(o.Im,{to:!1===(0,r.R1)(n).teleportTo.value?void 0:(0,r.R1)(n).teleportTo.value,disabled:!1===(0,r.R1)(n).teleportTo.value},[(0,r.R1)(s).entries.value.length>0?((0,o.uX)(),(0,o.CE)("ol",(0,o.v6)({key:0},h(h(h({},(0,r.R1)(c)),(0,r.R1)(u)),(0,r.R1)(a).rootAttrs.value),{"data-notivue-align":(0,r.R1)(n).position.value.split("-")[0],"aria-label":t.listAriaLabel,ref:(0,r.R1)(a).root,class:t.class,style:h(h({},(0,r.R1)(l).list),null==(f=t.styles)?void 0:f.list)}),[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)((0,r.R1)(s).entries.value,((n,c)=>{var u,d,f,p;return(0,o.uX)(),(0,o.CE)("li",{tabindex:"-1",key:n.id,"data-notivue-item":n.id,"aria-setsize":(0,r.R1)(s).length,"aria-posinset":c+1,ref_for:!0,ref:(0,r.R1)(a).items,style:(0,i.Tr)(h(h(h({},(0,r.R1)(l).listItem),n.positionStyles),null==(u=t.styles)?void 0:u.listItem))},[n.ariaLiveOnly?((0,o.uX)(),(0,o.Wv)(he,{key:0,item:n},null,8,["item"])):((0,o.uX)(),(0,o.CE)("div",(0,o.v6)({key:1,ref_for:!0},n.animationAttrs,{"aria-label":(0,r.R1)(fe)(n),tabindex:null!=(f=null==(d=e.containersTabIndex)?void 0:d[n.id])?f:-1,"data-notivue-container":n.id,ref_for:!0,ref:(0,r.R1)(a).containers,style:h(h({},(0,r.R1)(l).itemContainer),null==(p=t.styles)?void 0:p.itemContainer)}),[(0,o.RG)(e.$slots,"default",(0,o.v6)({ref_for:!0},(0,r.R1)(j)(n)))],16,Te))],12,Oe)})),128))],16,Ce)):(0,o.Q3)("",!0)],8,["to","disabled"])}}}),Ae=(0,o.pM)({__name:"Notivue",props:(0,o.HF)({class:{},containersTabIndex:{},listAriaLabel:{},styles:{}},ce),setup(e){const t=e,{isRunning:n}=oe();return(e,s)=>((0,o.uX)(),(0,o.Wv)((0,r.R1)(ue),null,{default:(0,o.k6)((()=>[(0,r.R1)(n)?((0,o.uX)(),(0,o.Wv)(Re,(0,i._B)((0,o.v6)({key:0},t)),{default:(0,o.k6)((t=>[(0,o.RG)(e.$slots,"default",(0,i._B)((0,o.Ng)(t)))])),_:3},16)):(0,o.Q3)("",!0)])),_:3}))}}),Ne={touchOnly:!1,exclude:"a, button",disabled:!1,threshold:.5},Le=300,Ie={Mouse:200,Touch:1e3,TouchExternal:1400};Boolean,Boolean,Boolean;function Pe(){const e=(0,r.KR)(!1),t=()=>e.value=!0,n=()=>e.value=!1,i=[["keydown",t],["mousedown",n],["touchstart",n]];return(0,o.sV)((()=>{i.forEach((([e,t])=>document.addEventListener(e,t)))})),(0,o.xo)((()=>{i.forEach((([e,t])=>document.removeEventListener(e,t)))})),{isKeyboardFocus:e}}function xe(){const{root:e}=re().elements,t=(0,r.KR)(null);function n(n){var r;const o=n.target instanceof HTMLElement;o&&(null==(r=e.value)?void 0:r.contains(n.target))||o&&(t.value=n.target)}function i(){t.value?t.value.focus():(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),document.body.focus())}return(0,o.sV)((()=>{document.addEventListener("focus",n,!0)})),(0,o.xo)((()=>{document.removeEventListener("focus",n,!0)})),{focusLastElement:i}}const Me=(0,o.pM)({__name:"NotivueKeyboardImpl",props:(0,o.HF)({comboKey:{},handleClicks:{type:Boolean},leaveMessage:{},emptyMessage:{},renderAnnouncement:{type:Boolean},maxAnnouncements:{}},le),setup(e){const t=e,{comboKey:n,handleClicks:s,leaveMessage:a,emptyMessage:l,renderAnnouncement:c,maxAnnouncements:u}=(0,r.QW)(t),d={ariaRole:"alert",ariaLive:"assertive",skipQueue:!0,ariaLiveOnly:!c.value,props:{isNotivueKeyboard:!0}},f=(0,o.EW)((()=>h({message:a.value},d))),p=(0,o.EW)((()=>h({message:l.value},d))),{elements:m,timeouts:v,queue:g}=re(),y=ie(),{focusLastElement:b}=xe(),{isKeyboardFocus:_}=Pe(),E=(0,r.KR)({qualified:[],unqualified:[]}),w=(0,r.KR)([]),S=(0,r.KR)([]),k=(0,r.KR)(-1);function C(e){k.value=e}let O=0,R=!0,A=[];const N=(0,o.EW)((()=>{const e={};return E.value.qualified.forEach((t=>e[t]=k.value)),E.value.unqualified.forEach((t=>e[t]=-1)),e}));function L(){0!==w.value.length&&(C(0),v.setStreamFocus(),v.pause(),(0,o.dY)((()=>{w.value[0].focus()})))}function I({announce:e=!0}={}){b(),C(-1),v.setStreamFocus(!1),v.resume(),e&&O({id:e.dataset.notivueContainer,container:e}))).sort(((e,t)=>+t.id-+e.id)).forEach((({id:e,container:i})=>{const s=Array.from(i.querySelectorAll(ae)).filter((e=>e instanceof HTMLElement));o.push(...s),s.length>1?(t.qualified.push(e),n.push(i)):(t.unqualified.push(e),r.push(i))})),E.value=t,w.value=n,S.value=r,A=o}function x(e){!e.shiftKey&&"Tab"===e.key&&w.value.length>0&&(e.preventDefault(),R&&(R=!1),L(),(0,o.dY)(D))}function M(){D(),document.addEventListener("keydown",x)}function D(){document.removeEventListener("keydown",x)}(0,o.Gt)(se,{containersTabIndex:N,elementsTabIndex:(0,r.tB)(k)}),(0,o.wB)(m.containers,P,{deep:!0}),(0,o.wB)(w,((e,t,n)=>{if(0===e.length)return;const r=e.length>0,o=e.some((e=>!t.some((t=>t===e)))),i=o&&v.isStreamFocused.value,s=o&&!v.isStreamFocused.value||r&&R;i?e[0].focus():s&&M(),n((()=>{s&&D()}))}),{flush:"post"}),(0,o.wB)(S,(e=>{y.enqueue.value&&v.isStreamFocused.value&&e.length>0&&(w.value.length>0?w.value[0].focus():I({announce:!1}))}),{flush:"post"});let $=!1;function F(e){let t=0;const n=w.value.some(((n,r)=>{if(n.contains(e.target)||n===e.target)return t=r,!0}));if(n){if("Escape"===e.key)return e.preventDefault(),$=!0,I();if(!s.value)return;const n=e.target instanceof HTMLButtonElement||e.target instanceof HTMLAnchorElement;if(n&&(" "===e.key||" "===e.key||"Enter"===e.key)){if(e.preventDefault(),$=!0,e.target.click(),g.length>0)return;const n=w.value[t+1];n?n.focus():I()}}}function j(e){if(e.ctrlKey&&(e.key===n.value.toLowerCase()||e.key===n.value.toUpperCase())){if(e.preventDefault(),v.isStreamFocused.value)return $=!0,I();w.value.length>0?L():T.info(p.value)}}function U(e){var t;v.isStreamFocused.value&&!_.value&&((null==(t=m.root.value)?void 0:t.contains(e.target))||I(),A.includes(e.target)&&I())}(0,o.wB)(m.root,((e,t,n)=>{function r(t){if(t.preventDefault(),t.stopPropagation(),v.isStreamFocused.value&&_.value)return $?$=!1:void((null==e?void 0:e.contains(t.relatedTarget))||I())}e&&e.addEventListener("focusout",r),n((()=>{e&&e.removeEventListener("focusout",r)}))}),{immediate:!0,flush:"post"});const B=[["click",U],["keydown",F],["keydown",j]];return(0,o.sV)((()=>{B.forEach((([e,t])=>document.addEventListener(e,t)))})),(0,o.xo)((()=>{B.forEach((([e,t])=>{document.removeEventListener(e,t)}))})),(e,t)=>(0,o.RG)(e.$slots,"default",(0,i._B)((0,o.Ng)({containersTabIndex:N.value,elementsTabIndex:k.value})))}}),De=(Boolean,Boolean,(0,o.Lk)("path",{d:"M6,-0c-3.308,-0 -6,2.692 -6,6c-0,3.308 2.692,6 6,6c3.308,-0 6,-2.692 6,-6c-0,-3.308 -2.692,-6 -6,-6Zm3.123,3.989l-3.877,4.616c-0.086,0.102 -0.213,0.162 -0.346,0.164l-0.008,0c-0.131,0 -0.256,-0.055 -0.343,-0.153l-1.662,-1.846c-0.081,-0.085 -0.126,-0.199 -0.126,-0.316c0,-0.254 0.209,-0.462 0.462,-0.462c0.135,0 0.263,0.059 0.35,0.161l1.307,1.451l3.536,-4.209c0.087,-0.101 0.215,-0.159 0.349,-0.159c0.253,-0 0.461,0.208 0.461,0.461c0,0.107 -0.036,0.21 -0.103,0.292Z"},null,-1)),$e=[De],Fe=(0,o.pM)({__name:"SuccessIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)((0,r.R1)(ht))),$e,16))}}),je=(0,o.Lk)("path",{d:"M6,-0c-3.308,-0 -6,2.692 -6,6c-0,3.308 2.692,6 6,6c3.308,-0 6,-2.692 6,-6c-0,-3.308 -2.692,-6 -6,-6Zm-0,9.228c-0.316,0 -0.577,-0.26 -0.577,-0.577c0,-0.316 0.261,-0.577 0.577,-0.577c0.316,0 0.577,0.261 0.577,0.577c-0,0.317 -0.261,0.577 -0.577,0.577Zm0.627,-5.802l-0.166,3.519c-0,0.253 -0.208,0.462 -0.462,0.462c-0.253,-0 -0.461,-0.209 -0.461,-0.462l-0.166,-3.518l0,-0.001c-0,-0.009 -0,-0.018 -0,-0.027c-0,-0.344 0.283,-0.627 0.627,-0.627c0.344,0 0.627,0.283 0.627,0.627c-0,0.009 -0,0.018 -0.001,0.027l0.002,-0Z"},null,-1),Ue=[je],Be=(0,o.pM)({__name:"ErrorIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)((0,r.R1)(ht))),Ue,16))}}),Ve=(0,o.Lk)("path",{d:"M6,0c-3.308,0 -6,2.692 -6,6c0,3.308 2.692,6 6,6c3.308,0 6,-2.692 6,-6c0,-3.308 -2.692,-6 -6,-6Zm0,2.46c0.428,0 0.78,0.352 0.78,0.78c-0,0.428 -0.352,0.78 -0.78,0.78c-0.428,0 -0.78,-0.352 -0.78,-0.78c0,-0.428 0.352,-0.78 0.78,-0.78Zm1.44,6.78l-2.64,0c-0.263,0 -0.48,-0.217 -0.48,-0.48c0,-0.263 0.217,-0.48 0.48,-0.48l0.84,0l0,-2.64l-0.48,0c-0.263,0 -0.48,-0.217 -0.48,-0.48c0,-0.263 0.217,-0.48 0.48,-0.48l0.96,0c0.263,0 0.48,0.217 0.48,0.48l0,3.12l0.84,0c0.263,0 0.48,0.217 0.48,0.48c0,0.263 -0.217,0.48 -0.48,0.48Z"},null,-1),He=[Ve],We=(0,o.pM)({__name:"InfoIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)((0,r.R1)(ht))),He,16))}}),Xe=(0,o.Lk)("path",{d:"M11.963,6.037c-0,3.292 -2.671,5.963 -5.963,5.963c-3.292,0 -5.963,-2.671 -5.963,-5.963c0,-3.292 2.671,-5.962 5.963,-5.962c3.292,-0 5.963,2.67 5.963,5.962Zm-0.918,0c0,-2.785 -2.26,-5.045 -5.045,-5.045c-2.785,0 -5.045,2.26 -5.045,5.045c-0,2.786 2.26,5.046 5.045,5.046c2.785,-0 5.045,-2.26 5.045,-5.046Z"},null,-1),Ge=(0,o.Lk)("path",{d:"M8.401,3.449c0.163,-0.194 0.452,-0.219 0.646,-0.056c0.194,0.163 0.219,0.452 0.056,0.646l-3.853,4.587c-0.085,0.101 -0.21,0.161 -0.343,0.163c-0.133,0.003 -0.26,-0.053 -0.349,-0.151l-1.651,-1.835c-0.169,-0.188 -0.154,-0.479 0.034,-0.648c0.188,-0.169 0.479,-0.154 0.648,0.034l1.298,1.443l3.514,-4.183Z"},null,-1),Ke=[Xe,Ge],ze=(0,o.pM)({__name:"SuccessOutlineIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)((0,r.R1)(ht))),Ke,16))}}),qe=(0,o.Lk)("path",{d:"M12, 6c0, 3.313 -2.687, 6 -6, 6c-3.313,-0 -6,-2.688 -6,-6c0,-3.313 2.688,-6 6,-6c3.313,-0 6,2.687 6,6Zm-0.923,-0c-0,-2.803 -2.274,-5.077 -5.077,-5.077c-2.803,0 -5.077,2.274 -5.077,5.077c0,2.803 2.274,5.077 5.077,5.077c2.803,-0 5.077,-2.274 5.077,-5.077Z"},null,-1),Ye=(0,o.Lk)("path",{d:"M5.373,3.426c-0,-0.009 -0,-0.019 -0,-0.028c-0,-0.342 0.279,-0.624 0.621,-0.627c0.002,-0 0.004,-0 0.006,-0c0.344,-0 0.627,0.283 0.627,0.627c-0,0.009 -0,0.019 -0.001,0.028l0,0.001l-0.165,3.518c-0.012,0.246 -0.215,0.44 -0.461,0.44c-0.246,-0 -0.449,-0.194 -0.461,-0.44l-0.166,-3.518l0,-0.001Z"},null,-1),Qe=(0,o.Lk)("path",{d:"M6,9.228c-0.316,0 -0.577,-0.26 -0.577,-0.577c0,-0.316 0.261,-0.577 0.577,-0.577c0.316,0 0.577,0.261 0.577,0.577c-0,0.317 -0.261,0.577 -0.577,0.577Z"},null,-1),Je=[qe,Ye,Qe],Ze=(0,o.pM)({__name:"ErrorOutlineIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)((0,r.R1)(ht))),Je,16))}}),et=(0,o.Lk)("path",{d:"M6, 0c3.313, 0 6, 2.687 6, 6c-0, 3.313 -2.687, 6 -6, 6c-3.313,-0 -6,-2.687 -6,-6c0,-3.313 2.687,-6 6,-6Zm0, 0.96c-2.783, 0 -5.04, 2.257 -5.04, 5.04c0, 2.783 2.257, 5.04 5.04, 5.04c2.783, 0 5.04,-2.257 5.04,-5.04c-0,-2.783 -2.257,-5.04 -5.04,-5.04Z"},null,-1),tt=(0,o.Lk)("path",{d:"M6.6, 8.28l0.84, 0c0.265, 0 0.48, 0.215 0.48, 0.48c-0, 0.265 -0.215, 0.48 -0.48, 0.48l-2.64,-0c-0.265, 0 -0.48,-0.215 -0.48,-0.48c-0,-0.265 0.215,-0.48 0.48,-0.48l0.84, 0l-0,-2.64l-0.48, 0c-0.265, 0 -0.48,-0.215 -0.48,-0.48c-0,-0.265 0.215,-0.48 0.48,-0.48l0.96, 0c0.265, 0 0.48, 0.215 0.48, 0.48l-0, 3.12Z"},null,-1),nt=(0,o.Lk)("path",{d:"M6, 2.46c-0.428, 0 -0.78, 0.352 -0.78, 0.78c-0, 0.428 0.352, 0.78 0.78, 0.78c0.428, 0 0.78,-0.352 0.78,-0.78c-0,-0.428 -0.352,-0.78 -0.78,-0.78Z"},null,-1),rt=[et,tt,nt],ot=(0,o.pM)({__name:"InfoOutlineIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)((0,r.R1)(ht))),rt,16))}}),it=(0,o.Lk)("path",{d:"M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z",opacity:".25"},null,-1),st=(0,o.Lk)("path",{d:"M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z",class:"Notivue__spinner"},null,-1),at=[it,st],lt=(0,o.pM)({__name:"PromiseIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)(m(h({},(0,r.R1)(pt)),{width:28,height:28,fill:"currentColor"}))),at,16))}}),ct=(0,o.Lk)("line",{x1:"18",y1:"6",x2:"6",y2:"18"},null,-1),ut=(0,o.Lk)("line",{x1:"6",y1:"6",x2:"18",y2:"18"},null,-1),dt=[ct,ut],ft=(0,o.pM)({__name:"CloseIcon",setup(e){return(e,t)=>((0,o.uX)(),(0,o.CE)("svg",(0,i._B)((0,o.Ng)((0,r.R1)(mt))),dt,16))}}),pt={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24","aria-hidden":"true"},ht=m(h({},pt),{fill:"currentColor",viewBox:"0 0 12 12"}),mt=m(h({},pt),{stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"}),vt={[b.SUCCESS]:(0,r.IG)(Fe),[b.ERROR]:(0,r.IG)(Be),[b.INFO]:(0,r.IG)(We),[b.WARNING]:(0,r.IG)(Be),[b.PROMISE]:(0,r.IG)(lt),[b.PROMISE_RESOLVE]:(0,r.IG)(Fe),[b.PROMISE_REJECT]:(0,r.IG)(Be),close:(0,r.IG)(ft)},gt=(b.SUCCESS,(0,r.IG)(ze),b.ERROR,(0,r.IG)(Ze),b.INFO,(0,r.IG)(ot),b.WARNING,(0,r.IG)(Ze),b.PROMISE,(0,r.IG)(lt),b.PROMISE_RESOLVE,(0,r.IG)(ze),b.PROMISE_REJECT,(0,r.IG)(Ze),(0,r.IG)(ft),{"--nv-width":"350px","--nv-spacing":"0.625rem","--nv-radius":"0.625rem","--nv-icon-size":"1.25rem","--nv-title-size":"0.925rem","--nv-message-size":"0.925rem","--nv-y-align":"center"}),yt={"--nv-shadow":"rgba(0, 0, 0, 0.06) 0px 4px 6px -1px, rgba(0, 0, 0, 0.03) 0px 2px 4px -1px"},bt=m(h(h({},gt),yt),{"--nv-global-bg":"#FFF","--nv-global-fg":"#171717","--nv-success-accent":"#28B780","--nv-error-accent":"#E74C3C","--nv-warning-accent":"#F59E0B","--nv-info-accent":"#3E8EFF","--nv-promise-accent":"#171717"}),_t=(m(h(h({},gt),yt),{"--nv-success-bg":"#E9FAEF","--nv-success-accent":"#059669","--nv-success-fg":"#057452","--nv-error-bg":"#FEEFEF","--nv-error-accent":"#E6523C","--nv-error-fg":"#C5412C","--nv-warning-bg":"#FFF0D8","--nv-warning-accent":"#F48533","--nv-warning-fg":"#81471D","--nv-info-bg":"#DEF0FA","--nv-info-accent":"#1F70AC","--nv-info-fg":"#1F70AC","--nv-promise-bg":"#FFF","--nv-promise-accent":"#334155","--nv-promise-fg":"#334155"}),m(h(h({},gt),yt),{"--nv-global-accent":"#FFF","--nv-global-fg":"#FFF","--nv-success-bg":"#178570","--nv-error-bg":"#C94430","--nv-info-bg":"#117AAE","--nv-warning-bg":"#FFE556","--nv-warning-fg":"#4F5358","--nv-warning-accent":"#4F5358","--nv-promise-bg":"#FFF","--nv-promise-fg":"#334155","--nv-promise-accent":"#64748B"}),m(h({},gt),{"--nv-border-width":"1px","--nv-global-bg":"#1F1F1F","--nv-global-border":"#414141","--nv-global-fg":"#D0D0D0","--nv-success-accent":"#8EF997","--nv-error-accent":"#FF7777","--nv-warning-accent":"#FFE554","--nv-info-accent":"#5FD4FF","--nv-promise-accent":"#D0D0D0"}),m(h({},gt),{"--nv-border-width":"1px","--nv-global-bg":"#20252E","--nv-global-border":"#353b45","--nv-global-fg":"#dfdfdf","--nv-success-accent":"#34D399","--nv-error-accent":"#FF7777","--nv-warning-accent":"#FFE554","--nv-info-accent":"#5FD4FF","--nv-promise-accent":"#D0D0D0"}),{NOTIFICATION:g+"notification",ICON:g+"icon",CONTENT:g+"content",TITLE:g+"content-title",MESSAGE:g+"content-message",CLOSE:g+"close",CLOSE_ICON:g+"close-icon",TRANSITION:g+"transition",PROGRESS:g+"progress",DUPLICATE:g+"duplicate"}),Et={icons:()=>vt,theme:()=>bt,hideClose:!1,closeAriaLabel:"Close"},wt=["data-notivue","data-notivue-has-title"],St=["aria-live","role"],kt=["textContent"],Ct=["textContent"],Ot=["aria-label"],Tt=["textContent"],Rt=(0,o.pM)({__name:"Notification",props:(0,o.HF)({item:{},icons:{},theme:{},closeAriaLabel:{},hideClose:{type:Boolean}},Et),setup(e){const t=e,n=(0,r.IJ)(t.icons[t.item.type]),a=t.icons.close;return(0,o.wB)((()=>t.item.type),(e=>n.value=t.icons[e]),{flush:"sync"}),(e,l)=>((0,o.uX)(),(0,o.CE)("div",{class:(0,i.C4)([(0,r.R1)(_t).NOTIFICATION,{[(0,r.R1)(_t).DUPLICATE]:e.item.duplicateCount>0}]),key:e.item.duplicateCount,"data-notivue":e.item.type,"data-notivue-has-title":Boolean(e.item.title),style:(0,i.Tr)(e.theme)},[n.value?((0,o.uX)(),(0,o.CE)(o.FK,{key:0},["object"===typeof n.value?((0,o.uX)(),(0,o.Wv)(s.eB,{key:0,name:(0,r.R1)(_t).TRANSITION,mode:"out-in"},{default:(0,o.k6)((()=>["object"===typeof n.value?((0,o.uX)(),(0,o.Wv)((0,o.$y)(n.value),{key:0,class:(0,i.C4)((0,r.R1)(_t).ICON),"aria-hidden":"true"},null,8,["class"])):(0,o.Q3)("",!0)])),_:1},8,["name"])):"string"===typeof n.value?((0,o.uX)(),(0,o.CE)("div",{key:1,class:(0,i.C4)((0,r.R1)(_t).ICON),"aria-hidden":"true"},(0,i.v_)(n.value),3)):(0,o.Q3)("",!0)],64)):(0,o.Q3)("",!0),(0,o.Lk)("div",{class:(0,i.C4)((0,r.R1)(_t).CONTENT),"aria-live":e.item.ariaLive,role:e.item.ariaRole,"aria-atomic":"true"},[e.item.title?((0,o.uX)(),(0,o.CE)("h3",{key:0,class:(0,i.C4)((0,r.R1)(_t).TITLE),textContent:(0,i.v_)((0,r.R1)(e.item.title))},null,10,kt)):(0,o.Q3)("",!0),(0,o.Lk)("p",{class:(0,i.C4)((0,r.R1)(_t).MESSAGE),textContent:(0,i.v_)((0,r.R1)(e.item.message))},null,10,Ct)],10,St),!t.hideClose&&(0,r.R1)(a)&&"promise"!==e.item.type?((0,o.uX)(),(0,o.CE)("button",{key:1,class:(0,i.C4)((0,r.R1)(_t).CLOSE),"aria-label":e.closeAriaLabel,type:"button",tabindex:"-1",onClick:l[0]||(l[0]=(...t)=>e.item.clear&&e.item.clear(...t))},["object"===typeof(0,r.R1)(a)?((0,o.uX)(),(0,o.Wv)((0,o.$y)((0,r.R1)(a)),{key:0,class:(0,i.C4)((0,r.R1)(_t).CLOSE_ICON)},null,8,["class"])):"string"===typeof(0,r.R1)(a)?((0,o.uX)(),(0,o.CE)("div",{key:1,"aria-hidden":"true",textContent:(0,i.v_)((0,r.R1)(a))},null,8,Tt)):(0,o.Q3)("",!0)],10,Ot)):(0,o.Q3)("",!0),(0,o.RG)(e.$slots,"default")],14,wt))}})},5745:function(e,t,n){"use strict";var r=n(7629);e.exports=function(e,t){return r[e]||(r[e]=t||{})}},5917:function(e,t,n){"use strict";var r=n(3724),o=n(9039),i=n(4055);e.exports=!r&&!o((function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},5951:function(e,t,n){"use strict";n.d(t,{A:function(){return d}});var r=n(641),o=n(33);const i=["src"],s={key:1,xmlns:"http://www.w3.org/2000/svg",viewBox:"2 2 20 20"};function a(e,t,n,a,l,c){return(0,r.uX)(),(0,r.CE)("div",null,[(0,r.Lk)("figure",{class:(0,o.C4)(c.computedClass)},[n.src?((0,r.uX)(),(0,r.CE)("img",{key:0,src:n.src,loading:"lazy",alt:""},null,8,i)):((0,r.uX)(),(0,r.CE)("svg",s,t[0]||(t[0]=[(0,r.Lk)("path",{d:"M4 4h7V2H4a2 2 0 0 0-2 2v7h2V4zm6 9-4 5h12l-3-4-2 2.7-3-3.7zm7-4.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0zM20 2h-7v2h7v7h2V4a2 2 0 0 0-2-2zm0 18h-7v2h7a2 2 0 0 0 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z"},null,-1)])))],2)])}var l={props:{src:String,componentClass:String},computed:{computedClass:e=>({"package-logo--fallback":!e.src,[e.componentClass]:!!e.componentClass,[`${e.componentClass}--fallback`]:!!e.componentClass&&!e.src})}},c=n(6262);const u=(0,c.A)(l,[["render",a],["__scopeId","data-v-9c1c5f6c"]]);var d=u},5966:function(e,t,n){"use strict";var r=n(9306),o=n(4117);e.exports=function(e,t){var n=e[t];return o(n)?void 0:r(n)}},6077:function(e,t,n){"use strict";n.d(t,{A:function(){return R}});var r=n(641),o=n(33);const i={key:0,class:"discover-package__hint"},s={class:"discover-package__inside"},a=["title"],l={class:"discover-package__details"},c={class:"discover-package__headline-container"},u=["title"],d=["title"],f={class:"discover-package__more"},p={class:"discover-package__counts"},h=["title"],m={key:1,class:"discover-package__count discover-package__count--updated"},v={key:2,class:"discover-package__count discover-package__count--downloads"},g={key:3,class:"discover-package__count discover-package__count--favers"},y={class:"discover-package__actions"};function b(e,t,n,b,_,E){const w=(0,r.g2)("package-logo"),S=(0,r.g2)("details-button");return(0,r.uX)(),(0,r.CE)("article",{class:(0,o.C4)(["discover-package",n.hint||!E.slotEmpty(e.$slots.hint)?"is--hint":""])},[n.hint||!E.slotEmpty(e.$slots.hint)?((0,r.uX)(),(0,r.CE)("div",i,[(0,r.RG)(e.$slots,"hint",{},(()=>[(0,r.eW)((0,o.v_)(n.hint),1)]))])):(0,r.Q3)("",!0),(0,r.Lk)("div",s,[n.data.abandoned?((0,r.uX)(),(0,r.CE)("div",{key:0,class:"discover-package__abandoned",title:E.abandonedText},(0,o.v_)(e.$t("ui.package.abandoned")),9,a)):(0,r.Q3)("",!0),(0,r.bF)(w,{class:(0,o.C4)(["discover-package__icon",{"discover-package__icon--fallback":!n.data.logo}]),src:n.data.logo},null,8,["class","src"]),(0,r.Lk)("div",l,[(0,r.Lk)("div",c,[n.data.contaoVersions?((0,r.uX)(),(0,r.CE)("ul",{key:0,class:(0,o.C4)(["discover-package__versions",{"discover-package__versions--fallback":!n.data.logo}]),title:`${e.$t("ui.package.contaoVersion")} ${n.data.contaoVersions.join(", ")}`},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(n.data.contaoVersions,((e,t)=>((0,r.uX)(),(0,r.CE)("li",{class:"discover-package__version",key:t},(0,o.v_)(e),1)))),128))],10,u)):(0,r.Q3)("",!0),(0,r.Lk)("h1",{class:(0,o.C4)(["discover-package__headline",{"discover-package__headline--fallback":!n.data.logo}]),title:n.data.name!==n.data.title?n.data.name:""},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(E.title.split("%%"),((e,t)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[t%2?((0,r.uX)(),(0,r.CE)("em",{key:t},(0,o.v_)(e),1)):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[(0,r.eW)((0,o.v_)(e),1)],64))],64)))),256))],10,d)]),(0,r.Lk)("p",{class:(0,o.C4)(["discover-package__description",{"discover-package__description--fallback":!n.data.logo}])},[((0,r.uX)(!0),(0,r.CE)(r.FK,null,(0,r.pI)(E.description.split("%%"),((e,t)=>((0,r.uX)(),(0,r.CE)(r.FK,null,[t%2?((0,r.uX)(),(0,r.CE)("em",{key:t},(0,o.v_)(e),1)):((0,r.uX)(),(0,r.CE)(r.FK,{key:1},[(0,r.eW)((0,o.v_)(e),1)],64))],64)))),256))],2),(0,r.Lk)("div",f,[(0,r.Lk)("p",p,[n.data.private?((0,r.uX)(),(0,r.CE)("span",{key:0,class:"discover-package__count discover-package__count--private",title:e.$t("ui.package.privateTitle")},(0,o.v_)(e.$t("ui.package.private")),9,h)):(0,r.Q3)("",!0),n.data.updated?((0,r.uX)(),(0,r.CE)("span",m,(0,o.v_)(E.datimFormat(n.data.updated,!1,"short")),1)):(0,r.Q3)("",!0),n.data.downloads?((0,r.uX)(),(0,r.CE)("span",v,(0,o.v_)(E.numberFormat(n.data.downloads)),1)):(0,r.Q3)("",!0),n.data.favers?((0,r.uX)(),(0,r.CE)("span",g,(0,o.v_)(E.numberFormat(n.data.favers)),1)):(0,r.Q3)("",!0)]),(0,r.Lk)("div",y,[(0,r.bF)(S,{small:"",name:n.data.name},null,8,["name"]),(0,r.RG)(e.$slots,"actions")])])])])],2)}var _=n(4210),E=n(266),w=n(9451),S=n(5951),k=n(9071),C={components:{PackageLogo:S.A,DetailsButton:k.A},props:{data:Object,hint:String},computed:{title:e=>e.data._highlightResult?e.data._highlightResult.title.value:e.data.title||e.data.name,description:e=>e.data._highlightResult?e.data._highlightResult.description.value:e.data.description,abandonedText:e=>!0===e.data.abandoned?e.$t("ui.package.abandonedText"):e.$t("ui.package.abandonedReplace",{replacement:e.data.abandoned})},methods:{datimFormat:_.A,numberFormat:E.A,slotEmpty:w.A}},O=n(6262);const T=(0,O.A)(C,[["render",b]]);var R=T},6080:function(e,t,n){"use strict";var r=n(7476),o=n(9306),i=n(616),s=r(r.bind);e.exports=function(e,t){return o(e),void 0===t?e:i?s(e,t):function(){return e.apply(t,arguments)}}},6119:function(e,t,n){"use strict";var r=n(5745),o=n(3392),i=r("keys");e.exports=function(e){return i[e]||(i[e]=o(e))}},6170:function(e,t,n){const r=n(3908),o=n(144),{safeRe:i,t:s}=n(9718),a=(e,t)=>{if(e instanceof r)return e;if("number"===typeof e&&(e=String(e)),"string"!==typeof e)return null;t=t||{};let n=null;if(t.rtl){const r=t.includePrerelease?i[s.COERCERTLFULL]:i[s.COERCERTL];let o;while((o=r.exec(e))&&(!n||n.index+n[0].length!==e.length))n&&o.index+o[0].length===n.index+n[0].length||(n=o),r.lastIndex=o.index+o[1].length+o[2].length;r.lastIndex=-1}else n=e.match(t.includePrerelease?i[s.COERCEFULL]:i[s.COERCE]);if(null===n)return null;const a=n[2],l=n[3]||"0",c=n[4]||"0",u=t.includePrerelease&&n[5]?`-${n[5]}`:"",d=t.includePrerelease&&n[6]?`+${n[6]}`:"";return o(`${a}.${l}.${c}${u}${d}`,t)};e.exports=a},6198:function(e,t,n){"use strict";var r=n(8014);e.exports=function(e){return r(e.length)}},6254:function(e,t,n){const r=n(3908),o=(e,t)=>new r(e,t).minor;e.exports=o},6262:function(e,t){"use strict";t.A=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n}},6269:function(e){"use strict";e.exports={}},6278:function(e,t,n){"use strict";n.d(t,{y$:function(){return ee},i0:function(){return se},L8:function(){return ie},PY:function(){return oe},aH:function(){return re}});var r=n(641),o=n(953);function i(){return s().__VUE_DEVTOOLS_GLOBAL_HOOK__}function s(){return"undefined"!==typeof navigator&&"undefined"!==typeof window?window:"undefined"!==typeof globalThis?globalThis:{}}const a="function"===typeof Proxy,l="devtools-plugin:setup",c="plugin:settings:set";let u,d;function f(){var e;return void 0!==u||("undefined"!==typeof window&&window.performance?(u=!0,d=window.performance):"undefined"!==typeof globalThis&&(null===(e=globalThis.perf_hooks)||void 0===e?void 0:e.performance)?(u=!0,d=globalThis.perf_hooks.performance):u=!1),u}function p(){return f()?d.now():Date.now()}class h{constructor(e,t){this.target=null,this.targetQueue=[],this.onQueue=[],this.plugin=e,this.hook=t;const n={};if(e.settings)for(const s in e.settings){const t=e.settings[s];n[s]=t.defaultValue}const r=`__vue-devtools-plugin-settings__${e.id}`;let o=Object.assign({},n);try{const e=localStorage.getItem(r),t=JSON.parse(e);Object.assign(o,t)}catch(i){}this.fallbacks={getSettings(){return o},setSettings(e){try{localStorage.setItem(r,JSON.stringify(e))}catch(i){}o=e},now(){return p()}},t&&t.on(c,((e,t)=>{e===this.plugin.id&&this.fallbacks.setSettings(t)})),this.proxiedOn=new Proxy({},{get:(e,t)=>this.target?this.target.on[t]:(...e)=>{this.onQueue.push({method:t,args:e})}}),this.proxiedTarget=new Proxy({},{get:(e,t)=>this.target?this.target[t]:"on"===t?this.proxiedOn:Object.keys(this.fallbacks).includes(t)?(...e)=>(this.targetQueue.push({method:t,args:e,resolve:()=>{}}),this.fallbacks[t](...e)):(...e)=>new Promise((n=>{this.targetQueue.push({method:t,args:e,resolve:n})}))})}async setRealTarget(e){this.target=e;for(const t of this.onQueue)this.target.on[t.method](...t.args);for(const t of this.targetQueue)t.resolve(await this.target[t.method](...t.args))}}function m(e,t){const n=e,r=s(),o=i(),c=a&&n.enableEarlyProxy;if(!o||!r.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__&&c){const e=c?new h(n,o):null,i=r.__VUE_DEVTOOLS_PLUGINS__=r.__VUE_DEVTOOLS_PLUGINS__||[];i.push({pluginDescriptor:n,setupFn:t,proxy:e}),e&&t(e.proxiedTarget)}else o.emit(l,e,t)} /*! * vuex v4.1.0 * (c) 2022 Evan You * @license MIT */ var v="store";function g(e,t){Object.keys(e).forEach((function(n){return t(e[n],n)}))}function y(e){return null!==e&&"object"===typeof e}function b(e){return e&&"function"===typeof e.then}function _(e,t){return function(){return e(t)}}function E(e,t,n){return t.indexOf(e)<0&&(n&&n.prepend?t.unshift(e):t.push(e)),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}function w(e,t){e._actions=Object.create(null),e._mutations=Object.create(null),e._wrappedGetters=Object.create(null),e._modulesNamespaceMap=Object.create(null);var n=e.state;k(e,n,[],e._modules.root,!0),S(e,n,t)}function S(e,t,n){var i=e._state,s=e._scope;e.getters={},e._makeLocalGettersCache=Object.create(null);var a=e._wrappedGetters,l={},c={},u=(0,o.uY)(!0);u.run((function(){g(a,(function(t,n){l[n]=_(t,e),c[n]=(0,r.EW)((function(){return l[n]()})),Object.defineProperty(e.getters,n,{get:function(){return c[n].value},enumerable:!0})}))})),e._state=(0,o.Kh)({data:t}),e._scope=u,e.strict&&N(e),i&&n&&e._withCommit((function(){i.data=null})),s&&s.stop()}function k(e,t,n,r,o){var i=!n.length,s=e._modules.getNamespace(n);if(r.namespaced&&(e._modulesNamespaceMap[s],e._modulesNamespaceMap[s]=r),!i&&!o){var a=L(t,n.slice(0,-1)),l=n[n.length-1];e._withCommit((function(){a[l]=r.state}))}var c=r.context=C(e,s,n);r.forEachMutation((function(t,n){var r=s+n;T(e,r,t,c)})),r.forEachAction((function(t,n){var r=t.root?n:s+n,o=t.handler||t;R(e,r,o,c)})),r.forEachGetter((function(t,n){var r=s+n;A(e,r,t,c)})),r.forEachChild((function(r,i){k(e,t,n.concat(i),r,o)}))}function C(e,t,n){var r=""===t,o={dispatch:r?e.dispatch:function(n,r,o){var i=I(n,r,o),s=i.payload,a=i.options,l=i.type;return a&&a.root||(l=t+l),e.dispatch(l,s)},commit:r?e.commit:function(n,r,o){var i=I(n,r,o),s=i.payload,a=i.options,l=i.type;a&&a.root||(l=t+l),e.commit(l,s,a)}};return Object.defineProperties(o,{getters:{get:r?function(){return e.getters}:function(){return O(e,t)}},state:{get:function(){return L(e.state,n)}}}),o}function O(e,t){if(!e._makeLocalGettersCache[t]){var n={},r=t.length;Object.keys(e.getters).forEach((function(o){if(o.slice(0,r)===t){var i=o.slice(r);Object.defineProperty(n,i,{get:function(){return e.getters[o]},enumerable:!0})}})),e._makeLocalGettersCache[t]=n}return e._makeLocalGettersCache[t]}function T(e,t,n,r){var o=e._mutations[t]||(e._mutations[t]=[]);o.push((function(t){n.call(e,r.state,t)}))}function R(e,t,n,r){var o=e._actions[t]||(e._actions[t]=[]);o.push((function(t){var o=n.call(e,{dispatch:r.dispatch,commit:r.commit,getters:r.getters,state:r.state,rootGetters:e.getters,rootState:e.state},t);return b(o)||(o=Promise.resolve(o)),e._devtoolHook?o.catch((function(t){throw e._devtoolHook.emit("vuex:error",t),t})):o}))}function A(e,t,n,r){e._wrappedGetters[t]||(e._wrappedGetters[t]=function(e){return n(r.state,r.getters,e.state,e.getters)})}function N(e){(0,r.wB)((function(){return e._state.data}),(function(){0}),{deep:!0,flush:"sync"})}function L(e,t){return t.reduce((function(e,t){return e[t]}),e)}function I(e,t,n){return y(e)&&e.type&&(n=t,t=e,e=e.type),{type:e,payload:t,options:n}}var P="vuex bindings",x="vuex:mutations",M="vuex:actions",D="vuex",$=0;function F(e,t){m({id:"org.vuejs.vuex",app:e,label:"Vuex",homepage:"https://next.vuex.vuejs.org/",logo:"https://vuejs.org/images/icons/favicon-96x96.png",packageName:"vuex",componentStateTypes:[P]},(function(n){n.addTimelineLayer({id:x,label:"Vuex Mutations",color:j}),n.addTimelineLayer({id:M,label:"Vuex Actions",color:j}),n.addInspector({id:D,label:"Vuex",icon:"storage",treeFilterPlaceholder:"Filter stores..."}),n.on.getInspectorTree((function(n){if(n.app===e&&n.inspectorId===D)if(n.filter){var r=[];X(r,t._modules.root,n.filter,""),n.rootNodes=r}else n.rootNodes=[W(t._modules.root,"")]})),n.on.getInspectorState((function(n){if(n.app===e&&n.inspectorId===D){var r=n.nodeId;O(t,r),n.state=G(z(t._modules,r),"root"===r?t.getters:t._makeLocalGettersCache,r)}})),n.on.editInspectorState((function(n){if(n.app===e&&n.inspectorId===D){var r=n.nodeId,o=n.path;"root"!==r&&(o=r.split("/").filter(Boolean).concat(o)),t._withCommit((function(){n.set(t._state.data,o,n.state.value)}))}})),t.subscribe((function(e,t){var r={};e.payload&&(r.payload=e.payload),r.state=t,n.notifyComponentUpdate(),n.sendInspectorTree(D),n.sendInspectorState(D),n.addTimelineEvent({layerId:x,event:{time:Date.now(),title:e.type,data:r}})})),t.subscribeAction({before:function(e,t){var r={};e.payload&&(r.payload=e.payload),e._id=$++,e._time=Date.now(),r.state=t,n.addTimelineEvent({layerId:M,event:{time:e._time,title:e.type,groupId:e._id,subtitle:"start",data:r}})},after:function(e,t){var r={},o=Date.now()-e._time;r.duration={_custom:{type:"duration",display:o+"ms",tooltip:"Action duration",value:o}},e.payload&&(r.payload=e.payload),r.state=t,n.addTimelineEvent({layerId:M,event:{time:Date.now(),title:e.type,groupId:e._id,subtitle:"end",data:r}})}})}))}var j=8702998,U=6710886,B=16777215,V={label:"namespaced",textColor:B,backgroundColor:U};function H(e){return e&&"root"!==e?e.split("/").slice(-2,-1)[0]:"Root"}function W(e,t){return{id:t||"root",label:H(t),tags:e.namespaced?[V]:[],children:Object.keys(e._children).map((function(n){return W(e._children[n],t+n+"/")}))}}function X(e,t,n,r){r.includes(n)&&e.push({id:r||"root",label:r.endsWith("/")?r.slice(0,r.length-1):r||"Root",tags:t.namespaced?[V]:[]}),Object.keys(t._children).forEach((function(o){X(e,t._children[o],n,r+o+"/")}))}function G(e,t,n){t="root"===n?t:t[n];var r=Object.keys(t),o={state:Object.keys(e.state).map((function(t){return{key:t,editable:!0,value:e.state[t]}}))};if(r.length){var i=K(t);o.getters=Object.keys(i).map((function(e){return{key:e.endsWith("/")?H(e):e,editable:!1,value:q((function(){return i[e]}))}}))}return o}function K(e){var t={};return Object.keys(e).forEach((function(n){var r=n.split("/");if(r.length>1){var o=t,i=r.pop();r.forEach((function(e){o[e]||(o[e]={_custom:{value:{},display:e,tooltip:"Module",abstract:!0}}),o=o[e]._custom.value})),o[i]=q((function(){return e[n]}))}else t[n]=q((function(){return e[n]}))})),t}function z(e,t){var n=t.split("/").filter((function(e){return e}));return n.reduce((function(e,r,o){var i=e[r];if(!i)throw new Error('Missing module "'+r+'" for path "'+t+'".');return o===n.length-1?i:i._children}),"root"===t?e:e.root._children)}function q(e){try{return e()}catch(t){return t}}var Y=function(e,t){this.runtime=t,this._children=Object.create(null),this._rawModule=e;var n=e.state;this.state=("function"===typeof n?n():n)||{}},Q={namespaced:{configurable:!0}};Q.namespaced.get=function(){return!!this._rawModule.namespaced},Y.prototype.addChild=function(e,t){this._children[e]=t},Y.prototype.removeChild=function(e){delete this._children[e]},Y.prototype.getChild=function(e){return this._children[e]},Y.prototype.hasChild=function(e){return e in this._children},Y.prototype.update=function(e){this._rawModule.namespaced=e.namespaced,e.actions&&(this._rawModule.actions=e.actions),e.mutations&&(this._rawModule.mutations=e.mutations),e.getters&&(this._rawModule.getters=e.getters)},Y.prototype.forEachChild=function(e){g(this._children,e)},Y.prototype.forEachGetter=function(e){this._rawModule.getters&&g(this._rawModule.getters,e)},Y.prototype.forEachAction=function(e){this._rawModule.actions&&g(this._rawModule.actions,e)},Y.prototype.forEachMutation=function(e){this._rawModule.mutations&&g(this._rawModule.mutations,e)},Object.defineProperties(Y.prototype,Q);var J=function(e){this.register([],e,!1)};function Z(e,t,n){if(t.update(n),n.modules)for(var r in n.modules){if(!t.getChild(r))return void 0;Z(e.concat(r),t.getChild(r),n.modules[r])}}J.prototype.get=function(e){return e.reduce((function(e,t){return e.getChild(t)}),this.root)},J.prototype.getNamespace=function(e){var t=this.root;return e.reduce((function(e,n){return t=t.getChild(n),e+(t.namespaced?n+"/":"")}),"")},J.prototype.update=function(e){Z([],this.root,e)},J.prototype.register=function(e,t,n){var r=this;void 0===n&&(n=!0);var o=new Y(t,n);if(0===e.length)this.root=o;else{var i=this.get(e.slice(0,-1));i.addChild(e[e.length-1],o)}t.modules&&g(t.modules,(function(t,o){r.register(e.concat(o),t,n)}))},J.prototype.unregister=function(e){var t=this.get(e.slice(0,-1)),n=e[e.length-1],r=t.getChild(n);r&&r.runtime&&t.removeChild(n)},J.prototype.isRegistered=function(e){var t=this.get(e.slice(0,-1)),n=e[e.length-1];return!!t&&t.hasChild(n)};function ee(e){return new te(e)}var te=function(e){var t=this;void 0===e&&(e={});var n=e.plugins;void 0===n&&(n=[]);var r=e.strict;void 0===r&&(r=!1);var o=e.devtools;this._committing=!1,this._actions=Object.create(null),this._actionSubscribers=[],this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new J(e),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._makeLocalGettersCache=Object.create(null),this._scope=null,this._devtools=o;var i=this,s=this,a=s.dispatch,l=s.commit;this.dispatch=function(e,t){return a.call(i,e,t)},this.commit=function(e,t,n){return l.call(i,e,t,n)},this.strict=r;var c=this._modules.root.state;k(this,c,[],this._modules.root),S(this,c),n.forEach((function(e){return e(t)}))},ne={state:{configurable:!0}};te.prototype.install=function(e,t){e.provide(t||v,this),e.config.globalProperties.$store=this;var n=void 0!==this._devtools&&this._devtools;n&&F(e,this)},ne.state.get=function(){return this._state.data},ne.state.set=function(e){0},te.prototype.commit=function(e,t,n){var r=this,o=I(e,t,n),i=o.type,s=o.payload,a=(o.options,{type:i,payload:s}),l=this._mutations[i];l&&(this._withCommit((function(){l.forEach((function(e){e(s)}))})),this._subscribers.slice().forEach((function(e){return e(a,r.state)})))},te.prototype.dispatch=function(e,t){var n=this,r=I(e,t),o=r.type,i=r.payload,s={type:o,payload:i},a=this._actions[o];if(a){try{this._actionSubscribers.slice().filter((function(e){return e.before})).forEach((function(e){return e.before(s,n.state)}))}catch(c){0}var l=a.length>1?Promise.all(a.map((function(e){return e(i)}))):a[0](i);return new Promise((function(e,t){l.then((function(t){try{n._actionSubscribers.filter((function(e){return e.after})).forEach((function(e){return e.after(s,n.state)}))}catch(c){0}e(t)}),(function(e){try{n._actionSubscribers.filter((function(e){return e.error})).forEach((function(t){return t.error(s,n.state,e)}))}catch(c){0}t(e)}))}))}},te.prototype.subscribe=function(e,t){return E(e,this._subscribers,t)},te.prototype.subscribeAction=function(e,t){var n="function"===typeof e?{before:e}:e;return E(n,this._actionSubscribers,t)},te.prototype.watch=function(e,t,n){var o=this;return(0,r.wB)((function(){return e(o.state,o.getters)}),t,Object.assign({},n))},te.prototype.replaceState=function(e){var t=this;this._withCommit((function(){t._state.data=e}))},te.prototype.registerModule=function(e,t,n){void 0===n&&(n={}),"string"===typeof e&&(e=[e]),this._modules.register(e,t),k(this,this.state,e,this._modules.get(e),n.preserveState),S(this,this.state)},te.prototype.unregisterModule=function(e){var t=this;"string"===typeof e&&(e=[e]),this._modules.unregister(e),this._withCommit((function(){var n=L(t.state,e.slice(0,-1));delete n[e[e.length-1]]})),w(this)},te.prototype.hasModule=function(e){return"string"===typeof e&&(e=[e]),this._modules.isRegistered(e)},te.prototype.hotUpdate=function(e){this._modules.update(e),w(this,!0)},te.prototype._withCommit=function(e){var t=this._committing;this._committing=!0,e(),this._committing=t},Object.defineProperties(te.prototype,ne);var re=ce((function(e,t){var n={};return ae(t).forEach((function(t){var r=t.key,o=t.val;n[r]=function(){var t=this.$store.state,n=this.$store.getters;if(e){var r=ue(this.$store,"mapState",e);if(!r)return;t=r.context.state,n=r.context.getters}return"function"===typeof o?o.call(this,t,n):t[o]},n[r].vuex=!0})),n})),oe=ce((function(e,t){var n={};return ae(t).forEach((function(t){var r=t.key,o=t.val;n[r]=function(){var t=[],n=arguments.length;while(n--)t[n]=arguments[n];var r=this.$store.commit;if(e){var i=ue(this.$store,"mapMutations",e);if(!i)return;r=i.context.commit}return"function"===typeof o?o.apply(this,[r].concat(t)):r.apply(this.$store,[o].concat(t))}})),n})),ie=ce((function(e,t){var n={};return ae(t).forEach((function(t){var r=t.key,o=t.val;o=e+o,n[r]=function(){if(!e||ue(this.$store,"mapGetters",e))return this.$store.getters[o]},n[r].vuex=!0})),n})),se=ce((function(e,t){var n={};return ae(t).forEach((function(t){var r=t.key,o=t.val;n[r]=function(){var t=[],n=arguments.length;while(n--)t[n]=arguments[n];var r=this.$store.dispatch;if(e){var i=ue(this.$store,"mapActions",e);if(!i)return;r=i.context.dispatch}return"function"===typeof o?o.apply(this,[r].concat(t)):r.apply(this.$store,[o].concat(t))}})),n}));function ae(e){return le(e)?Array.isArray(e)?e.map((function(e){return{key:e,val:e}})):Object.keys(e).map((function(t){return{key:t,val:e[t]}})):[]}function le(e){return Array.isArray(e)||y(e)}function ce(e){return function(t,n){return"string"!==typeof t?(n=t,t=""):"/"!==t.charAt(t.length-1)&&(t+="/"),e(t,n)}}function ue(e,t,n){var r=e._modulesNamespaceMap[n];return r}},6279:function(e,t,n){"use strict";var r=n(6840);e.exports=function(e,t,n){for(var o in t)r(e,o,t[o],n);return e}},6319:function(e,t,n){"use strict";var r=n(8551),o=n(9539);e.exports=function(e,t,n,i){try{return i?t(r(n)[0],n[1]):t(n)}catch(s){o(e,"throw",s)}}},6395:function(e){"use strict";e.exports=!1},6518:function(e,t,n){"use strict";var r=n(4576),o=n(7347).f,i=n(6699),s=n(6840),a=n(9433),l=n(7740),c=n(2796);e.exports=function(e,t){var n,u,d,f,p,h,m=e.target,v=e.global,g=e.stat;if(u=v?r:g?r[m]||a(m,{}):r[m]&&r[m].prototype,u)for(d in t){if(p=t[d],e.dontCallGetSet?(h=o(u,d),f=h&&h.value):f=u[d],n=c(v?d:m+(g?".":"#")+d,e.forced),!n&&void 0!==f){if(typeof p==typeof f)continue;l(p,f)}(e.sham||f&&f.sham)&&i(p,"sham",!0),s(u,d,p,e)}}},6637:function(e,t,n){"use strict";n.d(t,{A:function(){return f}});var r=n(641),o=n(33);const i={class:"theme-switch"},s=["title"],a=["title"];function l(e,t,n,l,c,u){return(0,r.uX)(),(0,r.CE)("div",i,["dark"===e.colorScheme?((0,r.uX)(),(0,r.CE)("button",{key:0,onClick:t[0]||(t[0]=(...e)=>u.toggle&&u.toggle(...e)),title:e.$t("ui.app.colorLightTitle")},(0,o.v_)(e.$t("ui.app.colorLight")),9,s)):((0,r.uX)(),(0,r.CE)("button",{key:1,onClick:t[1]||(t[1]=(...e)=>u.toggle&&u.toggle(...e)),title:e.$t("ui.app.colorDarkTitle")},(0,o.v_)(e.$t("ui.app.colorDark")),9,a))])}var c={data:()=>({colorScheme:"light"}),methods:{prefersDark(){const e=localStorage.getItem("contao--prefers-dark");return null===e?!!window.matchMedia("(prefers-color-scheme: dark)").matches:"true"===e},setColorScheme(){document.documentElement.dataset.colorScheme=this.colorScheme=this.prefersDark()?"dark":"light"},toggle(){const e=!this.prefersDark();e===window.matchMedia("(prefers-color-scheme: dark)").matches?localStorage.removeItem("contao--prefers-dark"):localStorage.setItem("contao--prefers-dark",String(e)),this.setColorScheme()}},mounted(){window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",this.setColorScheme),this.setColorScheme()},unmounted(){window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change",this.setColorScheme)}},u=n(6262);const d=(0,u.A)(c,[["render",l]]);var f=d},6699:function(e,t,n){"use strict";var r=n(3724),o=n(4913),i=n(6980);e.exports=r?function(e,t,n){return o.f(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},6780:function(e,t,n){const r=n(8311),o=(e,t,n)=>(e=new r(e,n),t=new r(t,n),e.intersects(t,n));e.exports=o},6801:function(e,t,n){"use strict";var r=n(3724),o=n(8686),i=n(4913),s=n(8551),a=n(5397),l=n(1072);t.f=r&&!o?Object.defineProperties:function(e,t){s(e);var n,r=a(t),o=l(t),c=o.length,u=0;while(c>u)i.f(e,n=o[u++],r[n]);return e}},6823:function(e){"use strict";var t=String;e.exports=function(e){try{return t(e)}catch(n){return"Object"}}},6837:function(e){"use strict";var t=TypeError,n=9007199254740991;e.exports=function(e){if(e>n)throw t("Maximum allowed index exceeded");return e}},6840:function(e,t,n){"use strict";var r=n(4901),o=n(4913),i=n(283),s=n(9433);e.exports=function(e,t,n,a){a||(a={});var l=a.enumerable,c=void 0!==a.name?a.name:t;if(r(n)&&i(n,c,a),a.global)l?e[t]=n:s(t,n);else{try{a.unsafe?e[t]&&(l=!0):delete e[t]}catch(u){}l?e[t]=n:o.f(e,t,{value:n,enumerable:!1,configurable:!a.nonConfigurable,writable:!a.nonWritable})}return e}},6874:function(e){const t="2.0.0",n=256,r=Number.MAX_SAFE_INTEGER||9007199254740991,o=16,i=n-6,s=["major","premajor","minor","preminor","patch","prepatch","prerelease"];e.exports={MAX_LENGTH:n,MAX_SAFE_COMPONENT_LENGTH:o,MAX_SAFE_BUILD_LENGTH:i,MAX_SAFE_INTEGER:r,RELEASE_TYPES:s,SEMVER_SPEC_VERSION:t,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}},6953:function(e,t,n){const r=n(144),o=(e,t)=>{const n=r(e,t);return n?n.version:null};e.exports=o},6955:function(e,t,n){"use strict";var r=n(2140),o=n(4901),i=n(2195),s=n(8227),a=s("toStringTag"),l=Object,c="Arguments"===i(function(){return arguments}()),u=function(e,t){try{return e[t]}catch(n){}};e.exports=r?i:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=u(t=l(e),a))?n:c?i(t):"Object"===(r=i(t))&&o(t.callee)?"Arguments":r}},6966:function(e,t,n){"use strict";n.d(t,{A:function(){return d}});var r=n(641),o=n(33),i=n(3751);function s(e,t,n,s,a,l){const c=(0,r.g2)("loading-spinner");return(0,r.uX)(),(0,r.Wv)((0,r.$y)(l.link?"a":"button"),{type:l.link?null:n.submit?"submit":"button",href:l.link,class:(0,o.C4)(l.buttonClass),disabled:n.disabled||n.loading,onClick:l.click,onMouseover:t[0]||(t[0]=t=>e.$emit("mouseover",t)),onMouseout:t[1]||(t[1]=t=>e.$emit("mouseout",t))},{default:(0,r.k6)((()=>[(0,r.Lk)("span",{class:(0,o.C4)(l.slotClass)},[(0,r.RG)(e.$slots,"default")],2),(0,r.bo)((0,r.bF)(c,null,null,512),[[i.aG,n.loading]])])),_:3},40,["type","href","class","disabled","onClick"])}var a=n(4999),l={components:{LoadingSpinner:a.A},emits:["click","mouseover","mouseout"],props:{href:String,to:[String,Object],color:String,icon:String,inline:Boolean,loading:Boolean,disabled:Boolean,submit:Boolean},computed:{buttonClass:e=>({"loading-button":!0,"widget-button":!0,"widget-button--inline":e.inline,[`widget-button--${e.color}`]:e.color,disabled:e.link&&(e.loading||e.disabled)}),slotClass:e=>({loading:e.loading,[`widget-button--${e.icon}`]:e.icon}),link:e=>e.href||e.to&&e.$router.resolve(e.to).href||null},methods:{click(e){this.submit||this.link||(e.preventDefault(),this.$emit("click",e))}}},c=n(6262);const u=(0,c.A)(l,[["render",s]]);var d=u},6969:function(e,t,n){"use strict";var r=n(2777),o=n(757);e.exports=function(e){var t=r(e,"string");return o(t)?t:t+""}},6980:function(e){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},6992:function(e,t,n){"use strict";n.d(t,{hU:function(){return Rr}}); /*! * shared v9.14.2 * (c) 2024 kazuya kawaguchi * Released under the MIT License. */ const r="undefined"!==typeof window;const o=(e,t=!1)=>t?Symbol.for(e):Symbol(e),i=(e,t,n)=>s({l:e,k:t,s:n}),s=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),a=e=>"number"===typeof e&&isFinite(e),l=e=>"[object Date]"===O(e),c=e=>"[object RegExp]"===O(e),u=e=>T(e)&&0===Object.keys(e).length,d=Object.assign,f=Object.create,p=(e=null)=>f(e);let h;const m=()=>h||(h="undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:"undefined"!==typeof global?global:p());function v(e){return e.replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}const g=Object.prototype.hasOwnProperty;function y(e,t){return g.call(e,t)}const b=Array.isArray,_=e=>"function"===typeof e,E=e=>"string"===typeof e,w=e=>"boolean"===typeof e,S=e=>null!==e&&"object"===typeof e,k=e=>S(e)&&_(e.then)&&_(e.catch),C=Object.prototype.toString,O=e=>C.call(e),T=e=>{if(!S(e))return!1;const t=Object.getPrototypeOf(e);return null===t||t.constructor===Object},R=e=>null==e?"":b(e)||T(e)&&e.toString===C?JSON.stringify(e,null,2):String(e);function A(e,t=""){return e.reduce(((e,n,r)=>0===r?e+n:e+t+n),"")}function N(e){let t=e;return()=>++t}function L(e,t){"undefined"!==typeof console&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}const I=e=>!S(e)||b(e);function P(e,t){if(I(e)||I(t))throw new Error("Invalid value");const n=[{src:e,des:t}];while(n.length){const{src:e,des:t}=n.pop();Object.keys(e).forEach((r=>{"__proto__"!==r&&(S(e[r])&&!S(t[r])&&(t[r]=Array.isArray(e[r])?[]:p()),I(t[r])||I(e[r])?t[r]=e[r]:n.push({src:e[r],des:t[r]}))}))}}function x(e,t,n){return{line:e,column:t,offset:n}}function M(e,t,n){const r={start:e,end:t};return null!=n&&(r.source=n),r}const D=/\{([0-9a-zA-Z]+)\}/g;function $(e,...t){return 1===t.length&&U(t[0])&&(t=t[0]),t&&t.hasOwnProperty||(t={}),e.replace(D,((e,n)=>t.hasOwnProperty(n)?t[n]:""))}const F=Object.assign,j=e=>"string"===typeof e,U=e=>null!==e&&"object"===typeof e;function B(e,t=""){return e.reduce(((e,n,r)=>0===r?e+n:e+t+n),"")}const V={USE_MODULO_SYNTAX:1,__EXTEND_POINT__:2},H={[V.USE_MODULO_SYNTAX]:"Use modulo before '{{0}}'."};function W(e,t,...n){const r=$(H[e]||"",...n||[]),o={message:String(r),code:e};return t&&(o.location=t),o}const X={EXPECTED_TOKEN:1,INVALID_TOKEN_IN_PLACEHOLDER:2,UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER:3,UNKNOWN_ESCAPE_SEQUENCE:4,INVALID_UNICODE_ESCAPE_SEQUENCE:5,UNBALANCED_CLOSING_BRACE:6,UNTERMINATED_CLOSING_BRACE:7,EMPTY_PLACEHOLDER:8,NOT_ALLOW_NEST_PLACEHOLDER:9,INVALID_LINKED_FORMAT:10,MUST_HAVE_MESSAGES_IN_PLURAL:11,UNEXPECTED_EMPTY_LINKED_MODIFIER:12,UNEXPECTED_EMPTY_LINKED_KEY:13,UNEXPECTED_LEXICAL_ANALYSIS:14,UNHANDLED_CODEGEN_NODE_TYPE:15,UNHANDLED_MINIFIER_NODE_TYPE:16,__EXTEND_POINT__:17},G={[X.EXPECTED_TOKEN]:"Expected token: '{0}'",[X.INVALID_TOKEN_IN_PLACEHOLDER]:"Invalid token in placeholder: '{0}'",[X.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]:"Unterminated single quote in placeholder",[X.UNKNOWN_ESCAPE_SEQUENCE]:"Unknown escape sequence: \\{0}",[X.INVALID_UNICODE_ESCAPE_SEQUENCE]:"Invalid unicode escape sequence: {0}",[X.UNBALANCED_CLOSING_BRACE]:"Unbalanced closing brace",[X.UNTERMINATED_CLOSING_BRACE]:"Unterminated closing brace",[X.EMPTY_PLACEHOLDER]:"Empty placeholder",[X.NOT_ALLOW_NEST_PLACEHOLDER]:"Not allowed nest placeholder",[X.INVALID_LINKED_FORMAT]:"Invalid linked format",[X.MUST_HAVE_MESSAGES_IN_PLURAL]:"Plural must have messages",[X.UNEXPECTED_EMPTY_LINKED_MODIFIER]:"Unexpected empty linked modifier",[X.UNEXPECTED_EMPTY_LINKED_KEY]:"Unexpected empty linked key",[X.UNEXPECTED_LEXICAL_ANALYSIS]:"Unexpected lexical analysis in token: '{0}'",[X.UNHANDLED_CODEGEN_NODE_TYPE]:"unhandled codegen node type: '{0}'",[X.UNHANDLED_MINIFIER_NODE_TYPE]:"unhandled mimifier node type: '{0}'"};function K(e,t,n={}){const{domain:r,messages:o,args:i}=n,s=$((o||G)[e]||"",...i||[]),a=new SyntaxError(String(s));return a.code=e,t&&(a.location=t),a.domain=r,a}function z(e){throw e}const q=" ",Y="\r",Q="\n",J=String.fromCharCode(8232),Z=String.fromCharCode(8233);function ee(e){const t=e;let n=0,r=1,o=1,i=0;const s=e=>t[e]===Y&&t[e+1]===Q,a=e=>t[e]===Q,l=e=>t[e]===Z,c=e=>t[e]===J,u=e=>s(e)||a(e)||l(e)||c(e),d=()=>n,f=()=>r,p=()=>o,h=()=>i,m=e=>s(e)||l(e)||c(e)?Q:t[e],v=()=>m(n),g=()=>m(n+i);function y(){return i=0,u(n)&&(r++,o=0),s(n)&&n++,n++,o++,t[n]}function b(){return s(n+i)&&i++,i++,t[n+i]}function _(){n=0,r=1,o=1,i=0}function E(e=0){i=e}function w(){const e=n+i;while(e!==n)y();i=0}return{index:d,line:f,column:p,peekOffset:h,charAt:m,currentChar:v,currentPeek:g,next:y,peek:b,reset:_,resetPeek:E,skipToPeek:w}}const te=void 0,ne="'",re="tokenizer";function oe(e,t={}){const n=!1!==t.location,r=ee(e),o=()=>r.index(),i=()=>x(r.line(),r.column(),r.index()),s=i(),a=o(),l={currentType:14,offset:a,startLoc:s,endLoc:s,lastType:14,lastOffset:a,lastStartLoc:s,lastEndLoc:s,braceNest:0,inLinked:!1,text:""},c=()=>l,{onError:u}=t;function d(e,t,r,...o){const i=c();if(t.column+=r,t.offset+=r,u){const r=n?M(i.startLoc,t):null,s=K(e,r,{domain:re,args:o});u(s)}}function f(e,t,r){e.endLoc=i(),e.currentType=t;const o={type:t};return n&&(o.loc=M(e.startLoc,e.endLoc)),null!=r&&(o.value=r),o}const p=e=>f(e,14);function h(e,t){return e.currentChar()===t?(e.next(),t):(d(X.EXPECTED_TOKEN,i(),0,t),"")}function m(e){let t="";while(e.currentPeek()===q||e.currentPeek()===Q)t+=e.currentPeek(),e.peek();return t}function v(e){const t=m(e);return e.skipToPeek(),t}function g(e){if(e===te)return!1;const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||95===t}function y(e){if(e===te)return!1;const t=e.charCodeAt(0);return t>=48&&t<=57}function b(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r=g(e.currentPeek());return e.resetPeek(),r}function _(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r="-"===e.currentPeek()?e.peek():e.currentPeek(),o=y(r);return e.resetPeek(),o}function E(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r=e.currentPeek()===ne;return e.resetPeek(),r}function w(e,t){const{currentType:n}=t;if(8!==n)return!1;m(e);const r="."===e.currentPeek();return e.resetPeek(),r}function S(e,t){const{currentType:n}=t;if(9!==n)return!1;m(e);const r=g(e.currentPeek());return e.resetPeek(),r}function k(e,t){const{currentType:n}=t;if(8!==n&&12!==n)return!1;m(e);const r=":"===e.currentPeek();return e.resetPeek(),r}function C(e,t){const{currentType:n}=t;if(10!==n)return!1;const r=()=>{const t=e.currentPeek();return"{"===t?g(e.peek()):!("@"===t||"%"===t||"|"===t||":"===t||"."===t||t===q||!t)&&(t===Q?(e.peek(),r()):R(e,!1))},o=r();return e.resetPeek(),o}function O(e){m(e);const t="|"===e.currentPeek();return e.resetPeek(),t}function T(e){const t=m(e),n="%"===e.currentPeek()&&"{"===e.peek();return e.resetPeek(),{isModulo:n,hasSpace:t.length>0}}function R(e,t=!0){const n=(t=!1,r="",o=!1)=>{const i=e.currentPeek();return"{"===i?"%"!==r&&t:"@"!==i&&i?"%"===i?(e.peek(),n(t,"%",!0)):"|"===i?!("%"!==r&&!o)||!(r===q||r===Q):i===q?(e.peek(),n(!0,q,o)):i!==Q||(e.peek(),n(!0,Q,o)):"%"===r||t},r=n();return t&&e.resetPeek(),r}function A(e,t){const n=e.currentChar();return n===te?te:t(n)?(e.next(),n):null}function N(e){const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||t>=48&&t<=57||95===t||36===t}function L(e){return A(e,N)}function I(e){const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||t>=48&&t<=57||95===t||36===t||45===t}function P(e){return A(e,I)}function D(e){const t=e.charCodeAt(0);return t>=48&&t<=57}function $(e){return A(e,D)}function F(e){const t=e.charCodeAt(0);return t>=48&&t<=57||t>=65&&t<=70||t>=97&&t<=102}function j(e){return A(e,F)}function U(e){let t="",n="";while(t=$(e))n+=t;return n}function B(e){v(e);const t=e.currentChar();return"%"!==t&&d(X.EXPECTED_TOKEN,i(),0,t),e.next(),"%"}function V(e){let t="";while(1){const n=e.currentChar();if("{"===n||"}"===n||"@"===n||"|"===n||!n)break;if("%"===n){if(!R(e))break;t+=n,e.next()}else if(n===q||n===Q)if(R(e))t+=n,e.next();else{if(O(e))break;t+=n,e.next()}else t+=n,e.next()}return t}function H(e){v(e);let t="",n="";while(t=P(e))n+=t;return e.currentChar()===te&&d(X.UNTERMINATED_CLOSING_BRACE,i(),0),n}function W(e){v(e);let t="";return"-"===e.currentChar()?(e.next(),t+=`-${U(e)}`):t+=U(e),e.currentChar()===te&&d(X.UNTERMINATED_CLOSING_BRACE,i(),0),t}function G(e){return e!==ne&&e!==Q}function z(e){v(e),h(e,"'");let t="",n="";while(t=A(e,G))n+="\\"===t?Y(e):t;const r=e.currentChar();return r===Q||r===te?(d(X.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER,i(),0),r===Q&&(e.next(),h(e,"'")),n):(h(e,"'"),n)}function Y(e){const t=e.currentChar();switch(t){case"\\":case"'":return e.next(),`\\${t}`;case"u":return J(e,t,4);case"U":return J(e,t,6);default:return d(X.UNKNOWN_ESCAPE_SEQUENCE,i(),0,t),""}}function J(e,t,n){h(e,t);let r="";for(let o=0;o{const r=e.currentChar();return"{"!==r&&"%"!==r&&"@"!==r&&"|"!==r&&"("!==r&&")"!==r&&r?r===q?n:(n+=r,e.next(),t(n)):n};return t("")}function ae(e){v(e);const t=h(e,"|");return v(e),t}function le(e,t){let n=null;const r=e.currentChar();switch(r){case"{":return t.braceNest>=1&&d(X.NOT_ALLOW_NEST_PLACEHOLDER,i(),0),e.next(),n=f(t,2,"{"),v(e),t.braceNest++,n;case"}":return t.braceNest>0&&2===t.currentType&&d(X.EMPTY_PLACEHOLDER,i(),0),e.next(),n=f(t,3,"}"),t.braceNest--,t.braceNest>0&&v(e),t.inLinked&&0===t.braceNest&&(t.inLinked=!1),n;case"@":return t.braceNest>0&&d(X.UNTERMINATED_CLOSING_BRACE,i(),0),n=ce(e,t)||p(t),t.braceNest=0,n;default:{let r=!0,o=!0,s=!0;if(O(e))return t.braceNest>0&&d(X.UNTERMINATED_CLOSING_BRACE,i(),0),n=f(t,1,ae(e)),t.braceNest=0,t.inLinked=!1,n;if(t.braceNest>0&&(5===t.currentType||6===t.currentType||7===t.currentType))return d(X.UNTERMINATED_CLOSING_BRACE,i(),0),t.braceNest=0,ue(e,t);if(r=b(e,t))return n=f(t,5,H(e)),v(e),n;if(o=_(e,t))return n=f(t,6,W(e)),v(e),n;if(s=E(e,t))return n=f(t,7,z(e)),v(e),n;if(!r&&!o&&!s)return n=f(t,13,oe(e)),d(X.INVALID_TOKEN_IN_PLACEHOLDER,i(),0,n.value),v(e),n;break}}return n}function ce(e,t){const{currentType:n}=t;let r=null;const o=e.currentChar();switch(8!==n&&9!==n&&12!==n&&10!==n||o!==Q&&o!==q||d(X.INVALID_LINKED_FORMAT,i(),0),o){case"@":return e.next(),r=f(t,8,"@"),t.inLinked=!0,r;case".":return v(e),e.next(),f(t,9,".");case":":return v(e),e.next(),f(t,10,":");default:return O(e)?(r=f(t,1,ae(e)),t.braceNest=0,t.inLinked=!1,r):w(e,t)||k(e,t)?(v(e),ce(e,t)):S(e,t)?(v(e),f(t,12,ie(e))):C(e,t)?(v(e),"{"===o?le(e,t)||r:f(t,11,se(e))):(8===n&&d(X.INVALID_LINKED_FORMAT,i(),0),t.braceNest=0,t.inLinked=!1,ue(e,t))}}function ue(e,t){let n={type:14};if(t.braceNest>0)return le(e,t)||p(t);if(t.inLinked)return ce(e,t)||p(t);const r=e.currentChar();switch(r){case"{":return le(e,t)||p(t);case"}":return d(X.UNBALANCED_CLOSING_BRACE,i(),0),e.next(),f(t,3,"}");case"@":return ce(e,t)||p(t);default:{if(O(e))return n=f(t,1,ae(e)),t.braceNest=0,t.inLinked=!1,n;const{isModulo:r,hasSpace:o}=T(e);if(r)return o?f(t,0,V(e)):f(t,4,B(e));if(R(e))return f(t,0,V(e));break}}return n}function de(){const{currentType:e,offset:t,startLoc:n,endLoc:s}=l;return l.lastType=e,l.lastOffset=t,l.lastStartLoc=n,l.lastEndLoc=s,l.offset=o(),l.startLoc=i(),r.currentChar()===te?f(l,14):ue(r,l)}return{nextToken:de,currentOffset:o,currentPosition:i,context:c}}const ie="parser",se=/(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;function ae(e,t,n){switch(e){case"\\\\":return"\\";case"\\'":return"'";default:{const e=parseInt(t||n,16);return e<=55295||e>=57344?String.fromCodePoint(e):"�"}}}function le(e={}){const t=!1!==e.location,{onError:n,onWarn:r}=e;function o(e,r,o,i,...s){const a=e.currentPosition();if(a.offset+=i,a.column+=i,n){const e=t?M(o,a):null,i=K(r,e,{domain:ie,args:s});n(i)}}function i(e,n,o,i,...s){const a=e.currentPosition();if(a.offset+=i,a.column+=i,r){const e=t?M(o,a):null;r(W(n,e,s))}}function s(e,n,r){const o={type:e};return t&&(o.start=n,o.end=n,o.loc={start:r,end:r}),o}function a(e,n,r,o){o&&(e.type=o),t&&(e.end=n,e.loc&&(e.loc.end=r))}function l(e,t){const n=e.context(),r=s(3,n.offset,n.startLoc);return r.value=t,a(r,e.currentOffset(),e.currentPosition()),r}function c(e,t){const n=e.context(),{lastOffset:r,lastStartLoc:o}=n,i=s(5,r,o);return i.index=parseInt(t,10),e.nextToken(),a(i,e.currentOffset(),e.currentPosition()),i}function u(e,t,n){const r=e.context(),{lastOffset:o,lastStartLoc:i}=r,l=s(4,o,i);return l.key=t,!0===n&&(l.modulo=!0),e.nextToken(),a(l,e.currentOffset(),e.currentPosition()),l}function d(e,t){const n=e.context(),{lastOffset:r,lastStartLoc:o}=n,i=s(9,r,o);return i.value=t.replace(se,ae),e.nextToken(),a(i,e.currentOffset(),e.currentPosition()),i}function f(e){const t=e.nextToken(),n=e.context(),{lastOffset:r,lastStartLoc:i}=n,l=s(8,r,i);return 12!==t.type?(o(e,X.UNEXPECTED_EMPTY_LINKED_MODIFIER,n.lastStartLoc,0),l.value="",a(l,r,i),{nextConsumeToken:t,node:l}):(null==t.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,n.lastStartLoc,0,ce(t)),l.value=t.value||"",a(l,e.currentOffset(),e.currentPosition()),{node:l})}function p(e,t){const n=e.context(),r=s(7,n.offset,n.startLoc);return r.value=t,a(r,e.currentOffset(),e.currentPosition()),r}function h(e){const t=e.context(),n=s(6,t.offset,t.startLoc);let r=e.nextToken();if(9===r.type){const t=f(e);n.modifier=t.node,r=t.nextConsumeToken||e.nextToken()}switch(10!==r.type&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(r)),r=e.nextToken(),2===r.type&&(r=e.nextToken()),r.type){case 11:null==r.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(r)),n.key=p(e,r.value||"");break;case 5:null==r.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(r)),n.key=u(e,r.value||"");break;case 6:null==r.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(r)),n.key=c(e,r.value||"");break;case 7:null==r.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(r)),n.key=d(e,r.value||"");break;default:{o(e,X.UNEXPECTED_EMPTY_LINKED_KEY,t.lastStartLoc,0);const i=e.context(),l=s(7,i.offset,i.startLoc);return l.value="",a(l,i.offset,i.startLoc),n.key=l,a(n,i.offset,i.startLoc),{nextConsumeToken:r,node:n}}}return a(n,e.currentOffset(),e.currentPosition()),{node:n}}function m(e){const t=e.context(),n=1===t.currentType?e.currentOffset():t.offset,r=1===t.currentType?t.endLoc:t.startLoc,f=s(2,n,r);f.items=[];let p=null,m=null;do{const n=p||e.nextToken();switch(p=null,n.type){case 0:null==n.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(n)),f.items.push(l(e,n.value||""));break;case 6:null==n.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(n)),f.items.push(c(e,n.value||""));break;case 4:m=!0;break;case 5:null==n.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(n)),f.items.push(u(e,n.value||"",!!m)),m&&(i(e,V.USE_MODULO_SYNTAX,t.lastStartLoc,0,ce(n)),m=null);break;case 7:null==n.value&&o(e,X.UNEXPECTED_LEXICAL_ANALYSIS,t.lastStartLoc,0,ce(n)),f.items.push(d(e,n.value||""));break;case 8:{const t=h(e);f.items.push(t.node),p=t.nextConsumeToken||null;break}}}while(14!==t.currentType&&1!==t.currentType);const v=1===t.currentType?t.lastOffset:e.currentOffset(),g=1===t.currentType?t.lastEndLoc:e.currentPosition();return a(f,v,g),f}function v(e,t,n,r){const i=e.context();let l=0===r.items.length;const c=s(1,t,n);c.cases=[],c.cases.push(r);do{const t=m(e);l||(l=0===t.items.length),c.cases.push(t)}while(14!==i.currentType);return l&&o(e,X.MUST_HAVE_MESSAGES_IN_PLURAL,n,0),a(c,e.currentOffset(),e.currentPosition()),c}function g(e){const t=e.context(),{offset:n,startLoc:r}=t,o=m(e);return 14===t.currentType?o:v(e,n,r,o)}function y(n){const r=oe(n,F({},e)),i=r.context(),l=s(0,i.offset,i.startLoc);return t&&l.loc&&(l.loc.source=n),l.body=g(r),e.onCacheKey&&(l.cacheKey=e.onCacheKey(n)),14!==i.currentType&&o(r,X.UNEXPECTED_LEXICAL_ANALYSIS,i.lastStartLoc,0,n[i.offset]||""),a(l,r.currentOffset(),r.currentPosition()),l}return{parse:y}}function ce(e){if(14===e.type)return"EOF";const t=(e.value||"").replace(/\r?\n/gu,"\\n");return t.length>10?t.slice(0,9)+"…":t}function ue(e,t={}){const n={ast:e,helpers:new Set},r=()=>n,o=e=>(n.helpers.add(e),e);return{context:r,helper:o}}function de(e,t){for(let n=0;nme(e))),e}function me(e){if(1===e.items.length){const t=e.items[0];3!==t.type&&9!==t.type||(e.static=t.value,delete t.value)}else{const t=[];for(let n=0;na;function c(e,t){a.code+=e}function u(e,t=!0){const n=t?o:"";c(i?n+" ".repeat(e):n)}function d(e=!0){const t=++a.indentLevel;e&&u(t)}function f(e=!0){const t=--a.indentLevel;e&&u(t)}function p(){u(a.indentLevel)}const h=e=>`_${e}`,m=()=>a.needIndent;return{context:l,push:c,indent:d,deindent:f,newline:p,helper:h,needIndent:m}}function _e(e,t){const{helper:n}=e;e.push(`${n("linked")}(`),ke(e,t.key),t.modifier?(e.push(", "),ke(e,t.modifier),e.push(", _type")):e.push(", undefined, _type"),e.push(")")}function Ee(e,t){const{helper:n,needIndent:r}=e;e.push(`${n("normalize")}([`),e.indent(r());const o=t.items.length;for(let i=0;i1){e.push(`${n("plural")}([`),e.indent(r());const o=t.cases.length;for(let n=0;n{const n=j(t.mode)?t.mode:"normal",r=j(t.filename)?t.filename:"message.intl",o=!!t.sourceMap,i=null!=t.breakLineCode?t.breakLineCode:"arrow"===n?";":"\n",s=t.needIndent?t.needIndent:"arrow"!==n,a=e.helpers||[],l=be(e,{mode:n,filename:r,sourceMap:o,breakLineCode:i,needIndent:s});l.push("normal"===n?"function __msg__ (ctx) {":"(ctx) => {"),l.indent(s),a.length>0&&(l.push(`const { ${B(a.map((e=>`${e}: _${e}`)),", ")} } = ctx`),l.newline()),l.push("return "),ke(l,e),l.deindent(s),l.push("}"),delete e.helpers;const{code:c,map:u}=l.context();return{ast:e,code:c,map:u?u.toJSON():void 0}};function Oe(e,t={}){const n=F({},t),r=!!n.jit,o=!!n.minify,i=null==n.optimize||n.optimize,s=le(n),a=s.parse(e);return r?(i&&he(a),o&&ge(a),{ast:a,code:""}):(pe(a,n),Ce(a,n))} /*! * core-base v9.14.2 * (c) 2024 kazuya kawaguchi * Released under the MIT License. */ function Te(){"boolean"!==typeof __INTLIFY_PROD_DEVTOOLS__&&(m().__INTLIFY_PROD_DEVTOOLS__=!1),"boolean"!==typeof __INTLIFY_JIT_COMPILATION__&&(m().__INTLIFY_JIT_COMPILATION__=!1),"boolean"!==typeof __INTLIFY_DROP_MESSAGE_COMPILER__&&(m().__INTLIFY_DROP_MESSAGE_COMPILER__=!1)}const Re=[];Re[0]={["w"]:[0],["i"]:[3,0],["["]:[4],["o"]:[7]},Re[1]={["w"]:[1],["."]:[2],["["]:[4],["o"]:[7]},Re[2]={["w"]:[2],["i"]:[3,0],["0"]:[3,0]},Re[3]={["i"]:[3,0],["0"]:[3,0],["w"]:[1,1],["."]:[2,1],["["]:[4,1],["o"]:[7,1]},Re[4]={["'"]:[5,0],['"']:[6,0],["["]:[4,2],["]"]:[1,3],["o"]:8,["l"]:[4,0]},Re[5]={["'"]:[4,0],["o"]:8,["l"]:[5,0]},Re[6]={['"']:[4,0],["o"]:8,["l"]:[6,0]};const Ae=/^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;function Ne(e){return Ae.test(e)}function Le(e){const t=e.charCodeAt(0),n=e.charCodeAt(e.length-1);return t!==n||34!==t&&39!==t?e:e.slice(1,-1)}function Ie(e){if(void 0===e||null===e)return"o";const t=e.charCodeAt(0);switch(t){case 91:case 93:case 46:case 34:case 39:return e;case 95:case 36:case 45:return"i";case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"w"}return"i"}function Pe(e){const t=e.trim();return("0"!==e.charAt(0)||!isNaN(parseInt(e)))&&(Ne(t)?Le(t):"*"+t)}function xe(e){const t=[];let n,r,o,i,s,a,l,c=-1,u=0,d=0;const f=[];function p(){const t=e[c+1];if(5===u&&"'"===t||6===u&&'"'===t)return c++,o="\\"+t,f[0](),!0}f[0]=()=>{void 0===r?r=o:r+=o},f[1]=()=>{void 0!==r&&(t.push(r),r=void 0)},f[2]=()=>{f[0](),d++},f[3]=()=>{if(d>0)d--,u=4,f[0]();else{if(d=0,void 0===r)return!1;if(r=Pe(r),!1===r)return!1;f[1]()}};while(null!==u)if(c++,n=e[c],"\\"!==n||!p()){if(i=Ie(n),l=Re[u],s=l[i]||l["l"]||8,8===s)return;if(u=s[0],void 0!==s[1]&&(a=f[s[1]],a&&(o=n,!1===a())))return;if(7===u)return t}}const Me=new Map;function De(e,t){return S(e)?e[t]:null}function $e(e,t){if(!S(e))return null;let n=Me.get(t);if(n||(n=xe(t),n&&Me.set(t,n)),!n)return null;const r=n.length;let o=e,i=0;while(ie,je=e=>"",Ue="text",Be=e=>0===e.length?"":A(e),Ve=R;function He(e,t){return e=Math.abs(e),2===t?e?e>1?1:0:1:e?Math.min(e,2):0}function We(e){const t=a(e.pluralIndex)?e.pluralIndex:-1;return e.named&&(a(e.named.count)||a(e.named.n))?a(e.named.count)?e.named.count:a(e.named.n)?e.named.n:t:t}function Xe(e,t){t.count||(t.count=e),t.n||(t.n=e)}function Ge(e={}){const t=e.locale,n=We(e),r=S(e.pluralRules)&&E(t)&&_(e.pluralRules[t])?e.pluralRules[t]:He,o=S(e.pluralRules)&&E(t)&&_(e.pluralRules[t])?He:void 0,i=e=>e[r(n,e.length,o)],s=e.list||[],l=e=>s[e],c=e.named||p();a(e.pluralIndex)&&Xe(n,c);const u=e=>c[e];function f(t){const n=_(e.messages)?e.messages(t):!!S(e.messages)&&e.messages[t];return n||(e.parent?e.parent.message(t):je)}const h=t=>e.modifiers?e.modifiers[t]:Fe,m=T(e.processor)&&_(e.processor.normalize)?e.processor.normalize:Be,v=T(e.processor)&&_(e.processor.interpolate)?e.processor.interpolate:Ve,g=T(e.processor)&&E(e.processor.type)?e.processor.type:Ue,y=(e,...t)=>{const[n,r]=t;let o="text",i="";1===t.length?S(n)?(i=n.modifier||i,o=n.type||o):E(n)&&(i=n||i):2===t.length&&(E(n)&&(i=n||i),E(r)&&(o=r||o));const s=f(e)(w),a="vnode"===o&&b(s)&&i?s[0]:s;return i?h(i)(a,o):a},w={["list"]:l,["named"]:u,["plural"]:i,["linked"]:y,["message"]:f,["type"]:g,["interpolate"]:v,["normalize"]:m,["values"]:d(p(),s,c)};return w}let Ke=null;function ze(e){Ke=e}function qe(e,t,n){Ke&&Ke.emit("i18n:init",{timestamp:Date.now(),i18n:e,version:t,meta:n})}const Ye=Qe("function:translate");function Qe(e){return t=>Ke&&Ke.emit(e,t)}const Je=V.__EXTEND_POINT__,Ze=N(Je),et={NOT_FOUND_KEY:Je,FALLBACK_TO_TRANSLATE:Ze(),CANNOT_FORMAT_NUMBER:Ze(),FALLBACK_TO_NUMBER_FORMAT:Ze(),CANNOT_FORMAT_DATE:Ze(),FALLBACK_TO_DATE_FORMAT:Ze(),EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER:Ze(),__EXTEND_POINT__:Ze()};et.NOT_FOUND_KEY,et.FALLBACK_TO_TRANSLATE,et.CANNOT_FORMAT_NUMBER,et.FALLBACK_TO_NUMBER_FORMAT,et.CANNOT_FORMAT_DATE,et.FALLBACK_TO_DATE_FORMAT,et.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER;const tt=X.__EXTEND_POINT__,nt=N(tt),rt={INVALID_ARGUMENT:tt,INVALID_DATE_ARGUMENT:nt(),INVALID_ISO_DATE_ARGUMENT:nt(),NOT_SUPPORT_NON_STRING_MESSAGE:nt(),NOT_SUPPORT_LOCALE_PROMISE_VALUE:nt(),NOT_SUPPORT_LOCALE_ASYNC_FUNCTION:nt(),NOT_SUPPORT_LOCALE_TYPE:nt(),__EXTEND_POINT__:nt()};function ot(e){return K(e,null,void 0)}rt.INVALID_ARGUMENT,rt.INVALID_DATE_ARGUMENT,rt.INVALID_ISO_DATE_ARGUMENT,rt.NOT_SUPPORT_NON_STRING_MESSAGE,rt.NOT_SUPPORT_LOCALE_PROMISE_VALUE,rt.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION,rt.NOT_SUPPORT_LOCALE_TYPE;function it(e,t){return null!=t.locale?at(t.locale):at(e.locale)}let st;function at(e){if(E(e))return e;if(_(e)){if(e.resolvedOnce&&null!=st)return st;if("Function"===e.constructor.name){const t=e();if(k(t))throw ot(rt.NOT_SUPPORT_LOCALE_PROMISE_VALUE);return st=t}throw ot(rt.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION)}throw ot(rt.NOT_SUPPORT_LOCALE_TYPE)}function lt(e,t,n){return[...new Set([n,...b(t)?t:S(t)?Object.keys(t):E(t)?[t]:[n]])]}function ct(e,t,n){const r=E(n)?n:mt,o=e;o.__localeChainCache||(o.__localeChainCache=new Map);let i=o.__localeChainCache.get(r);if(!i){i=[];let e=[n];while(b(e))e=ut(i,e,t);const s=b(t)||!T(t)?t:t["default"]?t["default"]:null;e=E(s)?[s]:s,b(e)&&ut(i,e,!1),o.__localeChainCache.set(r,i)}return i}function ut(e,t,n){let r=!0;for(let o=0;o`${e.charAt(0).toLocaleUpperCase()}${e.substr(1)}`;function yt(){return{upper:(e,t)=>"text"===t&&E(e)?e.toUpperCase():"vnode"===t&&S(e)&&"__v_isVNode"in e?e.children.toUpperCase():e,lower:(e,t)=>"text"===t&&E(e)?e.toLowerCase():"vnode"===t&&S(e)&&"__v_isVNode"in e?e.children.toLowerCase():e,capitalize:(e,t)=>"text"===t&&E(e)?gt(e):"vnode"===t&&S(e)&&"__v_isVNode"in e?gt(e.children):e}}let bt,_t,Et;function wt(e){bt=e}function St(e){_t=e}function kt(e){Et=e}let Ct=null;const Ot=e=>{Ct=e},Tt=()=>Ct;let Rt=null;const At=e=>{Rt=e},Nt=()=>Rt;let Lt=0;function It(e={}){const t=_(e.onWarn)?e.onWarn:L,n=E(e.version)?e.version:pt,r=E(e.locale)||_(e.locale)?e.locale:mt,o=_(r)?mt:r,i=b(e.fallbackLocale)||T(e.fallbackLocale)||E(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:o,s=T(e.messages)?e.messages:Pt(o),a=T(e.datetimeFormats)?e.datetimeFormats:Pt(o),l=T(e.numberFormats)?e.numberFormats:Pt(o),u=d(p(),e.modifiers,yt()),f=e.pluralRules||p(),h=_(e.missing)?e.missing:null,m=!w(e.missingWarn)&&!c(e.missingWarn)||e.missingWarn,v=!w(e.fallbackWarn)&&!c(e.fallbackWarn)||e.fallbackWarn,g=!!e.fallbackFormat,y=!!e.unresolving,k=_(e.postTranslation)?e.postTranslation:null,C=T(e.processor)?e.processor:null,O=!w(e.warnHtmlMessage)||e.warnHtmlMessage,R=!!e.escapeParameter,A=_(e.messageCompiler)?e.messageCompiler:bt;const N=_(e.messageResolver)?e.messageResolver:_t||De,I=_(e.localeFallbacker)?e.localeFallbacker:Et||lt,P=S(e.fallbackContext)?e.fallbackContext:void 0,x=e,M=S(x.__datetimeFormatters)?x.__datetimeFormatters:new Map,D=S(x.__numberFormatters)?x.__numberFormatters:new Map,$=S(x.__meta)?x.__meta:{};Lt++;const F={version:n,cid:Lt,locale:r,fallbackLocale:i,messages:s,modifiers:u,pluralRules:f,missing:h,missingWarn:m,fallbackWarn:v,fallbackFormat:g,unresolving:y,postTranslation:k,processor:C,warnHtmlMessage:O,escapeParameter:R,messageCompiler:A,messageResolver:N,localeFallbacker:I,fallbackContext:P,onWarn:t,__meta:$};return F.datetimeFormats=a,F.numberFormats=l,F.__datetimeFormatters=M,F.__numberFormatters=D,__INTLIFY_PROD_DEVTOOLS__&&qe(F,n,$),F}const Pt=e=>({[e]:p()});function xt(e,t,n,r,o){const{missing:i,onWarn:s}=e;if(null!==i){const r=i(e,n,t,o);return E(r)?r:t}return t}function Mt(e,t,n){const r=e;r.__localeChainCache=new Map,e.localeFallbacker(e,n,t)}function Dt(e,t){return e!==t&&e.split("-")[0]===t.split("-")[0]}function $t(e,t){const n=t.indexOf(e);if(-1===n)return!1;for(let r=n+1;rjt(t,e);return t}function jt(e,t){const n=Bt(t);if(null==n)throw sn(0);const r=Qt(n);if(1===r){const t=n,r=Ht(t);return e.plural(r.reduce(((t,n)=>[...t,Wt(e,n)]),[]))}return Wt(e,n)}const Ut=["b","body"];function Bt(e){return on(e,Ut)}const Vt=["c","cases"];function Ht(e){return on(e,Vt,[])}function Wt(e,t){const n=Gt(t);if(null!=n)return"text"===e.type?n:e.normalize([n]);{const n=zt(t).reduce(((t,n)=>[...t,qt(e,n)]),[]);return e.normalize(n)}}const Xt=["s","static"];function Gt(e){return on(e,Xt)}const Kt=["i","items"];function zt(e){return on(e,Kt,[])}function qt(e,t){const n=Qt(t);switch(n){case 3:return Zt(t,n);case 9:return Zt(t,n);case 4:{const r=t;if(y(r,"k")&&r.k)return e.interpolate(e.named(r.k));if(y(r,"key")&&r.key)return e.interpolate(e.named(r.key));throw sn(n)}case 5:{const r=t;if(y(r,"i")&&a(r.i))return e.interpolate(e.list(r.i));if(y(r,"index")&&a(r.index))return e.interpolate(e.list(r.index));throw sn(n)}case 6:{const n=t,r=tn(n),o=rn(n);return e.linked(qt(e,o),r?qt(e,r):void 0,e.type)}case 7:return Zt(t,n);case 8:return Zt(t,n);default:throw new Error(`unhandled node on format message part: ${n}`)}}const Yt=["t","type"];function Qt(e){return on(e,Yt)}const Jt=["v","value"];function Zt(e,t){const n=on(e,Jt);if(n)return n;throw sn(t)}const en=["m","modifier"];function tn(e){return on(e,en)}const nn=["k","key"];function rn(e){const t=on(e,nn);if(t)return t;throw sn(6)}function on(e,t,n){for(let r=0;re;let ln=p();function cn(e){return S(e)&&0===Qt(e)&&(y(e,"b")||y(e,"body"))}function un(e,t={}){let n=!1;const r=t.onError||z;return t.onError=e=>{n=!0,r(e)},{...Oe(e,t),detectError:n}}const dn=(e,t)=>{if(!E(e))throw ot(rt.NOT_SUPPORT_NON_STRING_MESSAGE);{!w(t.warnHtmlMessage)||t.warnHtmlMessage;const n=t.onCacheKey||an,r=n(e),o=ln[r];if(o)return o;const{code:i,detectError:s}=un(e,t),a=new Function(`return ${i}`)();return s?a:ln[r]=a}};function fn(e,t){if(__INTLIFY_JIT_COMPILATION__&&!__INTLIFY_DROP_MESSAGE_COMPILER__&&E(e)){!w(t.warnHtmlMessage)||t.warnHtmlMessage;const n=t.onCacheKey||an,r=n(e),o=ln[r];if(o)return o;const{ast:i,detectError:s}=un(e,{...t,location:!1,jit:!0}),a=Ft(i);return s?a:ln[r]=a}{0;const t=e.cacheKey;if(t){const n=ln[t];return n||(ln[t]=Ft(e))}return Ft(e)}}const pn=()=>"",hn=e=>_(e);function mn(e,...t){const{fallbackFormat:n,postTranslation:r,unresolving:o,messageCompiler:i,fallbackLocale:s,messages:a}=e,[l,c]=_n(...t),u=w(c.missingWarn)?c.missingWarn:e.missingWarn,f=w(c.fallbackWarn)?c.fallbackWarn:e.fallbackWarn,h=w(c.escapeParameter)?c.escapeParameter:e.escapeParameter,m=!!c.resolvedMessage,v=E(c.default)||w(c.default)?w(c.default)?i?l:()=>l:c.default:n?i?l:()=>l:"",g=n||""!==v,y=it(e,c);h&&vn(c);let[b,_,S]=m?[l,y,a[y]||p()]:gn(e,l,y,s,f,u),k=b,C=l;if(m||E(k)||cn(k)||hn(k)||g&&(k=v,C=k),!m&&(!(E(k)||cn(k)||hn(k))||!E(_)))return o?ht:l;let O=!1;const T=()=>{O=!0},R=hn(k)?k:yn(e,l,_,k,C,T);if(O)return k;const A=wn(e,_,S,c),N=Ge(A),L=bn(e,R,N),I=r?r(L,l):L;if(__INTLIFY_PROD_DEVTOOLS__){const t={timestamp:Date.now(),key:E(l)?l:hn(k)?k.key:"",locale:_||(hn(k)?k.locale:""),format:E(k)?k:hn(k)?k.source:"",message:I};t.meta=d({},e.__meta,Tt()||{}),Ye(t)}return I}function vn(e){b(e.list)?e.list=e.list.map((e=>E(e)?v(e):e)):S(e.named)&&Object.keys(e.named).forEach((t=>{E(e.named[t])&&(e.named[t]=v(e.named[t]))}))}function gn(e,t,n,r,o,i){const{messages:s,onWarn:a,messageResolver:l,localeFallbacker:c}=e,u=c(e,r,n);let d,f=p(),h=null,m=n,v=null;const g="translate";for(let y=0;yr;return e.locale=n,e.key=t,e}const l=s(r,En(e,n,o,r,a,i));return l.locale=n,l.key=t,l.source=r,l}function bn(e,t,n){const r=t(n);return r}function _n(...e){const[t,n,r]=e,o=p();if(!E(t)&&!a(t)&&!hn(t)&&!cn(t))throw ot(rt.INVALID_ARGUMENT);const i=a(t)?String(t):(hn(t),t);return a(n)?o.plural=n:E(n)?o.default=n:T(n)&&!u(n)?o.named=n:b(n)&&(o.list=n),a(r)?o.plural=r:E(r)?o.default=r:T(r)&&d(o,r),[i,o]}function En(e,t,n,r,o,s){return{locale:t,key:n,warnHtmlMessage:o,onError:e=>{throw s&&s(e),e},onCacheKey:e=>i(t,n,e)}}function wn(e,t,n,r){const{modifiers:o,pluralRules:i,messageResolver:s,fallbackLocale:l,fallbackWarn:c,missingWarn:u,fallbackContext:d}=e,f=r=>{let o=s(n,r);if(null==o&&d){const[,,e]=gn(d,r,t,l,c,u);o=s(e,r)}if(E(o)||cn(o)){let n=!1;const i=()=>{n=!0},s=yn(e,r,t,o,r,i);return n?pn:s}return hn(o)?o:pn},p={locale:t,modifiers:o,pluralRules:i,messages:f};return e.processor&&(p.processor=e.processor),r.list&&(p.list=r.list),r.named&&(p.named=r.named),a(r.plural)&&(p.pluralIndex=r.plural),p}const Sn="undefined"!==typeof Intl;Sn&&Intl.DateTimeFormat,Sn&&Intl.NumberFormat;function kn(e,...t){const{datetimeFormats:n,unresolving:r,fallbackLocale:o,onWarn:i,localeFallbacker:s}=e,{__datetimeFormatters:a}=e;const[l,c,f,p]=On(...t),h=w(f.missingWarn)?f.missingWarn:e.missingWarn,m=(w(f.fallbackWarn)?f.fallbackWarn:e.fallbackWarn,!!f.part),v=it(e,f),g=s(e,o,v);if(!E(l)||""===l)return new Intl.DateTimeFormat(v,p).format(c);let y,b={},_=null,S=v,k=null;const C="datetime format";for(let u=0;u{Cn.includes(e)?c[e]=n[e]:i[e]=n[e]})),E(r)?i.locale=r:T(r)&&(c=r),T(o)&&(c=o),[i.key||"",s,i,c]}function Tn(e,t,n){const r=e;for(const o in n){const e=`${t}__${o}`;r.__datetimeFormatters.has(e)&&r.__datetimeFormatters.delete(e)}}function Rn(e,...t){const{numberFormats:n,unresolving:r,fallbackLocale:o,onWarn:i,localeFallbacker:s}=e,{__numberFormatters:a}=e;const[l,c,f,p]=Nn(...t),h=w(f.missingWarn)?f.missingWarn:e.missingWarn,m=(w(f.fallbackWarn)?f.fallbackWarn:e.fallbackWarn,!!f.part),v=it(e,f),g=s(e,o,v);if(!E(l)||""===l)return new Intl.NumberFormat(v,p).format(c);let y,b={},_=null,S=v,k=null;const C="number format";for(let u=0;u{An.includes(e)?s[e]=n[e]:i[e]=n[e]})),E(r)?i.locale=r:T(r)&&(s=r),T(o)&&(s=o),[i.key||"",l,i,s]}function Ln(e,t,n){const r=e;for(const o in n){const e=`${t}__${o}`;r.__numberFormatters.has(e)&&r.__numberFormatters.delete(e)}}Te();var In=n(641),Pn=n(953); /*! * vue-i18n v9.14.2 * (c) 2024 kazuya kawaguchi * Released under the MIT License. */ const xn="9.14.2";function Mn(){"boolean"!==typeof __VUE_I18N_FULL_INSTALL__&&(m().__VUE_I18N_FULL_INSTALL__=!0),"boolean"!==typeof __VUE_I18N_LEGACY_API__&&(m().__VUE_I18N_LEGACY_API__=!0),"boolean"!==typeof __INTLIFY_JIT_COMPILATION__&&(m().__INTLIFY_JIT_COMPILATION__=!1),"boolean"!==typeof __INTLIFY_DROP_MESSAGE_COMPILER__&&(m().__INTLIFY_DROP_MESSAGE_COMPILER__=!1),"boolean"!==typeof __INTLIFY_PROD_DEVTOOLS__&&(m().__INTLIFY_PROD_DEVTOOLS__=!1)}const Dn=et.__EXTEND_POINT__,$n=N(Dn),Fn={FALLBACK_TO_ROOT:Dn,NOT_SUPPORTED_PRESERVE:$n(),NOT_SUPPORTED_FORMATTER:$n(),NOT_SUPPORTED_PRESERVE_DIRECTIVE:$n(),NOT_SUPPORTED_GET_CHOICE_INDEX:$n(),COMPONENT_NAME_LEGACY_COMPATIBLE:$n(),NOT_FOUND_PARENT_SCOPE:$n(),IGNORE_OBJ_FLATTEN:$n(),NOTICE_DROP_ALLOW_COMPOSITION:$n(),NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG:$n()};Fn.FALLBACK_TO_ROOT,Fn.NOT_SUPPORTED_PRESERVE,Fn.NOT_SUPPORTED_FORMATTER,Fn.NOT_SUPPORTED_PRESERVE_DIRECTIVE,Fn.NOT_SUPPORTED_GET_CHOICE_INDEX,Fn.COMPONENT_NAME_LEGACY_COMPATIBLE,Fn.NOT_FOUND_PARENT_SCOPE,Fn.IGNORE_OBJ_FLATTEN,Fn.NOTICE_DROP_ALLOW_COMPOSITION,Fn.NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG;const jn=rt.__EXTEND_POINT__,Un=N(jn),Bn={UNEXPECTED_RETURN_TYPE:jn,INVALID_ARGUMENT:Un(),MUST_BE_CALL_SETUP_TOP:Un(),NOT_INSTALLED:Un(),NOT_AVAILABLE_IN_LEGACY_MODE:Un(),REQUIRED_VALUE:Un(),INVALID_VALUE:Un(),CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN:Un(),NOT_INSTALLED_WITH_PROVIDE:Un(),UNEXPECTED_ERROR:Un(),NOT_COMPATIBLE_LEGACY_VUE_I18N:Un(),BRIDGE_SUPPORT_VUE_2_ONLY:Un(),MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION:Un(),NOT_AVAILABLE_COMPOSITION_IN_LEGACY:Un(),__EXTEND_POINT__:Un()};function Vn(e,...t){return K(e,null,void 0)}Bn.UNEXPECTED_RETURN_TYPE,Bn.INVALID_ARGUMENT,Bn.MUST_BE_CALL_SETUP_TOP,Bn.NOT_INSTALLED,Bn.UNEXPECTED_ERROR,Bn.NOT_AVAILABLE_IN_LEGACY_MODE,Bn.REQUIRED_VALUE,Bn.INVALID_VALUE,Bn.CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN,Bn.NOT_INSTALLED_WITH_PROVIDE,Bn.NOT_COMPATIBLE_LEGACY_VUE_I18N,Bn.BRIDGE_SUPPORT_VUE_2_ONLY,Bn.MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION,Bn.NOT_AVAILABLE_COMPOSITION_IN_LEGACY;const Hn=o("__translateVNode"),Wn=o("__datetimeParts"),Xn=o("__numberParts"),Gn=o("__setPluralRules");o("__intlifyMeta");const Kn=o("__injectWithOption"),zn=o("__dispose");function qn(e){if(!S(e))return e;for(const t in e)if(y(e,t))if(t.includes(".")){const n=t.split("."),r=n.length-1;let o=e,i=!1;for(let e=0;e{if("locale"in e&&"resource"in e){const{locale:t,resource:n}=e;t?(s[t]=s[t]||p(),P(n,s[t])):P(n,s)}else E(e)&&P(JSON.parse(e),s)})),null==o&&i)for(const a in s)y(s,a)&&qn(s[a]);return s}function Qn(e){return e.type}function Jn(e,t,n){let r=S(t.messages)?t.messages:p();"__i18nGlobal"in n&&(r=Yn(e.locale.value,{messages:r,__i18n:n.__i18nGlobal}));const o=Object.keys(r);if(o.length&&o.forEach((t=>{e.mergeLocaleMessage(t,r[t])})),S(t.datetimeFormats)){const n=Object.keys(t.datetimeFormats);n.length&&n.forEach((n=>{e.mergeDateTimeFormat(n,t.datetimeFormats[n])}))}if(S(t.numberFormats)){const n=Object.keys(t.numberFormats);n.length&&n.forEach((n=>{e.mergeNumberFormat(n,t.numberFormats[n])}))}}function Zn(e){return(0,In.bF)(In.EY,null,e,0)}const er="__INTLIFY_META__",tr=()=>[],nr=()=>!1;let rr=0;function or(e){return(t,n,r,o)=>e(n,r,(0,In.nI)()||void 0,o)}const ir=()=>{const e=(0,In.nI)();let t=null;return e&&(t=Qn(e)[er])?{[er]:t}:null};function sr(e={},t){const{__root:n,__injectWithOption:o}=e,i=void 0===n,s=e.flatJson,l=r?Pn.KR:Pn.IJ,u=!!e.translateExistCompatible;let f=!w(e.inheritLocale)||e.inheritLocale;const p=l(n&&f?n.locale.value:E(e.locale)?e.locale:mt),h=l(n&&f?n.fallbackLocale.value:E(e.fallbackLocale)||b(e.fallbackLocale)||T(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:p.value),m=l(Yn(p.value,e)),v=l(T(e.datetimeFormats)?e.datetimeFormats:{[p.value]:{}}),g=l(T(e.numberFormats)?e.numberFormats:{[p.value]:{}});let k=n?n.missingWarn:!w(e.missingWarn)&&!c(e.missingWarn)||e.missingWarn,C=n?n.fallbackWarn:!w(e.fallbackWarn)&&!c(e.fallbackWarn)||e.fallbackWarn,O=n?n.fallbackRoot:!w(e.fallbackRoot)||e.fallbackRoot,R=!!e.fallbackFormat,A=_(e.missing)?e.missing:null,N=_(e.missing)?or(e.missing):null,L=_(e.postTranslation)?e.postTranslation:null,I=n?n.warnHtmlMessage:!w(e.warnHtmlMessage)||e.warnHtmlMessage,x=!!e.escapeParameter;const M=n?n.modifiers:T(e.modifiers)?e.modifiers:{};let D,$=e.pluralRules||n&&n.pluralRules;const F=()=>{i&&At(null);const t={version:xn,locale:p.value,fallbackLocale:h.value,messages:m.value,modifiers:M,pluralRules:$,missing:null===N?void 0:N,missingWarn:k,fallbackWarn:C,fallbackFormat:R,unresolving:!0,postTranslation:null===L?void 0:L,warnHtmlMessage:I,escapeParameter:x,messageResolver:e.messageResolver,messageCompiler:e.messageCompiler,__meta:{framework:"vue"}};t.datetimeFormats=v.value,t.numberFormats=g.value,t.__datetimeFormatters=T(D)?D.__datetimeFormatters:void 0,t.__numberFormatters=T(D)?D.__numberFormatters:void 0;const n=It(t);return i&&At(n),n};function j(){return[p.value,h.value,m.value,v.value,g.value]}D=F(),Mt(D,p.value,h.value);const U=(0,In.EW)({get:()=>p.value,set:e=>{p.value=e,D.locale=p.value}}),B=(0,In.EW)({get:()=>h.value,set:e=>{h.value=e,D.fallbackLocale=h.value,Mt(D,p.value,e)}}),V=(0,In.EW)((()=>m.value)),H=(0,In.EW)((()=>v.value)),W=(0,In.EW)((()=>g.value));function X(){return _(L)?L:null}function G(e){L=e,D.postTranslation=e}function K(){return A}function z(e){null!==e&&(N=or(e)),A=e,D.missing=N}const q=(e,t,r,o,s,l)=>{let c;j();try{__INTLIFY_PROD_DEVTOOLS__&&Ot(ir()),i||(D.fallbackContext=n?Nt():void 0),c=e(D)}finally{__INTLIFY_PROD_DEVTOOLS__&&Ot(null),i||(D.fallbackContext=void 0)}if("translate exists"!==r&&a(c)&&c===ht||"translate exists"===r&&!c){const[e,r]=t();return n&&O?o(n):s(e)}if(l(c))return c;throw Vn(Bn.UNEXPECTED_RETURN_TYPE)};function Y(...e){return q((t=>Reflect.apply(mn,null,[t,...e])),(()=>_n(...e)),"translate",(t=>Reflect.apply(t.t,t,[...e])),(e=>e),(e=>E(e)))}function Q(...e){const[t,n,r]=e;if(r&&!S(r))throw Vn(Bn.INVALID_ARGUMENT);return Y(t,n,d({resolvedMessage:!0},r||{}))}function J(...e){return q((t=>Reflect.apply(kn,null,[t,...e])),(()=>On(...e)),"datetime format",(t=>Reflect.apply(t.d,t,[...e])),(()=>vt),(e=>E(e)))}function Z(...e){return q((t=>Reflect.apply(Rn,null,[t,...e])),(()=>Nn(...e)),"number format",(t=>Reflect.apply(t.n,t,[...e])),(()=>vt),(e=>E(e)))}function ee(e){return e.map((e=>E(e)||a(e)||w(e)?Zn(String(e)):e))}const te=e=>e,ne={normalize:ee,interpolate:te,type:"vnode"};function re(...e){return q((t=>{let n;const r=t;try{r.processor=ne,n=Reflect.apply(mn,null,[r,...e])}finally{r.processor=null}return n}),(()=>_n(...e)),"translate",(t=>t[Hn](...e)),(e=>[Zn(e)]),(e=>b(e)))}function oe(...e){return q((t=>Reflect.apply(Rn,null,[t,...e])),(()=>Nn(...e)),"number format",(t=>t[Xn](...e)),tr,(e=>E(e)||b(e)))}function ie(...e){return q((t=>Reflect.apply(kn,null,[t,...e])),(()=>On(...e)),"datetime format",(t=>t[Wn](...e)),tr,(e=>E(e)||b(e)))}function se(e){$=e,D.pluralRules=$}function ae(e,t){return q((()=>{if(!e)return!1;const n=E(t)?t:p.value,r=ue(n),o=D.messageResolver(r,e);return u?null!=o:cn(o)||hn(o)||E(o)}),(()=>[e]),"translate exists",(n=>Reflect.apply(n.te,n,[e,t])),nr,(e=>w(e)))}function le(e){let t=null;const n=ct(D,h.value,p.value);for(let r=0;r{f&&(p.value=e,D.locale=e,Mt(D,p.value,h.value))})),(0,In.wB)(n.fallbackLocale,(e=>{f&&(h.value=e,D.fallbackLocale=e,Mt(D,p.value,h.value))})));const be={id:rr,locale:U,fallbackLocale:B,get inheritLocale(){return f},set inheritLocale(e){f=e,e&&n&&(p.value=n.locale.value,h.value=n.fallbackLocale.value,Mt(D,p.value,h.value))},get availableLocales(){return Object.keys(m.value).sort()},messages:V,get modifiers(){return M},get pluralRules(){return $||{}},get isGlobal(){return i},get missingWarn(){return k},set missingWarn(e){k=e,D.missingWarn=k},get fallbackWarn(){return C},set fallbackWarn(e){C=e,D.fallbackWarn=C},get fallbackRoot(){return O},set fallbackRoot(e){O=e},get fallbackFormat(){return R},set fallbackFormat(e){R=e,D.fallbackFormat=R},get warnHtmlMessage(){return I},set warnHtmlMessage(e){I=e,D.warnHtmlMessage=e},get escapeParameter(){return x},set escapeParameter(e){x=e,D.escapeParameter=e},t:Y,getLocaleMessage:ue,setLocaleMessage:de,mergeLocaleMessage:fe,getPostTranslationHandler:X,setPostTranslationHandler:G,getMissingHandler:K,setMissingHandler:z,[Gn]:se};return be.datetimeFormats=H,be.numberFormats=W,be.rt=Q,be.te=ae,be.tm=ce,be.d=J,be.n=Z,be.getDateTimeFormat=pe,be.setDateTimeFormat=he,be.mergeDateTimeFormat=me,be.getNumberFormat=ve,be.setNumberFormat=ge,be.mergeNumberFormat=ye,be[Kn]=o,be[Hn]=re,be[Wn]=ie,be[Xn]=oe,be}function ar(e){const t=E(e.locale)?e.locale:mt,n=E(e.fallbackLocale)||b(e.fallbackLocale)||T(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:t,r=_(e.missing)?e.missing:void 0,o=!w(e.silentTranslationWarn)&&!c(e.silentTranslationWarn)||!e.silentTranslationWarn,i=!w(e.silentFallbackWarn)&&!c(e.silentFallbackWarn)||!e.silentFallbackWarn,s=!w(e.fallbackRoot)||e.fallbackRoot,a=!!e.formatFallbackMessages,l=T(e.modifiers)?e.modifiers:{},u=e.pluralizationRules,f=_(e.postTranslation)?e.postTranslation:void 0,p=!E(e.warnHtmlInMessage)||"off"!==e.warnHtmlInMessage,h=!!e.escapeParameterHtml,m=!w(e.sync)||e.sync;let v=e.messages;if(T(e.sharedMessages)){const t=e.sharedMessages,n=Object.keys(t);v=n.reduce(((e,n)=>{const r=e[n]||(e[n]={});return d(r,t[n]),e}),v||{})}const{__i18n:g,__root:y,__injectWithOption:S}=e,k=e.datetimeFormats,C=e.numberFormats,O=e.flatJson,R=e.translateExistCompatible;return{locale:t,fallbackLocale:n,messages:v,flatJson:O,datetimeFormats:k,numberFormats:C,missing:r,missingWarn:o,fallbackWarn:i,fallbackRoot:s,fallbackFormat:a,modifiers:l,pluralRules:u,postTranslation:f,warnHtmlMessage:p,escapeParameter:h,messageResolver:e.messageResolver,inheritLocale:m,translateExistCompatible:R,__i18n:g,__root:y,__injectWithOption:S}}function lr(e={},t){{const t=sr(ar(e)),{__extender:n}=e,r={id:t.id,get locale(){return t.locale.value},set locale(e){t.locale.value=e},get fallbackLocale(){return t.fallbackLocale.value},set fallbackLocale(e){t.fallbackLocale.value=e},get messages(){return t.messages.value},get datetimeFormats(){return t.datetimeFormats.value},get numberFormats(){return t.numberFormats.value},get availableLocales(){return t.availableLocales},get formatter(){return{interpolate(){return[]}}},set formatter(e){},get missing(){return t.getMissingHandler()},set missing(e){t.setMissingHandler(e)},get silentTranslationWarn(){return w(t.missingWarn)?!t.missingWarn:t.missingWarn},set silentTranslationWarn(e){t.missingWarn=w(e)?!e:e},get silentFallbackWarn(){return w(t.fallbackWarn)?!t.fallbackWarn:t.fallbackWarn},set silentFallbackWarn(e){t.fallbackWarn=w(e)?!e:e},get modifiers(){return t.modifiers},get formatFallbackMessages(){return t.fallbackFormat},set formatFallbackMessages(e){t.fallbackFormat=e},get postTranslation(){return t.getPostTranslationHandler()},set postTranslation(e){t.setPostTranslationHandler(e)},get sync(){return t.inheritLocale},set sync(e){t.inheritLocale=e},get warnHtmlInMessage(){return t.warnHtmlMessage?"warn":"off"},set warnHtmlInMessage(e){t.warnHtmlMessage="off"!==e},get escapeParameterHtml(){return t.escapeParameter},set escapeParameterHtml(e){t.escapeParameter=e},get preserveDirectiveContent(){return!0},set preserveDirectiveContent(e){},get pluralizationRules(){return t.pluralRules||{}},__composer:t,t(...e){const[n,r,o]=e,i={};let s=null,a=null;if(!E(n))throw Vn(Bn.INVALID_ARGUMENT);const l=n;return E(r)?i.locale=r:b(r)?s=r:T(r)&&(a=r),b(o)?s=o:T(o)&&(a=o),Reflect.apply(t.t,t,[l,s||a||{},i])},rt(...e){return Reflect.apply(t.rt,t,[...e])},tc(...e){const[n,r,o]=e,i={plural:1};let s=null,l=null;if(!E(n))throw Vn(Bn.INVALID_ARGUMENT);const c=n;return E(r)?i.locale=r:a(r)?i.plural=r:b(r)?s=r:T(r)&&(l=r),E(o)?i.locale=o:b(o)?s=o:T(o)&&(l=o),Reflect.apply(t.t,t,[c,s||l||{},i])},te(e,n){return t.te(e,n)},tm(e){return t.tm(e)},getLocaleMessage(e){return t.getLocaleMessage(e)},setLocaleMessage(e,n){t.setLocaleMessage(e,n)},mergeLocaleMessage(e,n){t.mergeLocaleMessage(e,n)},d(...e){return Reflect.apply(t.d,t,[...e])},getDateTimeFormat(e){return t.getDateTimeFormat(e)},setDateTimeFormat(e,n){t.setDateTimeFormat(e,n)},mergeDateTimeFormat(e,n){t.mergeDateTimeFormat(e,n)},n(...e){return Reflect.apply(t.n,t,[...e])},getNumberFormat(e){return t.getNumberFormat(e)},setNumberFormat(e,n){t.setNumberFormat(e,n)},mergeNumberFormat(e,n){t.mergeNumberFormat(e,n)},getChoiceIndex(e,t){return-1}};return r.__extender=n,r}}const cr={tag:{type:[String,Object]},locale:{type:String},scope:{type:String,validator:e=>"parent"===e||"global"===e,default:"parent"},i18n:{type:Object}};function ur({slots:e},t){if(1===t.length&&"default"===t[0]){const t=e.default?e.default():[];return t.reduce(((e,t)=>[...e,...t.type===In.FK?t.children:[t]]),[])}return t.reduce(((t,n)=>{const r=e[n];return r&&(t[n]=r()),t}),p())}function dr(e){return In.FK}const fr=(0,In.pM)({name:"i18n-t",props:d({keypath:{type:String,required:!0},plural:{type:[Number,String],validator:e=>a(e)||!isNaN(e)}},cr),setup(e,t){const{slots:n,attrs:r}=t,o=e.i18n||Ar({useScope:e.scope,__useComponent:!0});return()=>{const i=Object.keys(n).filter((e=>"_"!==e)),s=p();e.locale&&(s.locale=e.locale),void 0!==e.plural&&(s.plural=E(e.plural)?+e.plural:e.plural);const a=ur(t,i),l=o[Hn](e.keypath,a,s),c=d(p(),r),u=E(e.tag)||S(e.tag)?e.tag:dr();return(0,In.h)(u,c,l)}}}),pr=fr;function hr(e){return b(e)&&!E(e[0])}function mr(e,t,n,r){const{slots:o,attrs:i}=t;return()=>{const t={part:!0};let s=p();e.locale&&(t.locale=e.locale),E(e.format)?t.key=e.format:S(e.format)&&(E(e.format.key)&&(t.key=e.format.key),s=Object.keys(e.format).reduce(((t,r)=>n.includes(r)?d(p(),t,{[r]:e.format[r]}):t),p()));const a=r(e.value,t,s);let l=[t.key];b(a)?l=a.map(((e,t)=>{const n=o[e.type],r=n?n({[e.type]:e.value,index:t,parts:a}):[e.value];return hr(r)&&(r[0].key=`${e.type}-${t}`),r})):E(a)&&(l=[a]);const c=d(p(),i),u=E(e.tag)||S(e.tag)?e.tag:dr();return(0,In.h)(u,c,l)}}const vr=(0,In.pM)({name:"i18n-n",props:d({value:{type:Number,required:!0},format:{type:[String,Object]}},cr),setup(e,t){const n=e.i18n||Ar({useScope:e.scope,__useComponent:!0});return mr(e,t,An,((...e)=>n[Xn](...e)))}}),gr=vr,yr=(0,In.pM)({name:"i18n-d",props:d({value:{type:[Number,Date],required:!0},format:{type:[String,Object]}},cr),setup(e,t){const n=e.i18n||Ar({useScope:e.scope,__useComponent:!0});return mr(e,t,Cn,((...e)=>n[Wn](...e)))}}),br=yr;function _r(e,t){const n=e;if("composition"===e.mode)return n.__getInstance(t)||e.global;{const r=n.__getInstance(t);return null!=r?r.__composer:e.global.__composer}}function Er(e){const t=t=>{const{instance:n,modifiers:r,value:o}=t;if(!n||!n.$)throw Vn(Bn.UNEXPECTED_ERROR);const i=_r(e,n.$);const s=wr(o);return[Reflect.apply(i.t,i,[...Sr(s)]),i]},n=(n,o)=>{const[i,s]=t(o);r&&e.global===s&&(n.__i18nWatcher=(0,In.wB)(s.locale,(()=>{o.instance&&o.instance.$forceUpdate()}))),n.__composer=s,n.textContent=i},o=e=>{r&&e.__i18nWatcher&&(e.__i18nWatcher(),e.__i18nWatcher=void 0,delete e.__i18nWatcher),e.__composer&&(e.__composer=void 0,delete e.__composer)},i=(e,{value:t})=>{if(e.__composer){const n=e.__composer,r=wr(t);e.textContent=Reflect.apply(n.t,n,[...Sr(r)])}},s=e=>{const[n]=t(e);return{textContent:n}};return{created:n,unmounted:o,beforeUpdate:i,getSSRProps:s}}function wr(e){if(E(e))return{path:e};if(T(e)){if(!("path"in e))throw Vn(Bn.REQUIRED_VALUE,"path");return e}throw Vn(Bn.INVALID_VALUE)}function Sr(e){const{path:t,locale:n,args:r,choice:o,plural:i}=e,s={},l=r||{};return E(n)&&(s.locale=n),a(o)&&(s.plural=o),a(i)&&(s.plural=i),[t,l,s]}function kr(e,t,...n){const r=T(n[0])?n[0]:{},o=!!r.useI18nComponentName,i=!w(r.globalInstall)||r.globalInstall;i&&([o?"i18n":pr.name,"I18nT"].forEach((t=>e.component(t,pr))),[gr.name,"I18nN"].forEach((t=>e.component(t,gr))),[br.name,"I18nD"].forEach((t=>e.component(t,br)))),e.directive("t",Er(t))}function Cr(e,t,n){return{beforeCreate(){const r=(0,In.nI)();if(!r)throw Vn(Bn.UNEXPECTED_ERROR);const o=this.$options;if(o.i18n){const r=o.i18n;if(o.__i18n&&(r.__i18n=o.__i18n),r.__root=t,this===this.$root)this.$i18n=Or(e,r);else{r.__injectWithOption=!0,r.__extender=n.__vueI18nExtend,this.$i18n=lr(r);const e=this.$i18n;e.__extender&&(e.__disposer=e.__extender(this.$i18n))}}else if(o.__i18n)if(this===this.$root)this.$i18n=Or(e,o);else{this.$i18n=lr({__i18n:o.__i18n,__injectWithOption:!0,__extender:n.__vueI18nExtend,__root:t});const e=this.$i18n;e.__extender&&(e.__disposer=e.__extender(this.$i18n))}else this.$i18n=e;o.__i18nGlobal&&Jn(t,o,o),this.$t=(...e)=>this.$i18n.t(...e),this.$rt=(...e)=>this.$i18n.rt(...e),this.$tc=(...e)=>this.$i18n.tc(...e),this.$te=(e,t)=>this.$i18n.te(e,t),this.$d=(...e)=>this.$i18n.d(...e),this.$n=(...e)=>this.$i18n.n(...e),this.$tm=e=>this.$i18n.tm(e),n.__setInstance(r,this.$i18n)},mounted(){0},unmounted(){const e=(0,In.nI)();if(!e)throw Vn(Bn.UNEXPECTED_ERROR);const t=this.$i18n;delete this.$t,delete this.$rt,delete this.$tc,delete this.$te,delete this.$d,delete this.$n,delete this.$tm,t.__disposer&&(t.__disposer(),delete t.__disposer,delete t.__extender),n.__deleteInstance(e),delete this.$i18n}}}function Or(e,t){e.locale=t.locale||e.locale,e.fallbackLocale=t.fallbackLocale||e.fallbackLocale,e.missing=t.missing||e.missing,e.silentTranslationWarn=t.silentTranslationWarn||e.silentFallbackWarn,e.silentFallbackWarn=t.silentFallbackWarn||e.silentFallbackWarn,e.formatFallbackMessages=t.formatFallbackMessages||e.formatFallbackMessages,e.postTranslation=t.postTranslation||e.postTranslation,e.warnHtmlInMessage=t.warnHtmlInMessage||e.warnHtmlInMessage,e.escapeParameterHtml=t.escapeParameterHtml||e.escapeParameterHtml,e.sync=t.sync||e.sync,e.__composer[Gn](t.pluralizationRules||e.pluralizationRules);const n=Yn(e.locale,{messages:t.messages,__i18n:t.__i18n});return Object.keys(n).forEach((t=>e.mergeLocaleMessage(t,n[t]))),t.datetimeFormats&&Object.keys(t.datetimeFormats).forEach((n=>e.mergeDateTimeFormat(n,t.datetimeFormats[n]))),t.numberFormats&&Object.keys(t.numberFormats).forEach((n=>e.mergeNumberFormat(n,t.numberFormats[n]))),e}const Tr=o("global-vue-i18n");function Rr(e={},t){const n=__VUE_I18N_LEGACY_API__&&w(e.legacy)?e.legacy:__VUE_I18N_LEGACY_API__,r=!w(e.globalInjection)||e.globalInjection,i=!__VUE_I18N_LEGACY_API__||!n||!!e.allowComposition,s=new Map,[a,l]=Nr(e,n),c=o("");function u(e){return s.get(e)||null}function d(e,t){s.set(e,t)}function f(e){s.delete(e)}{const e={get mode(){return __VUE_I18N_LEGACY_API__&&n?"legacy":"composition"},get allowComposition(){return i},async install(t,...o){if(t.__VUE_I18N_SYMBOL__=c,t.provide(t.__VUE_I18N_SYMBOL__,e),T(o[0])){const t=o[0];e.__composerExtend=t.__composerExtend,e.__vueI18nExtend=t.__vueI18nExtend}let i=null;!n&&r&&(i=Ur(t,e.global)),__VUE_I18N_FULL_INSTALL__&&kr(t,e,...o),__VUE_I18N_LEGACY_API__&&n&&t.mixin(Cr(l,l.__composer,e));const s=t.unmount;t.unmount=()=>{i&&i(),e.dispose(),s()}},get global(){return l},dispose(){a.stop()},__instances:s,__getInstance:u,__setInstance:d,__deleteInstance:f};return e}}function Ar(e={}){const t=(0,In.nI)();if(null==t)throw Vn(Bn.MUST_BE_CALL_SETUP_TOP);if(!t.isCE&&null!=t.appContext.app&&!t.appContext.app.__VUE_I18N_SYMBOL__)throw Vn(Bn.NOT_INSTALLED);const n=Lr(t),r=Pr(n),o=Qn(t),i=Ir(e,o);if(__VUE_I18N_LEGACY_API__&&"legacy"===n.mode&&!e.__useComponent){if(!n.allowComposition)throw Vn(Bn.NOT_AVAILABLE_IN_LEGACY_MODE);return $r(t,i,r,e)}if("global"===i)return Jn(r,e,o),r;if("parent"===i){let o=xr(n,t,e.__useComponent);return null==o&&(o=r),o}const s=n;let a=s.__getInstance(t);if(null==a){const n=d({},e);"__i18n"in o&&(n.__i18n=o.__i18n),r&&(n.__root=r),a=sr(n),s.__composerExtend&&(a[zn]=s.__composerExtend(a)),Dr(s,t,a),s.__setInstance(t,a)}return a}function Nr(e,t,n){const r=(0,Pn.uY)();{const n=__VUE_I18N_LEGACY_API__&&t?r.run((()=>lr(e))):r.run((()=>sr(e)));if(null==n)throw Vn(Bn.UNEXPECTED_ERROR);return[r,n]}}function Lr(e){{const t=(0,In.WQ)(e.isCE?Tr:e.appContext.app.__VUE_I18N_SYMBOL__);if(!t)throw Vn(e.isCE?Bn.NOT_INSTALLED_WITH_PROVIDE:Bn.UNEXPECTED_ERROR);return t}}function Ir(e,t){return u(e)?"__i18n"in t?"local":"global":e.useScope?e.useScope:"local"}function Pr(e){return"composition"===e.mode?e.global:e.global.__composer}function xr(e,t,n=!1){let r=null;const o=t.root;let i=Mr(t,n);while(null!=i){const t=e;if("composition"===e.mode)r=t.__getInstance(i);else if(__VUE_I18N_LEGACY_API__){const e=t.__getInstance(i);null!=e&&(r=e.__composer,n&&r&&!r[Kn]&&(r=null))}if(null!=r)break;if(o===i)break;i=i.parent}return r}function Mr(e,t=!1){return null==e?null:t&&e.vnode.ctx||e.parent}function Dr(e,t,n){(0,In.sV)((()=>{0}),t),(0,In.hi)((()=>{const r=n;e.__deleteInstance(t);const o=r[zn];o&&(o(),delete r[zn])}),t)}function $r(e,t,n,r={}){const o="local"===t,i=(0,Pn.IJ)(null);if(o&&e.proxy&&!e.proxy.$options.i18n&&!e.proxy.$options.__i18n)throw Vn(Bn.MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION);const s=w(r.inheritLocale)?r.inheritLocale:!E(r.locale),a=(0,Pn.KR)(!o||s?n.locale.value:E(r.locale)?r.locale:mt),l=(0,Pn.KR)(!o||s?n.fallbackLocale.value:E(r.fallbackLocale)||b(r.fallbackLocale)||T(r.fallbackLocale)||!1===r.fallbackLocale?r.fallbackLocale:a.value),u=(0,Pn.KR)(Yn(a.value,r)),d=(0,Pn.KR)(T(r.datetimeFormats)?r.datetimeFormats:{[a.value]:{}}),f=(0,Pn.KR)(T(r.numberFormats)?r.numberFormats:{[a.value]:{}}),p=o?n.missingWarn:!w(r.missingWarn)&&!c(r.missingWarn)||r.missingWarn,h=o?n.fallbackWarn:!w(r.fallbackWarn)&&!c(r.fallbackWarn)||r.fallbackWarn,m=o?n.fallbackRoot:!w(r.fallbackRoot)||r.fallbackRoot,v=!!r.fallbackFormat,g=_(r.missing)?r.missing:null,y=_(r.postTranslation)?r.postTranslation:null,S=o?n.warnHtmlMessage:!w(r.warnHtmlMessage)||r.warnHtmlMessage,k=!!r.escapeParameter,C=o?n.modifiers:T(r.modifiers)?r.modifiers:{},O=r.pluralRules||o&&n.pluralRules;function R(){return[a.value,l.value,u.value,d.value,f.value]}const A=(0,In.EW)({get:()=>i.value?i.value.locale.value:a.value,set:e=>{i.value&&(i.value.locale.value=e),a.value=e}}),N=(0,In.EW)({get:()=>i.value?i.value.fallbackLocale.value:l.value,set:e=>{i.value&&(i.value.fallbackLocale.value=e),l.value=e}}),L=(0,In.EW)((()=>i.value?i.value.messages.value:u.value)),I=(0,In.EW)((()=>d.value)),P=(0,In.EW)((()=>f.value));function x(){return i.value?i.value.getPostTranslationHandler():y}function M(e){i.value&&i.value.setPostTranslationHandler(e)}function D(){return i.value?i.value.getMissingHandler():g}function $(e){i.value&&i.value.setMissingHandler(e)}function F(e){return R(),e()}function j(...e){return i.value?F((()=>Reflect.apply(i.value.t,null,[...e]))):F((()=>""))}function U(...e){return i.value?Reflect.apply(i.value.rt,null,[...e]):""}function B(...e){return i.value?F((()=>Reflect.apply(i.value.d,null,[...e]))):F((()=>""))}function V(...e){return i.value?F((()=>Reflect.apply(i.value.n,null,[...e]))):F((()=>""))}function H(e){return i.value?i.value.tm(e):{}}function W(e,t){return!!i.value&&i.value.te(e,t)}function X(e){return i.value?i.value.getLocaleMessage(e):{}}function G(e,t){i.value&&(i.value.setLocaleMessage(e,t),u.value[e]=t)}function K(e,t){i.value&&i.value.mergeLocaleMessage(e,t)}function z(e){return i.value?i.value.getDateTimeFormat(e):{}}function q(e,t){i.value&&(i.value.setDateTimeFormat(e,t),d.value[e]=t)}function Y(e,t){i.value&&i.value.mergeDateTimeFormat(e,t)}function Q(e){return i.value?i.value.getNumberFormat(e):{}}function J(e,t){i.value&&(i.value.setNumberFormat(e,t),f.value[e]=t)}function Z(e,t){i.value&&i.value.mergeNumberFormat(e,t)}const ee={get id(){return i.value?i.value.id:-1},locale:A,fallbackLocale:N,messages:L,datetimeFormats:I,numberFormats:P,get inheritLocale(){return i.value?i.value.inheritLocale:s},set inheritLocale(e){i.value&&(i.value.inheritLocale=e)},get availableLocales(){return i.value?i.value.availableLocales:Object.keys(u.value)},get modifiers(){return i.value?i.value.modifiers:C},get pluralRules(){return i.value?i.value.pluralRules:O},get isGlobal(){return!!i.value&&i.value.isGlobal},get missingWarn(){return i.value?i.value.missingWarn:p},set missingWarn(e){i.value&&(i.value.missingWarn=e)},get fallbackWarn(){return i.value?i.value.fallbackWarn:h},set fallbackWarn(e){i.value&&(i.value.missingWarn=e)},get fallbackRoot(){return i.value?i.value.fallbackRoot:m},set fallbackRoot(e){i.value&&(i.value.fallbackRoot=e)},get fallbackFormat(){return i.value?i.value.fallbackFormat:v},set fallbackFormat(e){i.value&&(i.value.fallbackFormat=e)},get warnHtmlMessage(){return i.value?i.value.warnHtmlMessage:S},set warnHtmlMessage(e){i.value&&(i.value.warnHtmlMessage=e)},get escapeParameter(){return i.value?i.value.escapeParameter:k},set escapeParameter(e){i.value&&(i.value.escapeParameter=e)},t:j,getPostTranslationHandler:x,setPostTranslationHandler:M,getMissingHandler:D,setMissingHandler:$,rt:U,d:B,n:V,tm:H,te:W,getLocaleMessage:X,setLocaleMessage:G,mergeLocaleMessage:K,getDateTimeFormat:z,setDateTimeFormat:q,mergeDateTimeFormat:Y,getNumberFormat:Q,setNumberFormat:J,mergeNumberFormat:Z};function te(e){e.locale.value=a.value,e.fallbackLocale.value=l.value,Object.keys(u.value).forEach((t=>{e.mergeLocaleMessage(t,u.value[t])})),Object.keys(d.value).forEach((t=>{e.mergeDateTimeFormat(t,d.value[t])})),Object.keys(f.value).forEach((t=>{e.mergeNumberFormat(t,f.value[t])})),e.escapeParameter=k,e.fallbackFormat=v,e.fallbackRoot=m,e.fallbackWarn=h,e.missingWarn=p,e.warnHtmlMessage=S}return(0,In.KC)((()=>{if(null==e.proxy||null==e.proxy.$i18n)throw Vn(Bn.NOT_AVAILABLE_COMPOSITION_IN_LEGACY);const n=i.value=e.proxy.$i18n.__composer;"global"===t?(a.value=n.locale.value,l.value=n.fallbackLocale.value,u.value=n.messages.value,d.value=n.datetimeFormats.value,f.value=n.numberFormats.value):o&&te(n)})),ee}const Fr=["locale","fallbackLocale","availableLocales"],jr=["t","rt","d","n","tm","te"];function Ur(e,t){const n=Object.create(null);Fr.forEach((e=>{const r=Object.getOwnPropertyDescriptor(t,e);if(!r)throw Vn(Bn.UNEXPECTED_ERROR);const o=(0,Pn.i9)(r.value)?{get(){return r.value.value},set(e){r.value.value=e}}:{get(){return r.get&&r.get()}};Object.defineProperty(n,e,o)})),e.config.globalProperties.$i18n=n,jr.forEach((n=>{const r=Object.getOwnPropertyDescriptor(t,n);if(!r||!r.value)throw Vn(Bn.UNEXPECTED_ERROR);Object.defineProperty(e.config.globalProperties,`$${n}`,r)}));const r=()=>{delete e.config.globalProperties.$i18n,jr.forEach((t=>{delete e.config.globalProperties[`$${t}`]}))};return r}if(Mn(),__INTLIFY_JIT_COMPILATION__?wt(fn):wt(dn),St($e),kt(ct),__INTLIFY_PROD_DEVTOOLS__){const e=m();e.__INTLIFY__=!0,ze(e.__INTLIFY_DEVTOOLS_GLOBAL_HOOK__)}},7040:function(e,t,n){"use strict";var r=n(4495);e.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},7055:function(e,t,n){"use strict";var r=n(9504),o=n(9039),i=n(2195),s=Object,a=r("".split);e.exports=o((function(){return!s("z").propertyIsEnumerable(0)}))?function(e){return"String"===i(e)?a(e,""):s(e)}:s},7059:function(e,t,n){const r=n(560),o=(e,t,n)=>r(e,t,n)<0;e.exports=o},7075:function(e,t,n){const r=n(3908),o=n(3904),{ANY:i}=o,s=n(8311),a=n(7638),l=n(5580),c=n(7059),u=n(5200),d=n(4089),f=(e,t,n,f)=>{let p,h,m,v,g;switch(e=new r(e,f),t=new s(t,f),n){case">":p=l,h=u,m=c,v=">",g=">=";break;case"<":p=c,h=d,m=l,v="<",g="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(a(e,t,f))return!1;for(let r=0;r{e.semver===i&&(e=new o(">=0.0.0")),s=s||e,a=a||e,p(e.semver,s.semver,f)?s=e:m(e.semver,a.semver,f)&&(a=e)})),s.operator===v||s.operator===g)return!1;if((!a.operator||a.operator===v)&&h(e,a.semver))return!1;if(a.operator===g&&m(e,a.semver))return!1}return!0};e.exports=f},7272:function(e){const t="object"===typeof process&&{NODE_ENV:"production",BASE_URL:""}.NODE_DEBUG&&/\bsemver\b/i.test({NODE_ENV:"production",BASE_URL:""}.NODE_DEBUG)?(...e)=>console.error("SEMVER",...e):()=>{};e.exports=t},7347:function(e,t,n){"use strict";var r=n(3724),o=n(9565),i=n(8773),s=n(6980),a=n(5397),l=n(6969),c=n(9297),u=n(5917),d=Object.getOwnPropertyDescriptor;t.f=r?d:function(e,t){if(e=a(e),t=l(t),u)try{return d(e,t)}catch(n){}if(c(e,t))return s(!o(i.f,e,t),e[t])}},7414:function(e,t,n){const r=n(144),o=(e,t)=>{const n=r(e.trim().replace(/^[=v]+/,""),t);return n?n.version:null};e.exports=o},7476:function(e,t,n){"use strict";var r=n(2195),o=n(9504);e.exports=function(e){if("Function"===r(e))return o(e)}},7566:function(e,t,n){"use strict";var r=n(6840),o=n(9504),i=n(655),s=n(2812),a=URLSearchParams,l=a.prototype,c=o(l.getAll),u=o(l.has),d=new a("a=1");!d.has("a",2)&&d.has("a",void 0)||r(l,"has",(function(e){var t=arguments.length,n=t<2?void 0:arguments[1];if(t&&void 0===n)return u(this,e);var r=c(this,e);s(t,1);var o=i(n),a=0;while(anew r(e,t).set.map((e=>e.map((e=>e.value)).join(" ").trim().split(" ")));e.exports=o},7638:function(e,t,n){const r=n(8311),o=(e,t,n)=>{try{t=new r(t,n)}catch(o){return!1}return t.test(e)};e.exports=o},7657:function(e,t,n){"use strict";var r,o,i,s=n(9039),a=n(4901),l=n(34),c=n(2360),u=n(2787),d=n(6840),f=n(8227),p=n(6395),h=f("iterator"),m=!1;[].keys&&(i=[].keys(),"next"in i?(o=u(u(i)),o!==Object.prototype&&(r=o)):m=!0);var v=!l(r)||s((function(){var e={};return r[h].call(e)!==e}));v?r={}:p&&(r=c(r)),a(r[h])||d(r,h,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:m}},7740:function(e,t,n){"use strict";var r=n(9297),o=n(5031),i=n(7347),s=n(4913);e.exports=function(e,t,n){for(var a=o(t),l=s.f,c=i.f,u=0;u{let n=new XMLHttpRequest;n.open(e.method,e.url,!0),Object.keys(e.headers).forEach((t=>n.setRequestHeader(t,e.headers[t])));let r,o=(e,r)=>setTimeout((()=>{n.abort(),t({status:0,content:r,isTimedOut:!0})}),e),i=o(e.connectTimeout,"Connection timeout");n.onreadystatechange=()=>{n.readyState>n.OPENED&&void 0===r&&(clearTimeout(i),r=o(e.responseTimeout,"Socket timeout"))},n.onerror=()=>{0===n.status&&(clearTimeout(i),clearTimeout(r),t({content:n.responseText||"Network request failed",status:n.status,isTimedOut:!1}))},n.onload=()=>{clearTimeout(i),clearTimeout(r),t({content:n.responseText,status:n.status,isTimedOut:!1})},n.send(e.data)}))}return{send:e}}function i(e){let t;const n=`algolia-client-js-${e.key}`;function r(){return void 0===t&&(t=e.localStorage||window.localStorage),t}function o(){return JSON.parse(r().getItem(n)||"{}")}function i(e){r().setItem(n,JSON.stringify(e))}function s(){const t=e.timeToLive?1e3*e.timeToLive:null,n=o(),r=Object.fromEntries(Object.entries(n).filter((([,e])=>void 0!==e.timestamp)));if(i(r),!t)return;const s=Object.fromEntries(Object.entries(r).filter((([,e])=>{const n=(new Date).getTime(),r=e.timestamp+tPromise.resolve()}){return Promise.resolve().then((()=>(s(),o()[JSON.stringify(e)]))).then((e=>Promise.all([e?e.value:t(),void 0!==e]))).then((([e,t])=>Promise.all([e,t||n.miss(e)]))).then((([e])=>e))},set(e,t){return Promise.resolve().then((()=>{const i=o();return i[JSON.stringify(e)]={timestamp:(new Date).getTime(),value:t},r().setItem(n,JSON.stringify(i)),t}))},delete(e){return Promise.resolve().then((()=>{const t=o();delete t[JSON.stringify(e)],r().setItem(n,JSON.stringify(t))}))},clear(){return Promise.resolve().then((()=>{r().removeItem(n)}))}}}function s(){return{get(e,t,n={miss:()=>Promise.resolve()}){const r=t();return r.then((e=>Promise.all([e,n.miss(e)]))).then((([e])=>e))},set(e,t){return Promise.resolve(t)},delete(e){return Promise.resolve()},clear(){return Promise.resolve()}}}function a(e){const t=[...e.caches],n=t.shift();return void 0===n?s():{get(e,r,o={miss:()=>Promise.resolve()}){return n.get(e,r,o).catch((()=>a({caches:t}).get(e,r,o)))},set(e,r){return n.set(e,r).catch((()=>a({caches:t}).set(e,r)))},delete(e){return n.delete(e).catch((()=>a({caches:t}).delete(e)))},clear(){return n.clear().catch((()=>a({caches:t}).clear()))}}}function l(e={serializable:!0}){let t={};return{get(n,r,o={miss:()=>Promise.resolve()}){const i=JSON.stringify(n);if(i in t)return Promise.resolve(e.serializable?JSON.parse(t[i]):t[i]);const s=r();return s.then((e=>o.miss(e))).then((()=>s))},set(n,r){return t[JSON.stringify(n)]=e.serializable?JSON.stringify(r):r,Promise.resolve(r)},delete(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear(){return t={},Promise.resolve()}}}function c(e){const t={value:`Algolia for JavaScript (${e})`,add(e){const n=`; ${e.segment}${void 0!==e.version?` (${e.version})`:""}`;return-1===t.value.indexOf(n)&&(t.value=`${t.value}${n}`),t}};return t}function u(e,t,n="WithinHeaders"){const r={"x-algolia-api-key":t,"x-algolia-application-id":e};return{headers(){return"WithinHeaders"===n?r:{}},queryParameters(){return"WithinQueryParameters"===n?r:{}}}}function d({algoliaAgents:e,client:t,version:n}){const r=c(n).add({segment:t,version:n});return e.forEach((e=>r.add(e))),r}function f(){return{debug(e,t){return Promise.resolve()},info(e,t){return Promise.resolve()},error(e,t){return Promise.resolve()}}}var p=12e4;function h(e,t="up"){const n=Date.now();function r(){return"up"===t||Date.now()-n>p}function o(){return"timed out"===t&&Date.now()-n<=p}return{...e,status:t,lastUpdate:n,isUp:r,isTimedOut:o}}var m=class extends Error{name="AlgoliaError";constructor(e,t){super(e),t&&(this.name=t)}},v=class extends m{stackTrace;constructor(e,t,n){super(e,n),this.stackTrace=t}},g=class extends v{constructor(e){super("Unreachable hosts - your application id may be incorrect. If the error persists, please reach out to the Algolia Support team: https://alg.li/support.",e,"RetryError")}},y=class extends v{status;constructor(e,t,n,r="ApiError"){super(e,n,r),this.status=t}},b=class extends m{response;constructor(e,t){super(e,"DeserializationError"),this.response=t}},_=class extends y{error;constructor(e,t,n,r){super(e,t,r,"DetailedApiError"),this.error=n}};function E(e){const t=e;for(let n=e.length-1;n>0;n--){const r=Math.floor(Math.random()*(n+1)),o=e[n];t[n]=e[r],t[r]=o}return t}function w(e,t,n){const r=S(n);let o=`${e.protocol}://${e.url}${e.port?`:${e.port}`:""}/${"/"===t.charAt(0)?t.substring(1):t}`;return r.length&&(o+=`?${r}`),o}function S(e){return Object.keys(e).filter((t=>void 0!==e[t])).sort().map((t=>`${t}=${encodeURIComponent("[object Array]"===Object.prototype.toString.call(e[t])?e[t].join(","):e[t]).replace(/\+/g,"%20")}`)).join("&")}function k(e,t){if("GET"===e.method||void 0===e.data&&void 0===t.data)return;const n=Array.isArray(e.data)?e.data:{...e.data,...t.data};return JSON.stringify(n)}function C(e,t,n){const r={Accept:"application/json",...e,...t,...n},o={};return Object.keys(r).forEach((e=>{const t=r[e];o[e.toLowerCase()]=t})),o}function O(e){try{return JSON.parse(e.content)}catch(t){throw new b(t.message,e)}}function T({content:e,status:t},n){try{const r=JSON.parse(e);return"error"in r?new _(r.message,t,r.error,n):new y(r.message,t,n)}catch{}return new y(e,t,n)}function R({isTimedOut:e,status:t}){return!e&&0===~~t}function A({isTimedOut:e,status:t}){return e||R({isTimedOut:e,status:t})||2!==~~(t/100)&&4!==~~(t/100)}function N({status:e}){return 2===~~(e/100)}function L(e){return e.map((e=>I(e)))}function I(e){const t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...e,request:{...e.request,headers:{...e.request.headers,...t}}}}function P({hosts:e,hostsCache:t,baseHeaders:n,logger:r,baseQueryParameters:o,algoliaAgent:i,timeouts:s,requester:a,requestsCache:l,responsesCache:c}){async function u(e){const n=await Promise.all(e.map((e=>t.get(e,(()=>Promise.resolve(h(e))))))),r=n.filter((e=>e.isUp())),o=n.filter((e=>e.isTimedOut())),i=[...r,...o],s=i.length>0?i:e;return{hosts:s,getTimeout(e,t){const n=0===o.length&&0===e?1:o.length+3+e;return n*t}}}async function d(l,c,d=!0){const f=[],p=k(l,c),m=C(n,l.headers,c.headers),v="GET"===l.method?{...l.data,...c.data}:{},y={...o,...l.queryParameters,...v};if(i.value&&(y["x-algolia-agent"]=i.value),c&&c.queryParameters)for(const e of Object.keys(c.queryParameters))c.queryParameters[e]&&"[object Object]"!==Object.prototype.toString.call(c.queryParameters[e])?y[e]=c.queryParameters[e].toString():y[e]=c.queryParameters[e];let b=0;const _=async(e,n)=>{const o=e.pop();if(void 0===o)throw new g(L(f));const i={...s,...c.timeouts},u={data:p,headers:m,method:l.method,url:w(o,l.path,y),connectTimeout:n(b,i.connect),responseTimeout:n(b,d?i.read:i.write)},v=t=>{const n={request:u,response:t,host:o,triesLeft:e.length};return f.push(n),n},E=await a.send(u);if(A(E)){const i=v(E);return E.isTimedOut&&b++,r.info("Retryable failure",I(i)),await t.set(o,h(o,E.isTimedOut?"timed out":"down")),_(e,n)}if(N(E))return O(E);throw v(E),T(E,f)},E=e.filter((e=>"readWrite"===e.accept||(d?"read"===e.accept:"write"===e.accept))),S=await u(E);return _([...S.hosts].reverse(),S.getTimeout)}function f(e,t={}){const r=e.useReadTransporter||"GET"===e.method;if(!r)return d(e,t,r);const i=()=>d(e,t),s=t.cacheable||e.cacheable;if(!0!==s)return i();const a={request:e,requestOptions:t,transporter:{queryParameters:o,headers:n}};return c.get(a,(()=>l.get(a,(()=>l.set(a,i()).then((e=>Promise.all([l.delete(a),e])),(e=>Promise.all([l.delete(a),Promise.reject(e)]))).then((([e,t])=>t))))),{miss:e=>c.set(a,e)})}return{hostsCache:t,requester:a,timeouts:s,logger:r,algoliaAgent:i,baseHeaders:n,baseQueryParameters:o,hosts:e,request:f,requestsCache:l,responsesCache:c}}var x="5.20.3";function M(e){return[{url:`${e}-dsn.algolia.net`,accept:"read",protocol:"https"},{url:`${e}.algolia.net`,accept:"write",protocol:"https"}].concat(E([{url:`${e}-1.algolianet.com`,accept:"readWrite",protocol:"https"},{url:`${e}-2.algolianet.com`,accept:"readWrite",protocol:"https"},{url:`${e}-3.algolianet.com`,accept:"readWrite",protocol:"https"}]))}function D({appId:e,apiKey:t,authMode:n,algoliaAgents:r,...o}){const i=u(e,t,n),s=P({hosts:M(e),...o,algoliaAgent:d({algoliaAgents:r,client:"Lite",version:x}),baseHeaders:{"content-type":"text/plain",...i.headers(),...o.baseHeaders},baseQueryParameters:{...i.queryParameters(),...o.baseQueryParameters}});return{transporter:s,appId:e,apiKey:t,clearCache(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then((()=>{}))},get _ua(){return s.algoliaAgent.value},addAlgoliaAgent(e,t){s.algoliaAgent.add({segment:e,version:t})},setClientApiKey({apiKey:e}){n&&"WithinHeaders"!==n?s.baseQueryParameters["x-algolia-api-key"]=e:s.baseHeaders["x-algolia-api-key"]=e},searchForHits(e,t){return this.search(e,t)},searchForFacets(e,t){return this.search(e,t)},customPost({path:e,parameters:t,body:n},r){if(!e)throw new Error("Parameter `path` is required when calling `customPost`.");const o="/{path}".replace("{path}",e),i={},a=t||{},l={method:"POST",path:o,queryParameters:a,headers:i,data:n||{}};return s.request(l,r)},getRecommendations(e,t){if(e&&Array.isArray(e)){const t={requests:e};e=t}if(!e)throw new Error("Parameter `getRecommendationsParams` is required when calling `getRecommendations`.");if(!e.requests)throw new Error("Parameter `getRecommendationsParams.requests` is required when calling `getRecommendations`.");const n="/1/indexes/*/recommendations",r={},o={},i={method:"POST",path:n,queryParameters:o,headers:r,data:e,useReadTransporter:!0,cacheable:!0};return s.request(i,t)},search(e,t){if(e&&Array.isArray(e)){const t={requests:e.map((({params:e,...t})=>"facet"===t.type?{...t,...e,type:"facet"}:{...t,...e,facet:void 0,maxFacetHits:void 0,facetQuery:void 0}))};e=t}if(!e)throw new Error("Parameter `searchMethodParams` is required when calling `search`.");if(!e.requests)throw new Error("Parameter `searchMethodParams.requests` is required when calling `search`.");const n="/1/indexes/*/queries",r={},o={},i={method:"POST",path:n,queryParameters:o,headers:r,data:e,useReadTransporter:!0,cacheable:!0};return s.request(i,t)}}}function $(e,t,n){if(!e||"string"!==typeof e)throw new Error("`appId` is missing.");if(!t||"string"!==typeof t)throw new Error("`apiKey` is missing.");return D({appId:e,apiKey:t,timeouts:{connect:1e3,read:2e3,write:3e4},logger:f(),requester:o(),algoliaAgents:[{segment:"Browser"}],authMode:"WithinQueryParameters",responsesCache:l(),requestsCache:l({serializable:!1}),hostsCache:a({caches:[i({key:`${x}-${e}`}),l()]}),...n})}var F=n(9589),j=n(9997);const U=$("60DW2LJW0P","13718a23f4e436f7e7614340bd87d913"),B=(e,t=6)=>{const n=Array.from(e),r=[];while(n.length>0&&r.lengthe(null)));if(Object.keys(e.metadata).includes(n))return e.metadata[n];const o=(async()=>{let t=null;try{const r=await U.search([{indexName:"v3_packages",params:{filters:`name:"${n}" AND languages:${e.language}`,hitsPerPage:1}}]);r.results[0].nbHits>0&&(t=r.results[0].hits[0])}catch(o){}try{if(t&&t.private)t=Object.assign({},(await r.A.get(`https://contao.github.io/package-metadata/meta/${n}/composer.json`)).data,t||{});else{let e,i=(await r.A.get(`https://packagist.org/packages/${n}.json`)).data.package,s=[];i.downloads=i.downloads.total,i.dependency=!0;try{const e=(await r.A.get(`https://repo.packagist.org/p2/${n}.json`)).data.packages[n];let t=null;Object.values(e).forEach((e=>{if(!t)return t=e,void s.push(JSON.parse(JSON.stringify(t)));Object.keys(e).forEach((n=>{"__unset"===e[n]?delete t[n]:t[n]=e[n]})),s.push(JSON.parse(JSON.stringify(t)))}))}catch(o){s=Object.values(i.versions)}if(e=s.filter((e=>"dev-"!==e.version.substr(0,4)&&"-dev"!==e.version.substr(-4)&&e.require&&"contao/core-bundle"in e.require)),e.length||(e=s.filter((e=>"dev-"!==e.version.substr(0,4)&&"-dev"!==e.version.substr(-4)))),e.length||(e=s),e&&e.length||(e=[]),e=e.sort(((e,t)=>{const n=(0,F.coerce)(e.version_normalized,{loose:!0}),r=(0,F.coerce)(t.version_normalized,{loose:!0}),o=(0,F.compare)(n,r);return 0===o?new Date(e.time)>new Date(t.time)?1:-1:o})),e.length){const t=e[e.length-1];i=Object.assign(i,t),i.latest={version:t.version,time:t.time}}t=Object.assign({},i,t||{},{versions:e})}}catch(o){console.info("No package metadata for "+n,o)}return t?(delete t.version,delete t.time,delete t.constraint,j.A[t.name]&&(t.features=j.A[t.name]),t):null})();return t("cache",{name:n,data:o}),o},async findPackages({state:e,dispatch:t},n){let r="",o="dependency:false";n.sorting&&(r=n.sorting?`_${n.sorting}`:"",o="discoverable:true",delete n.sorting),n.type&&(o=`type:${n.type}`,delete n.type),n.filters=`languages:${e.language} AND ${o}`,n.highlightPreTag="%%",n.highlightPostTag="%%";const i=(await U.search([{indexName:`v3_packages${r}`,params:n}])).results[0];if(i.nbHits>0)return i;const s=await t("getPackage",n.query);return s?{nbHits:1,hits:[s]}:i},async discover({state:e,commit:t}){try{const n=new Date,r=`${n.getFullYear()}${String(n.getMonth()+1).padStart(2,"0")}${String(n.getDate()).padStart(2,"0")}`,o=await U.search([{indexName:"v3_packages_latest",params:{hitsPerPage:6,filters:`languages:${e.language} AND discoverable:true`}},{indexName:"v3_packages_downloads",params:{hitsPerPage:4,filters:`languages:${e.language} AND discoverable:true`}},{indexName:"v3_packages_favers",params:{hitsPerPage:4,filters:`languages:${e.language} AND discoverable:true`}},{indexName:"v3_ads",params:{hitsPerPage:6,filters:`position:primary AND languages:${e.language} AND published:true AND validFrom <= ${r} AND validTo >= ${r}`}},{indexName:"v3_ads",params:{hitsPerPage:100,filters:`position:secondary AND languages:${e.language} AND published:true AND validFrom <= ${r} AND validTo >= ${r}`}},{indexName:"v3_ads",params:{hitsPerPage:100,filters:`position:subheader AND languages:${e.language} AND published:true AND validFrom <= ${r} AND validTo >= ${r}`}}]);t("setDiscover",{latest:o.results[0].hits,downloads:o.results[1].hits,favers:o.results[2].hits,ads:B(o.results[3].hits).concat(B(o.results[4].hits,6-o.results[3].nbHits)),news:B(o.results[5].hits)})}catch(n){t("setDiscover",null)}}}}},7944:function(e,t,n){"use strict";n.d(t,{dv:function(){return g}});var r,o=n(641),i=n(953),s=function(){return s=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.MAX_VERSION)throw new RangeError("Version value out of range");if(i<-1||i>7)throw new RangeError("Mask value out of range");this.size=4*e+17;for(var s=[],a=0;a7)throw new RangeError("Invalid value");var u,d;for(u=s;;u++){var f=8*t.getNumDataCodewords(u,r),p=i.getTotalBits(e,u);if(p<=f){d=p;break}if(u>=a)throw new RangeError("Data too long")}for(var h=0,m=[t.Ecc.MEDIUM,t.Ecc.QUARTILE,t.Ecc.HIGH];h>>3]|=e<<7-(7&t)})),new t(u,r,O,l)},t.prototype.getModule=function(e,t){return 0<=e&&e>>9);var s=21522^(t<<10|n);o(s>>>15==0);for(i=0;i<=5;i++)this.setFunctionModule(8,i,r(s,i));this.setFunctionModule(8,7,r(s,6)),this.setFunctionModule(8,8,r(s,7)),this.setFunctionModule(7,8,r(s,8));for(i=9;i<15;i++)this.setFunctionModule(14-i,8,r(s,i));for(i=0;i<8;i++)this.setFunctionModule(this.size-1-i,8,r(s,i));for(i=8;i<15;i++)this.setFunctionModule(8,this.size-15+i,r(s,i));this.setFunctionModule(8,this.size-8,!0)},t.prototype.drawVersion=function(){if(!(this.version<7)){for(var e=this.version,t=0;t<12;t++)e=e<<1^7973*(e>>>11);var n=this.version<<12|e;o(n>>>18==0);for(t=0;t<18;t++){var i=r(n,t),s=this.size-11+t%3,a=Math.floor(t/3);this.setFunctionModule(s,a,i),this.setFunctionModule(a,s,i)}}},t.prototype.drawFinderPattern=function(e,t){for(var n=-4;n<=4;n++)for(var r=-4;r<=4;r++){var o=Math.max(Math.abs(r),Math.abs(n)),i=e+r,s=t+n;0<=i&&i=l)&&v.push(t[e])}))};for(f=0;f=1;i-=2){6==i&&(i=5);for(var s=0;s>>3],7-(7&n)),n++)}}o(n==8*e.length)},t.prototype.applyMask=function(e){if(e<0||e>7)throw new RangeError("Mask value out of range");for(var t=0;t5&&e++):(this.finderPenaltyAddHistory(i,s),r||(e+=this.finderPenaltyCountPatterns(s)*t.PENALTY_N3),r=this.modules[n][a],i=1);e+=this.finderPenaltyTerminateAndCount(r,i,s)*t.PENALTY_N3}for(a=0;a5&&e++):(this.finderPenaltyAddHistory(l,s),r||(e+=this.finderPenaltyCountPatterns(s)*t.PENALTY_N3),r=this.modules[n][a],l=1);e+=this.finderPenaltyTerminateAndCount(r,l,s)*t.PENALTY_N3}for(n=0;nt.MAX_VERSION)throw new RangeError("Version number out of range");var n=(16*e+128)*e+64;if(e>=2){var r=Math.floor(e/7)+2;n-=(25*r-10)*r-55,e>=7&&(n-=36)}return o(208<=n&&n<=29648),n},t.getNumDataCodewords=function(e,n){return Math.floor(t.getNumRawDataModules(e)/8)-t.ECC_CODEWORDS_PER_BLOCK[n.ordinal][e]*t.NUM_ERROR_CORRECTION_BLOCKS[n.ordinal][e]},t.reedSolomonComputeDivisor=function(e){if(e<1||e>255)throw new RangeError("Degree out of range");for(var n=[],r=0;r>>8!=0||t>>>8!=0)throw new RangeError("Byte out of range");for(var n=0,r=7;r>=0;r--)n=n<<1^285*(n>>>7),n^=(t>>>r&1)*e;return o(n>>>8==0),n},t.prototype.finderPenaltyCountPatterns=function(e){var t=e[1];o(t<=3*this.size);var n=t>0&&e[2]==t&&e[3]==3*t&&e[4]==t&&e[5]==t;return(n&&e[0]>=4*t&&e[6]>=t?1:0)+(n&&e[6]>=4*t&&e[0]>=t?1:0)},t.prototype.finderPenaltyTerminateAndCount=function(e,t,n){return e&&(this.finderPenaltyAddHistory(t,n),t=0),t+=this.size,this.finderPenaltyAddHistory(t,n),this.finderPenaltyCountPatterns(n)},t.prototype.finderPenaltyAddHistory=function(e,t){0==t[0]&&(e+=this.size),t.pop(),t.unshift(e)},t.MIN_VERSION=1,t.MAX_VERSION=40,t.PENALTY_N1=3,t.PENALTY_N2=3,t.PENALTY_N3=40,t.PENALTY_N4=10,t.ECC_CODEWORDS_PER_BLOCK=[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]],t.NUM_ERROR_CORRECTION_BLOCKS=[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]],t}();function n(e,t,n){if(t<0||t>31||e>>>t!=0)throw new RangeError("Value out of range");for(var r=t-1;r>=0;r--)n.push(e>>>r&1)}function r(e,t){return 0!=(e>>>t&1)}function o(e){if(!e)throw new Error("Assertion error")}e.QrCode=t;var i=function(){function e(e,t,n){if(this.mode=e,this.numChars=t,this.bitData=n,t<0)throw new RangeError("Invalid argument");this.bitData=n.slice()}return e.makeBytes=function(t){for(var r=[],o=0,i=t;o=1<=t.y+t.h?e:e.map((function(e,n){return(n=t.x+t.w)&&e}))}))}var m={value:{type:String,required:!0,default:""},size:{type:Number,default:100},level:{type:String,default:l,validator:function(e){return d(e)}},background:{type:String,default:"#fff"},foreground:{type:String,default:"#000"},margin:{type:Number,required:!1,default:0},imageSettings:{type:Object,required:!1,default:function(){return{}}},gradient:{type:Boolean,required:!1,default:!1},gradientType:{type:String,required:!1,default:"linear",validator:function(e){return["linear","radial"].indexOf(e)>-1}},gradientStartColor:{type:String,required:!1,default:"#000"},gradientEndColor:{type:String,required:!1,default:"#fff"}},v=s(s({},m),{renderAs:{type:String,required:!1,default:"canvas",validator:function(e){return["canvas","svg"].indexOf(e)>-1}}}),g=(0,o.pM)({name:"QRCodeSvg",props:m,setup:function(e){var t,n=(0,i.KR)(0),r=(0,i.KR)(""),u=function(){var o=e.value,i=e.level,s=e.margin,u=s>>>0,m=d(i)?i:l,v=a.QrCode.encodeText(o,c[m]).getModules();if(n.value=v.length+2*u,e.imageSettings.src){var g=p(v,e.size,u,e.imageSettings);t={x:g.x+u,y:g.y+u,width:g.w,height:g.h},g.excavation&&(v=h(v,g.excavation))}r.value=f(v,u)},m=function(){if(!e.gradient)return null;var t="linear"===e.gradientType?{x1:"0%",y1:"0%",x2:"100%",y2:"100%"}:{cx:"50%",cy:"50%",r:"50%",fx:"50%",fy:"50%"};return(0,o.h)("linear"===e.gradientType?"linearGradient":"radialGradient",s({id:"qr-gradient"},t),[(0,o.h)("stop",{offset:"0%",style:{stopColor:e.gradientStartColor}}),(0,o.h)("stop",{offset:"100%",style:{stopColor:e.gradientEndColor}})])};return u(),(0,o.$u)(u),function(){return(0,o.h)("svg",{width:e.size,height:e.size,"shape-rendering":"crispEdges",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 ".concat(n.value," ").concat(n.value)},[(0,o.h)("defs",{},[m()]),(0,o.h)("rect",{width:"100%",height:"100%",fill:e.background}),(0,o.h)("path",{fill:e.gradient?"url(#qr-gradient)":e.foreground,d:r.value}),e.imageSettings.src&&(0,o.h)("image",s({href:e.imageSettings.src},t))])}}}),y=(0,o.pM)({name:"QRCodeCanvas",props:m,setup:function(e,t){var n=(0,i.KR)(null),r=(0,i.KR)(null),m=function(){var t=e.value,o=e.level,i=e.size,s=e.margin,m=e.background,v=e.foreground,g=e.gradient,y=e.gradientType,b=e.gradientStartColor,_=e.gradientEndColor,E=s>>>0,w=d(o)?o:l,S=n.value;if(S){var k=S.getContext("2d");if(k){var C=a.QrCode.encodeText(t,c[w]).getModules(),O=C.length+2*E,T=r.value,R={x:0,y:0,width:0,height:0},A=e.imageSettings.src&&null!=T&&0!==T.naturalWidth&&0!==T.naturalHeight;if(A){var N=p(C,e.size,E,e.imageSettings);R={x:N.x+E,y:N.y+E,width:N.w,height:N.h},N.excavation&&(C=h(C,N.excavation))}var L=window.devicePixelRatio||1,I=i/O*L;if(S.height=S.width=i*L,k.scale(I,I),k.fillStyle=m,k.fillRect(0,0,O,O),g){var P=void 0;P="linear"===y?k.createLinearGradient(0,0,O,O):k.createRadialGradient(O/2,O/2,0,O/2,O/2,O/2),P.addColorStop(0,b),P.addColorStop(1,_),k.fillStyle=P}else k.fillStyle=v;u?k.fill(new Path2D(f(C,E))):C.forEach((function(e,t){e.forEach((function(e,n){e&&k.fillRect(n+E,t+E,1,1)}))})),A&&k.drawImage(T,R.x,R.y,R.width,R.height)}}};(0,o.sV)(m),(0,o.$u)(m);var v=t.attrs.style;return function(){return(0,o.h)(o.FK,[(0,o.h)("canvas",s(s({},t.attrs),{ref:n,style:s(s({},v),{width:"".concat(e.size,"px"),height:"".concat(e.size,"px")})})),e.imageSettings.src&&(0,o.h)("img",{ref:r,src:e.imageSettings.src,style:{display:"none"},onLoad:m})])}}});(0,o.pM)({name:"Qrcode",render:function(){var e=this.$props,t=e.renderAs,n=e.value,r=e.size,i=e.margin,s=e.level,a=e.background,l=e.foreground,c=e.imageSettings,u=e.gradient,d=e.gradientType,f=e.gradientStartColor,p=e.gradientEndColor;return(0,o.h)("svg"===t?g:y,{value:n,size:r,margin:i,level:s,background:a,foreground:l,imageSettings:c,gradient:u,gradientType:d,gradientStartColor:f,gradientEndColor:p})},props:v})},8014:function(e,t,n){"use strict";var r=n(1291),o=Math.min;e.exports=function(e){var t=r(e);return t>0?o(t,9007199254740991):0}},8111:function(e,t,n){"use strict";var r=n(6518),o=n(4576),i=n(679),s=n(8551),a=n(4901),l=n(2787),c=n(2106),u=n(4659),d=n(9039),f=n(9297),p=n(8227),h=n(7657).IteratorPrototype,m=n(3724),v=n(6395),g="constructor",y="Iterator",b=p("toStringTag"),_=TypeError,E=o[y],w=v||!a(E)||E.prototype!==h||!d((function(){E({})})),S=function(){if(i(this,h),l(this)===h)throw new _("Abstract class Iterator not directly constructable")},k=function(e,t){m?c(h,e,{configurable:!0,get:function(){return t},set:function(t){if(s(this),this===h)throw new _("You can't redefine this property");f(this,e)?this[e]=t:u(this,e,t)}}):h[e]=t};f(h,b)||k(b,y),!w&&f(h,g)&&h[g]!==Object||k(g,S),S.prototype=h,r({global:!0,constructor:!0,forced:w},{Iterator:S})},8227:function(e,t,n){"use strict";var r=n(4576),o=n(5745),i=n(9297),s=n(3392),a=n(4495),l=n(7040),c=r.Symbol,u=o("wks"),d=l?c["for"]||c:c&&c.withoutSetter||s;e.exports=function(e){return i(u,e)||(u[e]=a&&i(c,e)?c[e]:d("Symbol."+e)),u[e]}},8237:function(e,t,n){"use strict";var r=n(6518),o=n(2652),i=n(9306),s=n(8551),a=n(1767),l=TypeError;r({target:"Iterator",proto:!0,real:!0},{reduce:function(e){s(this),i(e);var t=a(this),n=arguments.length<2,r=n?void 0:arguments[1],c=0;if(o(t,(function(t){n?(n=!1,r=t):r=e(r,t,c),c++}),{IS_RECORD:!0}),n)throw new l("Reduce of empty iterator with no initial value");return r}})},8311:function(e,t,n){const r=/\s+/g;class o{constructor(e,t){if(t=a(t),e instanceof o)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new o(e.raw,t);if(e instanceof l)return this.raw=e.value,this.set=[[e]],this.formatted=void 0,this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e.trim().replace(r," "),this.set=this.raw.split("||").map((e=>this.parseRange(e.trim()))).filter((e=>e.length)),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){const e=this.set[0];if(this.set=this.set.filter((e=>!y(e[0]))),0===this.set.length)this.set=[e];else if(this.set.length>1)for(const t of this.set)if(1===t.length&&b(t[0])){this.set=[t];break}}this.formatted=void 0}get range(){if(void 0===this.formatted){this.formatted="";for(let e=0;e0&&(this.formatted+="||");const t=this.set[e];for(let e=0;e0&&(this.formatted+=" "),this.formatted+=t[e].toString().trim()}}return this.formatted}format(){return this.range}toString(){return this.range}parseRange(e){const t=(this.options.includePrerelease&&v)|(this.options.loose&&g),n=t+":"+e,r=s.get(n);if(r)return r;const o=this.options.loose,i=o?d[f.HYPHENRANGELOOSE]:d[f.HYPHENRANGE];e=e.replace(i,L(this.options.includePrerelease)),c("hyphen replace",e),e=e.replace(d[f.COMPARATORTRIM],p),c("comparator trim",e),e=e.replace(d[f.TILDETRIM],h),c("tilde trim",e),e=e.replace(d[f.CARETTRIM],m),c("caret trim",e);let a=e.split(" ").map((e=>E(e,this.options))).join(" ").split(/\s+/).map((e=>N(e,this.options)));o&&(a=a.filter((e=>(c("loose invalid filter",e,this.options),!!e.match(d[f.COMPARATORLOOSE]))))),c("range list",a);const u=new Map,b=a.map((e=>new l(e,this.options)));for(const s of b){if(y(s))return[s];u.set(s.value,s)}u.size>1&&u.has("")&&u.delete("");const _=[...u.values()];return s.set(n,_),_}intersects(e,t){if(!(e instanceof o))throw new TypeError("a Range is required");return this.set.some((n=>_(n,t)&&e.set.some((e=>_(e,t)&&n.every((n=>e.every((e=>n.intersects(e,t)))))))))}test(e){if(!e)return!1;if("string"===typeof e)try{e=new u(e,this.options)}catch(t){return!1}for(let n=0;n"<0.0.0-0"===e.value,b=e=>""===e.value,_=(e,t)=>{let n=!0;const r=e.slice();let o=r.pop();while(n&&r.length)n=r.every((e=>o.intersects(e,t))),o=r.pop();return n},E=(e,t)=>(c("comp",e,t),e=C(e,t),c("caret",e),e=S(e,t),c("tildes",e),e=T(e,t),c("xrange",e),e=A(e,t),c("stars",e),e),w=e=>!e||"x"===e.toLowerCase()||"*"===e,S=(e,t)=>e.trim().split(/\s+/).map((e=>k(e,t))).join(" "),k=(e,t)=>{const n=t.loose?d[f.TILDELOOSE]:d[f.TILDE];return e.replace(n,((t,n,r,o,i)=>{let s;return c("tilde",e,t,n,r,o,i),w(n)?s="":w(r)?s=`>=${n}.0.0 <${+n+1}.0.0-0`:w(o)?s=`>=${n}.${r}.0 <${n}.${+r+1}.0-0`:i?(c("replaceTilde pr",i),s=`>=${n}.${r}.${o}-${i} <${n}.${+r+1}.0-0`):s=`>=${n}.${r}.${o} <${n}.${+r+1}.0-0`,c("tilde return",s),s}))},C=(e,t)=>e.trim().split(/\s+/).map((e=>O(e,t))).join(" "),O=(e,t)=>{c("caret",e,t);const n=t.loose?d[f.CARETLOOSE]:d[f.CARET],r=t.includePrerelease?"-0":"";return e.replace(n,((t,n,o,i,s)=>{let a;return c("caret",e,t,n,o,i,s),w(n)?a="":w(o)?a=`>=${n}.0.0${r} <${+n+1}.0.0-0`:w(i)?a="0"===n?`>=${n}.${o}.0${r} <${n}.${+o+1}.0-0`:`>=${n}.${o}.0${r} <${+n+1}.0.0-0`:s?(c("replaceCaret pr",s),a="0"===n?"0"===o?`>=${n}.${o}.${i}-${s} <${n}.${o}.${+i+1}-0`:`>=${n}.${o}.${i}-${s} <${n}.${+o+1}.0-0`:`>=${n}.${o}.${i}-${s} <${+n+1}.0.0-0`):(c("no pr"),a="0"===n?"0"===o?`>=${n}.${o}.${i}${r} <${n}.${o}.${+i+1}-0`:`>=${n}.${o}.${i}${r} <${n}.${+o+1}.0-0`:`>=${n}.${o}.${i} <${+n+1}.0.0-0`),c("caret return",a),a}))},T=(e,t)=>(c("replaceXRanges",e,t),e.split(/\s+/).map((e=>R(e,t))).join(" ")),R=(e,t)=>{e=e.trim();const n=t.loose?d[f.XRANGELOOSE]:d[f.XRANGE];return e.replace(n,((n,r,o,i,s,a)=>{c("xRange",e,n,r,o,i,s,a);const l=w(o),u=l||w(i),d=u||w(s),f=d;return"="===r&&f&&(r=""),a=t.includePrerelease?"-0":"",l?n=">"===r||"<"===r?"<0.0.0-0":"*":r&&f?(u&&(i=0),s=0,">"===r?(r=">=",u?(o=+o+1,i=0,s=0):(i=+i+1,s=0)):"<="===r&&(r="<",u?o=+o+1:i=+i+1),"<"===r&&(a="-0"),n=`${r+o}.${i}.${s}${a}`):u?n=`>=${o}.0.0${a} <${+o+1}.0.0-0`:d&&(n=`>=${o}.${i}.0${a} <${o}.${+i+1}.0-0`),c("xRange return",n),n}))},A=(e,t)=>(c("replaceStars",e,t),e.trim().replace(d[f.STAR],"")),N=(e,t)=>(c("replaceGTE0",e,t),e.trim().replace(d[t.includePrerelease?f.GTE0PRE:f.GTE0],"")),L=e=>(t,n,r,o,i,s,a,l,c,u,d,f)=>(n=w(r)?"":w(o)?`>=${r}.0.0${e?"-0":""}`:w(i)?`>=${r}.${o}.0${e?"-0":""}`:s?`>=${n}`:`>=${n}${e?"-0":""}`,l=w(c)?"":w(u)?`<${+c+1}.0.0-0`:w(d)?`<${c}.${+u+1}.0-0`:f?`<=${c}.${u}.${d}-${f}`:e?`<${c}.${u}.${+d+1}-0`:`<=${l}`,`${n} ${l}`.trim()),I=(e,t,n)=>{for(let r=0;r0){const r=e[n].semver;if(r.major===t.major&&r.minor===t.minor&&r.patch===t.patch)return!0}return!1}return!0}},8480:function(e,t,n){"use strict";var r=n(1828),o=n(8727),i=o.concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return r(e,i)}},8551:function(e,t,n){"use strict";var r=n(34),o=String,i=TypeError;e.exports=function(e){if(r(e))return e;throw new i(o(e)+" is not an object")}},8568:function(e,t,n){ /*! Name: vue-upload-component Component URI: https://github.com/lian-yue/vue-upload-component#readme Version: 3.1.16 Author: LianYue License: Apache-2.0 Description: Vue.js file upload component, Multi-file upload, Upload directory, Drag upload, Drag the directory, Upload multiple files at the same time, html4 (IE 9), `PUT` method, Customize the filter */ (function(t,r){e.exports=r(n(8756))})(0,(function(e){"use strict";function t(e){return i(e)||o(e)||r(e)||n()}function n(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(e,t){if(e){if("string"===typeof e)return s(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?s(e,t):void 0}}function o(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function i(e){if(Array.isArray(e))return s(e)}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=200&&e.status<300){var t;try{t=JSON.parse(e.response)}catch(o){t=e.response}n(t)}else r(e.response)},e.onerror=function(){return r(e.response)},e.send(JSON.stringify(t))}))},b=function(e,t){var n=new FormData;for(var r in t)n.append(r,t[r]);return new Promise((function(t,r){e.onload=function(){if(e.status>=200&&e.status<300){var n;try{n=JSON.parse(e.response)}catch(o){n=e.response}t(n)}else r(e.response)},e.onerror=function(){return r(e.response)},e.send(n)}))};function _(e){var t=g(e);return y(t,e.body)}var E=function(){function e(t,n){p(this,e),this.file=t,this.options=n,this.chunks=[],this.sessionId=null,this.chunkSize=null,this.speedInterval=null}return m(e,[{key:"maxRetries",get:function(){return parseInt(this.options.maxRetries,10)}},{key:"maxActiveChunks",get:function(){return parseInt(this.options.maxActive,10)}},{key:"fileType",get:function(){return this.file.type}},{key:"fileSize",get:function(){return this.file.size}},{key:"fileName",get:function(){return this.file.name}},{key:"action",get:function(){return this.options.action||null}},{key:"startBody",get:function(){return this.options.startBody||{}}},{key:"uploadBody",get:function(){return this.options.uploadBody||{}}},{key:"finishBody",get:function(){return this.options.finishBody||{}}},{key:"headers",get:function(){return this.options.headers||{}}},{key:"readyToUpload",get:function(){return!!this.chunks}},{key:"progress",get:function(){var e=this,t=this.chunksUploaded.length/this.chunks.length*100,n=this.chunksUploading.reduce((function(t,n){return t+(0|n.progress)/e.chunks.length}),0);return Math.min(t+n,100)}},{key:"chunksToUpload",get:function(){return this.chunks.filter((function(e){return!e.active&&!e.uploaded}))}},{key:"hasChunksToUpload",get:function(){return this.chunksToUpload.length>0}},{key:"chunksUploading",get:function(){return this.chunks.filter((function(e){return!!e.xhr&&!!e.active}))}},{key:"chunksUploaded",get:function(){return this.chunks.filter((function(e){return!!e.uploaded}))}},{key:"createChunks",value:function(){this.chunks=[];var e=0,t=this.chunkSize;while(e1&&o.length+this.files.length>=this.iMaximum)break;if(o.push(s),1===this.iMaximum)break}}if(o.length){var c;if(1===this.iMaximum&&this.clear(),!0===n||0===n)c=o.concat(this.files);else if(n){var u;c=this.files.concat([]),(u=c).splice.apply(u,[n,0].concat(t(o)))}else c=this.files.concat(o);this.files=c;var d=0;!0===n||0===n?d=0:n?n>=0?d=n+o.length>this.files.length?this.files.length-o.length:n:(d=this.files.length-o.length+n,d<0&&(d=0)):d=this.files.length-o.length,o=this.files.slice(d,d+o.length);for(var f=0;f0&&l.length>=a)break;return Promise.resolve(this.add(l))}return Promise.resolve([])},getFileSystemEntry:function(e){var n=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return new Promise((function(o){var i=n.iMaximum;if(e)if(e instanceof Array){var s=[],a=function a(l){var c=e[l];if(!c||i>0&&s.length>=i)return o(s);n.getFileSystemEntry(c,r).then((function(e){s.push.apply(s,t(e)),a(l+1)}))};a(0)}else if(e instanceof Blob)o([{id:"",size:e.size,name:r+e.name,type:e.type,file:e}]);else if(e.isFile){var l=e;l.file((function(e){o([{id:"",size:e.size,name:r+e.name,type:e.type,file:e}])}))}else if(e.isDirectory&&n.dropDirectory){var c=e,u=[];n.createDirectory&&u.push({id:"",name:r+c.name,size:0,type:"text/directory",file:new File([],r+c.name,{type:"text/directory"})});var d=c.createReader(),f=function e(){d.readEntries((function(s){var a=function a(l){return!s[l]&&0===l||i>0&&u.length>=i?o(u):s[l]?void n.getFileSystemEntry(s[l],r+c.name+"/").then((function(e){u.push.apply(u,t(e)),a(l+1)})):e()};a(0)}))};f()}else o([]);else o([])}))},replace:function(e,t){var n=this.get(e),r=this.get(t);if(!n||!r||n===r)return!1;var o=this.files.concat([]),i=o.indexOf(n),s=o.indexOf(r);return-1!==i&&-1!==s&&(o[i]=r,o[s]=n,this.files=o,this.emitInput(),!0)},remove:function(e){var t=this.get(e);if(t){if(this.emitFilter(void 0,t))return!1;var n=this.files.concat([]),r=n.indexOf(t);if(-1===r)return console.error("remove",t),!1;n.splice(r,1),this.files=n,delete this.maps[t.id],this.emitInput(),this.emitFile(void 0,t)}return t},update:function(e,t){var n=this.get(e);if(n){var r=l(l({},n),t);if(!n.fileObject||!n.active||r.active||r.error||r.success||(r.error="abort"),this.emitFilter(r,n))return!1;var o=this.files.concat([]),i=o.indexOf(n);return-1===i?(console.error("update",n),!1):(o.splice(i,1,r),this.files=o,r=this.files[i],delete this.maps[n.id],this.maps[r.id]=r,this.emitInput(),this.emitFile(r,n),r)}return!1},emitFilter:function(e,t){var n=!1;return this.$emit("input-filter",e,t,(function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return n=e,n})),n},emitFile:function(e,t){var n,r=this;this.$emit("input-file",e,t),null===(n=e)||void 0===n||!n.fileObject||!e.active||t&&t.active?e&&e.fileObject&&e.active||!t||!t.fileObject||!t.active||this.uploading--:(this.uploading++,this.$nextTick((function(){setTimeout((function(){e&&r.upload(e).then((function(){var t;e&&(e=r.get(e)||void 0),null!==(t=e)&&void 0!==t&&t.fileObject&&r.update(e,{active:!1,success:!e.error})})).catch((function(t){e&&r.update(e,{active:!1,success:!1,error:t.code||t.error||t.message||t})}))}),Math.ceil(50*Math.random()+50))}))),!this.active||Boolean(e)===Boolean(t)&&e.active===t.active||this.watchActive(!0)},emitInput:function(){this.$emit("update:modelValue",this.files)},upload:function(e){var t=this.get(e);if(!t)return Promise.reject(new Error("not_exists"));if(!t.fileObject)return Promise.reject(new Error("file_object"));if(t.error)return t.error instanceof Error?Promise.reject(t.error):Promise.reject(new Error(t.error));if(t.success)return Promise.resolve(t);if(t.name&&this.iExtensions&&"text/directory"!==t.type&&-1===t.name.search(this.iExtensions))return Promise.reject(new Error("extension"));if(this.size>0&&void 0!==t.size&&t.size>=0&&t.size>this.size&&"text/directory"!==t.type)return Promise.reject(new Error("size"));if(this.customAction)return this.customAction(t,this);if(this.features.html5){if(this.shouldUseChunkUpload(t))return this.uploadChunk(t);if(t.putAction)return this.uploadPut(t);if(t.postAction)return this.uploadHtml5(t)}return t.postAction?this.uploadHtml4(t):Promise.reject(new Error("No action configured"))},shouldUseChunkUpload:function(e){return this.chunkEnabled&&!!this.chunkOptions.handler&&e.size&&e.size>this.chunkOptions.minSize},uploadChunk:function(e){var t=this.chunkOptions.handler;return e.chunk=new t(e,this.chunkOptions),e.chunk.upload().then((function(t){return e}))},uploadPut:function(e){var t,n=[];for(var r in e.data)t=e.data[r],null!==t&&void 0!==t&&n.push(encodeURIComponent(r)+"="+encodeURIComponent(t));var o=e.putAction||"",i=n.length?(-1===o.indexOf("?")?"?":"&")+n.join("&"):"",s=new XMLHttpRequest;return s.open("PUT",o+i),this.uploadXhr(s,e,e.file)},uploadHtml5:function(e){var t,n=new window.FormData;for(var r in e.data)t=e.data[r],t&&"object"===u(t)&&"function"!==typeof t.toString?t instanceof File?n.append(r,t,t.name):n.append(r,JSON.stringify(t)):null!==t&&void 0!==t&&n.append(r,t);n.append(this.name,e.file,e.name||e.file.name||e.file.filename);var o=new XMLHttpRequest;return o.open("POST",e.postAction||""),this.uploadXhr(o,e,n)},uploadXhr:function(e,t,n){var r=this,o=t,i=0,s=0;e.upload.onprogress=function(e){if(o&&(o=r.get(o),e.lengthComputable&&o&&o.fileObject&&o.active)){var t=Math.round(Date.now()/1e3);t!==i&&(i=t,o=r.update(o,{progress:(e.loaded/e.total*100).toFixed(2),speed:e.loaded-s}),s=e.loaded)}};var a=window.setInterval((function(){var t;if(o&&((o=r.get(o))&&null!==(t=o)&&void 0!==t&&t.fileObject&&!o.success&&!o.error&&o.active))return;a&&(clearInterval(a),a=void 0);try{e.abort(),e.timeout=1}catch(n){}}),100);return new Promise((function(t,i){if(o){var s,l=function(n){if(!s){if(s=!0,a&&(clearInterval(a),a=void 0),!o)return i(new Error("not_exists"));if(o=r.get(o),!o)return i(new Error("not_exists"));if(!o.fileObject)return i(new Error("file_object"));if(o.error)return o.error instanceof Error?i(o.error):i(new Error(o.error));if(!o.active)return i(new Error("abort"));if(o.success)return t(o);var l={};switch(n.type){case"timeout":case"abort":l.error=n.type;break;case"error":e.status?e.status>=500?l.error="server":e.status>=400&&(l.error="denied"):l.error="network";break;default:e.status>=500?l.error="server":e.status>=400?l.error="denied":l.progress="100.00"}if(e.responseText){var c=e.getResponseHeader("Content-Type");c&&-1!==c.indexOf("/json")?l.response=JSON.parse(e.responseText):l.response=e.responseText}return o=r.update(o,l),o?o.error?o.error instanceof Error?i(o.error):i(new Error(o.error)):t(o):i(new Error("abort"))}};for(var c in e.onload=l,e.onerror=l,e.onabort=l,e.ontimeout=l,o.timeout&&(e.timeout=o.timeout),o.headers)e.setRequestHeader(c,o.headers[c]);o=r.update(o,{xhr:e}),o&&e.send(n)}else i(new Error("not_exists"))}))},uploadHtml4:function(e){var t=this,n=e;if(!n)return Promise.reject(new Error("not_exists"));var r=function(e){27===e.keyCode&&e.preventDefault()},o=document.createElement("iframe");o.id="upload-iframe-"+n.id,o.name="upload-iframe-"+n.id,o.src="about:blank",o.setAttribute("style","width:1px;height:1px;top:-999em;position:absolute; margin-top:-999em;");var i=document.createElement("form");for(var s in i.setAttribute("action",n.postAction||""),i.name="upload-form-"+n.id,i.setAttribute("method","POST"),i.setAttribute("target","upload-iframe-"+n.id),i.setAttribute("enctype","multipart/form-data"),n.data){var a=n.data[s];if(a&&"object"===u(a)&&"function"!==typeof a.toString&&(a=JSON.stringify(a)),null!==a&&void 0!==a){var l=document.createElement("input");l.type="hidden",l.name=s,l.value=a,i.appendChild(l)}}i.appendChild(n.el),document.body.appendChild(o).appendChild(i);var c=function(){var e,t;try{o.contentWindow&&(t=o.contentWindow.document)}catch(n){}if(!t)try{t=o.contentDocument?o.contentDocument:o.document}catch(n){t=o.document}return null!==(e=t)&&void 0!==e&&e.body?t.body.innerHTML:null};return new Promise((function(e,s){setTimeout((function(){if(n){if(n=t.update(n,{iframe:o}),!n)return s(new Error("not_exists"));var a,l=window.setInterval((function(){n&&(n=t.get(n))&&n.fileObject&&!n.success&&!n.error&&n.active||(l&&(clearInterval(l),l=void 0),o.onabort({type:n?"abort":"not_exists"}))}),100),u=function(o){var i;if(!a){if(a=!0,l&&(clearInterval(l),l=void 0),document.body.removeEventListener("keydown",r),!n)return s(new Error("not_exists"));if(n=t.get(n),!n)return s(new Error("not_exists"));if(!n.fileObject)return s(new Error("file_object"));if(n.error)return n.error instanceof Error?s(n.error):s(new Error(n.error));if(!n.active)return s(new Error("abort"));if(n.success)return e(n);var u=c(),d={};if("string"===typeof o)return s(new Error(o));switch(o.type){case"abort":d.error="abort";break;case"error":n.error?d.error=n.error:d.error=null===u?"network":"denied";break;default:n.error?d.error=n.error:null===u?d.error="network":d.progress="100.00"}if(null!==u){if(u&&"{"===u.substr(0,1)&&"}"===u.substr(u.length-1,1))try{u=JSON.parse(u)}catch(f){}d.response=u}return n=t.update(n,d),n?null!==(i=n)&&void 0!==i&&i.error?n.error instanceof Error?s(n.error):s(new Error(n.error)):e(n):s(new Error("not_exists"))}};o.onload=u,o.onerror=u,o.onabort=u,document.body.addEventListener("keydown",r),i.submit()}else s(new Error("not_exists"))}),50)})).then((function(e){var t;return null===o||void 0===o||null===(t=o.parentNode)||void 0===t||t.removeChild(o),e})).catch((function(e){var t;return null===o||void 0===o||null===(t=o.parentNode)||void 0===t||t.removeChild(o),e}))},watchActive:function(e){var t,n=0;while(t=this.files[n])if(n++,t.fileObject)if(e&&!this.destroy){if(this.uploading>=this.thread||this.uploading&&!this.features.html5)break;t.active||t.error||t.success||this.update(t,{active:!0})}else t.active&&this.update(t,{active:!1});else;0===this.uploading&&(this.active=!1)},watchDrop:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;if(this.features.drop&&e!==t){if(this.dropElement)try{document.removeEventListener("dragenter",this.onDocumentDragenter,!1),document.removeEventListener("dragleave",this.onDocumentDragleave,!1),document.removeEventListener("dragover",this.onDocumentDragover,!1),document.removeEventListener("drop",this.onDocumentDrop,!1),this.dropElement.removeEventListener("dragenter",this.onDragenter,!1),this.dropElement.removeEventListener("dragleave",this.onDragleave,!1),this.dropElement.removeEventListener("dragover",this.onDragover,!1),this.dropElement.removeEventListener("drop",this.onDrop,!1)}catch(i){}var n=null;if(e)if("string"===typeof e)n=document.querySelector(e)||this.$root.$el.querySelector(e);else if(!0===e){var r,o;if(n=this.$parent.$el,!n||8===(null===(r=n)||void 0===r?void 0:r.nodeType))n=this.$root.$el,n&&8!==(null===(o=n)||void 0===o?void 0:o.nodeType)||(n=document.body)}else n=e;else;this.dropElement=n,this.dropElement&&(document.addEventListener("dragenter",this.onDocumentDragenter,!1),document.addEventListener("dragleave",this.onDocumentDragleave,!1),document.addEventListener("dragover",this.onDocumentDragover,!1),document.addEventListener("drop",this.onDocumentDrop,!1),this.dropElement.addEventListener("dragenter",this.onDragenter,!1),this.dropElement.addEventListener("dragleave",this.onDragleave,!1),this.dropElement.addEventListener("dragover",this.onDragover,!1),this.dropElement.addEventListener("drop",this.onDrop,!1))}},watchDropActive:function(e,t){e!==t&&(!e&&this.dropElementActive&&(this.dropElementActive=!1),this.dropTimeout&&(clearTimeout(this.dropTimeout),this.dropTimeout=null),e&&(this.dropTimeout=setTimeout(this.onDocumentDrop,1e3)))},onDocumentDragenter:function(e){var t,n;if(!this.dropActive&&e.dataTransfer){var r=e.dataTransfer;null!==r&&void 0!==r&&null!==(t=r.files)&&void 0!==t&&t.length?this.dropActive=!0:r.types?(r.types.indexOf&&-1!==r.types.indexOf("Files")||null!==(n=r.types)&&void 0!==n&&n.contains&&r.types.contains("Files"))&&(this.dropActive=!0):this.dropActive=!0,this.dropActive&&this.watchDropActive(!0)}},onDocumentDragleave:function(e){this.dropActive&&(e.target===e.explicitOriginalTarget||!e.fromElement&&(e.clientX<=0||e.clientY<=0||e.clientX>=window.innerWidth||e.clientY>=window.innerHeight))&&(this.dropActive=!1,this.watchDropActive(!1))},onDocumentDragover:function(){this.watchDropActive(!0)},onDocumentDrop:function(){this.dropActive=!1,this.watchDropActive(!1)},onDragenter:function(e){this.dropActive&&!this.dropElementActive&&(this.dropElementActive=!0)},onDragleave:function(e){var t;if(this.dropElementActive){var n=e.relatedTarget;if(n)if(null!==(t=this.dropElement)&&void 0!==t&&t.contains)this.dropElement.contains(n)||(this.dropElementActive=!1);else{var r=n;while(r){if(r===this.dropElement)break;r=r.parentNode}r!==this.dropElement&&(this.dropElementActive=!1)}else this.dropElementActive=!1}},onDragover:function(e){e.preventDefault()},onDrop:function(e){e.preventDefault(),e.dataTransfer&&this.addDataTransfer(e.dataTransfer)},inputOnChange:async function(e){var t=this;if(!(e.target instanceof HTMLInputElement))return Promise.reject(new Error("not HTMLInputElement"));e.target;var n=function(e){return t.reload=!0,t.$nextTick((function(){t.reload=!1})),e};return this.addInputFile(e.target).then(n).catch(n)},isRelatedTargetSupported:function(){try{var e=new MouseEvent("mouseout",{relatedTarget:document.body});return"relatedTarget"in e}catch(t){return!1}}}}),k=["for"],C=["name","id","accept","capture","disabled","webkitdirectory","allowdirs","directory","multiple"];function O(t,n,r,o,i,s){return e.openBlock(),e.createElementBlock("span",{class:e.normalizeClass(t.className)},[e.renderSlot(t.$slots,"default"),e.createElementVNode("label",{for:t.forId},null,8,k),t.reload?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("input",{key:0,ref:"input",type:"file",name:t.name,id:t.forId,accept:t.accept,capture:t.capture,disabled:t.disabled,webkitdirectory:t.iDirectory,allowdirs:t.iDirectory,directory:t.iDirectory,multiple:t.multiple&&t.features.html5,onChange:n[0]||(n[0]=function(){return t.inputOnChange&&t.inputOnChange.apply(t,arguments)})},null,40,C))],2)}function T(e,t){void 0===t&&(t={});var n=t.insertAt;if(e&&"undefined"!==typeof document){var r=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css","top"===n&&r.firstChild?r.insertBefore(o,r.firstChild):r.appendChild(o),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(document.createTextNode(e))}}var R="\n.file-uploads {\n overflow: hidden;\n position: relative;\n text-align: center;\n display: inline-block;\n}\n.file-uploads.file-uploads-html4 input,\n.file-uploads.file-uploads-html5 label {\n /* background fix ie click */\n background: #fff;\n opacity: 0;\n font-size: 20em;\n z-index: 1;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n position: absolute;\n width: 100%;\n height: 100%;\n}\n.file-uploads.file-uploads-html5 input,\n.file-uploads.file-uploads-html4 label {\n /* background fix ie click */\n position: absolute;\n background: rgba(255, 255, 255, 0);\n overflow: hidden;\n position: fixed;\n width: 1px;\n height: 1px;\n z-index: -1;\n opacity: 0;\n}\n";return T(R),S.render=O,S}))},8587:function(e){const t=Object.freeze({loose:!0}),n=Object.freeze({}),r=e=>e?"object"!==typeof e?t:e:n;e.exports=r},8622:function(e,t,n){"use strict";var r=n(4576),o=n(4901),i=r.WeakMap;e.exports=o(i)&&/native code/.test(String(i))},8686:function(e,t,n){"use strict";var r=n(3724),o=n(9039);e.exports=r&&o((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype}))},8721:function(e,t,n){"use strict";var r=n(3724),o=n(9504),i=n(2106),s=URLSearchParams.prototype,a=o(s.forEach);r&&!("size"in s)&&i(s,"size",{get:function(){var e=0;return a(this,(function(){e++})),e},configurable:!0,enumerable:!0})},8727:function(e){"use strict";e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},8756:function(e,t,n){"use strict";n.r(t),n.d(t,{BaseTransition:function(){return r.pR},BaseTransitionPropsValidators:function(){return r.QP},Comment:function(){return r.Mw},DeprecationTypes:function(){return r.aT},EffectScope:function(){return r.yC},ErrorCodes:function(){return r.tG},ErrorTypeStrings:function(){return r.ZQ},Fragment:function(){return r.FK},KeepAlive:function(){return r.PR},ReactiveEffect:function(){return r.X2},Static:function(){return r.jC},Suspense:function(){return r.tY},Teleport:function(){return r.Im},Text:function(){return r.EY},TrackOpTypes:function(){return r.Ul},Transition:function(){return r.eB},TransitionGroup:function(){return r.F},TriggerOpTypes:function(){return r.PP},VueElement:function(){return r.Vy},assertNumber:function(){return r.U4},callWithAsyncErrorHandling:function(){return r.qL},callWithErrorHandling:function(){return r.gh},camelize:function(){return r.PT},capitalize:function(){return r.ZH},cloneVNode:function(){return r.E3},compatUtils:function(){return r.Y5},compile:function(){return o},computed:function(){return r.EW},createApp:function(){return r.Ef},createBlock:function(){return r.Wv},createCommentVNode:function(){return r.Q3},createElementBlock:function(){return r.CE},createElementVNode:function(){return r.Lk},createHydrationRenderer:function(){return r.ci},createPropsRestProxy:function(){return r.bn},createRenderer:function(){return r.K9},createSSRApp:function(){return r.m1},createSlots:function(){return r.eX},createStaticVNode:function(){return r.Fv},createTextVNode:function(){return r.eW},createVNode:function(){return r.bF},customRef:function(){return r.rY},defineAsyncComponent:function(){return r.$V},defineComponent:function(){return r.pM},defineCustomElement:function(){return r.Xq},defineEmits:function(){return r.qP},defineExpose:function(){return r.wk},defineModel:function(){return r.NP},defineOptions:function(){return r.GM},defineProps:function(){return r.Yj},defineSSRCustomElement:function(){return r.Po},defineSlots:function(){return r.Lu},devtools:function(){return r.lt},effect:function(){return r.QZ},effectScope:function(){return r.uY},getCurrentInstance:function(){return r.nI},getCurrentScope:function(){return r.o5},getCurrentWatcher:function(){return r.Yv},getTransitionRawChildren:function(){return r.Df},guardReactiveProps:function(){return r.Ng},h:function(){return r.h},handleError:function(){return r.H4},hasInjectionContext:function(){return r.PS},hydrate:function(){return r.Qv},hydrateOnIdle:function(){return r.rU},hydrateOnInteraction:function(){return r.Tq},hydrateOnMediaQuery:function(){return r.dA},hydrateOnVisible:function(){return r.Pn},initCustomFormatter:function(){return r.y$},initDirectivesForSSR:function(){return r.Ib},inject:function(){return r.WQ},isMemoSame:function(){return r.Bs},isProxy:function(){return r.ju},isReactive:function(){return r.g8},isReadonly:function(){return r.Tm},isRef:function(){return r.i9},isRuntimeOnly:function(){return r.wX},isShallow:function(){return r.fE},isVNode:function(){return r.vv},markRaw:function(){return r.IG},mergeDefaults:function(){return r.HF},mergeModels:function(){return r.zz},mergeProps:function(){return r.v6},nextTick:function(){return r.dY},normalizeClass:function(){return r.C4},normalizeProps:function(){return r._B},normalizeStyle:function(){return r.Tr},onActivated:function(){return r.n},onBeforeMount:function(){return r.KC},onBeforeUnmount:function(){return r.xo},onBeforeUpdate:function(){return r.Ic},onDeactivated:function(){return r.Y4},onErrorCaptured:function(){return r.qG},onMounted:function(){return r.sV},onRenderTracked:function(){return r.qR},onRenderTriggered:function(){return r.bj},onScopeDispose:function(){return r.jr},onServerPrefetch:function(){return r.SS},onUnmounted:function(){return r.hi},onUpdated:function(){return r.$u},onWatcherCleanup:function(){return r.ch},openBlock:function(){return r.uX},popScopeId:function(){return r.jt},provide:function(){return r.Gt},proxyRefs:function(){return r.Pr},pushScopeId:function(){return r.Qi},queuePostFlushCb:function(){return r.Dl},reactive:function(){return r.Kh},readonly:function(){return r.tB},ref:function(){return r.KR},registerRuntimeCompiler:function(){return r.tC},render:function(){return r.XX},renderList:function(){return r.pI},renderSlot:function(){return r.RG},resolveComponent:function(){return r.g2},resolveDirective:function(){return r.gN},resolveDynamicComponent:function(){return r.$y},resolveFilter:function(){return r.LJ},resolveTransitionHooks:function(){return r.OW},setBlockTracking:function(){return r.Vq},setDevtoolsHook:function(){return r.iD},setTransitionHooks:function(){return r.MZ},shallowReactive:function(){return r.Gc},shallowReadonly:function(){return r.nD},shallowRef:function(){return r.IJ},ssrContextKey:function(){return r.Fw},ssrUtils:function(){return r.Gw},stop:function(){return r.ds},toDisplayString:function(){return r.v_},toHandlerKey:function(){return r.Kf},toHandlers:function(){return r.Tb},toRaw:function(){return r.ux},toRef:function(){return r.lW},toRefs:function(){return r.QW},toValue:function(){return r.BA},transformVNodeArgs:function(){return r.gW},triggerRef:function(){return r.mu},unref:function(){return r.R1},useAttrs:function(){return r.OA},useCssModule:function(){return r.D},useCssVars:function(){return r.$9},useHost:function(){return r.KT},useId:function(){return r.Bi},useModel:function(){return r.fn},useSSRContext:function(){return r.LM},useShadowRoot:function(){return r._U},useSlots:function(){return r.Ht},useTemplateRef:function(){return r.rk},useTransitionState:function(){return r.Gy},vModelCheckbox:function(){return r.lH},vModelDynamic:function(){return r.hp},vModelRadio:function(){return r.XL},vModelSelect:function(){return r.u1},vModelText:function(){return r.Jo},vShow:function(){return r.aG},version:function(){return r.rE},warn:function(){return r.R8},watch:function(){return r.wB},watchEffect:function(){return r.nT},watchPostEffect:function(){return r.p9},watchSyncEffect:function(){return r.U_},withAsyncContext:function(){return r.E},withCtx:function(){return r.k6},withDefaults:function(){return r.rO},withDirectives:function(){return r.bo},withKeys:function(){return r.jR},withMemo:function(){return r.bU},withModifiers:function(){return r.D$},withScopeId:function(){return r.YY}});var r=n(3751); /** * vue v3.5.13 * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT **/const o=()=>{0}},8773:function(e,t){"use strict";var n={}.propertyIsEnumerable,r=Object.getOwnPropertyDescriptor,o=r&&!n.call({1:2},1);t.f=o?function(e){var t=r(this,e);return!!t&&t.enumerable}:n},8794:function(e){class t{constructor(){this.max=1e3,this.map=new Map}get(e){const t=this.map.get(e);return void 0===t?void 0:(this.map.delete(e),this.map.set(e,t),t)}delete(e){return this.map.delete(e)}set(e,t){const n=this.delete(e);if(!n&&void 0!==t){if(this.map.size>=this.max){const e=this.map.keys().next().value;this.delete(e)}this.map.set(e,t)}return this}}e.exports=t},8981:function(e,t,n){"use strict";var r=n(7750),o=Object;e.exports=function(e){return o(r(e))}},9039:function(e){"use strict";e.exports=function(e){try{return!!e()}catch(t){return!0}}},9071:function(e,t,n){"use strict";n.d(t,{A:function(){return f}});var r=n(641),o=n(33),i=n(3751);const s=["href"];function a(e,t,n,a,l,c){return n.name.includes("/")?((0,r.uX)(),(0,r.CE)("a",{key:0,href:e.$router.resolve({query:{p:n.name}}).href,class:(0,o.C4)(["widget-button widget-button--details widget-button--info",{"widget-button--small":n.small,"widget-button--inline":n.inline}]),onClick:t[0]||(t[0]=(0,i.D$)((t=>e.setCurrent(n.name)),["prevent"]))},(0,o.v_)(e.$t("ui.discover.detailsButton")),11,s)):(0,r.Q3)("",!0)}var l=n(6278),c={props:{name:{type:String,required:!0},small:Boolean,inline:Boolean},methods:{...(0,l.PY)("packages/details",["setCurrent"])}},u=n(6262);const d=(0,u.A)(c,[["render",a]]);var f=d},9297:function(e,t,n){"use strict";var r=n(9504),o=n(8981),i=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return i(o(e),t)}},9306:function(e,t,n){"use strict";var r=n(4901),o=n(6823),i=TypeError;e.exports=function(e){if(r(e))return e;throw new i(o(e)+" is not a function")}},9348:function(){(function(){"use strict";var e=document.createElement("details"),t="undefined"!=typeof HTMLDetailsElement&&e instanceof HTMLDetailsElement,n={open:"open"in e||t,toggle:"ontoggle"in e},r='\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n',o=[],i=o.forEach,s=o.slice;function a(){document.head.insertAdjacentHTML("afterbegin","")}function l(){var e=document.createElement("details").constructor.prototype,t=e.setAttribute,n=e.removeAttribute,r=Object.getOwnPropertyDescriptor(e,"open");Object.defineProperties(e,{open:{get:function(){return"DETAILS"==this.tagName?this.hasAttribute("open"):r&&r.get?r.get.call(this):void 0},set:function(e){return"DETAILS"==this.tagName?e?this.setAttribute("open",""):this.removeAttribute("open"):r&&r.set?r.set.call(this,e):void 0}},setAttribute:{value:function(e,n){var r=this,o=function(){return t.call(r,e,n)};if("open"==e&&"DETAILS"==this.tagName){var i=this.hasAttribute("open"),s=o();if(!i){var a=this.querySelector("summary");a&&a.setAttribute("aria-expanded",!0),m(this)}return s}return o()}},removeAttribute:{value:function(e){var t=this,r=function(){return n.call(t,e)};if("open"==e&&"DETAILS"==this.tagName){var o=this.hasAttribute("open"),i=r();if(o){var s=this.querySelector("summary");s&&s.setAttribute("aria-expanded",!1),m(this)}return i}return r()}}})}function c(){h((function(e){e.hasAttribute("open")?e.removeAttribute("open"):e.setAttribute("open","")}))}function u(){window.MutationObserver?new MutationObserver((function(e){i.call(e,(function(e){var t=e.target,n=e.attributeName;"DETAILS"==t.tagName&&"open"==n&&m(t)}))})).observe(document.documentElement,{attributes:!0,subtree:!0}):h((function(e){var t=e.getAttribute("open");setTimeout((function(){var n=e.getAttribute("open");t!=n&&m(e)}),1)}))}function d(){f(document),window.MutationObserver?new MutationObserver((function(e){i.call(e,(function(e){i.call(e.addedNodes,f)}))})).observe(document.documentElement,{subtree:!0,childList:!0}):document.addEventListener("DOMNodeInserted",(function(e){f(e.target)}))}function f(e){v(e,"SUMMARY").forEach((function(e){var t=g(e,"DETAILS");e.setAttribute("aria-expanded",t.hasAttribute("open")),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0"),e.hasAttribute("role")||e.setAttribute("role","button")}))}function p(e){return!(e.defaultPrevented||e.ctrlKey||e.metaKey||e.shiftKey||e.target.isContentEditable)}function h(e){addEventListener("click",(function(t){if(p(t)&&t.which<=1){var n=g(t.target,"SUMMARY");n&&n.parentNode&&"DETAILS"==n.parentNode.tagName&&e(n.parentNode)}}),!1),addEventListener("keydown",(function(t){if(p(t)&&(13==t.keyCode||32==t.keyCode)){var n=g(t.target,"SUMMARY");n&&n.parentNode&&"DETAILS"==n.parentNode.tagName&&(e(n.parentNode),t.preventDefault())}}),!1)}function m(e){var t=document.createEvent("Event");t.initEvent("toggle",!1,!1),e.dispatchEvent(t)}function v(e,t){return(e.tagName==t?[e]:[]).concat("function"==typeof e.getElementsByTagName?s.call(e.getElementsByTagName(t)):[])}function g(e,t){if("function"==typeof e.closest)return e.closest(t);while(e){if(e.tagName==t)return e;e=e.parentNode}}n.open||(a(),l(),c(),d()),n.open&&!n.toggle&&u()})()},9376:function(e,t){"use strict";t.A={en:"English",de:"Deutsch (German)",br:"brezhoneg (Breton)",cs:"čeština (Czech)",es:"Español (Spanish)",fa:"فارسی (Persian)",fr:"Français (French)",it:"Italiano (Italian)",ja:"日本語 (Japanese)",lv:"latviešu valoda (Latvian)",nl:"Nederlands (Dutch)",pl:"polszczyzna (Polish)",pt:"Português (Portuguese)",ru:"русский (Russian)",sr:"српски језик (Serbian)",sv:"Svenska (Swedish)",tr:"Türkçe (Turkish)",zh:"中文 (Chinese)"}},9433:function(e,t,n){"use strict";var r=n(4576),o=Object.defineProperty;e.exports=function(e,t){try{o(r,e,{value:t,configurable:!0,writable:!0})}catch(n){r[e]=t}return t}},9451:function(e,t,n){"use strict";n.d(t,{A:function(){return i}});var r=n(641);const o=e=>e&&e.every((e=>e.type===r.Mw||(e.type===Text&&"string"===typeof e.children&&!e.children.trim()||!(e.type!==r.FK||!o(e.children)))));function i(e){return!e||o(e())}},9462:function(e,t,n){"use strict";var r=n(9565),o=n(2360),i=n(6699),s=n(6279),a=n(8227),l=n(1181),c=n(5966),u=n(7657).IteratorPrototype,d=n(2529),f=n(9539),p=a("toStringTag"),h="IteratorHelper",m="WrapForValidIterator",v=l.set,g=function(e){var t=l.getterFor(e?m:h);return s(o(u),{next:function(){var n=t(this);if(e)return n.nextHandler();if(n.done)return d(void 0,!0);try{var r=n.nextHandler();return n.returnHandlerResult?r:d(r,n.done)}catch(o){throw n.done=!0,o}},return:function(){var n=t(this),o=n.iterator;if(n.done=!0,e){var i=c(o,"return");return i?r(i,o):d(void 0,!0)}if(n.inner)try{f(n.inner.iterator,"normal")}catch(s){return f(o,"throw",s)}return o&&f(o,"normal"),d(void 0,!0)}})},y=g(!0),b=g(!1);i(b,p,"Iterator Helper"),e.exports=function(e,t,n){var r=function(r,o){o?(o.iterator=r.iterator,o.next=r.next):o=r,o.type=t?m:h,o.returnHandlerResult=!!n,o.nextHandler=e,o.counter=0,o.done=!1,v(this,o)};return r.prototype=t?y:b,r}},9504:function(e,t,n){"use strict";var r=n(616),o=Function.prototype,i=o.call,s=r&&o.bind.bind(i,i);e.exports=r?s:function(e){return function(){return i.apply(e,arguments)}}},9519:function(e,t,n){"use strict";var r,o,i=n(4576),s=n(2839),a=i.process,l=i.Deno,c=a&&a.versions||l&&l.version,u=c&&c.v8;u&&(r=u.split("."),o=r[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&s&&(r=s.match(/Edge\/(\d+)/),(!r||r[1]>=74)&&(r=s.match(/Chrome\/(\d+)/),r&&(o=+r[1]))),e.exports=o},9539:function(e,t,n){"use strict";var r=n(9565),o=n(8551),i=n(5966);e.exports=function(e,t,n){var s,a;o(e);try{if(s=i(e,"return"),!s){if("throw"===t)throw n;return n}s=r(s,e)}catch(l){a=!0,s=l}if("throw"===t)throw n;if(a)throw s;return o(s),n}},9565:function(e,t,n){"use strict";var r=n(616),o=Function.prototype.call;e.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},9589:function(e,t,n){const r=n(9718),o=n(6874),i=n(3908),s=n(1123),a=n(144),l=n(6953),c=n(7414),u=n(3007),d=n(1832),f=n(2938),p=n(6254),h=n(4493),m=n(1729),v=n(560),g=n(9970),y=n(1763),b=n(909),_=n(3927),E=n(4277),w=n(5580),S=n(7059),k=n(4641),C=n(3999),O=n(4089),T=n(5200),R=n(2111),A=n(6170),N=n(3904),L=n(8311),I=n(7638),P=n(7631),x=n(9628),M=n(270),D=n(1261),$=n(3874),F=n(7075),j=n(5571),U=n(5342),B=n(6780),V=n(2525),H=n(5032);e.exports={parse:a,valid:l,clean:c,inc:u,diff:d,major:f,minor:p,patch:h,prerelease:m,compare:v,rcompare:g,compareLoose:y,compareBuild:b,sort:_,rsort:E,gt:w,lt:S,eq:k,neq:C,gte:O,lte:T,cmp:R,coerce:A,Comparator:N,Range:L,satisfies:I,toComparators:P,maxSatisfying:x,minSatisfying:M,minVersion:D,validRange:$,outside:F,gtr:j,ltr:U,intersects:B,simplifyRange:V,subset:H,SemVer:i,re:r.re,src:r.src,tokens:r.t,SEMVER_SPEC_VERSION:o.SEMVER_SPEC_VERSION,RELEASE_TYPES:o.RELEASE_TYPES,compareIdentifiers:s.compareIdentifiers,rcompareIdentifiers:s.rcompareIdentifiers}},9617:function(e,t,n){"use strict";var r=n(5397),o=n(5610),i=n(6198),s=function(e){return function(t,n,s){var a=r(t),l=i(a);if(0===l)return!e&&-1;var c,u=o(s,l);if(e&&n!==n){while(l>u)if(c=a[u++],c!==c)return!0}else for(;l>u;u++)if((e||u in a)&&a[u]===n)return e||u||0;return!e&&-1}};e.exports={includes:s(!0),indexOf:s(!1)}},9628:function(e,t,n){const r=n(3908),o=n(8311),i=(e,t,n)=>{let i=null,s=null,a=null;try{a=new o(t,n)}catch(l){return null}return e.forEach((e=>{a.test(e)&&(i&&-1!==s.compare(e)||(i=e,s=new r(i,n)))})),i};e.exports=i},9718:function(e,t,n){const{MAX_SAFE_COMPONENT_LENGTH:r,MAX_SAFE_BUILD_LENGTH:o,MAX_LENGTH:i}=n(6874),s=n(7272);t=e.exports={};const a=t.re=[],l=t.safeRe=[],c=t.src=[],u=t.safeSrc=[],d=t.t={};let f=0;const p="[a-zA-Z0-9-]",h=[["\\s",1],["\\d",i],[p,o]],m=e=>{for(const[t,n]of h)e=e.split(`${t}*`).join(`${t}{0,${n}}`).split(`${t}+`).join(`${t}{1,${n}}`);return e},v=(e,t,n)=>{const r=m(t),o=f++;s(e,o,t),d[e]=o,c[o]=t,u[o]=r,a[o]=new RegExp(t,n?"g":void 0),l[o]=new RegExp(r,n?"g":void 0)};v("NUMERICIDENTIFIER","0|[1-9]\\d*"),v("NUMERICIDENTIFIERLOOSE","\\d+"),v("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${p}*`),v("MAINVERSION",`(${c[d.NUMERICIDENTIFIER]})\\.(${c[d.NUMERICIDENTIFIER]})\\.(${c[d.NUMERICIDENTIFIER]})`),v("MAINVERSIONLOOSE",`(${c[d.NUMERICIDENTIFIERLOOSE]})\\.(${c[d.NUMERICIDENTIFIERLOOSE]})\\.(${c[d.NUMERICIDENTIFIERLOOSE]})`),v("PRERELEASEIDENTIFIER",`(?:${c[d.NUMERICIDENTIFIER]}|${c[d.NONNUMERICIDENTIFIER]})`),v("PRERELEASEIDENTIFIERLOOSE",`(?:${c[d.NUMERICIDENTIFIERLOOSE]}|${c[d.NONNUMERICIDENTIFIER]})`),v("PRERELEASE",`(?:-(${c[d.PRERELEASEIDENTIFIER]}(?:\\.${c[d.PRERELEASEIDENTIFIER]})*))`),v("PRERELEASELOOSE",`(?:-?(${c[d.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${c[d.PRERELEASEIDENTIFIERLOOSE]})*))`),v("BUILDIDENTIFIER",`${p}+`),v("BUILD",`(?:\\+(${c[d.BUILDIDENTIFIER]}(?:\\.${c[d.BUILDIDENTIFIER]})*))`),v("FULLPLAIN",`v?${c[d.MAINVERSION]}${c[d.PRERELEASE]}?${c[d.BUILD]}?`),v("FULL",`^${c[d.FULLPLAIN]}$`),v("LOOSEPLAIN",`[v=\\s]*${c[d.MAINVERSIONLOOSE]}${c[d.PRERELEASELOOSE]}?${c[d.BUILD]}?`),v("LOOSE",`^${c[d.LOOSEPLAIN]}$`),v("GTLT","((?:<|>)?=?)"),v("XRANGEIDENTIFIERLOOSE",`${c[d.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`),v("XRANGEIDENTIFIER",`${c[d.NUMERICIDENTIFIER]}|x|X|\\*`),v("XRANGEPLAIN",`[v=\\s]*(${c[d.XRANGEIDENTIFIER]})(?:\\.(${c[d.XRANGEIDENTIFIER]})(?:\\.(${c[d.XRANGEIDENTIFIER]})(?:${c[d.PRERELEASE]})?${c[d.BUILD]}?)?)?`),v("XRANGEPLAINLOOSE",`[v=\\s]*(${c[d.XRANGEIDENTIFIERLOOSE]})(?:\\.(${c[d.XRANGEIDENTIFIERLOOSE]})(?:\\.(${c[d.XRANGEIDENTIFIERLOOSE]})(?:${c[d.PRERELEASELOOSE]})?${c[d.BUILD]}?)?)?`),v("XRANGE",`^${c[d.GTLT]}\\s*${c[d.XRANGEPLAIN]}$`),v("XRANGELOOSE",`^${c[d.GTLT]}\\s*${c[d.XRANGEPLAINLOOSE]}$`),v("COERCEPLAIN",`(^|[^\\d])(\\d{1,${r}})(?:\\.(\\d{1,${r}}))?(?:\\.(\\d{1,${r}}))?`),v("COERCE",`${c[d.COERCEPLAIN]}(?:$|[^\\d])`),v("COERCEFULL",c[d.COERCEPLAIN]+`(?:${c[d.PRERELEASE]})?`+`(?:${c[d.BUILD]})?(?:$|[^\\d])`),v("COERCERTL",c[d.COERCE],!0),v("COERCERTLFULL",c[d.COERCEFULL],!0),v("LONETILDE","(?:~>?)"),v("TILDETRIM",`(\\s*)${c[d.LONETILDE]}\\s+`,!0),t.tildeTrimReplace="$1~",v("TILDE",`^${c[d.LONETILDE]}${c[d.XRANGEPLAIN]}$`),v("TILDELOOSE",`^${c[d.LONETILDE]}${c[d.XRANGEPLAINLOOSE]}$`),v("LONECARET","(?:\\^)"),v("CARETTRIM",`(\\s*)${c[d.LONECARET]}\\s+`,!0),t.caretTrimReplace="$1^",v("CARET",`^${c[d.LONECARET]}${c[d.XRANGEPLAIN]}$`),v("CARETLOOSE",`^${c[d.LONECARET]}${c[d.XRANGEPLAINLOOSE]}$`),v("COMPARATORLOOSE",`^${c[d.GTLT]}\\s*(${c[d.LOOSEPLAIN]})$|^$`),v("COMPARATOR",`^${c[d.GTLT]}\\s*(${c[d.FULLPLAIN]})$|^$`),v("COMPARATORTRIM",`(\\s*)${c[d.GTLT]}\\s*(${c[d.LOOSEPLAIN]}|${c[d.XRANGEPLAIN]})`,!0),t.comparatorTrimReplace="$1$2$3",v("HYPHENRANGE",`^\\s*(${c[d.XRANGEPLAIN]})\\s+-\\s+(${c[d.XRANGEPLAIN]})\\s*$`),v("HYPHENRANGELOOSE",`^\\s*(${c[d.XRANGEPLAINLOOSE]})\\s+-\\s+(${c[d.XRANGEPLAINLOOSE]})\\s*$`),v("STAR","(<|>)?=?\\s*\\*"),v("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),v("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")},9970:function(e,t,n){const r=n(560),o=(e,t,n)=>r(t,e,n);e.exports=o},9997:function(e,t){"use strict";t.A={"contao/manager-bundle":["contao/news-bundle","contao/calendar-bundle","contao/faq-bundle","contao/comments-bundle","contao/newsletter-bundle","contao/listing-bundle"]}}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[669],{9669:function(e){e.exports=JSON.parse('{"ui.app.title":"افزونه‌های کنتائو","ui.app.loading":"بارگذاری لیست افزونه...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"بارگذاری ...","ui.discover.offline":"Could not fetch any results.","ui.discover.offlineExplain":"Check your internet connection and disable JavaScript blockers in your browser.","ui.discover.offlineButton":"دوباره تلاش کنید","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"هیچ نتیجه‌ای برای {query}","ui.discover.more":"نتایج بیشتر","ui.discover.sortBy":"مرتب‌سازی براساس","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"بروزرسانی شده","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"دانلودها","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"امتیاز","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"جزئیات","ui.discover.latestPackages":"Latest and updated extensions","ui.discover.faversPackages":"افزونه‌های با امتیاز بالا","ui.discover.downloadsPackages":"Most downloaded extensions","ui.package.homepage":"وب‌سایت پروژه","ui.package.private":"بسته اختصاصی","ui.package.privateTitle":"Private packages are only available from the vendor (e.g. as a ZIP download). Please visit the website for more information.","ui.package.abandoned":"منع شده","ui.package.abandonedText":"This package is abandoned and no longer maintained.","ui.package.abandonedReplace":"This package is abandoned and no longer maintained. The author suggests using the {replacement} package instead.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"جزئیات افزونه قبلی","ui.package-details.close":"بستن جزئیات افزونه","ui.package-details.loading":"بارگذاری ...","ui.package-details.tabDescription":"توضیح","ui.package-details.tabRequire":"نیازمندی‌ها","ui.package-details.tabFeatures":"ویژگی‌ها","ui.package-details.tabSuggest":"پیشنهادها","ui.package-details.tabConflict":"ناسازگاری‌ها","ui.package-details.tabDependents":"وابسته‌ها","ui.package-details.linkRequires":"نیاز دارد","ui.package-details.linkReplaces":"جایگزین می‌کند","ui.package-details.linkProvides":"فراهم می‌کند","ui.package-details.linkConflicts":"ناسازگار است","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"آخرین نسخه","ui.package-details.released":"منتشر شده در","ui.package-details.license":"مجوز(ها)","ui.package-details.authors":"از","ui.package-details.more":"بیشتر","ui.package-details.packagist":"جژئیات بسته","ui.package-details.metadata":"ویرایش فرداده","ui.package-details.support_docs":"مستندات","ui.package-details.support_wiki":"ویکی","ui.package-details.support_forum":"انجمن پشتیبانی","ui.package-details.support_issues":"مشکلات / گزارش باگ","ui.package-details.support_source":"کد منبع","ui.package-details.support_irc":"IRC / چت","ui.package-details.support_email":"ایمیل پشتیبانی","ui.package-details.support_rss":"خوراک RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[60],{60:function(e,t,r){function n(e){const t=new Uint8Array(e);let r="";for(const o of t)r+=String.fromCharCode(o);const n=btoa(r);return n.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function o(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,n=t.padEnd(t.length+r,"="),o=atob(n),i=new ArrayBuffer(o.length),a=new Uint8Array(i);for(let s=0;se};function s(e){const{id:t}=e;return{...e,id:o(t),transports:e.transports}}function c(e){return"localhost"===e||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(e)}class l extends Error{constructor({message:e,code:t,cause:r,name:n}){super(e,{cause:r}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name=n??r.name,this.code=t}}function u({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new l({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if("ConstraintError"===e.name){if(!0===r.authenticatorSelection?.requireResidentKey)return new l({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if("conditional"===t.mediation&&"required"===r.authenticatorSelection?.userVerification)return new l({message:"User verification was required during automatic registration but it could not be performed",code:"ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",cause:e});if("required"===r.authenticatorSelection?.userVerification)return new l({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:e})}else{if("InvalidStateError"===e.name)return new l({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if("NotAllowedError"===e.name)return new l({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("NotSupportedError"===e.name){const t=r.pubKeyCredParams.filter((e=>"public-key"===e.type));return 0===t.length?new l({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:e}):new l({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:e})}if("SecurityError"===e.name){const t=globalThis.location.hostname;if(!c(t))return new l({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rp.id!==t)return new l({message:`The RP ID "${r.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("TypeError"===e.name){if(r.user.id.byteLength<1||r.user.id.byteLength>64)return new l({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:e})}else if("UnknownError"===e.name)return new l({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}class d{constructor(){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0})}createNewAbortSignal(){if(this.controller){const e=new Error("Cancelling existing WebAuthn API call for new one");e.name="AbortError",this.controller.abort(e)}const e=new AbortController;return this.controller=e,e.signal}cancelCeremony(){if(this.controller){const e=new Error("Manually cancelling existing WebAuthn API call");e.name="AbortError",this.controller.abort(e),this.controller=void 0}}}const h=new d,p=["cross-platform","platform"];function f(e){if(e&&!(p.indexOf(e)<0))return e}async function R(e){!e.optionsJSON&&e.challenge&&(console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useAutoRegister:r=!1}=e;if(!i())throw new Error("WebAuthn is not supported in this browser");const a={...t,challenge:o(t.challenge),user:{...t.user,id:o(t.user.id)},excludeCredentials:t.excludeCredentials?.map(s)},c={};let l;r&&(c.mediation="conditional"),c.publicKey=a,c.signal=h.createNewAbortSignal();try{l=await navigator.credentials.create(c)}catch(y){throw u({error:y,options:c})}if(!l)throw new Error("Registration was not completed");const{id:d,rawId:p,response:R,type:w}=l;let b,E,m,A;if("function"===typeof R.getTransports&&(b=R.getTransports()),"function"===typeof R.getPublicKeyAlgorithm)try{E=R.getPublicKeyAlgorithm()}catch(_){g("getPublicKeyAlgorithm()",_)}if("function"===typeof R.getPublicKey)try{const e=R.getPublicKey();null!==e&&(m=n(e))}catch(_){g("getPublicKey()",_)}if("function"===typeof R.getAuthenticatorData)try{A=n(R.getAuthenticatorData())}catch(_){g("getAuthenticatorData()",_)}return{id:d,rawId:n(p),response:{attestationObject:n(R.attestationObject),clientDataJSON:n(R.clientDataJSON),transports:b,publicKeyAlgorithm:E,publicKey:m,authenticatorData:A},type:w,clientExtensionResults:l.getClientExtensionResults(),authenticatorAttachment:f(l.authenticatorAttachment)}}function g(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them.\n`,t)}function w(){if(!i())return b.stubThis(new Promise((e=>e(!1))));const e=globalThis.PublicKeyCredential;return void 0===e?.isConditionalMediationAvailable?b.stubThis(new Promise((e=>e(!1)))):b.stubThis(e.isConditionalMediationAvailable())}const b={stubThis:e=>e};function E({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new l({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if("NotAllowedError"===e.name)return new l({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("SecurityError"===e.name){const t=globalThis.location.hostname;if(!c(t))return new l({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rpId!==t)return new l({message:`The RP ID "${r.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("UnknownError"===e.name)return new l({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}async function m(e){!e.optionsJSON&&e.challenge&&(console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:t,useBrowserAutofill:r=!1,verifyBrowserAutofillInput:a=!0}=e;if(!i())throw new Error("WebAuthn is not supported in this browser");let c;0!==t.allowCredentials?.length&&(c=t.allowCredentials?.map(s));const l={...t,challenge:o(t.challenge),allowCredentials:c},u={};if(r){if(!await w())throw Error("Browser does not support WebAuthn autofill");const e=document.querySelectorAll("input[autocomplete$='webauthn']");if(e.length<1&&a)throw Error('No with "webauthn" as the only or last value in its `autocomplete` attribute was detected');u.mediation="conditional",l.allowCredentials=[]}let d;u.publicKey=l,u.signal=h.createNewAbortSignal();try{d=await navigator.credentials.get(u)}catch(A){throw E({error:A,options:u})}if(!d)throw new Error("Authentication was not completed");const{id:p,rawId:R,response:g,type:b}=d;let m;return g.userHandle&&(m=n(g.userHandle)),{id:p,rawId:n(R),response:{authenticatorData:n(g.authenticatorData),clientDataJSON:n(g.clientDataJSON),signature:n(g.signature),userHandle:m},type:b,clientExtensionResults:d.getClientExtensionResults(),authenticatorAttachment:f(d.authenticatorAttachment)}}}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[518],{2518:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensies","ui.app.loading":"Extensie Lijst laden …","ui.app.language":"Wijzig de taal voor de Contao Manager","ui.app.colorDark":"Donkere modus","ui.app.colorDarkTitle":"Verander het kleurenschema naar donker","ui.app.colorLight":"Lichte modus","ui.app.colorLightTitle":"Verander het kleurenschema naar licht","ui.discover.advertisement":"Advertentie in de extensielijst","ui.discover.loading":"Bezig met laden ...","ui.discover.offline":"Kon geen resultaten ophalen.","ui.discover.offlineExplain":"Controleer uw internetverbinding en schakel JavaScript blokkers uit in uw browser.","ui.discover.offlineButton":"Probeer opnieuw","ui.discover.searchPlaceholder":"Zoeken in {count} extensies…","ui.discover.empty":"Geen resultaten voor {query}","ui.discover.more":"Meer resultaten","ui.discover.sortBy":"Sorteren op","ui.discover.sortReleased":"Uitgebracht","ui.discover.sortReleasedTitle":"Sorteer de resultaten op releasedatum","ui.discover.sortLatest":"Updated","ui.discover.sortLatestTitle":"Sorteer de resultaten op laatst bijgewerkt","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Sorteer resultaten op aantal downloads","ui.discover.sortFavers":"Beoordeling","ui.discover.sortFaversTitle":"Sorteer de resultaten op beoordeling","ui.discover.detailsButton":"Details","ui.discover.latestPackages":"Nieuwste en bijgewerkte extensies","ui.discover.faversPackages":"Best beoordeelde extensies","ui.discover.downloadsPackages":"Meest gedownloade extensies","ui.package.homepage":"Project Website","ui.package.private":"Privépakket","ui.package.privateTitle":"Privépakketten zijn alleen verkrijgbaar bij de leverancier (bijvoorbeeld als ZIP-download). Bezoek de website voor meer informatie.","ui.package.abandoned":"niet meer ondersteund","ui.package.abandonedText":"Dit pakket wordt niet langer ondersteund en onderhouden.","ui.package.abandonedReplace":"Dit pakket wordt niet langer ondersteund en onderhouden. De auteur stelt voor om in plaats daarvan het {vervangend} pakket te gebruiken.","ui.package.contaoVersion":"Beschikbaar voor Contao","ui.package-details.previous":"Vorige Extensie Details","ui.package-details.close":"Sluit Extensie Details","ui.package-details.loading":"Bezig met laden ...","ui.package-details.tabDescription":"Beschrijving","ui.package-details.tabRequire":"Vereisten","ui.package-details.tabFeatures":"Kenmerken","ui.package-details.tabSuggest":"Suggesties","ui.package-details.tabConflict":"Conflicten","ui.package-details.tabDependents":"Afhankelijkheden","ui.package-details.linkRequires":"vereist","ui.package-details.linkReplaces":"vervangt","ui.package-details.linkProvides":"biedt","ui.package-details.linkConflicts":"conflicten","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Ondersteunde Contao versie(s)","ui.package-details.latest":"Laatste versie","ui.package-details.released":"uitgebracht op","ui.package-details.license":"Licentie(s)","ui.package-details.authors":"van","ui.package-details.more":"Meer","ui.package-details.packagist":"Details bundel","ui.package-details.metadata":"Bewerk Metadata","ui.package-details.support_docs":"Documentatie","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support Forum","ui.package-details.support_issues":"Problemen / Foutrapport","ui.package-details.support_source":"Broncode","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[554],{4554:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Connexion non sécurisée !!","ui.app.httpsDescription":"Sans HTTPS, vos données confidentielles seront transférées non chiffrées.","ui.app.httpsLink":"Plus d\'information","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Safe Mode enabled !!","ui.app.safeModeDescription":"Some features of the Contao Manager are not available.","ui.app.safeModeExit":"Exit Safe Mode","ui.app.limitedHeadline":"Remote Authentication","ui.app.limitedDescription":"You have limited permissions due to passwordless login.","ui.app.limitedLogout":"Re-authenticate","ui.app.totpHeadline":"Security Notice","ui.app.totpDescription":"Configure two-factor authentication now to secure your account.","ui.app.totpSetup":"Configuration","ui.app.loading":"Chargement de Contao Manager …","ui.app.apiError":"Statut de l\'API inattendu","ui.app.configSecurity1":"ALERTE DE SÉCURITÉ !!! Répertoire de configuration non protégé détecté","ui.app.configSecurity2":"Contao Manager a détecté que ses fichiers de configuration sont accessibles au public. Toutes les opérations sont désactivées jusqu\'à ce que le répertoire soit sécurisé, sinon une personne malintentionnée pourrait accéder aux données sensibles de votre installation.\\n\\nPour résoudre ce problème, assurez-vous d\'empêcher l\'accès au répertoire \\"contao-manager\\" sur votre serveur. Pour savoir comment faire cela, référez-vous au manuel de votre serveur Web ou contactez votre fournisseur d\'hébergement.","ui.account.welcome":"Bienvenue","ui.account.intro1":"Bienvenue dans Contao Manager, un outil universel pour installer et gérer Contao Open Source CMS. Si vous êtes nouveau dans ce domaine, veuillez {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} pour commencer","ui.account.introManual":"lire le manuel","ui.account.intro2":"Si vous rencontrez des problèmes, vérifiez {ourGithubIssues} et n\'hésitez pas à créer un nouveau rapport de bug pour tout ce qui n\'a pas encore été signalé.","ui.account.introIssues":"nos problèmes GitHub","ui.account.headline":"Compte d\'utilisateur","ui.account.description":"Pour gérer votre installation, veuillez créer un compte Contao Manager. Sachez que ce compte n\'est pas lié au back office ou front office de Contao.","ui.account.username":"Nom d\'utilisateur","ui.account.password":"Mot de passe","ui.account.passwordPlaceholder":"Min. 8 caractères","ui.account.passwordLength":"Veuillez insérer au moins 8 caractères.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Créer un compte","ui.account.usePassword":"Use password for login","ui.account.usePasskey":"Use Passkey for login","ui.account.totpHeadline":"Two-factor authentication","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Configure now","ui.account.totpSkip":"Configure later","ui.account.login":"Decline Invitation","ui.account.contribute1":"Contao et le Contao Manager sont parrainés par l\'association à but non lucratif Contao.","ui.account.contribute2":"Please consider contributing to open source by {donate}.","ui.account.contributeDonate":"making a donation","ui.login.headline":"Se connecter","ui.login.description":"Connectez-vous afin de gérer votre installation.","ui.login.username":"Nom d\'utilisateur","ui.login.password":"Mot de passe","ui.login.totpHeadline":"Two-factor authentication","ui.login.totpDescription":"Please enter your verification code to complete the login process.","ui.login.totp":"Verification code","ui.login.forgotPassword":"Mot de passe oublié ?","ui.login.button":"Se connecter","ui.login.passkey":"Sign In with Passkey","ui.login.cancel":"Annuler","ui.login.locked":"Access has been denied because the Contao Manager is locked. To unlock, delete the {lockFile} file in your Contao root directory.","ui.logout.headline":"Timeout session","ui.logout.warning":"Vous êtes inactif depuis plus de 25 minutes. Pour des raisons de sécurité, votre session va se terminera sous peu.","ui.logout.expired":"votre session a été automatiquement interrompue car vous êtes resté inactif pendant plus de 30 minutes.","ui.logout.renew":"Restez connecté","ui.logout.logout":"Se déconnecter","ui.logout.login":"Retour à la page de connexion","ui.oauth.error":"Tentative de connexion OAuth invalide. Contrôlez le paramètre de la requête.","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Remote Authentication","ui.oauth.description":"L\'application ou le service suivant demande un accès à distance de votre instance Contao Manager.","ui.oauth.domain":"Before allowing access, make sure you know this URL and trust its owner!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Permettre l\'accès","ui.oauth.deny":"Refuser l\'accès","ui.oauth.switchUser":"Switch User","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"Vérification du système","ui.boot.description":"Veuillez patienter, nous analysons votre serveur…","ui.boot.issue1":"Problèmes d\'installation détectés","ui.boot.issue2":"Votre installation présente des problèmes qui doivent être résolus avant que Contao Manager puisse être utilisé.","ui.boot.run":"Lancez Contao Manager","ui.boot.safeMode":"Lancer en mode sans échec","ui.recovery.headline":"Récupération du système","ui.recovery.description":"Le Contao Manager a détecté des fichiers qui ressemblent à Contao, mais l\'interface de ligne de commande ne fonctionne pas comme prévu.","ui.recovery.console":"Console Output","ui.recovery.repairOptions":"Veuillez choisir une option pour réparer votre installation.","ui.recovery.repairHeadline":"Réparation automatique","ui.recovery.repairDescription":"Essaye de réparer automatiquement l\'installation en reconstruisant le cache de l\'application et en réinstallant les packages Composer.","ui.recovery.repairWarning":"Toutes les modifications apportées aux fichiers présents dans le dossier Vendor peuvent être supprimées au cours du processus!","ui.recovery.repairFailed":"La réparation automatique a échoué. Essayez le mode sans échec pour réparer manuellement l\'installation.","ui.recovery.repairButton":"Lancer la réparation","ui.recovery.safeModeHeadline":"Mode sans échec","ui.recovery.safeModeDescription":"Lancer le Contao Manager en mode sans échec permet de gérer les packages et d\'exécuter certaines tâches de maintenance, mais les fonctionnalités qui reposent sur une installation fonctionnelle de Contao ne seront pas disponibles.","ui.recovery.safeModeButton":"Lancer en mode sans échec","ui.server.pending":"En attente…","ui.server.running":"En cours d\'analyse…","ui.server.error":"La vérification a échoué en raison d\'une réponse inattendue du serveur.","ui.server.details":"Détails","ui.server.prerequisite":"Vérification annulée en raison d\'un prérequis manquant","ui.server.selfUpdate.title":"Mises à jour de Contao Manager","ui.server.selfUpdate.update":"Une nouvelle version de Contao Manager ({latest}) est disponible.","ui.server.selfUpdate.manualUpdate":"Une nouvelle version {latest} de Contao Manager est disponible. Votre serveur ne prend pas en charge les mises à jour automatiques, veuillez télécharger la nouvelle version à partir de {download}.","ui.server.selfUpdate.latest":"Vous utilisez la dernière version {current}.","ui.server.selfUpdate.dev":"Les versions de développement ne supportent pas les mises à jour automatiques.","ui.server.selfUpdate.unsupported":"Une nouvelle version est disponible mais elle ne supporte pas votre version de PHP.","ui.server.selfUpdate.button":"Lancer la mise à jour","ui.server.selfUpdate.continue":"Continuer","ui.server.config.title":"Configuration du serveur","ui.server.config.setup":"Configurer","ui.server.config.change":"Modifier","ui.server.config.save":"Sauvegarder","ui.server.config.cancel":"Annuler","ui.server.config.customOption":"Autre… ","ui.server.config.description":"Pour exécuter correctement les opérations en tâche de fond, Contao Manager doit savoir où trouver le binaire de PHP en ligne de commande (CLI) et comment exécuter des commandes séparées du processus Web.","ui.server.config.formTitle":"Configuration du serveur","ui.server.config.formText":"Merci de saisir le chemin vers le binaire PHP. La version du binaire PHP doit être la même que pour le processus web.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud permet d\'installer des dépendances Composer même si votre serveur ne fournit pas suffisamment de mémoire. Veuillez noter que les informations relatives à votre package seront transmises à un serveur cloud géré par l\'Association Contao.","ui.server.config.cloud":"Utilisé le Composer Resolver Cloud","ui.server.config.cli":"Binaire PHP","ui.server.config.stateErrorCli":"Aucun binaire PHP valide n\'a été trouvé sur le serveur.","ui.server.config.stateErrorCloud":"Le Composer Resolver Cloud n\'est pas pris en charge.","ui.server.config.stateSuccess":"Binaire PHP à {php_cli}.","ui.server.php_web.title":"Processus web de PHP","ui.server.php_web.below7":"La version {version} de PHP a été trouvée. Passez s\'il vous plaît à PHP 7 dès que possible.","ui.server.php_web.success":"Version PHP {version} trouvée, aucun problème connu trouvé.","ui.server.php_cli.title":"PHP en ligne de commande (CLI)","ui.server.php_cli.success":"Version PHP {version} trouvée, aucun problème connu trouvé.","ui.server.composer.title":"Environnement Composer","ui.server.composer.success":"Aucun problème connu trouvé.","ui.server.composer.install":"Les dépendances de Composer ne sont pas installées.","ui.server.composer.button":"Install","ui.server.contao.title":"Installation de Contao","ui.server.contao.setup":"Configuration","ui.server.contao.check":"Vérifier la base de données.","ui.server.contao.empty":"Aucune installation de Contao n\'a été trouvée.","ui.server.contao.old":"La version {version} de Contao n\'est pas compatible avec Contao Manager, veuillez mettre à jour manuellement votre installation.","ui.server.contao.found":"Contao {version} a été détecté (version API {api}).","ui.server.contao.connectionError":"Impossible de se connecter au serveur de base de données","ui.server.contao.connectionProblem":"La base de données a un problème.","ui.server.contao.missingUser":"Admin account not found.","ui.setup.continue":"Continuer","ui.setup.manager":"Lancez Contao Manager","ui.setup.cancel":"Annuler","ui.setup.welcome":"Bienvenue","ui.setup.welcome1":"This wizard will take you through the necessary steps to set up your Contao Open Source CMS installation.","ui.setup.welcome2":"If you have any questions, please find documentation, forums, a Slack channel and more on the {support} page.","ui.setup.support":"community support","ui.setup.start":"Get started","ui.setup.complete":"Congratulations!","ui.setup.complete1":"Contao {version} has been installed successfully.","ui.setup.complete2":"Pour terminer l\'installation, vous devez ouvrir l\'Outil d\'installation pour configurer la connexion à la base de données et créer un utilisateur back end.","ui.setup.complete3":"You can now start to create your website in the Contao back end. If you need additional extensions, continue to the Contao Manager.","ui.setup.installTool":"Open the Install Tool","ui.setup.login":"Login to Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". An Open Source project like Contao requires amounts of money that can\'t be raised by a single person or company.\\nIf you have a website or sell websites built with Contao, we would love to see you contribute back financially to the product your business relies upon.","ui.setup.fundingLink":"Learn more","ui.setup.document-root.headline":"Configuration du serveur web","ui.setup.document-root.warning":"Pour installer Contao via Contao Manager, vous devez définir la racine du site sur le serveur web.","ui.setup.document-root.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed if the folder structure is not correct or the folders are not empty.","ui.setup.document-root.description2":"Si vous ne savez pas comment configurer la racine de votre site, veuillez lire la documentation Contao ou contacter votre hébergeur.","ui.setup.document-root.documentation":"Lire la Documentation","ui.setup.document-root.conflictsTitle":"Installation directory not empty","ui.setup.document-root.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and check again if you are sure they are unused.","ui.setup.document-root.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.setup.document-root.check":"Check again","ui.setup.document-root.create":"Create directories","ui.setup.document-root.change":"Change directories","ui.setup.document-root.formTitle":"Configuration des répertoires","ui.setup.document-root.formText1":"Le Contao-manager peut créer automatiquement une nouvelle structure de répertoires sur le serveur.","ui.setup.document-root.formText2":"Vous devrez configurer manuellement la nouvelle racine du site (par exemple via un panneau d\'administration d\'hébergement).","ui.setup.document-root.autoconfig":"Je comprends que je dois modifier la configuration de mon serveur. Ne pas configurer la racine du site bloquera le Contao Manager et exposera les fichiers de configuration (y compris les détails du compte et les mots de passe)!","ui.setup.document-root.directory":"Nouveau répertoire","ui.setup.document-root.currentRoot":"Racine du site actuel","ui.setup.document-root.newRoot":"Nouvelle racine du site","ui.setup.document-root.finish":"Répertoires créés","ui.setup.document-root.publicDir":"Use {dir} for public files (for Contao {version})","ui.setup.document-root.directoryInvalid":"Veuillez saisir un nom de répertoire valide.","ui.setup.document-root.directoryExists":"Le répertoire cible existe déjà. Veuillez saisir un autre nom.","ui.setup.document-root.confirmation":"Le Contao Manager a créé avec succès les répertoires nécessaires pour votre installation Contao. Vous devez maintenant configurer la racine du site sur votre serveur web. Ne rechargez pas cette page jusque-là.","ui.setup.document-root.reload":"Recharger la page","ui.setup.document-root.success":"The directory structure on your web server is set up correctly!","ui.setup.document-root.installingProjectDir":"Application files will be installed to {dir}.","ui.setup.document-root.installingPublicDir":"Public files will be installed to {dir}.","ui.setup.document-root.installedProjectDir":"Application files are installed in {dir}.","ui.setup.document-root.installedPublicDir":"Public files are installed in {dir}.","ui.setup.create-project.headline":"Installation de Contao","ui.setup.create-project.description":"Contao development follows the principle of {semver}, a new minor version is released every six months. The currently supported releases are:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"Dernière version","ui.setup.create-project.ltsTitle":"Long Term Support (LTS)","ui.setup.create-project.latestQ1":"Our latest version, offers the most features with support until February {year}.","ui.setup.create-project.latestQ3":"Our latest version, offers the most features with support until August {year}.","ui.setup.create-project.ltsText":"Our current LTS version, if you focus on stability. Offers long term support until February {year}.","ui.setup.create-project.pltsText":"The previous LTS version, still has long term support until February {year}.","ui.setup.create-project.requiresPHP":"Requires at least PHP {version}, you have PHP {current}.","ui.setup.create-project.releaseplan":"Consultez le {contaoReleasePlan} pour obtenir des informations détaillées","ui.setup.create-project.releaseplanLink":"Plan de publication","ui.setup.create-project.installed":"Contao {version} is successfully installed on the server. Continue to set up your database or launch the Contao Manager to install a different version.","ui.setup.create-project.formTitle":"Select a distribution","ui.setup.create-project.formText":"Please choose which version should be installed.","ui.setup.create-project.version":"Version","ui.setup.create-project.demo":"Install the Contao demo website","ui.setup.create-project.demoDescription":"The demo website helps you to get familiar with Contao and all of its core features. More themes can be found in the {store}.","ui.setup.create-project.coreOnly":"Installation de base (Core seulement)","ui.setup.create-project.noUpdate":"Ignorer l\'installation (réservé aux experts !)","ui.setup.create-project.theme":"Contao Theme","ui.setup.create-project.themeInstall":"To install a Contao theme, use the search input or upload a theme file (.cto/.zip) that supports installation through the Contao Manager.","ui.setup.create-project.themeBuy":"Make sure to visit the official {store}.","ui.setup.create-project.themeStore":"Contao Themes Store","ui.setup.create-project.themeUpload":"Upload theme file (.cto/.zip)","ui.setup.create-project.themeInvalid":"The uploaded file is not a Contao theme or does not support the Contao Manager.","ui.setup.create-project.themeWarning":"The Contao Manager cannot tell whether this theme is compatible with your server. Please check with the theme vendor if you have any questions.","ui.setup.create-project.themeTitle":"Review theme details","ui.setup.create-project.themeDetails":"The following dependencies and files will be installed with this theme.","ui.setup.create-project.themeRequire":"{count} Dependencies | {count} Dependencies","ui.setup.create-project.themeFiles":"{count} File | {count} Files","ui.setup.create-project.theme.or":"or search public themes","ui.setup.create-project.theme.search":"Search themes","ui.setup.create-project.theme.more":"More themes","ui.setup.create-project.theme.empty":"No themes matching {query}","ui.setup.create-project.theme.uploaded":"The theme file was uploaded successfully.","ui.setup.create-project.theme.packageName":"Package name","ui.setup.create-project.theme.version":"Version","ui.setup.create-project.theme.authors":"Author(s)","ui.setup.create-project.install":"Install","ui.setup.create-project.cancel":"Annuler","ui.setup.database-connection.headline":"Connexion à la base de données;","ui.setup.database-connection.description":"Contao nécessite une base de données MySQL (ou un équivalent comme MariaDB) pour stocker les pages, les contenus, les utilisateurs et les données relationnelles. Les paramètres de connexion sont stockés le fichier (env) à la racine de votre installation Contao. ","ui.setup.database-connection.formTitle":"Connection Parameters","ui.setup.database-connection.formText":"Entrez l\'URL d\'une base de données ou saisissez séparément utilisateur, mot de passe, serveur et autres champs de base de donnée.","ui.setup.database-connection.url":"URL de la base de données","ui.setup.database-connection.validUrl":"L\'URL de la base de données est invalide ou la connexion au serveur a échoué.","ui.setup.database-connection.or":"or","ui.setup.database-connection.user":"Nom d\'utilisateur","ui.setup.database-connection.password":"Mot de passe","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Nom de la base de données","ui.setup.database-connection.connected":"Successfully connected to database {database} on {server}.","ui.setup.database-connection.error":"Erreur de connexion à la base de données","ui.setup.database-connection.problem":"Contao a détecté un problème avec votre serveur de bases de données.\\n","ui.setup.database-connection.schemaTitle":"Database Schema","ui.setup.database-connection.migration":"There is one pending migration. | There are {count} pending migrations.","ui.setup.database-connection.schema":"There is one pending schema update. | There are {count} pending schema updates.","ui.setup.database-connection.noChanges":"Le schéma de votre base de données est à jour.","ui.setup.database-connection.check":"Vérifier la base de données.","ui.setup.database-connection.skip":"Skip","ui.setup.database-connection.save":"Sauvegarder","ui.setup.database-connection.change":"Change credentials","ui.setup.database-connection.restoreTitle":"Database Import","ui.setup.database-connection.restoreText":"The theme you just installed contains a database backup. Restore the database to import theme data or skip this step to start with a blank Contao installation. | The theme you just installed contains multiple database backups. Select a backup file to import theme data or skip this step to start with a blank Contao installation.","ui.setup.database-connection.backup":"Backup current database before import","ui.setup.database-connection.backupWarning":"All data in database will be overwritten on import! Create a backup first if the database is not empty.","ui.setup.database-connection.restore":"Import theme database","ui.setup.database-connection.restoreOption":"Backup from {date} ({size})","ui.setup.database-connection.restored":"Your theme database was successfully imported. Continue to validate your database schema.","ui.setup.backend-user.success":"Un compte administrateur pour le back end de Contao a été trouvé dans votre base de données. veuillez utiliser le back end pour ajouter d\'autres utilisateurs.","ui.setup.backend-user.error":"Unable to retrieve user list. Check the console output for details.","ui.setup.backend-user.headline":"Backend Account","ui.setup.backend-user.description":"To manage your website, you need to have at least one admin account for the Contao back end. Be aware that this account is not related to the Contao Manager.","ui.setup.backend-user.formTitle":"Créer un compte","ui.setup.backend-user.formText":"Please enter the details for the new back end account.","ui.setup.backend-user.username":"Nom d\'utilisateur","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-mail address","ui.setup.backend-user.emailInvalid":"Please enter a valid e-mail address","ui.setup.backend-user.password":"Mot de passe","ui.setup.backend-user.passwordPlaceholder":"Min. 8 caractères","ui.setup.backend-user.passwordLength":"Veuillez insérer au moins 8 caractères.","ui.setup.backend-user.create":"Add account","ui.task.headline":"Tâche de fond","ui.task.loading":"Chargement des détails…","ui.task.created":"Chargement des détails…","ui.task.active":"Veuillez patienter pendant que Contao Manager exécute des opérations en tâche de fond.","ui.task.complete":"Toutes les opérations sont terminées avec succès. Vérifiez les détails dans la console.","ui.task.aborting":"Veuillez patienter le temps que les opérations en tâche de fond se terminent.","ui.task.stopped":"Certaines opérations en tâche de fond ont été annulées. Veuillez vérifier les détails dans la console","ui.task.error":"Une opération en tâche de fond s\'est arrêtée de manière inattendue. Veuillez vérifier les détails dans la console.","ui.task.failed":"Le Contao Manager n\'a pas pu démarrer!","ui.task.failedDescription1":"Une erreur s\'est produite lors de la tentative d\'exécution des opérations en arrière plan","ui.task.failedDescription2":"Si cela se reproduit, votre serveur peut ne pas être pris en charge","ui.task.reportProblem":"Signaler un problème","ui.task.sponsor":"Composer Cloud sponsored by {sponsor}","ui.task.buttonAudit":"Mettre à jour la base de données","ui.task.buttonClose":"Fermer","ui.task.buttonConfirm":"Confirmer & fermer","ui.task.buttonCancel":"Annuler","ui.task.confirmCancel":"Êtes-vous sûr de vouloir annuler cette tâche? Cela pourrait laisser votre installation Contao inutilisable!","ui.task.autoclose":"Fermer les détails de la tâche en cas de succès","ui.console.toggle":"Afficher / masquer la console","ui.console.showLog":"Show full console log","ui.console.copyLog":"Copier le journal dans le presse-papiers","ui.migrate.headline":"Database Updates","ui.migrate.migrationsOnly":"(migrations only)","ui.migrate.schemaOnly":"(schema only)","ui.migrate.loading":"Please wait, we are checking your database …","ui.migrate.empty":"No pending migrations or schema updates found. Your database is up to date.","ui.migrate.emptyMigrations":"No pending migrations found. Make sure to also check for schema updates.","ui.migrate.emptySchema":"No pending schema updates found. Make sure to also check for migrations.","ui.migrate.pending":"Your database is not up to date. Please review the console output below and execute the changes.","ui.migrate.previousChanges":"A previous database migration was not confirmed.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.previousComplete":"A previous database migration was not confirmed, please review the console output below.\\nThere are no more pending changes.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Database updates have been applied.\\nThere are no more pending migrations or schema updates. Your database is up to date.","ui.migrate.problem":"Contao has detected a problem with your database server.\\nPlease review the console output below to find out what needs to be fixed. | Contao has detected problems with your database server.\\nPlease review the console output below to find out what needs to be fixed.","ui.migrate.warning":"Contao has detected a misconfiguration of your database server.\\nWarnings can be skipped temporarily, but should be fixed for optimal performance and data integrity.","ui.migrate.error":"The changes could not be applied. Your database might have been changed, please check again to retry.","ui.migrate.execute":"Execute","ui.migrate.close":"Fermer","ui.migrate.confirm":"Confirmer & fermer","ui.migrate.cancel":"Annuler","ui.migrate.continue":"Continuer","ui.migrate.setup":"Configuration","ui.migrate.skip":"Skip","ui.migrate.retry":"Check again","ui.migrate.retryAll":"Check all","ui.migrate.withDeletes":"Execute all database changes including DROP queries.","ui.migrate.migrationTitle":"Database Migrations","ui.migrate.schemaTitle":"Schema Updates","ui.migrate.problemTitle":"Database Problems","ui.migrate.warningTitle":"Database Warnings","ui.migrate.addTable":"Add table {table}","ui.migrate.dropTable":"Drop table {table}","ui.migrate.addField":"Add field {table}.{field}","ui.migrate.changeField":"Change field {table}.{field}","ui.migrate.dropField":"Drop field {table}.{field}","ui.migrate.createIndex":"Create index \\"{name}\\" on {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" on {table}","ui.widget.mandatory":"Ce champ ne doit pas être vide.","ui.widget.blankOption":"Veuillez sélectionner","ui.widget.showPassword":"Show password","ui.widget.hidePassword":"Hide password","ui.error.title":"La requête HTTP pour \\"{method} {url}\\" a échoué.","ui.error.server500":"Il semble qu\'une erreur inattendue s\'est produite sur votre serveur. Veuillez vérifier les fichiers journaux de votre serveur Web (Apache / Nginx) et les journaux de Contao Manager à \\"contao-manager/logs\\".","ui.error.response":"Le serveur a renvoyé une réponse avec le status {status}.","ui.error.moreLink":"Plus d\'informations","ui.error.support":"Contao Support","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Aide","ui.footer.reportProblem":"Signaler un problème","ui.navigation.discover":"Découvrir","ui.navigation.packages":"Packages","ui.navigation.tools":"Outils","ui.navigation.installTool":"Outil d\'installation","ui.navigation.backend":"Back office de Contao","ui.navigation.debug":"Mode de débogage","ui.navigation.logViewer":"Log Viewer","ui.navigation.phpinfo":"Informations PHP","ui.navigation.phpinfoLoading":"Loading PHP Information…","ui.navigation.maintenance":"Maintenance","ui.navigation.rebuildCache":"Reconstruire le cache","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"Vérification du système","ui.navigation.advanced":"Avancé","ui.navigation.logout":"Se déconnecter","ui.maintenance.database.title":"Database Migrations and Backups","ui.maintenance.database.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.database.migrations":"One pending database migration | {count} pending database migrations","ui.maintenance.database.schemaUpdates":"One pending schema update | {count} pending schema updates","ui.maintenance.database.error":"La base de données a un problème.","ui.maintenance.database.warning":"Database warnings found.","ui.maintenance.database.button":"Vérifier la base de données.","ui.maintenance.database.migrationOnly":"Check migrations only","ui.maintenance.database.schemaOnly":"Check schema only","ui.maintenance.database.installTool":"Open Install Tool","ui.maintenance.database.createBackup":"Create Backup","ui.maintenance.database.backupUnsupported":"Database backups are not supported by your Contao version.","ui.maintenance.database.backupList":"You have one database backup, created on {date}. | You have {count} database backups, the latest one was created on {date}.","ui.maintenance.database.backupEmpty":"You currently have no database backups.","ui.maintenance.rebuildCache.title":"Cache de l\'application","ui.maintenance.rebuildCache.description":"La reconstruction du cache de l\'application est requise après toute modification des fichiers de configuration.","ui.maintenance.rebuildCache.rebuildProd":"Reconstruire le cache de production","ui.maintenance.rebuildCache.rebuildDev":"Reconstruire le cache de développement","ui.maintenance.rebuildCache.clearProd":"Vider le cache de production","ui.maintenance.rebuildCache.clearDev":"Vider le cache de développement","ui.maintenance.installTool.title":"Outil d\'installation Contao","ui.maintenance.installTool.description":"L\'outil d\'installation Contao est automatiquement verrouillé si vous entrez un mauvais mot de passe trois fois de suite.","ui.maintenance.installTool.unlock":"Dévérouillage de l\'outil d\'installation Contao","ui.maintenance.installTool.lock":"Vérouillage de l\'outil d\'installation Contao","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"L\'autoloader de Composer est responsable du chargement des classes PHP. L\'autoloader doit être vidé après l\'ajout de namespaces à la racine composer.json.","ui.maintenance.dumpAutoload.button":"Purger l\'Autoloader","ui.maintenance.composerInstall.title":"Composer Dependencies","ui.maintenance.composerInstall.description":"Les dépendances de Composer se trouvent dans le dossier {vendor} à la racine de votre application. La réinstallation des dépendances peut être nécessaire après manipulation ou téléchargement manuel du fichier {composerLock}","ui.maintenance.composerInstall.button":"Lancer Composer Install","ui.maintenance.composerInstall.update":"Lancer Composer Update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Pour améliorer ses performences, Composer met en cache les packages téléchargés. Si vous rencontrez des problèmes comme par exemple des fichiers corrompdus, vous pouvez essayer de d\'effacer le cache de Composer pour forcer un nouveau téléchargement des packages.","ui.maintenance.composerCache.button":"Vider le cache","ui.maintenance.maintenanceMode.title":"Maintenance Mode","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Enable","ui.maintenance.maintenanceMode.disable":"Disable","ui.maintenance.debugMode.title":"Mode de débogage","ui.maintenance.debugMode.description":"Activez le mode débogage en définissant un utilisateur et un mot de passe pour le point d\'entrée {appDevPhp}","ui.maintenance.debugMode.descriptionJwt":"Activez le mode débogage en définissant le cookie de débogage pour le domaine actuel.","ui.maintenance.debugMode.activate":"Activer","ui.maintenance.debugMode.deactivate":"Désactiver","ui.maintenance.debugMode.credentials":"Données de connexion","ui.maintenance.debugMode.user":"Veuillez saisir un nom d\'utilisateur pour le mode de débogage.","ui.maintenance.debugMode.password":"Veuillez saisir un mot de passe pour le mode de débogage.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode met en cache les fichiers PHP pour améliorer la vitesse d\'exécution du processus web. Cette fonctionnalité doit être supprimée dans certaines circontances et notammment si certanis fichiers ne sont pas reconnus après des modifications.","ui.maintenance.opcodeCache.button":"Vider le cache","ui.maintenance.safeMode":"Non disponible en mode sans échec","ui.maintenance.unsupported":"Non pris en charge par votre version Contao","ui.packages.updateButton":"Mise à jour des packages","ui.packages.searchButton":"Rechercher des packages","ui.packages.searchPlaceholder":"Rechercher des packages…","ui.packages.uploadOverlay":"Glisser-déposez les fichiers à uploader","ui.packages.uploadButton":"Uploader des packages","ui.packages.uploadMessage":"Vous avez un upload non confirmé. | Vous avez {count} uploads non confirmés.","ui.packages.uploadApply":"Confirmer les uploads","ui.packages.uploadReset":"Supprimer les uploads","ui.packages.uploadIncomplete":"Ce fichier n\'a pas été entièrement uploadé. Veuillez le supprimer et réessayer.","ui.packages.uploadDuplicate":"Ce fichier semble avoir été uploadé plusieurs fois. Veuillez supprimer les doublons.","ui.packages.uploadInstalled":"Ce fichier est déjà installé. Veuillez supprimer les doublons.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure that the PHP ZIP extension is installed and update your dependencies.","ui.packages.changesMessage":"Vous avez un changement non confirmé. | Vous avez {count} changements non confirmés.","ui.packages.changesDryrun":"Tester (Dry run)","ui.packages.changesApply":"Appliquer les changements","ui.packages.changesApplyAll":"Update all packages","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"Annuler les changements","ui.packages.changesReview":"Revoir les changements","ui.packagelist.loading":"Chargement…","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"Nouveaux packages","ui.packagelist.installed":"Packages installés","ui.package.hintRevert":"Rétablir les modifications","ui.package.hintNoupdate":"Ne pas mettre à jour","ui.package.hintConstraint":"Ce package va être installé avec la contrainte {constraint} quand vous appliquerez les modifications.","ui.package.hintConstraintBest":"Ce package sera installé avec la meilleure version disponible lorsque vous appliquerez les modifications.","ui.package.hintConstraintChange":"La contrainte pour ce package sera changée de \\"{from}\\" à \\"{to}\\" lorsque vous appliquerez les modifications.","ui.package.hintConstraintUpdate":"Ce package sera mis à jour lorsque vous appliquez les modifications.","ui.package.hintAdded":"Ce package sera installé lorsque vous appliquerez les modifications.","ui.package.hintRemoved":"Ce package sera supprimé lorsque vous appliquerez les modifications.","ui.package.requiredTitle":"ajouté manuellement","ui.package.requiredText":"Ce package est requis dans votre composer.json mais n\'est pas installé.","ui.package.removedTitle":"supprimé manuellement","ui.package.removedText":"Ce package a été supprimé de votre composer.json.","ui.package.installed":"Actuellement installé:","ui.package.version":"Version {version}","ui.package.additionalDownloads":"{count} Téléchargement | {count} Téléchargements","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"Éditer","ui.package.uploadConstraint":"Cette contrainte est définie par le package téléchargé.","ui.package.updateButton":"Mettre à jour","ui.package.removeButton":"Supprimer","ui.package.installButton":"Ajouter un package","ui.package.installButtonShort":"Ajouter","ui.package.detailsButton":"Détails","ui.package.latestConstraint":"dernière version","ui.package.update":"Update available","ui.package.updateLatest":"dernière version","ui.package.updateAvailable":"{version} available","ui.package.updateUnknown":"unknown version","ui.package.updateConstraint":"A newer version outside your version constraint is available.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Version {version}","ui.cloudStatus.waitingTime":"Temps d\'attente","ui.cloudStatus.jobs":"Jobs en cours","ui.cloudStatus.workers":"Workers","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"sans","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sec","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Refresh Cloud Status","ui.log-viewer.loading":"Chargement…","ui.log-viewer.empty":"There are no log files on your server.","ui.log-viewer.reload":"Reload","ui.log-viewer.file":"Log file","ui.log-viewer.channel":"Channel","ui.log-viewer.channelTitle":"The channel this message was logged to.","ui.log-viewer.level":"Level","ui.log-viewer.levelTitle":"Severity of the log message.","ui.log-viewer.timeHeader":"Time","ui.log-viewer.messageHeader":"Message","ui.log-viewer.showContext":"Show Context","ui.log-viewer.hideContext":"Hide Context","ui.log-viewer.showExtra":"Show Extra","ui.log-viewer.hideExtra":"Hide Extra","ui.log-viewer.more":"Load more …","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download file \\"{file}\\"","ui.log-viewer.prodEnvironment":"Production Environment","ui.log-viewer.devEnvironment":"Development Environment (Debug Mode)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Change Password","ui.user-manager.setupTotp":"Setup Two-Factor Authentication","ui.user-manager.disableTotp":"Disable Two-Factor Authentication","ui.user-manager.invite":"Invite User","ui.user-manager.delete":"Delete","ui.user-manager.deleteConfirm":"Do you really want to delete user \\"{username}\\"?","ui.user-manager.deleted":"User {username} deleted successfully","ui.user-manager.passwordHeadline":"Change Password","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Current password","ui.user-manager.newPassword":"New password","ui.user-manager.passwordPlaceholder":"Min. 8 caractères","ui.user-manager.submitPassword":"Submit","ui.user-manager.passwordChanged":"Your password has been changed successfully.","ui.user-manager.passwordError":"This password is incorrect.","ui.user-manager.inviteHeadline":"Invite User","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Create Invitation Link","ui.user-manager.clipboard":"Copy to clipboard","ui.user-manager.permissions":"Learn about permissions","ui.user-manager.cancel":"Annuler","ui.user-manager.close":"Fermer","ui.user-manager.you":"You","ui.totp.headline":"Two-Factor Authentication","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verification code","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"The verification code is invalid.","ui.totp.enable":"Enable","ui.totp.disable":"Disable","ui.totp.cancel":"Annuler","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Setup Two-Factor Authentication","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[706],{2706:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Conexión insegura !!","ui.app.httpsDescription":"Sin HTTPS, sus datos confidenciales se transferirán sin cifrar.","ui.app.httpsLink":"Mas información","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"¡Modo seguro habilitado!","ui.app.safeModeDescription":"Algunas funciones de Contao Manager no están disponibles.","ui.app.safeModeExit":"Salida del modo seguro","ui.app.limitedHeadline":"Autenticación remota ","ui.app.limitedDescription":"Tiene permisos limitados debido al inicio de sesión sin contraseña.","ui.app.limitedLogout":"Volver a autenticar","ui.app.totpHeadline":"Aviso de seguridad","ui.app.totpDescription":"Configure la autenticación de dos factores ahora para proteger su cuenta.","ui.app.totpSetup":"Configuración","ui.app.loading":"Cargando Contao Manager ...","ui.app.apiError":"Estado inesperado de la API","ui.app.configSecurity1":"ALERTA DE SEGURIDAD !!! Detectado directorio de configuración desprotegido","ui.app.configSecurity2":"Contao Manager ha detectado que sus archivos de configuración son de acceso público. Todas las operaciones están deshabilitadas hasta que el directorio esté seguro; de lo contrario, un atacante podría acceder a datos confidenciales de su instalación.\\n\\nPara solucionar este problema, asegúrese de evitar el acceso al directorio \\"contao-manager\\" en su servidor. Para saber cómo hacer esto, consulte el manual de su servidor web o póngase en contacto con su proveedor de alojamiento.","ui.account.welcome":"Bienvenido","ui.account.intro1":"Bienvenido a Contao Manager, una herramienta universal para instalar y administrar Contao Open Source CMS. Si es nuevo en esto, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} para comenzar","ui.account.introManual":"lea el manual","ui.account.intro2":"Si encuentra algún problema, consulte {ourGithubIssues} y siéntase libre de crear uno nuevo para cualquier cosa que aún no se haya informado.","ui.account.introIssues":"nuestros problemas de GitHub","ui.account.headline":"Cuenta de usuario","ui.account.description":"Para administrar su instalación, cree una cuenta para Contao Manager. Tenga en cuenta que esta cuenta no está relacionada con el back end o front end de Contao.","ui.account.username":"Nombre de usuario","ui.account.password":"Contraseña","ui.account.passwordPlaceholder":"min. 8 caracteres","ui.account.passwordLength":"Por favor introduzca al menos 8 caracteres.","ui.account.loginInvalid":"Se produjo un error al crear la cuenta. Intente con otro nombre de usuario.","ui.account.submit":"Crear una cuenta","ui.account.usePassword":"Utilice contraseña para iniciar sesión","ui.account.usePasskey":"Utilice la clave de acceso (Passkey) para iniciar sesión","ui.account.totpHeadline":"Autenticación de dos factores","ui.account.totpDescription":"Habilite la autenticación de dos factores, que agrega una capa adicional de seguridad a su cuenta. Además de su nombre de usuario y contraseña, deberá ingresar un código de verificación generado por una aplicación de dos factores como 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator o cualquier otra aplicación TOTP.","ui.account.totpSetup":"Configurar ahora","ui.account.totpSkip":"Configurar más tarde","ui.account.login":"Rechazar invitación","ui.account.contribute1":"Contao y Contao Manager están patrocinados por la Asociación Contao sin fines de lucro.","ui.account.contribute2":"Considere contribuir al código abierto con {donate}.","ui.account.contributeDonate":"hacer una donación","ui.login.headline":"Registrarse","ui.login.description":"Inicie sesión para administrar su instalación.","ui.login.username":"Nombre de usuario","ui.login.password":"Contraseña","ui.login.totpHeadline":"Autenticación de dos factores","ui.login.totpDescription":"Ingrese su código de verificación para completar el proceso de inicio de sesión.","ui.login.totp":"Código de verificación","ui.login.forgotPassword":"¿Ha olvidado su contraseña?","ui.login.button":"Registrarse","ui.login.passkey":"Iniciar sesión con clave de acceso (Passkey)","ui.login.cancel":"Cancelar","ui.login.locked":"Se ha denegado el acceso porque Contao Manager está bloqueado. Para desbloquear, elimine el archivo {lockFile} en su directorio raíz de Contao.","ui.logout.headline":"Timeout de la sesión","ui.logout.warning":"Ha estado inactivo por más de 25 minutos. Por razones de seguridad, su sesión finalizará en breve.","ui.logout.expired":"Su sesión finalizó automáticamente porque ha estado inactivo durante más de 30 minutos.","ui.logout.renew":"Mantener conectado","ui.logout.logout":"Cerrar sesión","ui.logout.login":"Volver para iniciar sesión","ui.oauth.error":"Intento de OAuth no válido Verifique los parámetros de solicitud.","ui.oauth.https":"El URI de redireccionamiento DEBE usar un protocolo seguro (https :) para evitar que el token de autenticación se transmita en texto sin cifrar. ","ui.oauth.headline":"Autenticación remota ","ui.oauth.description":"La siguiente aplicación o servicio está solicitando acceso remoto a su instancia del Contao Manager.","ui.oauth.domain":"Antes de permitir el acceso, asegúrese de conocer esta URL y confíe en su propietario.","ui.oauth.outOfScope":"Lamentablemente, no tienes los permisos necesarios para otorgar este acceso.","ui.oauth.allow":"Permitir el acceso","ui.oauth.deny":"Acceso denegado","ui.oauth.switchUser":"Cambiar de usuario","ui.scope.admin":"Acceso de administrador, incluida la gestión de usuarios","ui.scope.install":"Instalar nuevos paquetes y cambiar la configuración de Contao","ui.scope.update":"Actualizar paquetes y ejecutar tareas de mantenimiento","ui.scope.read":"Leer paquetes y configuración","ui.boot.headline":"Comprobar sistema","ui.boot.description":"Por favor espere, estamos analizando su servidor ...","ui.boot.issue1":"Se han detectado problemas de instalación","ui.boot.issue2":"Su instalación tiene problemas que deben solucionarse antes de que se pueda utilizar Contao Manager.","ui.boot.run":"Lanzamiento de Contao Manager","ui.boot.safeMode":"Lanzamiento en modo seguro","ui.recovery.headline":"Recuperación del sistema","ui.recovery.description":"El Contao Manager detectó archivos que se parecen a Contao, pero la Interfaz de línea de comandos no funciona como se esperaba.","ui.recovery.console":"Salida de consola","ui.recovery.repairOptions":"Por favor, elija una opción para reparar su instalación.","ui.recovery.repairHeadline":"Reparación automática","ui.recovery.repairDescription":"Intenta reparar automáticamente la instalación reconstruyendo el caché de la aplicación y reinstalando los paquetes de Composer.","ui.recovery.repairWarning":"¡Cualquier modificación de los archivos del proveedor podría ser eliminada en el proceso!","ui.recovery.repairFailed":"La reparación automática no tuvo éxito. Pruebe el Modo seguro para reparar manualmente la instalación.","ui.recovery.repairButton":"Ejecutar la reparación del sistema","ui.recovery.safeModeHeadline":"Modo seguro","ui.recovery.safeModeDescription":"Iniciar el Contao Manager en Modo seguro permite administrar paquetes y ejecutar ciertas tareas de mantenimiento, pero las funciones que dependen de una instalación de Contao que funcione no estarán disponibles.","ui.recovery.safeModeButton":"Lanzamiento en modo seguro","ui.server.pending":"Esperando …","ui.server.running":"Analizando ...","ui.server.error":"La comprobación falló debido a una respuesta inesperada del servidor.","ui.server.details":"Detalles","ui.server.prerequisite":"Verificación cancelada debido a un prerrequisito faltante.","ui.server.selfUpdate.title":"Actualizaciones del Contao Manager","ui.server.selfUpdate.update":"Una nueva versión {latest} de Contao Manager está disponible.","ui.server.selfUpdate.manualUpdate":"Hay disponible una nueva versión {latest} de Contao Manager. Su servidor no admite actualizaciones automáticas, descargue la nueva versión de {download}.","ui.server.selfUpdate.latest":"Estás utilizando la última versión {current}.","ui.server.selfUpdate.dev":"Las compilaciones de desarrollo no admiten actualizaciones automáticas.","ui.server.selfUpdate.unsupported":"Hay una nueva versión disponible pero no es compatible con su versión de PHP.","ui.server.selfUpdate.button":"Ejecutar autoactualización","ui.server.selfUpdate.continue":"Continuar","ui.server.config.title":"Configuración del servidor","ui.server.config.setup":"Configurar","ui.server.config.change":"Cambiar","ui.server.config.save":"Guardar","ui.server.config.cancel":"Cancelar","ui.server.config.customOption":"Otros ...","ui.server.config.description":"Para ejecutar correctamente las tareas en segundo plano, Contao Manager necesita saber dónde encontrar el binario de la línea de comandos PHP y cómo ejecutar comandos separados del proceso web.","ui.server.config.formTitle":"Configuración del servidor","ui.server.config.formText":"Por favor ingrese la ruta a su binario de PHP. Asegúrese de que el binario sea la misma versión PHP que su proceso web.","ui.server.config.cloudTitle":"Compositor Resolver Cloud","ui.server.config.cloudText":"El Composer Resolver Cloud permite instalar dependencias de Composer incluso si su servidor no proporciona suficiente memoria local. Tenga en cuenta que la información de su paquete se transmitirá a un servidor en la nube operado por la Asociación Contao.","ui.server.config.cloud":"Utilice la nube Composer Resolver Cloud","ui.server.config.cli":"PHP binario","ui.server.config.stateErrorCli":"No se encontró ningún binario PHP válido en el servidor.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud no es compatible.","ui.server.config.stateSuccess":"PHP binario en {php_cli}.","ui.server.php_web.title":"Proceso web de PHP","ui.server.php_web.below7":"Versión PHP encontrada {versión}. ¡Cambie a PHP 7 lo antes posible!","ui.server.php_web.success":"Se encontró la versión PHP {versión}, no se encontraron problemas conocidos.","ui.server.php_cli.title":"Interfaz de línea de comandos de PHP","ui.server.php_cli.success":"Se encontró la versión PHP {versión}, no se encontraron problemas conocidos.","ui.server.composer.title":"Entorno Composer","ui.server.composer.success":"No se encontraron problemas conocidos.","ui.server.composer.install":"Las dependencias del Composer no están instaladas.","ui.server.composer.button":"Instalar","ui.server.contao.title":"Instalación de Contao","ui.server.contao.setup":"Configuración","ui.server.contao.check":"Consultar base de datos","ui.server.contao.empty":"No se ha encontrado una instalación de Contao.","ui.server.contao.old":"La versión de Contao {versión} no es compatible con Contao Manager, actualice su instalación manualmente.","ui.server.contao.found":"Se ha encontrado Contao {version} (API version {api}).","ui.server.contao.connectionError":"No se puede conectar con el servidor de la base de datos.","ui.server.contao.connectionProblem":"Problema de base de datos encontrado.","ui.server.contao.missingUser":"Cuenta de administrador no encontrada.","ui.setup.continue":"Continuar","ui.setup.manager":"Lanzamiento de Contao Manager","ui.setup.cancel":"Cancelar","ui.setup.welcome":"Bienvenido","ui.setup.welcome1":"Este asistente le guiará a través de los pasos necesarios para configurar su instalación de CMS de código abierto de Contao.","ui.setup.welcome2":"Si tiene alguna pregunta, busque documentación, foros, un canal de Slack y más en la página de {support}.","ui.setup.support":"soporte comunitario","ui.setup.start":"Empezar","ui.setup.complete":"¡Enhorabuena!","ui.setup.complete1":"Contao {versión} se ha instalado correctamente.","ui.setup.complete2":"Para finalizar el proceso de configuración, abra la herramienta de instalación para configurar la conexión de la base de datos y crear un usuario final.","ui.setup.complete3":"Ahora puede comenzar a crear su sitio web en el back-end de Contao. Si necesita extensiones adicionales, continúe con Contao Manager.","ui.setup.installTool":"Abra la herramienta de instalación","ui.setup.login":"Iniciar sesión en Contao","ui.setup.funding":"El software libre es \\"libre\\" como en \\"libertad de expresión\\", no como en \\"cerveza gratis\\". Un proyecto de código abierto como Contao requiere cantidades de dinero que no pueden ser recaudadas por una sola persona o empresa.\\nSi tiene un sitio web o vende sitios web creados con Contao, nos encantaría ver que contribuye financieramente al producto del que depende su negocio.","ui.setup.fundingLink":"Aprende más","ui.setup.document-root.headline":"Configuración del servidor web","ui.setup.document-root.warning":"Para instalar Contao a través de Contao Manager, debe arreglar la raíz del documento en el servidor web.","ui.setup.document-root.description1":"Contao usa una carpeta separada para los archivos públicos, los archivos de la aplicación se instalan en su carpeta principal. Contao no se puede instalar si la estructura de carpetas no es correcta o las carpetas no están vacías.","ui.setup.document-root.description2":"Si no sabe cómo configurar la raíz de su documento, lea la documentación de Contao o comuníquese con su proveedor de alojamiento.","ui.setup.document-root.documentation":"Lea la documentación","ui.setup.document-root.conflictsTitle":"El directorio de instalación no está vacío","ui.setup.document-root.conflictsDirectory":"El directorio raíz de su futura instalación de Contao no está vacío, hemos encontrado (un) archivo(s) {count} que podrían sobrescribirse durante el proceso de instalación. Se recomienda crear una estructura de directorios vacía para Contao, pero también puede eliminar los siguientes archivos y verificar nuevamente si está seguro de que no se utilizan.","ui.setup.document-root.ignoreConflicts":"Quiero instalar Contao en el directorio no vacío. Entiendo que esto podría sobrescribir cualquier archivo existente en mi espacio web.","ui.setup.document-root.check":"Revisar otra vez","ui.setup.document-root.create":"Crear directorios","ui.setup.document-root.change":"Cambiar directorios","ui.setup.document-root.formTitle":"Configuración de directorio","ui.setup.document-root.formText1":"Contao Manager puede crear automáticamente una nueva estructura de directorio en el servidor.","ui.setup.document-root.formText2":"Deberá configurar manualmente la nueva raíz del documento (por ejemplo, a través de un panel de administración de alojamiento).","ui.setup.document-root.autoconfig":"Entiendo que tengo que cambiar la configuración de mi servidor. ¡No configurar la raíz del documento romperá el Contao Manager y expondrá los archivos de configuración (incluidos los detalles de la cuenta y las contraseñas)!","ui.setup.document-root.directory":"Nuevo directorio","ui.setup.document-root.currentRoot":"Raíz del documento actual","ui.setup.document-root.newRoot":"Nueva raíz del documento","ui.setup.document-root.finish":"Configurar directorios","ui.setup.document-root.publicDir":"Use {dir} para archivos públicos (para Contao {version})","ui.setup.document-root.directoryInvalid":"Introduzca un nombre de directorio válido.","ui.setup.document-root.directoryExists":"El directorio de destino ya existe. Ingrese un nombre diferente.","ui.setup.document-root.confirmation":"Contao Manager ha creado con éxito el directorio necesario para su instalación de Contao. Ahora debe configurar la raíz del documento en su servidor web. No recargues esta página hasta entonces.","ui.setup.document-root.reload":"Recargar página","ui.setup.document-root.success":"¡La estructura de directorios en su servidor web está configurada correctamente!","ui.setup.document-root.installingProjectDir":"Los archivos de la aplicación se instalarán en {dir}.","ui.setup.document-root.installingPublicDir":"Los archivos públicos se instalarán en {dir}.","ui.setup.document-root.installedProjectDir":"Los archivos de la aplicación se instalan en {dir}.","ui.setup.document-root.installedPublicDir":"Los archivos públicos se instalan en {dir}.","ui.setup.create-project.headline":"Instalación de Contao","ui.setup.create-project.description":"El desarrollo de Contao sigue el principio de {semver}, se lanza una nueva versión secundaria cada seis meses. Las versiones admitidas actualmente son:","ui.setup.create-project.semver":"Versionado semántico","ui.setup.create-project.latestTitle":"Última","ui.setup.create-project.ltsTitle":"Soporte a largo plazo","ui.setup.create-project.latestQ1":"Nuestra última versión ofrece la mayoría de las funciones con soporte hasta febrero de {year}.","ui.setup.create-project.latestQ3":"Nuestra última versión ofrece la mayor cantidad de funciones con soporte hasta agosto del {year}.","ui.setup.create-project.ltsText":"Nuestra versión LTS actual, si te enfocas en la estabilidad. Ofrece soporte a largo plazo hasta febrero {year}.","ui.setup.create-project.pltsText":"La versión anterior de LTS todavía tiene soporte a largo plazo hasta febrero de {year}.","ui.setup.create-project.requiresPHP":"Requiere al menos PHP {version}, tiene PHP {current}.","ui.setup.create-project.releaseplan":"Consulte el {contaoReleasePlan} para obtener información detallada.","ui.setup.create-project.releaseplanLink":"Plan de lanzamiento de Contao","ui.setup.create-project.installed":"Contao {version} se instaló correctamente en el servidor. Continúe configurando su base de datos o inicie Contao Manager para instalar una versión diferente.","ui.setup.create-project.formTitle":"Seleccione una distribución","ui.setup.create-project.formText":"Elija qué versión debe instalarse.","ui.setup.create-project.version":"Versión","ui.setup.create-project.demo":"Instale el sitio web de demostración de Contao","ui.setup.create-project.demoDescription":"The demo website helps you to get familiar with Contao and all of its core features. More themes can be found in the {store}.Instale el sitio web de demostración de Contao","ui.setup.create-project.coreOnly":"Instalación mínima (solo el núcleo)","ui.setup.create-project.noUpdate":"Omitir instalación (¡Solo experto!)","ui.setup.create-project.theme":"Tema Contao","ui.setup.create-project.themeInstall":"Para instalar un tema de Contao, utilice la entrada de búsqueda o cargue un archivo de tema (.cto/.zip) que admita la instalación a través de Contao Manager.","ui.setup.create-project.themeBuy":"Asegúrate de visitar la {store} oficial.","ui.setup.create-project.themeStore":"Tienda de temas Contao","ui.setup.create-project.themeUpload":"Cargar archivo de tema (.cto/.zip)","ui.setup.create-project.themeInvalid":"El archivo cargado no es un tema de Contao o no es compatible con Contao Manager.","ui.setup.create-project.themeWarning":"El Contao Manager no puede saber si este tema es compatible con su servidor. Consulte con el proveedor del tema si tiene alguna pregunta.","ui.setup.create-project.themeTitle":"Revisar los detalles del tema","ui.setup.create-project.themeDetails":"Las siguientes dependencias y archivos se instalarán con este tema.","ui.setup.create-project.themeRequire":"{count} Dependencias | {count} Dependencias","ui.setup.create-project.themeFiles":"{count} Archivo | {count} Archivos","ui.setup.create-project.theme.or":"o buscar temas públicos","ui.setup.create-project.theme.search":"Buscar temas","ui.setup.create-project.theme.more":"Más temas","ui.setup.create-project.theme.empty":"No hay temas que coincidan con {query}","ui.setup.create-project.theme.uploaded":"El archivo del tema se cargó correctamente.","ui.setup.create-project.theme.packageName":"Nombre del paquete","ui.setup.create-project.theme.version":"Versión","ui.setup.create-project.theme.authors":"Autor(es)","ui.setup.create-project.install":"Instalar","ui.setup.create-project.cancel":"Cancelar","ui.setup.database-connection.headline":"Conexión de base de datos","ui.setup.database-connection.description":"Contao requiere una base de datos MySQL (o una bifurcación compatible como MariaDB) para almacenar páginas, contenido, usuarios y otros datos relacionales. Los parámetros de conexión se almacenan en el archivo {env} en la raíz del proyecto de su instalación de Contao.","ui.setup.database-connection.formTitle":"Parámetros de conexión","ui.setup.database-connection.formText":"Ingrese una URL de base de datos o complete los campos de nombre de usuario, contraseña, servidor y base de datos por separado.","ui.setup.database-connection.url":"URL de la base de datos","ui.setup.database-connection.validUrl":"La URL de la base de datos no es válida o la conexión con el servidor falló.","ui.setup.database-connection.or":"o","ui.setup.database-connection.user":"Nombre de usuario","ui.setup.database-connection.password":"Contraseña","ui.setup.database-connection.server":"Servidor (:Port)","ui.setup.database-connection.database":"Nombre de la base de datos","ui.setup.database-connection.connected":"Conexión exitosa a la base de datos {database} en {server}.","ui.setup.database-connection.error":"Error al conectarse a la base de datos.","ui.setup.database-connection.problem":"Contao ha detectado un problema con su servidor de base de datos.","ui.setup.database-connection.schemaTitle":"Esquema de base de datos","ui.setup.database-connection.migration":"Hay una migración pendiente. | Hay {count} migraciones pendientes.","ui.setup.database-connection.schema":"Hay una actualización de esquema pendiente. | Hay {count} actualizaciones de esquema pendientes.","ui.setup.database-connection.noChanges":"El esquema de su base de datos está actualizado.","ui.setup.database-connection.check":"Consultar base de datos","ui.setup.database-connection.skip":"Saltar","ui.setup.database-connection.save":"Guardar","ui.setup.database-connection.change":"Cambiar credenciales","ui.setup.database-connection.restoreTitle":"Importar base de datos","ui.setup.database-connection.restoreText":"El tema que acaba de instalar contiene una copia de seguridad de la base de datos. Restaure la base de datos para importar datos del tema u omita este paso para comenzar con una instalación de Contao en blanco. | El tema que acaba de instalar contiene múltiples copias de seguridad de bases de datos. Seleccione un archivo de respaldo para importar datos del tema u omita este paso para comenzar con una instalación de Contao en blanco.","ui.setup.database-connection.backup":"Copia de seguridad de la base de datos actual antes de importar","ui.setup.database-connection.backupWarning":"¡Todos los datos de la base de datos se sobrescribirán al importar! Primero cree una copia de seguridad si la base de datos no está vacía.","ui.setup.database-connection.restore":"Importar base de datos de temas","ui.setup.database-connection.restoreOption":"Copia de seguridad de {date} ({size})","ui.setup.database-connection.restored":"Su base de datos de temas se importó correctamente. Continúe validando el esquema de su base de datos.","ui.setup.backend-user.success":"Se encontró una cuenta de administrador para el back-end de Contao en su base de datos. Use el back-end de Contao para agregar más usuarios.","ui.setup.backend-user.error":"No se puede recuperar la lista de usuarios. Consulte la salida de la consola para obtener más detalles.","ui.setup.backend-user.headline":"Cuenta back-end","ui.setup.backend-user.description":"Para administrar su sitio web, debe tener al menos una cuenta de administrador para el back-end de Contao. Tenga en cuenta que esta cuenta no está relacionada con Contao Manager.","ui.setup.backend-user.formTitle":"Crear una cuenta","ui.setup.backend-user.formText":"Introduzca los detalles de la nueva cuenta back-end.","ui.setup.backend-user.username":"Nombre de usuario","ui.setup.backend-user.name":"Nombre","ui.setup.backend-user.email":"Dirección de correo electrónico","ui.setup.backend-user.emailInvalid":"Por favor, introduzca una dirección de correo electrónico válida","ui.setup.backend-user.password":"Contraseña","ui.setup.backend-user.passwordPlaceholder":"min. 8 caracteres","ui.setup.backend-user.passwordLength":"Por favor introduzca al menos 8 caracteres.","ui.setup.backend-user.create":"Añadir cuenta","ui.task.headline":"Tarea de fondo","ui.task.loading":"Cargando detalles…","ui.task.created":"Cargando detalles…","ui.task.active":"Espere mientras Contao Manager ejecuta las operaciones de tareas en segundo plano.","ui.task.complete":"Todas las operaciones se completan con éxito. Consulte la salida de la consola para obtener más detalles.","ui.task.aborting":"Espere mientras se cancelan las operaciones en segundo plano.","ui.task.stopped":"Se cancelaron algunas operaciones en segundo plano. Compruebe la salida de la consola.","ui.task.error":"Una operación en segundo plano se detuvo inesperadamente. Compruebe la salida de la consola.","ui.task.failed":"¡El Contao Manager no pudo iniciar una tarea en segundo plano!","ui.task.failedDescription1":"Algo salió mal al intentar ejecutar operaciones en segundo plano.","ui.task.failedDescription2":"Si esto vuelve a suceder, es posible que su servidor no sea compatible.","ui.task.reportProblem":"Informar de un problema","ui.task.sponsor":"Composer Cloud patrocinado por {sponsor}","ui.task.buttonAudit":"Actualizar base de datos","ui.task.buttonClose":"Cerrar","ui.task.buttonConfirm":"Confirmar y cerrar","ui.task.buttonCancel":"Cancelar","ui.task.confirmCancel":"¿Está seguro de cancelar esta tarea? ¡Esto podría dejar su instalación de Contao en un estado roto!","ui.task.autoclose":"Cerrar los detalles de la tarea en caso de éxito","ui.console.toggle":"Mostrar / Ocultar salida de consola","ui.console.showLog":"Mostrar registro completo de la consola","ui.console.copyLog":"Copiar registro al portapapeles","ui.migrate.headline":"Actualizaciones de la base de datos","ui.migrate.migrationsOnly":"(solo migraciones)","ui.migrate.schemaOnly":"(solo esquema)","ui.migrate.loading":"Por favor espere, estamos revisando su base de datos...","ui.migrate.empty":"No se encontraron migraciones pendientes ni actualizaciones de esquema. Su base de datos está actualizada.","ui.migrate.emptyMigrations":"No se encontraron migraciones pendientes. Asegúrese de verificar también las actualizaciones del esquema.","ui.migrate.emptySchema":"No se encontraron actualizaciones de esquema pendientes. Asegúrese de verificar también las migraciones.","ui.migrate.pending":"Su base de datos no está actualizada. Revise la salida de la consola a continuación y ejecute los cambios.","ui.migrate.previousChanges":"No se confirmó una migración de base de datos anterior.\\nRevise el resultado de la consola a continuación, luego continúe para ver los próximos cambios.","ui.migrate.previousComplete":"No se confirmó una migración de base de datos anterior, revise el resultado de la consola a continuación.\\nNo hay más cambios pendientes.","ui.migrate.appliedChanges":"Se han aplicado actualizaciones de la base de datos.\\nRevise el resultado de la consola a continuación, luego continúe para ver los próximos cambios.","ui.migrate.appliedComplete":"Se han aplicado actualizaciones de la base de datos.\\nNo hay más migraciones pendientes ni actualizaciones de esquemas. Su base de datos está actualizada.","ui.migrate.problem":"Contao ha detectado un problema con su servidor de base de datos.\\nRevise la salida de la consola a continuación para averiguar qué debe corregirse. | Contao ha detectado problemas con su servidor de base de datos.\\nRevise la salida de la consola a continuación para averiguar qué debe corregirse.","ui.migrate.warning":"Contao ha detectado una configuración incorrecta de su servidor de base de datos.\\nLas advertencias se pueden omitir temporalmente, pero se deben corregir para lograr un rendimiento y una integridad de los datos óptimos.","ui.migrate.error":"No se pudieron aplicar los cambios. Es posible que su base de datos haya cambiado, verifique nuevamente para volver a intentarlo.","ui.migrate.execute":"Ejecutar","ui.migrate.close":"Cerrar","ui.migrate.confirm":"Confirmar y cerrar","ui.migrate.cancel":"Cancelar","ui.migrate.continue":"Continuar","ui.migrate.setup":"Configuración","ui.migrate.skip":"Saltar","ui.migrate.retry":"Revisar otra vez","ui.migrate.retryAll":"Comprobar todo","ui.migrate.withDeletes":"Ejecute todos los cambios de la base de datos, incluidas las consultas DROP.","ui.migrate.migrationTitle":"Migraciones de bases de datos","ui.migrate.schemaTitle":"Actualizaciones de esquema","ui.migrate.problemTitle":"Problemas de base de datos","ui.migrate.warningTitle":"Advertencias de la base de datos","ui.migrate.addTable":"Añadir tabla {table}","ui.migrate.dropTable":"Soltar tabla {table}","ui.migrate.addField":"Añadir campo {table}.{field}","ui.migrate.changeField":"Cambiar campo {table}.{field}","ui.migrate.dropField":"Soltar campo {table}.{field}","ui.migrate.createIndex":"Crear índice \\"{name}\\" en {table}","ui.migrate.dropIndex":"Coloque el índice \\"{name}\\" en {table}","ui.widget.mandatory":"Este campo no debe estar vacío.","ui.widget.blankOption":"Por favor seleccione","ui.widget.showPassword":"Mostrar contraseña","ui.widget.hidePassword":"Ocultar contraseña","ui.error.title":"Error en la solicitud HTTP para \\"{method} {url}\\".","ui.error.server500":"Parece que ocurrió un error inesperado en su servidor. Consulte los archivos de registro de su servidor web (Apache/Nginx) y los registros de Contao Manager en \\"contao-manager/logs\\".","ui.error.response":"El servidor devolvió una respuesta con el código de estado {status}.","ui.error.moreLink":"Más información","ui.error.support":"Soporte Contao","ui.error.permission":"No tiene permiso para utilizar esta función.","ui.footer.help":"Ayuda","ui.footer.reportProblem":"Informar de un problema","ui.navigation.discover":"Descubrir","ui.navigation.packages":"Paquetes","ui.navigation.tools":"Herramientas","ui.navigation.installTool":"Herramienta de instalación","ui.navigation.backend":"Backend de Contao","ui.navigation.debug":"Modo Contao Debug","ui.navigation.logViewer":"Visor de registros","ui.navigation.phpinfo":"Información PHP","ui.navigation.phpinfoLoading":"Cargando información de PHP…","ui.navigation.maintenance":"Mantenimiento","ui.navigation.rebuildCache":"Reconstruir caché","ui.navigation.users":"Cuentas","ui.navigation.systemCheck":"Comprobar sistema","ui.navigation.advanced":"Avanzado","ui.navigation.logout":"Cerrar sesión","ui.maintenance.database.title":"Migraciones y copias de seguridad de bases de datos","ui.maintenance.database.description":"Las migraciones de bases de datos garantizan esquemas de tablas y datos coherentes.","ui.maintenance.database.migrations":"Una migración de base de datos pendiente | {count} migraciones de bases de datos pendientes","ui.maintenance.database.schemaUpdates":"Una actualización de esquema pendiente | {count} actualizaciones de esquema pendientes","ui.maintenance.database.error":"Problema de base de datos encontrado.","ui.maintenance.database.warning":"Se encontraron advertencias de la base de datos.","ui.maintenance.database.button":"Consultar base de datos","ui.maintenance.database.migrationOnly":"Comprobar solo migraciones","ui.maintenance.database.schemaOnly":"Comprobar solamente esquema ","ui.maintenance.database.installTool":"Abrir herramienta de instalación","ui.maintenance.database.createBackup":"Crear copia de seguridad","ui.maintenance.database.backupUnsupported":"Las copias de seguridad de bases de datos no son compatibles con su versión de Contao.","ui.maintenance.database.backupList":"Tiene una copia de seguridad de la base de datos, creada el {fecha}. | Tiene {count} copias de seguridad de la base de datos; la última se creó el {fecha}.","ui.maintenance.database.backupEmpty":"Actualmente no tiene copias de seguridad de la base de datos.","ui.maintenance.rebuildCache.title":"Caché de la aplicación","ui.maintenance.rebuildCache.description":"Es necesario volver a generar la caché de la aplicación después de modificar cualquiera de los archivos de configuración.","ui.maintenance.rebuildCache.rebuildProd":"Reconstruir caché de producción","ui.maintenance.rebuildCache.rebuildDev":"Reconstruir caché de desarrollo","ui.maintenance.rebuildCache.clearProd":"Borrar caché de producción","ui.maintenance.rebuildCache.clearDev":"Borrar caché de desarrollo","ui.maintenance.installTool.title":"Herramienta de Instalación Contao","ui.maintenance.installTool.description":"La herramienta de instalación de Contao se bloquea automáticamente si introduce una contraseña incorrecta tres veces seguidas.","ui.maintenance.installTool.unlock":"Desbloquear herramienta de instalación","ui.maintenance.installTool.lock":"Bloquear herramienta de instalación","ui.maintenance.dumpAutoload.title":"Cargador Composer Class","ui.maintenance.dumpAutoload.description":"El autocargador Composer es responsable de la carga de la clase PHP. El autocargador debe volcarse después de agregar espacios de nombres personalizados a la raíz composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Dependencias Composer","ui.maintenance.composerInstall.description":"Las dependencias de Composer se encuentran en la carpeta {vendor} en la raíz de su aplicación. Puede ser necesario reinstalar las dependencias después de la manipulación o de cargar manualmente el archivo {composerLock}.","ui.maintenance.composerInstall.button":"Ejecutar instalador","ui.maintenance.composerInstall.update":"Ejecutar actualización de Composer","ui.maintenance.composerCache.title":"Caché del Composer","ui.maintenance.composerCache.description":"El Composer almacena en el caché los paquetes descargados para un mejor rendimiento. Si tiene problemas como archivos rotos, intente eliminar el caché de Composer para forzar una nueva descarga.","ui.maintenance.composerCache.button":"Limpiar cache","ui.maintenance.maintenanceMode.title":"Modo de mantenimiento","ui.maintenance.maintenanceMode.description":"Poner a Contao en modo de mantenimiento mostrará una plantilla \\"503 Servicio no disponible\\" para el sitio web.","ui.maintenance.maintenanceMode.enable":"Habilitar","ui.maintenance.maintenanceMode.disable":"Deshabilitar","ui.maintenance.debugMode.title":"Modo Debug","ui.maintenance.debugMode.description":"Active el modo de depuración configurando un usuario y una contraseña para el punto de entrada {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Active el modo de depuración configurando la cookie de depuración para el dominio actual.","ui.maintenance.debugMode.activate":"Activar","ui.maintenance.debugMode.deactivate":"Desactivar","ui.maintenance.debugMode.credentials":"Credenciales","ui.maintenance.debugMode.user":"Introduzca un nombre de usuario para el modo Debug.","ui.maintenance.debugMode.password":"Introduzca una contraseña de usuario para el modo Debug.","ui.maintenance.opcodeCache.title":"Caché Opcode","ui.maintenance.opcodeCache.description":"Opcode guarda en caché los archivos PHP en el proceso web para una ejecución más rápida. Debe borrarse bajo ciertas circunstancias si los archivos no son reconocidos después de cambiarlos.","ui.maintenance.opcodeCache.button":"Truncar caché","ui.maintenance.safeMode":"No disponible en modo seguro","ui.maintenance.unsupported":"No es compatible con su versión de Contao","ui.packages.updateButton":"Paquetes de actualización","ui.packages.searchButton":"Buscar paquetes","ui.packages.searchPlaceholder":"Buscando paquetes ...","ui.packages.uploadOverlay":"Arrastra y suelta archivos para subir","ui.packages.uploadButton":"Subir paquetes","ui.packages.uploadMessage":"Tiene una carga sin confirmar. | Tienes {count} cargas sin confirmar.","ui.packages.uploadApply":"Confirmar subidas","ui.packages.uploadReset":"Eliminar subidas","ui.packages.uploadIncomplete":"Este archivo no se cargó por completo. Elimínelo e intente nuevamente.","ui.packages.uploadDuplicate":"Este archivo parece haberse cargado varias veces. Por favor, elimine los duplicados.","ui.packages.uploadInstalled":"Este archivo ya está instalado. Por favor, elimine los duplicados.","ui.packages.uploadUnsupported":"Las cargas no son compatibles con su instalación. Asegúrese de que la extensión PHP ZIP esté instalada y actualice sus dependencias.","ui.packages.changesMessage":"Tiene un cambio sin confirmar. | Tiene {count} cambios sin confirmar.","ui.packages.changesDryrun":"Funcionamiento en seco","ui.packages.changesApply":"Aplicar cambios","ui.packages.changesApplyAll":"Actualizar todos los paquetes ","ui.packages.changesDryrunAll":"Ejecutar en seco todos los paquetes","ui.packages.changesReset":"Restablecer cambios","ui.packages.changesReview":"Revisar cambios","ui.packagelist.loading":"Cargando ...","ui.packagelist.uploads":"Subidas","ui.packagelist.added":"Neuvos paquetes","ui.packagelist.installed":"paquetes instalados","ui.package.hintRevert":"Revertir cambios","ui.package.hintNoupdate":"No actualice","ui.package.hintConstraint":"Este paquete se instalará con restricción {constraint} al aplicar los cambios.","ui.package.hintConstraintBest":"Este paquete se instalará en la mejor versión disponible cuando aplique los cambios.","ui.package.hintConstraintChange":"La restricción para este paquete cambiará de \\"{from}\\" a \\"{to}\\" cuando aplique los cambios.","ui.package.hintConstraintUpdate":"Este paquete se actualizará cuando aplique los cambios.","ui.package.hintAdded":"Este paquete se instalará cuando aplique los cambios.","ui.package.hintRemoved":"Este paquete se eliminará cuando aplique los cambios.","ui.package.requiredTitle":"agregado manualmente","ui.package.requiredText":"Este paquete es obligatorio en su composer.json pero no está instalado.","ui.package.removedTitle":"Eliminado manualmente","ui.package.removedText":"Este paquete se eliminó de su composer.json.","ui.package.installed":"Actualmente instalado:","ui.package.version":"Versión {version}","ui.package.additionalDownloads":"{count} Descargar | {count} Descargas","ui.package.additionalStars":"{count} estrella | {count} estrellas","ui.package.editConstraint":"Editar","ui.package.uploadConstraint":"Esta restricción está definida por el paquete cargado.","ui.package.updateButton":"Actualizar","ui.package.removeButton":"Eliminar","ui.package.installButton":"Agregar paquete","ui.package.installButtonShort":"Añadir","ui.package.detailsButton":"Detalles","ui.package.latestConstraint":"Última versión","ui.package.update":"Actualización disponible ","ui.package.updateLatest":"Última versión","ui.package.updateAvailable":"{version} disponible","ui.package.updateUnknown":"versión desconocida ","ui.package.updateConstraint":"Hay disponible una versión más nueva fuera de su restricción de versión.","ui.package.incompatible":"{package} no funciona con Contao {constraint}.","ui.cloudStatus.headline":"Compositor Resolver Cloud","ui.cloudStatus.version":"Versión {version}","ui.cloudStatus.waitingTime":"Tiempo de espera","ui.cloudStatus.jobs":"Trabajos actuales","ui.cloudStatus.workers":"Trabajadores","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"ninguno","ui.cloudStatus.short":"aprox. {minutes} min","ui.cloudStatus.long":"aprox. {minutes} min {seconds} seg","ui.cloudStatus.error":"No se puede obtener el estado del Composer Resolver Cloud. Puede haber una ventana de mantenimiento o problemas del sistema.","ui.cloudStatus.button":"Cloud-Status ","ui.cloudStatus.refresh":"Actualizar el Cloud-Status","ui.log-viewer.loading":"Cargando ...","ui.log-viewer.empty":"No hay archivos de registro en su servidor.","ui.log-viewer.reload":"Recargar","ui.log-viewer.file":"Archivo de registro","ui.log-viewer.channel":"Canal","ui.log-viewer.channelTitle":"El canal en el que se registró este mensaje.","ui.log-viewer.level":"Nivel","ui.log-viewer.levelTitle":"Gravedad del mensaje de registro.","ui.log-viewer.timeHeader":"Tiempo","ui.log-viewer.messageHeader":"Mensaje","ui.log-viewer.showContext":"Mostrar contenido","ui.log-viewer.hideContext":"Ocultar contenido","ui.log-viewer.showExtra":"Mostrar Extra","ui.log-viewer.hideExtra":"Ocultar Extra","ui.log-viewer.more":"Cargar más ...","ui.log-viewer.download":"Descargar","ui.log-viewer.downloadTitle":"Descargar archivo \\"{file}\\"","ui.log-viewer.prodEnvironment":"Entorno de producción","ui.log-viewer.devEnvironment":"Entorno de desarrollo (Debug Mode)","ui.user-manager.loading":"Cargando usuarios…","ui.user-manager.changePassword":"Cambiar contraseña","ui.user-manager.setupTotp":"Configurar la autenticación de dos factores","ui.user-manager.disableTotp":"Deshabilitar la autenticación de dos factores","ui.user-manager.invite":"Invitar usuario","ui.user-manager.delete":"Borrar","ui.user-manager.deleteConfirm":"¿Está seguro de que desea eliminar el usuario \\"{username}\\"?","ui.user-manager.deleted":"El usuario {username} fue eliminado exitosamente","ui.user-manager.passwordHeadline":"Cambiar contraseña","ui.user-manager.passwordText":"Para cambiar su contraseña, ingrese la contraseña actual y la nueva en los campos respectivos.","ui.user-manager.currentPassword":"Contraseña actual","ui.user-manager.newPassword":"Nueva contraseña","ui.user-manager.passwordPlaceholder":"min. 8 caracteres","ui.user-manager.submitPassword":"Enviar","ui.user-manager.passwordChanged":"Su contraseña ha sido cambiada exitosamente","ui.user-manager.passwordError":"Esta contraseña es incorrecta.","ui.user-manager.inviteHeadline":"Invitar usuario","ui.user-manager.inviteText":"Si necesita varios inicios de sesión para Contao Manager, puede crear un enlace de invitación aquí. Comparta este enlace con alguien o úselo en otro dispositivo para crear una nueva cuenta con los permisos otorgados.","ui.user-manager.inviteSuccess1":"Se ha creado un nuevo enlace de invitación. La URL que aparece a continuación se puede utilizar para crear una nueva cuenta de usuario para este administrador de cuentas. La invitación vence el {expires} (dentro de una semana).","ui.user-manager.inviteSuccess2":"Copie el enlace en su portapapeles. Solo funcionará una vez y no podra verlo nuevamente luego de cerrar este cuadro de diálogo.","ui.user-manager.createInvitation":"Crear enlace de invitación","ui.user-manager.clipboard":"Copiar al portapapeles","ui.user-manager.permissions":"Obtenga más información sobre los permisos","ui.user-manager.cancel":"Cancelar","ui.user-manager.close":"Cerrar","ui.user-manager.you":"Usted","ui.totp.headline":"Autenticación de dos factores","ui.totp.setupQr":"Escanee el código QR con su aplicación 2FA/TOTP.","ui.totp.setupCode":"Si no puede escanear el código QR, ingrese esta clave en su lugar:","ui.totp.codeLabel":"Código de verificación","ui.totp.codeDescription":"Ingrese el código de verificación generado por su aplicación 2FA/TOTP.","ui.totp.disableText":"Ingrese el código de verificación para desactivar la autenticación de dos factores.","ui.totp.invalid":"El código de verificación no es válido.","ui.totp.enable":"Habilitar","ui.totp.disable":"Deshabilitar","ui.totp.cancel":"Cancelar","ui.totp.enabled":"La autenticación de dos factores se habilitó correctamente.","ui.totp.disabled":"La autenticación de dos factores se deshabilitó correctamente.","ui.totp.setup":"Configurar la autenticación de dos factores","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[953],{3953:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensions","ui.app.loading":"Laddar tilläggslista …","ui.app.language":"Byt språk för Contao Manager","ui.app.colorDark":"Mörkt läge","ui.app.colorDarkTitle":"Byt färgschema till mörkt","ui.app.colorLight":"Ljusläge","ui.app.colorLightTitle":"Byt färgschema till ljus","ui.discover.advertisement":"Annons i tilläggslistan","ui.discover.loading":"Laddning ...","ui.discover.offline":"Det gick inte att hämta några resultat.","ui.discover.offlineExplain":"Kontrollera din internetanslutning och inaktivera JavaScript-blockerare i din webbläsare.","ui.discover.offlineButton":"Försök igen","ui.discover.searchPlaceholder":"Sök i {count} tillägg …","ui.discover.empty":"Inga resultat för {query}","ui.discover.more":"Fler resultat","ui.discover.sortBy":"Sortera efter","ui.discover.sortReleased":"Släppte","ui.discover.sortReleasedTitle":"Sortera resultat efter releasedatum","ui.discover.sortLatest":"Uppdaterad","ui.discover.sortLatestTitle":"Sortera resultat efter senast uppdaterade","ui.discover.sortDownloads":"Nedladdningar","ui.discover.sortDownloadsTitle":"Sortera resultat efter antal nedladdningar","ui.discover.sortFavers":"Betyg","ui.discover.sortFaversTitle":"Sortera resultat efter betyg","ui.discover.detailsButton":"Detaljer","ui.discover.latestPackages":"Senaste och uppdaterade tillägg","ui.discover.faversPackages":"Högst rankade tillägg","ui.discover.downloadsPackages":"Mest nedladdade tillägg","ui.package.homepage":"Projektets hemsida","ui.package.private":"Privat paket","ui.package.privateTitle":"Privata paket är endast tillgängliga från leverantören (t.ex. som en ZIP-nedladdning). Besök gärna webbplatsen för mer information.","ui.package.abandoned":"övergiven","ui.package.abandonedText":"Detta paket är övergivet och underhålls inte längre.","ui.package.abandonedReplace":"Detta paket är övergivet och underhålls inte längre. Författaren föreslår att du istället använder paketet {replacement}.","ui.package.contaoVersion":"Tillgänglig för Contao","ui.package-details.previous":"Tidigare tilläggsinformation","ui.package-details.close":"Stäng tilläggsinformation","ui.package-details.loading":"Laddning ...","ui.package-details.tabDescription":"Beskrivning","ui.package-details.tabRequire":"Krav","ui.package-details.tabFeatures":"Funktioner","ui.package-details.tabSuggest":"Förslag","ui.package-details.tabConflict":"Konflikter","ui.package-details.tabDependents":"Anhöriga","ui.package-details.linkRequires":"kräver","ui.package-details.linkReplaces":"ersätter","ui.package-details.linkProvides":"tillhandahåller","ui.package-details.linkConflicts":"konflikter","ui.package-details.funding":"Underhåll av fondpaket!","ui.package-details.contaoVersions":"Stödd Contao version(er)","ui.package-details.latest":"Senaste versionen","ui.package-details.released":"släppt på","ui.package-details.license":"Licens(er)","ui.package-details.authors":"från","ui.package-details.more":"Mer","ui.package-details.packagist":"Paketdetaljer","ui.package-details.metadata":"Redigera metadata","ui.package-details.support_docs":"Dokumentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Supportforum","ui.package-details.support_issues":"Problem/felrapport","ui.package-details.support_source":"Källkod","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-post","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[715],{3715:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Небезопасное соединение !!","ui.app.httpsDescription":"Без использования HTTPS ваши конфиденциальные данные будут переданы не зашифрованными.","ui.app.httpsLink":"Больше информации","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Включен безопасный режим !!","ui.app.safeModeDescription":"Некоторые функции Contao Manager недоступны.","ui.app.safeModeExit":"Выйти из безопасного режима","ui.app.limitedHeadline":"Удаленная авторизация ","ui.app.limitedDescription":"У вас ограничены разрешения, поскольку вы вошли без ввода пароля.","ui.app.limitedLogout":"Повторная авторизация","ui.app.totpHeadline":"Примечание о безопасности","ui.app.totpDescription":"Настройте двухфакторную авторизацию сейчас, чтобы защитить ваш аккаунт.","ui.app.totpSetup":"Настроить","ui.app.loading":"Загрузка Contao Manager...","ui.app.apiError":"Неожиданный статус API","ui.app.configSecurity1":"ПРЕДУПРЕЖДЕНИЕ СИСТЕМЫ БЕЗОПАСНОСТИ !!! Обнаружен незащищенный каталог конфигурации","ui.app.configSecurity2":"Contao Manager обнаружил, что файлы его конфигурации общедоступны. Все операции отключены до тех пор, пока каталог не будет защищен, в противном случае злоумышленник сможет получить доступ к конфиденциальным данным установки.\\n\\nЧтобы устранить эту проблему, обязательно запретите доступ к каталогу \\"contao-manager\\" на вашем сервере. Чтобы узнать, как это сделать, обратитесь к руководству пользователя веб-сервера или свяжитесь с вашим хостинг-провайдером.","ui.account.welcome":"Приветствие","ui.account.intro1":"Добро пожаловать в Contao Manager, универсальный набор инструментов для установки и управления Contao Open Source CMS. Если вы новичок в этом, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} чтобы начать работу","ui.account.introManual":"прочтите руководство","ui.account.intro2":"Если у вас возникли какие-либо проблемы, см. {ourGithubIssues}, а так-же не стесняйтесь создавать новые вопросы для всего, о чем еще не сообщалось.","ui.account.introIssues":"наши GitHub вопросы","ui.account.headline":"Учетная запись","ui.account.description":"Для управления установкой, создайте учетную запись для Contao Manager. Имейте в виду, что эта учетная запись не связана с панелью управления Contao, либо внешним интерфейсом.","ui.account.username":"Имя пользователя","ui.account.password":"Пароль","ui.account.passwordPlaceholder":"мин. 8 символов","ui.account.passwordLength":"Введите не менее 8 символов.","ui.account.loginInvalid":"Произошла ошибка при создании аккаунта. Попробуйте другое имя пользователя.","ui.account.submit":"Создать учетную запись","ui.account.usePassword":"Использовать пароль для входа","ui.account.usePasskey":"Использовать Passkey для входа","ui.account.totpHeadline":"Двухфакторная авторизация","ui.account.totpDescription":"Включите двухфакторную авторизацию, которая добавит дополнительный уровень безопасности к вашей учетной записи. В дополнение к вашему имени пользователя и паролю вам нужно будет ввести код подтверждения, сгенерированный двухфакторным приложением, таким как 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator или любым другим приложением TOTP.","ui.account.totpSetup":"Настроить сейчас","ui.account.totpSkip":"Настроить потом","ui.account.login":"Отклонить приглашение","ui.account.contribute1":"Contao и Contao Manager спонсируются некоммерческой ассоциацией Contao.","ui.account.contribute2":"Пожалуйста, подумайте о внесении вклада в открытый исходный код {donate}.","ui.account.contributeDonate":"сделать пожертвование","ui.login.headline":"Вход в систему","ui.login.description":"Войдите в систему для управления установкой.","ui.login.username":"Имя пользователя","ui.login.password":"Пароль","ui.login.totpHeadline":"Двухфакторная авторизация","ui.login.totpDescription":"Введите проверочный код для завершения процесса входа.","ui.login.totp":"Проверочный код","ui.login.forgotPassword":"Забыли пароль?","ui.login.button":"Вход в систему","ui.login.passkey":"Войти с помощью Passkey","ui.login.cancel":"Отмена","ui.login.locked":"Доступ запрещен, потому, что Contao Manager заблокирован. Чтобы разблокировать, удалите файл {lockFile} в корневом каталоге Contao.","ui.logout.headline":"Тайм-аут сеанса","ui.logout.warning":"Вы были неактивны более 25 минут. Из соображений безопасности ваша сессия будет прервана в ближайшее время.","ui.logout.expired":"Ваш сеанс был автоматически прерван, потому, что вы были неактивны более 30 минут.","ui.logout.renew":"Оставаться в системе","ui.logout.logout":"Выход","ui.logout.login":"Вернуться на страницу входа","ui.oauth.error":"Неверная попытка OAuth. Проверьте параметры запроса.","ui.oauth.https":"URI перенаправления ДОЛЖЕН использовать защищенный протокол (https:), чтобы предотвратить передачу токена авторизации в виде открытого текста.","ui.oauth.headline":"Удаленная авторизация ","ui.oauth.description":"Следующее приложение или служба запрашивает удаленный доступ к экземпляру Contao Manager.","ui.oauth.domain":"Прежде чем разрешить доступ, убедитесь, что этот URL вам известен и вы доверяете его владельцу!","ui.oauth.outOfScope":"К сожалению, у вас нет необходимых разрешений для предоставления такого доступа.","ui.oauth.allow":"Разрешить доступ","ui.oauth.deny":"Запретить доступ","ui.oauth.switchUser":"Сменить пользователя","ui.scope.admin":"Административный доступ, включая управление пользователями","ui.scope.install":"Установка новых пакетов и изменение конфигурации Contao","ui.scope.update":"Обновление пакетов и выполнение задач по техническому обслуживанию","ui.scope.read":"Чтение пакетов и конфигурации","ui.boot.headline":"Проверка системы","ui.boot.description":"Подождите, мы анализируем ваш сервер...","ui.boot.issue1":"Обнаруженные проблемы установки","ui.boot.issue2":"Ваша установка имеет проблемы, которые должны быть исправлены, перед использованием Contao Manager.","ui.boot.run":"Запуск Contao Manager","ui.boot.safeMode":"Запуск в безопасном режиме","ui.recovery.headline":"Восстановление системы","ui.recovery.description":"Contao Manager обнаружил файлы, которые выглядят как файлы Contao, но интерфейс командной строки не работает как положено.","ui.recovery.console":"Вывод консоли","ui.recovery.repairOptions":"Выберите вариант восстановления вашей установки.","ui.recovery.repairHeadline":"Автоматическое восстановление","ui.recovery.repairDescription":"Пытаться автоматически восстановить установку путем перестроения кеша приложения и повторной установки пакетов Composer.","ui.recovery.repairWarning":"Любые изменения в файлах каталога vendor могут быть удалены в процессе!","ui.recovery.repairFailed":"Автоматическое восстановление не удалось. Используйте безопасный режим, чтобы восстановить установку вручную.","ui.recovery.repairButton":"Запустить системное восстановление","ui.recovery.safeModeHeadline":"Безопасный режим","ui.recovery.safeModeDescription":"Запуск Contao Manager в безопасном режиме позволяет управлять пакетами и запускать определенные задачи обслуживания, но функции, которые опираются на рабочую установку Contao, будут недоступны.","ui.recovery.safeModeButton":"Запуск в безопасном режиме","ui.server.pending":"Ожидание...","ui.server.running":"Анализ...","ui.server.error":"Проверка завершилась неудачно из-за неожиданного ответа с сервера.","ui.server.details":"Сведения","ui.server.prerequisite":"Проверка отменена из-за отсутствия необходимых условий.","ui.server.selfUpdate.title":"Обновления Contao Manager","ui.server.selfUpdate.update":"Доступна новая версия Contao Manager {latest}.","ui.server.selfUpdate.manualUpdate":"Доступна новая версия Contao Manager {latest}. Ваш сервер не поддерживает автоматическое обновление, загрузите новую версию из {download}.","ui.server.selfUpdate.latest":"Вы используете последнюю версию {current}.","ui.server.selfUpdate.dev":"Тестовые сборки не поддерживает автоматическое обновление.","ui.server.selfUpdate.unsupported":"Доступна новая версия, но она не поддерживает вашу версию PHP.","ui.server.selfUpdate.button":"Запустить самообновление","ui.server.selfUpdate.continue":"Продолжить","ui.server.config.title":"Конфигурация сервера","ui.server.config.setup":"Настроить","ui.server.config.change":"Изменить","ui.server.config.save":"Сохранить","ui.server.config.cancel":"Отмена","ui.server.config.customOption":"Другие…","ui.server.config.description":"Для правильного выполнения фоновых задач, Contao Manager необходимо знать, где найти двоичный файл командной строки PHP и как выполнять команды, отделенные от веб-процесса.","ui.server.config.formTitle":"Конфигурация сервера","ui.server.config.formText":"Введите путь к вашему бинарному файлу PHP. Убедитесь, что бинарный файл той же версии PHP, что и ваш веб-процесс.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud позволяет устанавливать зависимости Composer даже если сервер не предоставляет достаточно локальной памяти. Имейте в виду, что информация о пакетах будет передана на облачный сервер, управляемый Contao Association.","ui.server.config.cloud":"Использовать Composer Resolver Cloud","ui.server.config.cli":"Бинарный файл PHP","ui.server.config.stateErrorCli":"На сервере не найден верный бинарный файл PHP.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud не поддерживается.","ui.server.config.stateSuccess":"Бинарный файл PHP {php_cli}.","ui.server.php_web.title":"Веб-процесс PHP","ui.server.php_web.below7":"Найдена версия PHP {version}. Перейдите на PHP 7 как можно скорее!","ui.server.php_web.success":"Найдена версия PHP {version}, известные проблемы не найдены.","ui.server.php_cli.title":"Интерфейс командной строки PHP","ui.server.php_cli.success":"Найдена версия PHP {version}, известные проблемы не найдены.","ui.server.composer.title":"Окружающая среда Composer","ui.server.composer.success":"Известных проблем не обнаружено.","ui.server.composer.install":"Зависимости Composer не установлены.","ui.server.composer.button":"Установить","ui.server.contao.title":"Установка Contao","ui.server.contao.setup":"Настроить","ui.server.contao.check":"Проверить базу данных","ui.server.contao.empty":"Установка Contao не найдена.","ui.server.contao.old":"Contao версии {version} не совместима с Contao Manager, пожалуйста, обновите установку Contao вручную.","ui.server.contao.found":"Найдена Contao {version} (версия API {api}).","ui.server.contao.connectionError":"Не удается подключиться к серверу базы данных.","ui.server.contao.connectionProblem":"Обнаружена проблема с базой данных.","ui.server.contao.missingUser":"Учетная запись администратора не найдена.","ui.setup.continue":"Продолжить","ui.setup.manager":"Запуск Contao Manager","ui.setup.cancel":"Отмена","ui.setup.welcome":"Приветствие","ui.setup.welcome1":"Этот мастер проведет вас через необходимые шаги для настройки и установки системы с открытым исходным кодом Contao CMS.","ui.setup.welcome2":"Если у вас есть какие-либо вопросы, найдите документацию, форумы, канал Slack и многое другое на странице {support}.","ui.setup.support":"поддержка сообщества","ui.setup.start":"Начать","ui.setup.complete":"Поздравляем!","ui.setup.complete1":"Contao {version} успешно установлена.","ui.setup.complete2":"Для завершения установки, откройте мастер установки, настройте подключение к базе данных и создайте учетную запись панели управления.","ui.setup.complete3":"Теперь можно приступить к созданию своего веб-сайта, с помощью панели управления Contao. Если нужны дополнительные расширения, перейдите в Contao Manager.","ui.setup.installTool":"Открыть мастер установки","ui.setup.login":"Войти в Contao","ui.setup.funding":"Свободное программное обеспечение означает \\"бесплатно\\" как \\"свобода слова\\", а не как \\"бесплатное пиво\\". Для такого проекта с открытым исходным кодом, как Contao, требуются суммы денег, которые не могут быть собраны одним человеком или компанией.\\nЕсли у Вас есть веб-сайт или Вы продаете веб-сайты, созданные с помощью Contao, мы были бы рады, если бы Вы внесли посильный финансовый вклад в продукт, на который опирается Ваш бизнес.","ui.setup.fundingLink":"Узнать больше","ui.setup.document-root.headline":"Настройка веб-сервера","ui.setup.document-root.warning":"Чтобы установить Contao с помощью Contao Manager, необходимо исправить корень документа на веб-сервере.","ui.setup.document-root.description1":"Contao использует отдельный каталог для общедоступных файлов, файлы приложений устанавливаются в родительский каталог. Contao не может быть установлен, если структура каталогов неверна или каталоги не пусты.","ui.setup.document-root.description2":"Если вы не знаете, как настроить корень документа, ознакомьтесь с документацией Contao или обратитесь к хостинг-провайдеру.","ui.setup.document-root.documentation":"Читать документацию","ui.setup.document-root.conflictsTitle":"Каталог установки не пустой","ui.setup.document-root.conflictsDirectory":"Корневой каталог будущей установки Contao не пустой, найдено {count} файла(ов), которые могут быть перезаписаны в процессе установки. Рекомендуется создать пустую структуру каталогов для установки Contao. Также вы можете удалить следующие файлы и проверить еще раз, уверены ли вы, что они не используются.","ui.setup.document-root.ignoreConflicts":"Я хочу установить Contao в непустой каталог. Я понимаю, что это может перезаписать любые существующие файлы в моем веб-пространстве.","ui.setup.document-root.check":"Проверить еще раз","ui.setup.document-root.create":"Создать каталоги","ui.setup.document-root.change":"Изменить каталоги","ui.setup.document-root.formTitle":"Настройка каталога","ui.setup.document-root.formText1":"Contao Manager может автоматически создать новую структуру каталогов на сервере.","ui.setup.document-root.formText2":"Необходимо вручную настроить новый корень документа (например, через панель администратора хостинга).","ui.setup.document-root.autoconfig":"Я понимаю, что мне нужно изменить конфигурацию сервера. Если не настроить корневой каталог документа, это сломает Contao Manager и откроет файлы конфигурации (включая данные учетной записи и пароли)!","ui.setup.document-root.directory":"Новый каталог","ui.setup.document-root.currentRoot":"Текущий корень документа","ui.setup.document-root.newRoot":"Новый корень документа","ui.setup.document-root.finish":"Каталоги установки","ui.setup.document-root.publicDir":"Использовать {dir} для общедоступных файлов (Contao {version})","ui.setup.document-root.directoryInvalid":"Введите допустимое имя каталога.","ui.setup.document-root.directoryExists":"Целевой каталог уже существует. Введите другое имя.","ui.setup.document-root.confirmation":"Contao Manager успешно создал каталог, необходимый для установки Contao. Теперь необходимо настроить корневой каталог документа на веб-сервере. Не перезагружайте эту страницу до тех пор.","ui.setup.document-root.reload":"Перезагрузить страницу","ui.setup.document-root.success":"Структура каталогов на веб-сервере настроена правильно!","ui.setup.document-root.installingProjectDir":"Файлы приложения будут установлены в {dir}.","ui.setup.document-root.installingPublicDir":"Общедоступные файлы будут установлены в {dir}.","ui.setup.document-root.installedProjectDir":"Файлы приложения устанавливаются в {dir}.","ui.setup.document-root.installedPublicDir":"Общедоступные файлы устанавливаются в {dir}.","ui.setup.create-project.headline":"Установка Contao","ui.setup.create-project.description":"Разработка Contao следует принципу {semver}, новая минорная версия выпускается каждые шесть месяцев. В настоящее время поддерживаются следующие релизы:","ui.setup.create-project.semver":"Семантическое управление версиями","ui.setup.create-project.latestTitle":"Последняя версия","ui.setup.create-project.ltsTitle":"Версия с долгосрочной поддержкой","ui.setup.create-project.latestQ1":"Последняя версия предлагает большинство функций с поддержкой до февраля {year}.","ui.setup.create-project.latestQ3":"Последняя версия предлагает большинство функций с поддержкой до августа {year}.","ui.setup.create-project.ltsText":"Текущая LTS-версия, если вы предпочитаете стабильность, предлагает долгосрочную поддержку до февраля {year}.","ui.setup.create-project.pltsText":"Предыдущая LTS-версия, по-прежнему имеет долгосрочную поддержку до февраля {year}.","ui.setup.create-project.requiresPHP":"Требуется PHP версии минимум {version}, у вас PHP {current}.","ui.setup.create-project.releaseplan":"Для получения дополнительной информации см. {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"План выпуска Contao","ui.setup.create-project.installed":"Contao {version} успешно установлена на сервере. Продолжайте настройку базы данных или запустите Contao Manager для установки другой версии.","ui.setup.create-project.formTitle":"Выберите дистрибутив","ui.setup.create-project.formText":"Выберите, какую версию следует установить.","ui.setup.create-project.version":"Версия","ui.setup.create-project.demo":"Установить демонстрационный веб-сайт Contao.","ui.setup.create-project.demoDescription":"Демонстрационный веб-сайт поможет вам познакомиться с Contao и всеми его основными функциями. Дополнительные темы можно найти в {store}.","ui.setup.create-project.coreOnly":"Минимальная установка (Только ядро)","ui.setup.create-project.noUpdate":"Пропустить установку (Только для экспертов!)","ui.setup.create-project.theme":"Contao тема","ui.setup.create-project.themeInstall":"Для установки темы Contao, используйте поиск или загрузите файл темы (.cto/.zip), который поддерживает установку через Contao Manager.","ui.setup.create-project.themeBuy":"Обязательно посетите официальный {store}.","ui.setup.create-project.themeStore":"Магазин тем Contao","ui.setup.create-project.themeUpload":"Загрузить файл темы (.cto/.zip)","ui.setup.create-project.themeInvalid":"Загруженный файл не является темой Contao или не поддерживает Contao Manager.","ui.setup.create-project.themeWarning":"Contao Manager не может определить, совместима ли эта тема с вашим сервером. Если у вас возникают вопросы, обратитесь к поставщику темы.","ui.setup.create-project.themeTitle":"Просмотр сведений о теме","ui.setup.create-project.themeDetails":"С этой темой будут установлены следующие зависимости и файлы.","ui.setup.create-project.themeRequire":"{count} зависимость | {count} зависимостей","ui.setup.create-project.themeFiles":"{count} файл | {count} файлов","ui.setup.create-project.theme.or":"или выполните поиск в общедоступных темах","ui.setup.create-project.theme.search":"Поиск тем","ui.setup.create-project.theme.more":"Больше тем","ui.setup.create-project.theme.empty":"Нет соответствующих тем {query}","ui.setup.create-project.theme.uploaded":"Файл темы загружен успешно.","ui.setup.create-project.theme.packageName":"Имя пакета","ui.setup.create-project.theme.version":"Версия","ui.setup.create-project.theme.authors":"Автор(ы)","ui.setup.create-project.install":"Установить","ui.setup.create-project.cancel":"Отмена","ui.setup.database-connection.headline":"Подключение к базе данных","ui.setup.database-connection.description":"Contao требуется базы данных MySQL (или совместимого форка, такого как MariaDB) для хранения страниц, контента, пользователей и других реляционных данных. Параметры подключения хранятся в файле {env} в корне проекта вашей установки Contao.","ui.setup.database-connection.formTitle":"Параметры подключения","ui.setup.database-connection.formText":"Введите URL-адрес базы данных или заполните поля имени пользователя, пароля, сервера и базы данных отдельно.","ui.setup.database-connection.url":"URL базы данных","ui.setup.database-connection.validUrl":"URL-адрес базы данных недействителен или соединение с сервером не выполнено.","ui.setup.database-connection.or":"или","ui.setup.database-connection.user":"Имя пользователя","ui.setup.database-connection.password":"Пароль","ui.setup.database-connection.server":"Сервер (:Порт)","ui.setup.database-connection.database":"Имя базы данных","ui.setup.database-connection.connected":"Соединение с базой данных {database} на {server} успешно установлено.","ui.setup.database-connection.error":"Ошибка подключения к базе данных.","ui.setup.database-connection.problem":"Contao обнаружила проблему с сервером базы данных.","ui.setup.database-connection.schemaTitle":"Схема базы данных","ui.setup.database-connection.migration":"Существует одна незавершенная миграция. | Есть {count} ожидающие миграции.","ui.setup.database-connection.schema":"Существует одна ожидающая обновления схема. | Есть {count} ожидающих обновления схем.","ui.setup.database-connection.noChanges":"Схема базы данных обновлена.","ui.setup.database-connection.check":"Проверить базу данных","ui.setup.database-connection.skip":"Пропустить","ui.setup.database-connection.save":"Сохранить","ui.setup.database-connection.change":"Изменить учетные данные","ui.setup.database-connection.restoreTitle":"Импорт базы данных","ui.setup.database-connection.restoreText":"Только что установленная тема содержит резервную копию базы данных. Восстановите базу данных, чтобы импортировать данные темы или пропустите этот шаг, чтобы начать с чистой установки Contao. | Только что установленная тема содержит несколько резервных копий базы данных. Выберите файл резервной копии для импорта данных темы или пропустите этот шаг, чтобы начать с чистой установки Contao.","ui.setup.database-connection.backup":"Резервное копирование текущей базы данных перед импортом","ui.setup.database-connection.backupWarning":"При импорте все данные в базе данных будут перезаписаны! Если база данных не пуста, сначала создайте резервную копию.","ui.setup.database-connection.restore":"Импорт базы данных темы","ui.setup.database-connection.restoreOption":"Резервная копия из {date} ({size})","ui.setup.database-connection.restored":"База данных темы была успешно импортирована. Продолжайте проверять схему базы данных.","ui.setup.backend-user.success":"В базе данных обнаружена учетная запись администратора для панели управления Contao. Используйте панель управления Contao, чтобы добавить больше пользователей.","ui.setup.backend-user.error":"Не удалось получить список пользователей. Для получения подробной информации см. вывод консоли.","ui.setup.backend-user.headline":"Учетная запись панели управления","ui.setup.backend-user.description":"Для управления своим веб-сайтом, вам необходимо иметь хотя бы одну учетную запись администратора в панели управления Contao. Имейте в виду, что эта учетная запись не связана с Contao Manager.","ui.setup.backend-user.formTitle":"Создать учетную запись","ui.setup.backend-user.formText":"Введите данные для новой учетной записи панели управления.","ui.setup.backend-user.username":"Имя пользователя","ui.setup.backend-user.name":"Имя","ui.setup.backend-user.email":"E-mail адрес","ui.setup.backend-user.emailInvalid":"Введите допустимый e-mail","ui.setup.backend-user.password":"Пароль","ui.setup.backend-user.passwordPlaceholder":"мин. 8 символов","ui.setup.backend-user.passwordLength":"Введите не менее 8 символов.","ui.setup.backend-user.create":"Добавить учетную запись","ui.task.headline":"Фоновая задача","ui.task.loading":"Загрузка сведений...","ui.task.created":"Загрузка сведений...","ui.task.active":"Подождите, пока Contao Manager выполняет задачи в фоновом режиме.","ui.task.complete":"Все операции успешно завершены. Дополнительные сведения см. в протоколе консоли.","ui.task.aborting":"Подождите, пока отменяются фоновые операции.","ui.task.stopped":"Некоторые фоновые операции были отменены. Проверьте протокол консоли.","ui.task.error":"Непредвиденная остановка фоновой операции. Проверьте протокол консоли.","ui.task.failed":"Contao Manager не удалось запустить фоновую задачу!","ui.task.failedDescription1":"Что-то пошло не так при попытке выполнения операций в фоновом режиме.","ui.task.failedDescription2":"Если это событие произойдет снова, ваш сервер может не поддерживаться.","ui.task.reportProblem":"Сообщить о проблеме","ui.task.sponsor":"Composer Cloud спонсируется {sponsor}","ui.task.buttonAudit":"Обновить базу данных","ui.task.buttonClose":"Закрыть","ui.task.buttonConfirm":"Подтвердить и закрыть","ui.task.buttonCancel":"Отмена","ui.task.confirmCancel":"Вы действительно хотите отменить задачу? Это может оставить вашу установку Contao в не работающем состоянии!","ui.task.autoclose":"Закрыть сведения об успешном выполнении задачи","ui.console.toggle":"Показать/Скрыть вывод консоли","ui.console.showLog":"Показать полный журнал консоли","ui.console.copyLog":"Скопировать журнал в буфер обмена","ui.migrate.headline":"Обновления базы данных","ui.migrate.migrationsOnly":"(только миграции)","ui.migrate.schemaOnly":"(только схема)","ui.migrate.loading":"Подождите, идет проверка базы данных...","ui.migrate.empty":"Отложенных миграций или обновлений схемы не обнаружено. Ваша база данных актуальна.","ui.migrate.emptyMigrations":"Отложенных миграций не найдено. Не забудьте проверить наличие обновлений схемы.","ui.migrate.emptySchema":"Отложенных обновлений схемы не найдено. Не забудьте проверить миграции.","ui.migrate.pending":"Ваша база данных не обновлена. Просмотрите приведенный ниже вывод консоли и внесите изменения.","ui.migrate.previousChanges":"Предыдущая миграция базы данных не была подтверждена.\\nПросмотрите приведенный ниже вывод консоли, а затем продолжите просмотр следующих изменений.","ui.migrate.previousComplete":"Предыдущая миграция базы данных не была подтверждена, просмотрите вывод консоли ниже.\\nОжидаемых изменений больше нет.","ui.migrate.appliedChanges":"Были применены обновления базы данных.\\nПросмотрите приведенный ниже вывод консоли, а затем продолжите просмотр следующих изменений.","ui.migrate.appliedComplete":"Были применены обновления базы данных.\\nБольше нет ожидающих миграций или обновлений схемы. База данных обновлена.","ui.migrate.problem":"Contao обнаружила проблему с сервером базы данных.\\nПросмотрите вывод консоли ниже, чтобы узнать, что необходимо исправить. | Contao обнаружила проблемы с сервером базы данных.\\nПросмотрите вывод консоли ниже, чтобы узнать, что необходимо исправить.","ui.migrate.warning":"Contao обнаружила неправильную конфигурацию сервера базы данных.\\nПредупреждения могут быть временно пропущены, но должны быть исправлены для обеспечения оптимальной производительности и целостности данных.","ui.migrate.error":"Изменения не могут быть применены. Возможно, ваша база данных была изменена, проверьте еще раз, чтобы повторить попытку.","ui.migrate.execute":"Выполнить","ui.migrate.close":"Закрыть","ui.migrate.confirm":"Подтвердить и закрыть","ui.migrate.cancel":"Отмена","ui.migrate.continue":"Продолжить","ui.migrate.setup":"Настроить","ui.migrate.skip":"Пропустить","ui.migrate.retry":"Проверить еще раз","ui.migrate.retryAll":"Проверить все","ui.migrate.withDeletes":"Выполнить все изменения базы данных, включая запросы DROP.","ui.migrate.migrationTitle":"Миграции базы данных","ui.migrate.schemaTitle":"Обновления схемы","ui.migrate.problemTitle":"Проблемы с базой данных","ui.migrate.warningTitle":"Предупреждения базы данных","ui.migrate.addTable":"Добавить таблицу {table}","ui.migrate.dropTable":"Удалить таблицу {table}","ui.migrate.addField":"Добавить поле {table}.{field}","ui.migrate.changeField":"Изменить поле {table}.{field}","ui.migrate.dropField":"Удалить поле {table}.{field}","ui.migrate.createIndex":"Создать индекс \\"{name}\\" в {table}","ui.migrate.dropIndex":"Удалить индекс \\"{name}\\" в {table}","ui.widget.mandatory":"Поле не должно быть пустым.","ui.widget.blankOption":"Пожалуйста, выберите…","ui.widget.showPassword":"Показать пароль","ui.widget.hidePassword":"Скрыть пароль","ui.error.title":"HTTP запрос для \\"{method} {url}\\" не выполнен.","ui.error.server500":"Вероятно, на сервере произошла непредвиденная ошибка. Проверьте файлы журнала вашего веб-сервера (Apache/Nginx) и журналы Contao Manager по адресу \\"contao-manager/logs\\".","ui.error.response":"Сервер вернул ответ с кодом состояния {status}.","ui.error.moreLink":"Больше информации","ui.error.support":"Поддержка Contao","ui.error.permission":"У вас нет разрешения на использование этой функции.","ui.footer.help":"Справка","ui.footer.reportProblem":"Сообщить о проблеме","ui.navigation.discover":"Обзор","ui.navigation.packages":"Пакеты","ui.navigation.tools":"Инструменты","ui.navigation.installTool":"Мастер установки","ui.navigation.backend":"Панель управления Contao","ui.navigation.debug":"Режим отладки Contao","ui.navigation.logViewer":"Просмотр журнала","ui.navigation.phpinfo":"Информация о PHP","ui.navigation.phpinfoLoading":"Загрузка информации о PHP...","ui.navigation.maintenance":"Обслуживание","ui.navigation.rebuildCache":"Восстановить кеш","ui.navigation.users":"Учетные записи","ui.navigation.systemCheck":"Проверка системы","ui.navigation.advanced":"Расширенный","ui.navigation.logout":"Выход","ui.maintenance.database.title":"Миграция баз данных и резервное копирование","ui.maintenance.database.description":"Миграция базы данных обеспечивает согласованность данных и схем таблиц.","ui.maintenance.database.migrations":"Одна отложенная миграция базы данных | {count} незавершенных миграций базы данных.","ui.maintenance.database.schemaUpdates":"Одно ожидающее обновление схемы | {count} ожидающих обновлений схемы","ui.maintenance.database.error":"Обнаружена проблема с базой данных.","ui.maintenance.database.warning":"Обнаружены предупреждения базы данных.","ui.maintenance.database.button":"Проверить базу данных","ui.maintenance.database.migrationOnly":"Проверить только миграции","ui.maintenance.database.schemaOnly":"Проверить только схему","ui.maintenance.database.installTool":"Открыть мастер установки","ui.maintenance.database.createBackup":"Создать резервную копию","ui.maintenance.database.backupUnsupported":"Резервное копирование баз данных не поддерживается вашей версией Contao.","ui.maintenance.database.backupList":"У вас есть одна резервная копия базы данных, созданная {date}. | У вас есть {count} резервных копий базы данных, последняя из которых была создана {date}.","ui.maintenance.database.backupEmpty":"На данный момент у вас нет резервных копий базы данных.","ui.maintenance.rebuildCache.title":"Кеш приложения","ui.maintenance.rebuildCache.description":"После изменения любого из файлов конфигурации требуется восстановление кеша приложений.","ui.maintenance.rebuildCache.rebuildProd":"Перестроить производственный кеш","ui.maintenance.rebuildCache.rebuildDev":"Перестроить кеш разработки","ui.maintenance.rebuildCache.clearProd":"Очистить производственный кеш","ui.maintenance.rebuildCache.clearDev":"Очистить кеш разработки","ui.maintenance.installTool.title":"Мастер установки Contao","ui.maintenance.installTool.description":"Мастер установки Contao автоматически блокируется, если вы введете неправильный пароль три раза подряд.","ui.maintenance.installTool.unlock":"Разблокировать мастер установки","ui.maintenance.installTool.lock":"Заблокировать мастер установки","ui.maintenance.dumpAutoload.title":"Загрузчик класса Composer","ui.maintenance.dumpAutoload.description":"Автозагрузчик Composer отвечает за загрузку классов PHP. Автозагрузчик должен быть сброшен после добавления пользовательских пространств имен в корневой файл composer.json.","ui.maintenance.dumpAutoload.button":"Дамп автозапуска","ui.maintenance.composerInstall.title":"Зависимости Composer","ui.maintenance.composerInstall.description":"Зависимости Composer находятся в каталоге {vendor}, в корне приложения. Повторная установка зависимостей может потребоваться после различных манипуляций или ручной загрузки файла {composerLock}.","ui.maintenance.composerInstall.button":"Запустить установщик","ui.maintenance.composerInstall.update":"Запустить обновление Composer","ui.maintenance.composerCache.title":"Кеш Composer","ui.maintenance.composerCache.description":"Composer кеширует загруженные пакеты для улучшения производительности. Если у вас есть проблемы, например, испорченные файлы, попробуйте очистить кеш Composer, чтобы запустить новую загрузку.","ui.maintenance.composerCache.button":"Очистить кеш","ui.maintenance.maintenanceMode.title":"Режим обслуживания","ui.maintenance.maintenanceMode.description":"Перевод Contao в режим обслуживания отобразит шаблон \\"503 Service Unavailable\\" для веб-сайта.","ui.maintenance.maintenanceMode.enable":"Включить","ui.maintenance.maintenanceMode.disable":"Выключить","ui.maintenance.debugMode.title":"Режим отладки","ui.maintenance.debugMode.description":"Активируйте режим отладки, задав имя пользователя и пароль для точки входа {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Активируйте режим отладки, установив файл отладки cookie для текущего домена.","ui.maintenance.debugMode.activate":"Активировать","ui.maintenance.debugMode.deactivate":"Деактивировать","ui.maintenance.debugMode.credentials":"Полномочия","ui.maintenance.debugMode.user":"Введите имя пользователя для режима отладки.","ui.maintenance.debugMode.password":"Введите пароль для режима отладки.","ui.maintenance.opcodeCache.title":"Кеш Opcode","ui.maintenance.opcodeCache.description":"Opcode кеширует PHP-файлы в веб-процессе для более быстрого выполнения. Он должен быть удален при определенных обстоятельствах, если файлы не распознаются после изменения.","ui.maintenance.opcodeCache.button":"Усечение кеша","ui.maintenance.safeMode":"Недоступно в безопасном режиме","ui.maintenance.unsupported":"Не поддерживается этой версией Contao","ui.packages.updateButton":"Обновить пакеты","ui.packages.searchButton":"Поиск пакетов","ui.packages.searchPlaceholder":"Поиск пакетов...","ui.packages.uploadOverlay":"Перетащите файлы для загрузки","ui.packages.uploadButton":"Загрузить пакеты","ui.packages.uploadMessage":"У вас одна неподтвержденная загрузка. | У вас неподтвержденных загрузок {count}.","ui.packages.uploadApply":"Подтвердить загрузки","ui.packages.uploadReset":"Удалить загрузки","ui.packages.uploadIncomplete":"Этот файл не был загружен полностью. Удалите его и попробуйте еще раз.","ui.packages.uploadDuplicate":"Этот файл загружен несколько раз. Удалите дубликаты.","ui.packages.uploadInstalled":"Этот файл уже установлен. Удалите дубликаты.","ui.packages.uploadUnsupported":"Загрузка не поддерживается текущей установкой. Убедитесь, что установлено расширение PHP ZIP и не забудьте обновить зависимости.","ui.packages.changesMessage":"У вас одно неподтвержденное изменение. | У вас неподтвержденных изменений {count}.","ui.packages.changesDryrun":"Пробный прогон","ui.packages.changesApply":"Применить изменения","ui.packages.changesApplyAll":"Обновить все пакеты","ui.packages.changesDryrunAll":"Пробный прогон всех пакетов","ui.packages.changesReset":"Сброс изменений","ui.packages.changesReview":"Обзор изменений","ui.packagelist.loading":"Загрузка...","ui.packagelist.uploads":"Загрузки","ui.packagelist.added":"Новые пакеты","ui.packagelist.installed":"Установленные пакеты","ui.package.hintRevert":"Отменить изменения","ui.package.hintNoupdate":"Не обновлять","ui.package.hintConstraint":"Этот пакет будет установлен с ограничением {constraint} при применении изменений.","ui.package.hintConstraintBest":"Этот пакет будет установлен в наилучшей доступной версии при применении изменений.","ui.package.hintConstraintChange":"Ограничение этого пакета будет изменено с \\"{from}\\" на \\"{to}\\" при применении изменений.","ui.package.hintConstraintUpdate":"Этот пакет будет обновлен при применении изменений.","ui.package.hintAdded":"Этот пакет будет установлен при применении изменений.","ui.package.hintRemoved":"Этот пакет будет удален при применении изменений.","ui.package.requiredTitle":"добавлено вручную","ui.package.requiredText":"Этот пакет необходим в composer.json, но он не установлен.","ui.package.removedTitle":"удалено вручную","ui.package.removedText":"Этот пакет удален из вашего composer.json.","ui.package.installed":"Установлена:","ui.package.version":"Версия {version}","ui.package.additionalDownloads":"Загрузок {count} | Загрузок {count}","ui.package.additionalStars":"Звёзд {count} | Звёзд {count}","ui.package.editConstraint":"Редактировать","ui.package.uploadConstraint":"Это ограничение определяется загруженным пакетом.","ui.package.updateButton":"Обновить","ui.package.removeButton":"Удалить","ui.package.installButton":"Добавить пакет","ui.package.installButtonShort":"Добавить","ui.package.detailsButton":"Сведения","ui.package.latestConstraint":"последняя версия","ui.package.update":"Доступно обновление","ui.package.updateLatest":"последняя версия","ui.package.updateAvailable":"{version} доступна","ui.package.updateUnknown":"неизвестная версия","ui.package.updateConstraint":"Доступна более новая версия, выходящая за рамки вашего ограничения версии.","ui.package.incompatible":"{package} не работает с Contao {constraint}.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Версия {version}","ui.cloudStatus.waitingTime":"Время ожидания","ui.cloudStatus.jobs":"Текущие задания","ui.cloudStatus.workers":"Рабочие","ui.cloudStatus.approx":"{minutes} мин","ui.cloudStatus.none":"ни один","ui.cloudStatus.short":"прим. {minutes} мин","ui.cloudStatus.long":"прим. {minutes} мин {seconds} сек","ui.cloudStatus.error":"Не удалось получить статус облака Resolver Composer. Вероятно, он не работает из-за проблем с обслуживанием или неполадок.","ui.cloudStatus.button":"Статус облака","ui.cloudStatus.refresh":"Обновить статус облака","ui.log-viewer.loading":"Загрузка...","ui.log-viewer.empty":"На вашем сервере нет файлов журнала.","ui.log-viewer.reload":"Перезагрузить","ui.log-viewer.file":"Файл журнала","ui.log-viewer.channel":"Канал","ui.log-viewer.channelTitle":"Канал, на который было зарегистрировано это сообщение.","ui.log-viewer.level":"Уровень","ui.log-viewer.levelTitle":"Уровень журнала или серьезность сообщения журнала.","ui.log-viewer.timeHeader":"Время","ui.log-viewer.messageHeader":"Сообщение","ui.log-viewer.showContext":"Показать контекст","ui.log-viewer.hideContext":"Скрыть контекст","ui.log-viewer.showExtra":"Показать дополнительное","ui.log-viewer.hideExtra":"Скрыть дополнительное","ui.log-viewer.more":"Загрузить больше...","ui.log-viewer.download":"Загрузка","ui.log-viewer.downloadTitle":"Загрузка файла \\"{file}\\"","ui.log-viewer.prodEnvironment":"Рабочая среда","ui.log-viewer.devEnvironment":"Среда разработки (режим отладки)","ui.user-manager.loading":"Загрузка пользователей…","ui.user-manager.changePassword":"Изменить пароль","ui.user-manager.setupTotp":"Настройка двухфакторной авторизации","ui.user-manager.disableTotp":"Отключить двухфакторную авторизацию","ui.user-manager.invite":"Пригласить пользователя","ui.user-manager.delete":"Удалить","ui.user-manager.deleteConfirm":"Вы действительно хотите удалить пользователя \\"{username}\\"?","ui.user-manager.deleted":"Пользователь {username} успешно удален","ui.user-manager.passwordHeadline":"Изменить пароль","ui.user-manager.passwordText":"Чтобы изменить пароль, введите текущий и новый пароль в соответствующие поля.","ui.user-manager.currentPassword":"Текущий пароль","ui.user-manager.newPassword":"Новый пароль","ui.user-manager.passwordPlaceholder":"мин. 8 символов","ui.user-manager.submitPassword":"Отправить","ui.user-manager.passwordChanged":"Ваш пароль был успешно изменён.","ui.user-manager.passwordError":"Этот пароль неверный.","ui.user-manager.inviteHeadline":"Пригласить пользователя","ui.user-manager.inviteText":"Если вам нужно несколько учётных записей для Contao Manager, вы можете создать здесь ссылку-приглашение. Поделитесь этой ссылкой или используйте её на другом устройстве, чтобы создать новую учётную запись с заданными правами доступа.","ui.user-manager.inviteSuccess1":"Создана новая ссылка-приглашение. URL-адрес ниже можно использовать для создания новой учетной записи пользователя для Contao Manager. Приглашение истекает {expires} (через неделю).","ui.user-manager.inviteSuccess2":"Скопируйте ссылку в буфер обмена. Эта ссылка сработает только один раз, и вы больше не сможете её увидеть после закрытия этого диалогового окна.","ui.user-manager.createInvitation":"Создать ссылку-приглашение","ui.user-manager.clipboard":"Копировать в буфер обмена","ui.user-manager.permissions":"Узнать о разрешениях","ui.user-manager.cancel":"Отмена","ui.user-manager.close":"Закрыть","ui.user-manager.you":"Вы","ui.totp.headline":"Двухфакторная авторизация","ui.totp.setupQr":"Пожалуйста, отсканируйте QR-код с помощью вашего приложения для 2FA/TOTP.","ui.totp.setupCode":"Если вы не можете отсканировать QR-код, введите этот ключ вместо него:","ui.totp.codeLabel":"Проверочный код","ui.totp.codeDescription":"Пожалуйста, введите проверочный код, сгенерированный с помощью вашего приложения для 2FA/TOTP.","ui.totp.disableText":"Пожалуйста, введите проверочный код для отключения двухфакторной авторизации.","ui.totp.invalid":"Проверочный код неверный.","ui.totp.enable":"Включить","ui.totp.disable":"Выключить","ui.totp.cancel":"Отмена","ui.totp.enabled":"Двухфакторная авторизация успешно включена.","ui.totp.disabled":"Двухфакторная авторизация успешно отключена.","ui.totp.setup":"Настройка двухфакторной авторизации","ui.totp.skip":"Пропустить двухфакторную авторизацию"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[139],{3139:function(t,e,s){s.r(e),s.d(e,{default:function(){return K}});var a=s(641),i=s(33),n=s(9472);const o={class:"database-migration__header"},l={class:"database-migration__headline"},r={key:0,class:"database-migration__text"},c={key:1,class:"database-migration__text"},u={class:"database-migration__description"},h={class:"database-migration__loading"},g={key:0,class:"database-migration__description"},m={key:1,class:"database-migration__description"},d={key:2,class:"database-migration__description"},p={class:"database-migration__actions"},b=["disabled"],y={class:"database-migration__actions"},k=["disabled"],_=["disabled"],w=["disabled"],$=["disabled"],v=["disabled"],C={class:"database-migration__description"},E={class:"database-migration__actions"},f={key:0,class:"database-migration__actions"};function x(t,e,s,x,A,D){const L=(0,a.g2)("loading-spinner"),T=(0,a.g2)("loading-button"),X=(0,a.g2)("check-box"),R=(0,a.g2)("console-output"),F=(0,a.g2)("boxed-layout");return(0,a.uX)(),(0,a.Wv)(F,{wide:!0,slotClass:"database-migration"},{default:(0,a.k6)((()=>[(0,a.Lk)("header",o,[e[7]||(e[7]=(0,a.Lk)("img",{src:n,width:"80",height:"80",alt:"",class:"database-migration__icon"},null,-1)),(0,a.Lk)("h1",l,(0,i.v_)(t.$t("ui.migrate.headline")),1),"migrations-only"===t.type?((0,a.uX)(),(0,a.CE)("p",r,(0,i.v_)(t.$t("ui.migrate.migrationsOnly")),1)):(0,a.Q3)("",!0),"schema-only"===t.type?((0,a.uX)(),(0,a.CE)("p",c,(0,i.v_)(t.$t("ui.migrate.schemaOnly")),1)):(0,a.Q3)("",!0),t.checking?((0,a.uX)(),(0,a.CE)(a.FK,{key:2},[(0,a.Lk)("p",u,(0,i.v_)(t.$t("ui.migrate.loading")),1),(0,a.Lk)("div",h,[(0,a.bF)(L)])],64)):D.isEmpty?((0,a.uX)(),(0,a.CE)(a.FK,{key:3},["migrations-only"===t.type?((0,a.uX)(),(0,a.CE)("p",g,(0,i.v_)(t.$t("ui.migrate.emptyMigrations")),1)):"schema-only"===t.type?((0,a.uX)(),(0,a.CE)("p",m,(0,i.v_)(t.$t("ui.migrate.emptySchema")),1)):((0,a.uX)(),(0,a.CE)("p",d,(0,i.v_)(t.$t("ui.migrate.empty")),1)),(0,a.Lk)("div",p,["migrations-only"===t.type||"schema-only"===t.type?((0,a.uX)(),(0,a.CE)("button",{key:0,class:"widget-button widget-button--primary",disabled:t.closing,onClick:e[0]||(e[0]=t=>D.checkAll())},(0,i.v_)(t.$t("ui.migrate.retryAll")),9,b)):(0,a.Q3)("",!0),(0,a.bF)(T,{loading:t.closing,onClick:D.close},{default:(0,a.k6)((()=>[(0,a.eW)((0,i.v_)(t.$t("ui.migrate.close")),1)])),_:1},8,["loading","onClick"])])],64)):!t.executing&&(D.isComplete||D.hasError||D.hasProblem)?((0,a.uX)(),(0,a.CE)(a.FK,{key:4},[((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(D.description.split("\n"),((t,e)=>((0,a.uX)(),(0,a.CE)("p",{class:"database-migration__description",key:e},(0,i.v_)(t),1)))),128)),(0,a.Lk)("div",y,["problem"===t.type?((0,a.uX)(),(0,a.CE)(a.FK,{key:0},[(0,a.bF)(T,{loading:t.closing,onClick:D.close},{default:(0,a.k6)((()=>[(0,a.eW)((0,i.v_)(t.$t("ui.migrate.cancel")),1)])),_:1},8,["loading","onClick"]),(0,a.Lk)("button",{class:"widget-button",disabled:t.closing,onClick:e[1]||(e[1]=function(){return D.setup&&D.setup(...arguments)})},(0,i.v_)(t.$t("ui.migrate.setup")),9,k),(0,a.Lk)("button",{class:"widget-button widget-button--primary",disabled:t.closing,onClick:e[2]||(e[2]=t=>D.checkAll())},(0,i.v_)(t.$t("ui.migrate.retry")),9,_)],64)):"warning"===t.type?((0,a.uX)(),(0,a.CE)(a.FK,{key:1},[(0,a.bF)(T,{loading:t.closing,onClick:D.close},{default:(0,a.k6)((()=>[(0,a.eW)((0,i.v_)(t.$t("ui.migrate.cancel")),1)])),_:1},8,["loading","onClick"]),(0,a.Lk)("button",{class:"widget-button widget-button",disabled:t.closing,onClick:e[3]||(e[3]=t=>D.checkAll())},(0,i.v_)(t.$t("ui.migrate.retry")),9,w),(0,a.Lk)("button",{class:"widget-button widget-button--primary",disabled:t.closing,onClick:e[4]||(e[4]=t=>D.checkAll(!0))},(0,i.v_)(t.$t("ui.migrate.skip")),9,$)],64)):t.hasChanges?((0,a.uX)(),(0,a.CE)(a.FK,{key:2},[(0,a.bF)(T,{loading:t.closing,onClick:D.close},{default:(0,a.k6)((()=>[(0,a.eW)((0,i.v_)(t.$t("ui.migrate.cancel")),1)])),_:1},8,["loading","onClick"]),(0,a.Lk)("button",{class:"widget-button widget-button--primary",disabled:t.closing,onClick:e[5]||(e[5]=t=>D.check())},(0,i.v_)(t.$t("ui.migrate.continue")),9,v)],64)):((0,a.uX)(),(0,a.Wv)(T,{key:3,loading:t.closing,onClick:D.close},{default:(0,a.k6)((()=>[(0,a.eW)((0,i.v_)(t.$t("ui.migrate.confirm")),1)])),_:1},8,["loading","onClick"]))])],64)):((0,a.uX)(),(0,a.CE)(a.FK,{key:5},[(0,a.Lk)("p",C,(0,i.v_)(t.$t("ui.migrate.pending")),1),(0,a.Lk)("div",E,[(0,a.bF)(T,{class:"database-migration__action",loading:t.closing,disabled:t.executing,onClick:D.close},{default:(0,a.k6)((()=>[(0,a.eW)((0,i.v_)(t.$t("ui.migrate.cancel")),1)])),_:1},8,["loading","disabled","onClick"]),(0,a.bF)(T,{class:"database-migration__action",color:"primary",loading:t.executing,disabled:t.closing,onClick:D.execute},{default:(0,a.k6)((()=>[(0,a.eW)((0,i.v_)(t.$t("ui.migrate.execute")),1)])),_:1},8,["loading","disabled","onClick"])]),t.hasDeletes?((0,a.uX)(),(0,a.CE)("div",f,[(0,a.bF)(X,{name:"withDeletes",label:t.$t("ui.migrate.withDeletes"),disabled:t.executing,modelValue:t.withDeletes,"onUpdate:modelValue":e[6]||(e[6]=e=>t.withDeletes=e)},null,8,["label","disabled","modelValue"])])):(0,a.Q3)("",!0)],64))]),!t.checking&&t.operations&&t.operations.length?((0,a.uX)(),(0,a.Wv)(R,{key:0,class:"database-migration__main",title:D.consoleTitle,operations:t.operations,"console-output":D.console,"force-console":D.hasProblem},null,8,["title","operations","console-output","force-console"])):(0,a.Q3)("",!0)])),_:1})}s(4114),s(8111),s(7588),s(1701);var A=s(6278),D=s(4335),L=s(707),T=s(5404),X=s(4999),R=s(6966),F=s(6774),O=s(3018),W={components:{BoxedLayout:T.A,LoadingSpinner:X.A,LoadingButton:R.A,ConsoleOutput:F.A,CheckBox:O.A},data:()=>({type:null,status:"",changes:null,hasDeletes:!1,operations:null,hash:null,withDeletes:!1,previousResult:!0,checking:!0,executing:!1,closing:!1}),computed:{...(0,A.aH)("server/database",["supported"]),...(0,A.aH)(["setupStep"]),...(0,A.L8)("server/database",["hasChanges"]),isEmpty:t=>"active"!==t.status&&t.operations&&!t.operations.length,isComplete:t=>"complete"===t.status,hasError:t=>"error"===t.status,hasProblem:t=>"problem"===t.type||"warning"===t.type,description(){return"problem"===this.type?this.$tc("ui.migrate.problem",this.operations?.length||0):"warning"===this.type?this.$t("ui.migrate.warning"):this.previousResult&&this.hasChanges?this.$t("ui.migrate.previousChanges"):this.previousResult?this.$t("ui.migrate.previousComplete"):this.isComplete&&this.hasChanges?this.$t("ui.migrate.appliedChanges"):this.isComplete?this.$t("ui.migrate.appliedComplete"):this.$t("ui.migrate.error")},consoleTitle(){switch(this.type){case"migrations":case"migrations-only":return this.$t("ui.migrate.migrationTitle");case"schema":case"schema-only":return this.$t("ui.migrate.schemaTitle");case"problem":return this.$t("ui.migrate.problemTitle");case"warning":return this.$t("ui.migrate.warningTitle")}return""},console(){if(!this.changes||!this.changes.length)return"";let t="";return this.changes.forEach((e=>{t+=`${e.name}\n`})),t}},methods:{async poll(t){if(201===t.status)return new Promise((t=>{setTimeout((async()=>{await this.poll(await D.A.get("api/contao/database-migration")),t()}),1e3)}));const e=t.data;return this.changes&&!e.status||(this.type=e.type,this.status=e.status,this.hash=e.hash,this.changes=e.operations),e.status&&"active"!==e.status?void 0:new Promise((t=>{setTimeout((async()=>{await this.poll(await D.A.get("api/contao/database-migration")),t()}),1e3)}))},async execute(){this.executing=!0,await D.A.put("api/contao/database-migration",{type:this.type,hash:this.hash,withDeletes:this.withDeletes&&this.hasDeletes}),setTimeout((async()=>{await this.poll(await D.A.get("api/contao/database-migration")),await this.$store.dispatch("server/database/get",!1),this.executing=!1}),1e3)},async check(){let t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.checking=!0;const e=this.type||this.$store.state.migrationsType;this.status&&(this.type=null,this.status="",this.changes=null,this.hash=null,await D.A.delete("api/contao/database-migration"));let s=await D.A.get("api/contao/database-migration");204===s.status&&(this.previousResult=!1,s=await D.A.put("api/contao/database-migration",{type:e,skipWarnings:t})),await this.poll(s),await D.A.delete("api/contao/database-migration"),this.checking=!1},checkAll(){let t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.type=null,this.check(t)},generateStatus(t,e){return e?`~${t}~`:t},async close(){this.closing=!0,await D.A.delete("api/contao/database-migration"),await this.$store.dispatch("server/database/get",!1),this.setupStep>0?(await this.$store.dispatch("server/adminUser/get",!1),this.$store.commit("setView",L.A.SETUP)):this.$store.commit("setView",L.A.READY),this.closing=!1},async setup(){this.$store.commit("setup",3)},updateOperations(){if(this.hasDeletes=!1,this.operations=null,!this.changes)return;if(this.hasProblem)return void(this.operations=this.changes.map((t=>({status:t.status,summary:t.name,details:t.message,console:t.trace}))));if("migrations"===this.type||"migrations-only"===this.type)return void(this.operations=this.changes.map((t=>({status:t.status,summary:t.name,details:t.message}))));const t=[];this.changes.forEach((e=>{let s;if(s=new RegExp("^CREATE TABLE ([^ ]+) .+$").exec(e.name),s)t.push({status:e.status,summary:this.$t("ui.migrate.addTable",{table:s[1]}),details:e.message,console:e.name});else{if(s=new RegExp("^DROP TABLE (.+)$").exec(e.name),s)return t.push({status:this.withDeletes?e.status:"skipped",summary:this.generateStatus(this.$t("ui.migrate.dropTable",{table:s[1]}),!this.withDeletes),details:e.message,console:e.name}),void(this.hasDeletes=!0);if(s=new RegExp("^CREATE INDEX ([^ ]+) ON ([^ ]+) \\(([^)]+)\\)$").exec(e.name),s)t.push({status:e.status,summary:this.$t("ui.migrate.createIndex",{name:s[1],table:s[2]}),details:e.message||s[3],console:e.name});else{if(s=new RegExp("^DROP INDEX ([^ ]+) ON ([^ ]+)$").exec(e.name),s)return t.push({status:this.withDeletes?e.status:"skipped",summary:this.generateStatus(this.$t("ui.migrate.dropIndex",{name:s[1],table:s[2]}),!this.withDeletes),details:e.message,console:e.name}),void(this.hasDeletes=!0);if(s=new RegExp("^ALTER TABLE ([^ ]+) (.+)$").exec(e.name),s){const a=s[1],i={status:e.status,summary:[],details:[],console:e.name};e.message&&i.details.push(e.message);let n="";s[2].split("'").forEach(((t,e)=>{n=e%2?`${n}'${t.replace(",","%comma%")}'`:`${n}${t}`}));const o=n.split(",").map((t=>t.trim().replace("%comma%",",")));let l=0;return o.forEach((t=>{let s;return s=new RegExp("^ADD ([^ ]+) (.+)$").exec(t),s?(i.summary.push(this.$t("ui.migrate.addField",{table:a,field:s[1]})),void(e.message||i.details.push(s[2]))):(s=new RegExp("^CHANGE ([^ ]+) ([^ ]+) (.+)$").exec(t),s?(i.summary.push(this.$t("ui.migrate.changeField",{table:a,field:s[1]})),void(e.message||i.details.push(s[3]))):(s=new RegExp("^DROP (.+)$").exec(t),s?(i.summary.push(this.generateStatus(this.$t("ui.migrate.dropField",{table:a,field:s[1]}),!this.withDeletes)),i.details.push(""),this.hasDeletes=!0,void l++):(i.summary.push(`ALTER TABLE ${a} ${t}`),void i.details.push(""))))})),l===o.length&&(i.status=this.withDeletes?e.status:"skipped"),void t.push(i)}t.push({status:e.status,summary:e.name,details:e.message,console:e.name}),this.hasDeletes=!0}}})),this.operations=t}},watch:{changes(){this.updateOperations()},withDeletes(){this.updateOperations()}},mounted(){this.check()}},P=s(6262);const S=(0,P.A)(W,[["render",x]]);var K=S},9472:function(t,e,s){t.exports=s.p+"img/database.7f0a8c49.svg"}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[958],{2958:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Kevreadur diasur !!","ui.app.httpsDescription":"Hep HTTPS ho roadennoù kuzhut a vo treuzkaset dirinegañ.","ui.app.httpsLink":"Muioc\'h a ditouroù","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.loading":"O kargañ Contao Manager ...","ui.app.apiError":"Statud API dic\'hortoz","ui.app.configSecurity1":"SECURITY ALERT !!! Unprotected config directory detected","ui.app.configSecurity2":"The Contao Manager has detected that its config files are publicly accessible. All operations are disabled until the directory is secured, otherwise an attacker could access sensitive data of your installation.\\n\\nTo fix this issue, make sure to prevent access to the \\"contao-manager\\" directory on your server. To learn how to do this, please refer to the manual of your webserver or contact your hosting provider.","ui.account.welcome":"Degemer mat","ui.account.intro1":"Welcome to the Contao Manager, a universal tool to install and manage Contao Open Source CMS. If you are new to it, please {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} to get started","ui.account.introManual":"read the manual","ui.account.intro2":"If you encounter any problems, check {ourGithubIssues} and feel free to create new one for anything that has not been reported yet.","ui.account.introIssues":"our GitHub issues","ui.account.headline":"Kont implijer","ui.account.description":"Da verañ ho staliadur, krouit ur gont mar plij evit Contao Manager. Deoc\'h da c\'houzout n\'eo ket liammet d\'ar c\'hontoù Contao back end pe front end.","ui.account.username":"Anv-implijer","ui.account.password":"Ger-tremen","ui.account.passwordConfirm":"Adskrivit ar ger-tremen","ui.account.passwordPlaceholder":"min. 8 arouezenn","ui.account.passwortLength":"Ebarzhit da vihanañ 8 arouezenn.","ui.account.passwortDifferent":"Ar ger-tremen na glot ket gant ar c\'hadarnadur.","ui.account.submit":"Krouiñ ur gont","ui.account.contribute1":"Contao and the Contao Manager are sponsored by the non-profit Contao Association.","ui.account.contribute2":"Please consider contributing to open source by {donate}.","ui.account.contributeDonate":"making a donation","ui.login.headline":"Kevreañ","ui.login.description":"Kevreit evit merañ ho staliadur.","ui.login.username":"Anv-implijer","ui.login.password":"Ger-tremen","ui.login.forgotPassword":"Ankouaet ho ker-tremen?","ui.login.button":"Kevreañ","ui.login.locked":"Access has been denied because the Contao Manager is locked. To unlock, delete the {lockFile} file in your Contao root directory.","ui.logout.headline":"Session Timeout","ui.logout.warning":"Your have been inactive for more than 25 minutes. For security reasons your session will be terminated shortly.","ui.logout.expired":"Your session was automatically terminated because you have been inactive for more than 30 minutes.","ui.logout.renew":"Keep Logged In","ui.logout.logout":"Digevreañ","ui.logout.login":"Back To Login","ui.oauth.error":"Invalid OAuth attempt. Check the request parameters.","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Remote Authentication","ui.oauth.description":"The following application or service is requesting remote access to your Contao Manager instance.","ui.oauth.domain":"Before allowing access, make sure you know this URL and trust its owner!","ui.oauth.allow":"Allow Access","ui.oauth.deny":"Deny Access","ui.boot.headline":"Gwiriadur ar reizhad","ui.boot.description":"Please wait, we are analyzing your server …","ui.boot.issue1":"Kudennoù diguzhet en ur staliañ","ui.boot.issue2":"Your installation has issues that have to be fixed before the Contao Manager can be used.","ui.boot.run":"Loc\'hañ Contao Manager","ui.recovery.headline":"System Recovery","ui.recovery.description":"The Contao Manager detected files that look like Contao, but the Command Line Interface does not work as expected.","ui.recovery.console":"Console Output","ui.recovery.repairOptions":"Please choose an option to repair your installation.","ui.recovery.repairHeadline":"Automatic Repair","ui.recovery.repairDescription":"Attempts to automatically repair the installation by rebuilding the application cache and re-installing the Composer packages.","ui.recovery.repairWarning":"Any modifications to the vendor files might be deleted in the process!","ui.recovery.repairFailed":"Automatic repair was not successful. Try the Safe Mode to manually repair the installation.","ui.recovery.repairButton":"Run System Repair","ui.recovery.safeModeHeadline":"Safe Mode","ui.recovery.safeModeDescription":"Launching the Contao Manager in Safe Mode allows to manage packages and run certain maintenance tasks, but features that rely on a working Contao installation will not be available.","ui.recovery.safeModeButton":"Launch in Safe Mode","ui.server.pending":"Waiting …","ui.server.running":"Oc\'h analizañ ...","ui.server.error":"Check failed due to an unexpected response from the server.","ui.server.details":"Munudoù","ui.server.prerequisite":"Check cancelled due to a missing prerequisite.","ui.server.selfUpdate.title":"Hizivadurioù Contao Manager","ui.server.selfUpdate.update":"Ur stumm nevez eus Contao Managaer a zo hegerz: {latest}.","ui.server.selfUpdate.manualUpdate":"A new Contao Manager version {latest} is available. Your server does not support automatic updates, please download the new version from {download}.","ui.server.selfUpdate.latest":"You are using the latest version {current}.","ui.server.selfUpdate.dev":"Development builds do not support automatic updates.","ui.server.selfUpdate.unsupported":"A new version is available but it does not support your PHP version.","ui.server.selfUpdate.button":"Seveniñ an em-hizivaat","ui.server.selfUpdate.continue":"Continue","ui.server.config.title":"Kefluniadur ar servijer","ui.server.config.setup":"Kefluniañ","ui.server.config.change":"Cheñch","ui.server.config.save":"Enrollañ","ui.server.config.blankOption":"Diuzit mar plij ...","ui.server.config.customOption":"Traoù all ...","ui.server.config.description":"To correctly run background tasks, the Contao Manager needs to know where to find the PHP command line binary and how to run commands separated from the web process.","ui.server.config.formTitle":"Kefluniadur ar servijer","ui.server.config.formText":"Please enter the path to your PHP binary. Make sure the binary is the same PHP version as your web process.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"The Composer Resolver Cloud allows to install Composer dependencies even if your server does not provide enough local memory. Please be aware that your package information will be transmitted to a cloud server operated by the Contao Association.","ui.server.config.cloud":"Use the Composer Resolver Cloud","ui.server.config.cli":"PHP daouel","ui.server.config.stateErrorCli":"No valid PHP binary was found on the server.","ui.server.config.stateErrorCloud":"The Composer Resolver Cloud is not supported.","ui.server.config.stateSuccess":"PHP binary at {php_cli}.","ui.server.php_web.title":"PHP Web Process","ui.server.php_web.below7":"Found PHP version {version}. Please switch to PHP 7 as soon as possible!","ui.server.php_web.success":"Found PHP version {version}, no known issues found.","ui.server.php_cli.title":"PHP Command Line Interface","ui.server.php_cli.success":"Found PHP version {version}, no known issues found.","ui.server.composer.title":"Endro kompozer","ui.server.composer.success":"N\'eus bet kavet kudenn ebet.","ui.server.composer.install":"Composer dependencies are not installed.","ui.server.composer.button":"Run Composer","ui.server.composer.safeMode":"Run Safe Mode","ui.server.contao.title":"Staliadur Contao","ui.server.contao.setup":"Setup","ui.server.contao.empty":"Staliadur Contao ebet bet kavet","ui.server.contao.old":"Contao version {version} is not compatible with the Contao Manager, please update your installation manually.","ui.server.contao.found":"Kavet Contao {version} (API stumm {api}).","ui.server.contao.headline":"Kefluniadur Contao","ui.server.contao.description":"Welcome to the setup process of your Contao Open Source CMS. You can choose between two versions to install.","ui.server.contao.publicDir":"Use {dir} for public files (for Contao {version})","ui.server.contao.ltsTitle":"Skor war hir amzer","ui.server.contao.ltsText":"The LTS version has an extended support period of up to four years.","ui.server.contao.latestTitle":"Diwezhatañ","ui.server.contao.latestText":"A new latest version is released every six months in February and August.","ui.server.contao.noLatest":"Requires at least PHP {version}.","ui.server.contao.releaseplan":"See the {contaoReleasePlan} for detailed information.","ui.server.contao.releaseplanLink":"Contao Release Plan","ui.server.contao.formTitle":"Staliadur Contao","ui.server.contao.formText":"Select the Contao version to install.","ui.server.contao.version":"Stumm","ui.server.contao.coreOnly":"Initial Setup","ui.server.contao.coreOnlyNo":"Full Installation (News, Calendar, etc.)","ui.server.contao.coreOnlyYes":"Minimal Installation (Core only)","ui.server.contao.coreOnlyFeatures":"What\'s the difference?","ui.server.contao.noUpdate":"Skip Installation (Expert Only!)","ui.server.contao.install":"Finish","ui.server.docroot.headline":"Webserver Setup","ui.server.docroot.warning":"To install Contao through the Contao Manager, you have to fix the document root on the web server.","ui.server.docroot.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed right now, because your folder structure is not correct or the folders are not empty.","ui.server.docroot.description2":"If you don\'t know how to configure your document root, please read the Contao documentation or contact your hosting provider.","ui.server.docroot.documentation":"Read the Documentation","ui.server.docroot.conflictsTitle":"Installation directory not empty","ui.server.docroot.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and reload the page if you are sure they are unused.","ui.server.docroot.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.server.docroot.create":"Create directories","ui.server.docroot.formTitle":"Directory Setup","ui.server.docroot.formText1":"The Contao Manager can automatically create a new directory structure on the server.","ui.server.docroot.formText2":"You will need to manually configure the new document root (e.g. through a hosting admin panel).","ui.server.docroot.autoconfig":"I understand that I have to change my server configuration. Not configuring the document root will break the Contao Manager and expose configuration files (including account details and passwords)!","ui.server.docroot.directory":"New Directory","ui.server.docroot.currentRoot":"Current Document Root","ui.server.docroot.newRoot":"New Document Root","ui.server.docroot.finish":"Setup Directories","ui.server.docroot.directoryInvalid":"Please enter a valid directory name.","ui.server.docroot.directoryExists":"The target directory already exists. Please enter a different name.","ui.server.docroot.confirmation":"The Contao Manager has successfully created the necessary directory for your Contao installation. You now have to configure the document root on your web server. Do not reload this page until then.","ui.server.docroot.reload":"Reload Page","ui.task.headline":"Background Task","ui.task.loading":"Loading details …","ui.task.created":"Loading details …","ui.task.active":"Please wait while the Contao Manager is running task operations in the background.","ui.task.complete":"All operations are completed successfully. Check the console output for details.","ui.task.aborting":"Please wait while the background operations are being cancelled.","ui.task.stopped":"Some background operations were cancelled. Please check the console output.","ui.task.error":"A background operation stopped unexpectedly. Please check the console output.","ui.task.failed":"The Contao Manager failed to start a background task!","ui.task.failedDescription1":"Something went wrong while trying to execute operations in the background.","ui.task.failedDescription2":"If this happens again, your server might not be supported.","ui.task.reportProblem":"Danevelliñ ur gudenn","ui.task.buttonAudit":"Update Database","ui.task.buttonClose":"Serriñ","ui.task.buttonConfirm":"Kadarnaat & ha serriñ","ui.task.buttonCancel":"Nullañ","ui.task.confirmCancel":"Are you sure to cancel this task? This might leave your Contao installation in a broken state!","ui.task.autoclose":"Close task details on success","ui.console.toggle":"Show/Hide Console Output","ui.console.showLog":"Show full console log","ui.console.copyLog":"Copy log to clipboard","ui.widget.mandatory":"Ar vaezienn-mañ n\'hall ket bezañ goullo.","ui.error.title":"HTTP request for \\"{method} {url}\\" failed.","ui.error.server500":"Looks like an unexpected error happened on your server. Please check the log files of your web server (Apache/Nginx) and the Contao Manager logs at \\"contao-manager/logs\\".","ui.error.response":"The server returned a response with status code {status}.","ui.error.moreLink":"Muioc\'h a ditouroù","ui.error.support":"Contao Support","ui.footer.help":"Skoazell","ui.footer.reportProblem":"Danevelliñ ur gudenn","ui.navigation.discover":"Discover","ui.navigation.packages":"Pakadoù","ui.navigation.tools":"Ostilhoù","ui.navigation.installTool":"Staliañ an ostilh","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Contao Debug Mode","ui.navigation.phpinfo":"PHP Information","ui.navigation.maintenance":"Trezalc\'h","ui.navigation.rebuildCache":"Adsevel ar c\'hrubuilh","ui.navigation.systemCheck":"Gwiriadur ar reizhad","ui.navigation.advanced":"Araokaet","ui.navigation.logout":"Digevreañ","ui.maintenance.rebuildCache.title":"Application Cache","ui.maintenance.rebuildCache.description":"Rebuilding the application cache is required after modifying any of the configuration files.","ui.maintenance.rebuildCache.rebuildProd":"Rebuild Production Cache","ui.maintenance.rebuildCache.rebuildDev":"Rebuild Development Cache","ui.maintenance.rebuildCache.clearProd":"Clear Production Cache","ui.maintenance.rebuildCache.clearDev":"Clear Development Cache","ui.maintenance.installTool.title":"Contao Install Tool","ui.maintenance.installTool.description":"The Contao Install Tool is automatically locked if you enter a wrong password three times in a row.","ui.maintenance.installTool.unlock":"Unlock Install Tool","ui.maintenance.installTool.lock":"Lock Install Tool","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"The Composer autoloader is responsible for PHP class loading. The autoloader must be dumped after adding custom namespaces to the root composer.json.","ui.maintenance.dumpAutoload.button":"Dump Autoloader","ui.maintenance.composerInstall.title":"Composer Dependencies","ui.maintenance.composerInstall.description":"Composer dependencies are located in the {vendor} folder in your application root. Reinstalling the dependencies can be necessary after manipulation or manually uploading the {composerLock} file.","ui.maintenance.composerInstall.button":"Run Installer","ui.maintenance.composerInstall.update":"Run Composer Update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer caches downloaded packages for improved performance. If you have issues like broken files, try to delete the Composer cache to force a new download.","ui.maintenance.composerCache.button":"Clear Cache","ui.maintenance.maintenanceMode.title":"Maintenance Mode","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Enable","ui.maintenance.maintenanceMode.disable":"Disable","ui.maintenance.debugMode.title":"Debug Mode","ui.maintenance.debugMode.description":"Activate the debug mode by setting a user and password for the {appDevPhp} entry point.","ui.maintenance.debugMode.descriptionJwt":"Activate the debug mode by setting the debug cookie for the current domain.","ui.maintenance.debugMode.activate":"Activate","ui.maintenance.debugMode.deactivate":"Deactivate","ui.maintenance.debugMode.credentials":"Credentials","ui.maintenance.debugMode.user":"Please enter a username for the debug mode.","ui.maintenance.debugMode.password":"Please enter a password for the debug mode.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode caches PHP files on the web process for faster execution. It must be deleted under certain circumstances if files are not recognized after changing.","ui.maintenance.opcodeCache.button":"Truncate Cache","ui.maintenance.safeMode":"Not available in Safe Mode","ui.maintenance.unsupported":"Not supported by your Contao version","ui.packages.updateButton":"Hizivaat ar pakadoù","ui.packages.searchButton":"Search Packages","ui.packages.searchPlaceholder":"Klask war-lerc\'h pakadoù ...","ui.packages.uploadOverlay":"Drag & drop files to upload","ui.packages.uploadButton":"Upload Packages","ui.packages.uploadMessage":"You have one unconfirmed upload. | You have {count} unconfirmed uploads.","ui.packages.uploadApply":"Confirm Uploads","ui.packages.uploadReset":"Delete Uploads","ui.packages.uploadIncomplete":"This file was not uploaded completely. Please remove it and try again.","ui.packages.uploadDuplicate":"This file seems to be uploaded multiple times. Please remove the duplicates.","ui.packages.uploadInstalled":"This file is already installed. Please remove the duplicates.","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure to update your dependencies.","ui.packages.changesMessage":"You have one unconfirmed change. | You have {count} unconfirmed changes.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Arloañ ar c\'hemmoù","ui.packages.changesApplyAll":"Update all packages","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"Adderaouekaat ar cheñchamantoù","ui.packages.changesReview":"Review Changes","ui.packagelist.loading":"O kargañ ...","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"New packages","ui.packagelist.installed":"Installed packages","ui.package.hintRevert":"Adlakaat ar cheñchamantoù","ui.package.hintNoupdate":"Do not update","ui.package.hintConstraint":"This package will be installed with constraint {constraint} when you apply the changes.","ui.package.hintConstraintBest":"This package will be installed in the best available version when you apply the changes.","ui.package.hintConstraintChange":"The constraint for this package will be changed from \\"{from}\\" to \\"{to}\\" when you apply the changes.","ui.package.hintConstraintUpdate":"This package will be updated when you apply the changes.","ui.package.hintAdded":"This package will be installed when you apply the changes.","ui.package.hintRemoved":"This package will be removed when you apply the changes.","ui.package.requiredTitle":"manually added","ui.package.requiredText":"This package is required in your composer.json but not installed.","ui.package.removedTitle":"manually removed","ui.package.removedText":"This package was removed from your composer.json.","ui.package.installed":"Currently installed:","ui.package.version":"Stumm {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"Kemm","ui.package.uploadConstraint":"This constraint is defined by the uploaded package.","ui.package.updateButton":"Update","ui.package.removeButton":"Dilemel","ui.package.installButton":"Add Package","ui.package.installButtonShort":"Add","ui.package.detailsButton":"Munudoù","ui.package.latestConstraint":"stumm diwezhañ","ui.package.update":"Update available","ui.package.updateLatest":"stumm diwezhañ","ui.package.updateAvailable":"{version} available","ui.package.updateUnknown":"unknown version","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Stumm {version}","ui.cloudStatus.waitingTime":"Waiting Time","ui.cloudStatus.jobs":"Current Jobs","ui.cloudStatus.workers":"Workers","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"none","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sec","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Refresh Cloud Status"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[367],{8367:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Веза није безбедна !!","ui.app.httpsDescription":"Ако не користите HTTPS ваши поверљиви подаци ће се преносити без енкрипције.","ui.app.httpsLink":"Детаљније","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Сигурни мод је омогућен !!","ui.app.safeModeDescription":"Неке функционалности Contao Manager-a нису доступне.","ui.app.safeModeExit":"Изађи из Сигурног мода","ui.app.limitedHeadline":"Даљинска аутентификација","ui.app.limitedDescription":"You have limited permissions due to passwordless login.","ui.app.limitedLogout":"Re-authenticate","ui.app.totpHeadline":"Security Notice","ui.app.totpDescription":"Configure two-factor authentication now to secure your account.","ui.app.totpSetup":"Покретање инсталације","ui.app.loading":"Contao Manager се учитава...","ui.app.apiError":"Неочекиван статус API","ui.app.configSecurity1":"УПОЗОРЕЊЕ !!! Пронађен је незаштићен config фолдер","ui.app.configSecurity2":"Contao Manager је открио да су конфигурациони фајлови јавно доступни. Све операције су обустављене док се config фолдер не заштити. У супротном би потенцијални нападач могао да приступи осетљивим подацима о Вашој инсталацији.\\n\\nДа поправите ово, осигурајте да приступ фолдеру \\"contao-manager\\" на Вашем серверу буде спречен. Ако је потребно да прво научите како то да урадите, прочитајте упутство за ваш сервер или контактирајте корисничку подршку Вашег хостинг провајдера.","ui.account.welcome":"Добро дошли","ui.account.intro1":"Добродошли у Contao Manager, универзални алат за инсталацију и управљање са Вашом инсталацијом Contao Open Source CMS. Ако се први пут срећете са њим, погледајте {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} да почнете","ui.account.introManual":"прочитајте приручник","ui.account.intro2":"Ако наиђете на неки проблем, проверите {ourGithubIssues}  и слободно креирајте нову тему за било шта што до сада није пријављено.","ui.account.introIssues":"наши GitHub проблеми","ui.account.headline":"Кориснички налог","ui.account.description":"Да управљате Вашом инсталацијом, потребно је да креирате налог за Contao Manager. Имајте на уму да овај налог није исто што и налог за Contao Фронт- и БекЕнд.","ui.account.username":"Корисничко име","ui.account.password":"Лозинка","ui.account.passwordPlaceholder":"мин. 8 знакова","ui.account.passwordLength":"Унесите барем 8 знакова.","ui.account.loginInvalid":"There was an error when creating the account. Please try a different username.","ui.account.submit":"Креирај налог","ui.account.usePassword":"Use password for login","ui.account.usePasskey":"Use Passkey for login","ui.account.totpHeadline":"Two-factor authentication","ui.account.totpDescription":"Please enable two-factor authentication, which adds an extra layer of security to your account. In addition to your username and password, you will need to enter a verification code generated by a two-factor app such as 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator or any other TOTP app.","ui.account.totpSetup":"Configure now","ui.account.totpSkip":"Configure later","ui.account.login":"Decline Invitation","ui.account.contribute1":"Contao и Contao Manager су под покровитељством непрофитне организације Contao Association.","ui.account.contribute2":"Молимо Вас да размислите о томе да помогнете отвореном пројекту својом {donate}.","ui.account.contributeDonate":"донирање","ui.login.headline":"Пријава","ui.login.description":"Пријави се ради управљања инсталацијом.","ui.login.username":"Корисничко име","ui.login.password":"Лозинка","ui.login.totpHeadline":"Two-factor authentication","ui.login.totpDescription":"Please enter your verification code to complete the login process.","ui.login.totp":"Verification code","ui.login.forgotPassword":"Заборавили сте лозинку?","ui.login.button":"Пријава","ui.login.passkey":"Sign In with Passkey","ui.login.cancel":"Откажи","ui.login.locked":"Приступ је одбијен јер је Contao Manager закључан. Да бисте га откључали, обришите {lockFile} у почетном директоријуму ваше Contao инсталације.","ui.logout.headline":"Сесија је истекла","ui.logout.warning":"Нисте били активни дуже од 25 минута. Из безбедносних разлога ваша сесија ће бити ускоро прекинута.","ui.logout.expired":"Ваша сесија је аутоматски прекинута јер сте били неактивни дуже од 30 минута.","ui.logout.renew":"Остани пријављен","ui.logout.logout":"Одјава","ui.logout.login":"Назад на пријаву","ui.oauth.error":"Неисправан OAuth покушај. Проверите параметре.","ui.oauth.https":"URI за редирекцију МОРА да користи сигурни протокол (https:) чиме се спречава да се аутентификациони токен преноси као обични текст.","ui.oauth.headline":"Даљинска аутентификација","ui.oauth.description":"Следеће апликације или сервиси захтевају удаљени приступ Вашој инстанци Contao Manager-а.","ui.oauth.domain":"Пре него што дозволите приступ, будите сигурни да познајете овај URL и имате поверење у власника!","ui.oauth.outOfScope":"Unfortunately, you do not have the necessary permissions to grant this access.","ui.oauth.allow":"Дозволи приступ","ui.oauth.deny":"Одбиј приступ","ui.oauth.switchUser":"Switch User","ui.scope.admin":"Admin access including user management","ui.scope.install":"Install new packages and change Contao configuration","ui.scope.update":"Update packages and execute maintenance tasks","ui.scope.read":"Read packages and configuration","ui.boot.headline":"Провера система","ui.boot.description":"Молимо сачекајте, анализирам ваш сервер ...","ui.boot.issue1":"Пронађен је проблем приликом инсталације","ui.boot.issue2":"Ваша инсталација има проблеме који морају бити решени како бисте могли да користите Contao Manager.","ui.boot.run":"Покрени Contao Manager","ui.boot.safeMode":"Покрени у Safe Mode","ui.recovery.headline":"Опоравак система","ui.recovery.description":"Contao Manager је открио фајлове који наликују на Contaо, али интерфејс командне линије - Command Line Interface - не ради како би требао.","ui.recovery.console":"Испис конзоле","ui.recovery.repairOptions":"Одаберите опцију за опоравак инсталације.","ui.recovery.repairHeadline":"Аутоматска поправка","ui.recovery.repairDescription":"Аутоматска поправка инсталације поновним креирањем апликативног cache-а и реинсталацијом пакета Композера.","ui.recovery.repairWarning":"Било која модификација vendor фајлова можда ће бити обрисана приликом процедуре!","ui.recovery.repairFailed":"Аутоматска поправка није успела. Пробајте ручно да поправите инсталацију у Safe Mode-у.","ui.recovery.repairButton":"Покрени системску поправку","ui.recovery.safeModeHeadline":"Safe Mode","ui.recovery.safeModeDescription":"Покретањем Contao Manager-а у Safe Mode-у омогућиће управљање пакетима и одређеним задацима одржавања, али могућности које се ослањају на постојећу инсталацију Contao неће бити доступне.","ui.recovery.safeModeButton":"Покрени у Safe Mode","ui.server.pending":"Причекајте...","ui.server.running":"Анализа је у току...","ui.server.error":"Провера није успела због неочекиваног одговора са сервера.","ui.server.details":"Детаљи","ui.server.prerequisite":"Провера је заустављена због тога што потребни предуслови нису задовољени.","ui.server.selfUpdate.title":"Ажурирања Contao Manager-а","ui.server.selfUpdate.update":"Нова верзија Contao Manager {latest} је доступна.","ui.server.selfUpdate.manualUpdate":"Нова верзија Contao Manager {latest} је доступна. Ваш сервер не подржава аутоматско ажурирање, панову верзију преузмите са {download}.","ui.server.selfUpdate.latest":"Користите последњу верзију {current}.","ui.server.selfUpdate.dev":"Развојне верзије не подржавају аутоматско ажурирање.","ui.server.selfUpdate.unsupported":"Нова верзија је доступна али не подржава вашу верзију PHP-а.","ui.server.selfUpdate.button":"Покрени Само-ажурирање","ui.server.selfUpdate.continue":"Настави","ui.server.config.title":"Конфигурација сервера","ui.server.config.setup":"Конфигуриши","ui.server.config.change":"Промени","ui.server.config.save":"Сачувај","ui.server.config.cancel":"Откажи","ui.server.config.customOption":"Остало...","ui.server.config.description":"Да би исправно извршавао позадинске задатке, Contao Manager треба да зна где се налази PHP command line binary и како да извршава команде одвојено од мрежних процеса.","ui.server.config.formTitle":"Конфигурација сервера","ui.server.config.formText":"Унесите путању до вашег PHP binary. Проверите да ли је binary у истој верзији PHP као ваш веб процес.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud омогућава инсталацију Composer зависности и у случају када ваш локални сервер не поседује довољно радне меморије. Имајте на уму да ће информације о вашим пакетима бити пренете на сервер којим управља Contao Association.","ui.server.config.cloud":"Користи Composer Resolver Cloud","ui.server.config.cli":"PHP binary","ui.server.config.stateErrorCli":"На серверу није пронађен валидан PHP binary.","ui.server.config.stateErrorCloud":"Употреба Composer Resolver Cloud није подржана.","ui.server.config.stateSuccess":"PHP binary на {php_cli}.","ui.server.php_web.title":"PHP Web Process","ui.server.php_web.below7":"Пронађена је верзија PHP {version}. Молимо Вас да што пре пређете на PHP 7!","ui.server.php_web.success":"Пронађена верзија PHP {version}, нема познатих проблема.","ui.server.php_cli.title":"PHP Command Line Interface","ui.server.php_cli.success":"Пронађена верзија PHP {version}, нема познатих проблема.","ui.server.composer.title":"Composer Environment","ui.server.composer.success":"Нема познатих проблема.","ui.server.composer.install":"Зависности Композера нису инсталиране.","ui.server.composer.button":"Инсталирај","ui.server.contao.title":"Инсталација Contao","ui.server.contao.setup":"Покретање инсталације","ui.server.contao.check":"Провери базу података","ui.server.contao.empty":"Није пронађена инсталација Contao.","ui.server.contao.old":"Верзија Contao {version} није усклађена са Contao Менаџером, па ћете морати ручно да ажурирате вашу инсталацију.","ui.server.contao.found":"Пронађен Contao {version} (API version {api}).","ui.server.contao.connectionError":"Неуспешно повезивање са сервером базе података.","ui.server.contao.connectionProblem":"Пронађен је проблем у бази података.","ui.server.contao.missingUser":"Није пронађен администраторски налог.","ui.setup.continue":"Настави","ui.setup.manager":"Покрени Contao Manager","ui.setup.cancel":"Откажи","ui.setup.welcome":"Добро дошли","ui.setup.welcome1":"Овај чаробњак ће вас водити кроз неопходне кораке за инсталацију Contao Open Source CMS.","ui.setup.welcome2":"У случају да имате било каква питања, претражите документацију, форуме, канал на Slack-у и остале ресурсе на страници {support}.","ui.setup.support":"подршка из заједнице","ui.setup.start":"Почни","ui.setup.complete":"Честитамо!","ui.setup.complete1":"Contao {version} је успешно инсталиран.","ui.setup.complete2":"За завршетак процеса инсталације, отворите алат за инсталацију да бисте пдесили параметре конекције са базом података и креирали корисника за Бек Енд.","ui.setup.complete3":"Сада можете почети да развијате свој сајт у Бек Енду. Ако су вам потребне додатне екстензије, наставите у Contao Manager.","ui.setup.installTool":"Отвори Инсталациони алат","ui.setup.login":"Пријави се у Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". Пројекат Отвореног кода попут Contao захтева новац који не може да обезбеди само један појединац или комапнија.\\nАко имате сајт или продајете сајтове засноване на Contao, волели бисмо да добијемо вашу подршку у виду донације те да на тај начин подржите пројекат од кога зависи и ваш пословни резултат.","ui.setup.fundingLink":"Више информација","ui.setup.document-root.headline":"Подешавања мрежног сервера","ui.setup.document-root.warning":"Да бисте инсталирали Contao уз помоћ Contao Manager-а, морате да исправно подесите локацију root-а на Вашем мрежном серверу.","ui.setup.document-root.description1":"Contao користи посебан фолдер за јавно доступне фајлове, а апликативни фајлови су инсталирани у надређеном фолдеру. Contao сада није могуће инсталирати јер структура фолдера није тачна или фолдери нису празни.","ui.setup.document-root.description2":"Ако нисте сигурни како да подесите root, прочитајте документацију или контактирајте администратора Вашег хостинг провајдера.","ui.setup.document-root.documentation":"Прочитајте документацију","ui.setup.document-root.conflictsTitle":"Инсталациони фолдер није празан","ui.setup.document-root.conflictsDirectory":"Основни директоријум ваше будуће инсталације Contao није празан. Пронашли смо {count} фајла(ова) који ће можда бити обрисани приликом инсталације. Препоручујемо да направите празну структуру директоријума, али можете и да преместите следеће фајлове и проверите поново ако нисте сигурни да ли су у употреби.","ui.setup.document-root.ignoreConflicts":"Желим да инсталирам Contao у директоријум који није празан. Разумем да ће ово можда обрисати постојеће фајлове.","ui.setup.document-root.check":"Провери поново","ui.setup.document-root.create":"Направи директоријуме","ui.setup.document-root.change":"Промени директоријуме","ui.setup.document-root.formTitle":"Подешавање директоријума","ui.setup.document-root.formText1":"Contao Manager може аутоматски да креира нову структуру директоријума на серверу.","ui.setup.document-root.formText2":"Мораћете рућно да подесите нови root за документе (нпр. преко администраторског контрол панела на хостингу).","ui.setup.document-root.autoconfig":"Разумем да морам да променим моју конфигурацију сервера. Ако то не урадим, конфигурациони фајлови ће бити изложени (укључујући детаље налога и лозинке)!","ui.setup.document-root.directory":"Нови директоријум","ui.setup.document-root.currentRoot":"Тренутни Document Root","ui.setup.document-root.newRoot":"Нови Document Root","ui.setup.document-root.finish":"Постављање директоријума","ui.setup.document-root.publicDir":"Користи {dir} за јавне фајлове (за Contao {version})","ui.setup.document-root.directoryInvalid":"Унесите исправан назив за директоријум.","ui.setup.document-root.directoryExists":"Одредишни директоријум већ постоји. Унесите други назив.","ui.setup.document-root.confirmation":"Contao Manager је успешно завршио креирање потребног директоријума за Вашу Contao инсталацију. Сада треба да подесите document root на Вашем мрежном серверу. Немојте да поново учитавате ову страницу пре тога.","ui.setup.document-root.reload":"Поново учитај страницу","ui.setup.document-root.success":"Структура директоријума на вашем серверу је исправно постављена.","ui.setup.document-root.installingProjectDir":"Апликативни фајлови ће бити инсталирани у {dir}.","ui.setup.document-root.installingPublicDir":"Јавни фајлови ће бити инсталирани у {dir}.","ui.setup.document-root.installedProjectDir":"Апликативни фајлови су инсталирани у {dir}.","ui.setup.document-root.installedPublicDir":"Јавни фајлови су инсталирани у {dir}.","ui.setup.create-project.headline":"Инсталација Contao","ui.setup.create-project.description":"Развој Contao следи принципе {semver}, што значи да се нова мања верзија објављује сваких шест месеци. Тренутно подржана издања су:","ui.setup.create-project.semver":"Семантичко верзионисање","ui.setup.create-project.latestTitle":"Последња верзија","ui.setup.create-project.ltsTitle":"Long Term Support","ui.setup.create-project.latestQ1":"Наша последња верзија нуди највише функционалности са подршком до фебруара {year}.","ui.setup.create-project.latestQ3":"Напа последња верзија нуди највише функционалности са подршком до августа {year}.","ui.setup.create-project.ltsText":"Наша тренутна LTS верзија, ако сте фокусирани на стабилност. Нуди дугорочну подршку до фебруара {year}.","ui.setup.create-project.pltsText":"Претходна LTS верзија, још увек нуди дугорочну подршку до фебруара {year}.","ui.setup.create-project.requiresPHP":"Захтева минималну верзију PHP {version}, а ви имате PHP {current}.","ui.setup.create-project.releaseplan":"За више информација, проверите {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"План издања за Contao","ui.setup.create-project.installed":"Contao {version} је успешно инсталиран на сервер. Наставите са постављањем ваше базе података или покрените Contao Manager да инсталирате другу верзију.","ui.setup.create-project.formTitle":"Изабери дистрибуцију","ui.setup.create-project.formText":"Изаберите верзију која треба да се инсталира.","ui.setup.create-project.version":"Верзија","ui.setup.create-project.demo":"Инсталирај Contao демо сајт.","ui.setup.create-project.demoDescription":"Демо сајт помаже да се упознате са Contao и са основним функционалностима. Више тема можете пронаћи у {store}.","ui.setup.create-project.coreOnly":"Минимална инсталација (само основни модули)","ui.setup.create-project.noUpdate":"Прескочи инсталацију (само за експерте!)","ui.setup.create-project.theme":"Теме за Contao","ui.setup.create-project.themeInstall":"Да инсталирате тему за Contao, користите претрагу или учитајте фајл теме (.cto/.zip) који подржава инсталацију помоћу Contao Manager.","ui.setup.create-project.themeBuy":"Не заборавите да посетите званични {store}.","ui.setup.create-project.themeStore":"Продавница тема за Contao ","ui.setup.create-project.themeUpload":"Учитај фајл теме (.cto/.zip)","ui.setup.create-project.themeInvalid":"Учитани фајл није тема за Contao или не подржава Contao Manager.","ui.setup.create-project.themeWarning":"Contao Manager не може да процени да ли је ова тема компатибилна са вашим сервером. Проверите то са испоручиоцем од кога сте набавили тему ако имате било каква питања.","ui.setup.create-project.themeTitle":"Прегледај детаље теме","ui.setup.create-project.themeDetails":"Следеће зависности и фајлови ће бити инсталирани са овом темом.","ui.setup.create-project.themeRequire":"{count} Зависности | {count} Зависности","ui.setup.create-project.themeFiles":"{count} Фајл | {count} Фајлови","ui.setup.create-project.theme.or":"или претраже јавне теме","ui.setup.create-project.theme.search":"Претражи теме","ui.setup.create-project.theme.more":"Више тема","ui.setup.create-project.theme.empty":"Нема тема које се поклапају са {query}","ui.setup.create-project.theme.uploaded":"Фајл теме је успешно учитан.","ui.setup.create-project.theme.packageName":"Име пакета","ui.setup.create-project.theme.version":"Верзија","ui.setup.create-project.theme.authors":"Аутор(и)","ui.setup.create-project.install":"Инсталирај","ui.setup.create-project.cancel":"Откажи","ui.setup.database-connection.headline":"Конекција са базом података","ui.setup.database-connection.description":"Да би могао да чува странице, садржај, кориснике и остале релационе податке, Contao захтева MySQL базу података (или компатибилну варијанту као што је MariaDB). Параметри за повезивање су сачувани у фајлу {env} који се чува у основном фолдеру ваше Contao инсталације.","ui.setup.database-connection.formTitle":"Параметри за повезивање","ui.setup.database-connection.formText":"Унесите URL базе података или испуните корисничко име, лозинку, сервер и име базе података.","ui.setup.database-connection.url":"URL базе података","ui.setup.database-connection.validUrl":"URL базе података није исправан или повезивање са сервером није успело.","ui.setup.database-connection.or":"или","ui.setup.database-connection.user":"Корисничко име","ui.setup.database-connection.password":"Лозинка","ui.setup.database-connection.server":"Сервер (:Порт)","ui.setup.database-connection.database":"Назив базе података","ui.setup.database-connection.connected":"Повезивање са базом података {database} на серверу {server} је успело.","ui.setup.database-connection.error":"Грешка приликом повезивања са базом података.","ui.setup.database-connection.problem":"Contao је поронашао проблем са вашим сервером базе података.","ui.setup.database-connection.schemaTitle":"Шема базе података","ui.setup.database-connection.migration":"На чекању је једна миграција. | На чекању је {count} миграција.","ui.setup.database-connection.schema":"Једно ажурирање шеме је на чекању. | На чекању је {count} ажурирања шеме.","ui.setup.database-connection.noChanges":"Ваша шема у оквиру базе података је ажурна.","ui.setup.database-connection.check":"Провери базу података","ui.setup.database-connection.skip":"ПрескочиПрескочи","ui.setup.database-connection.save":"Сачувај","ui.setup.database-connection.change":"Промени креденцијале","ui.setup.database-connection.restoreTitle":"Увоз базе података","ui.setup.database-connection.restoreText":"Тема коју сте управо инсталирали садржи копију базе података. Увезите базу података да бисте увезли податке теме или прескочите овај корак да почнете са празном инсталацијом Contao. | Тема коју сте управо инсталирали садржи неколико копија базе података. Изаберите копију да увезете податке теме или прескочите овај корак да почнете са празном инсталацијом Contao.","ui.setup.database-connection.backup":"Спреми копију тренутне базе података прије увоза","ui.setup.database-connection.backupWarning":"Сви подаци у бази података ће бити обрисани и уместо њих ће се уписати нови подаци! Ако база није празна, прво направите резервну копију. ","ui.setup.database-connection.restore":"Увоз базе података","ui.setup.database-connection.restoreOption":"Резервна копија од {date} ({size})","ui.setup.database-connection.restored":"Ваша база података која припада теми је успешно увезена. Наставите према валидацији шеме базе података.","ui.setup.backend-user.success":"У бази је пронађен администраторски налог за Contao Бек Енд. Употребите Contao Бек Енд да додате нове кориснике.","ui.setup.backend-user.error":"Повлачење листе корисника није успело. Проверите испис конзоле за више детаља.","ui.setup.backend-user.headline":"Налог за Бек Енд","ui.setup.backend-user.description":"Да бисте управљали својим сајтом, морате да имате барем један администраторски налог за Contao Бек Енд. Имајте на уму да овај налог није повезан са Contao Manager.","ui.setup.backend-user.formTitle":"Креирај налог","ui.setup.backend-user.formText":"Унесите податке за нови налог Бек Енда.","ui.setup.backend-user.username":"Корисничко име","ui.setup.backend-user.name":"Име","ui.setup.backend-user.email":"E-mail адреса","ui.setup.backend-user.emailInvalid":"Унесите исправну адресу e-mailа.","ui.setup.backend-user.password":"Лозинка","ui.setup.backend-user.passwordPlaceholder":"мин. 8 знакова","ui.setup.backend-user.passwordLength":"Унесите барем 8 знакова.","ui.setup.backend-user.create":"Додај налог","ui.task.headline":"Позадински задаци","ui.task.loading":"Учитавам детаље...","ui.task.created":"Учитавам детаље...","ui.task.active":"Сачекајте док Contao Manager заврши са позадинским задацима и операцијама.","ui.task.complete":"Сви задаци су успешно завршени. За више детаља, проверите излаз конзоле.","ui.task.aborting":"Сачекајте док се позадински задаци не откажу.","ui.task.stopped":"Неки позадински задаци су отказани. Проверите излаз конзоле.","ui.task.error":"Позадински задатак је неочекивано заустављен. Проверите излаз конзоле.","ui.task.failed":"Contao Manager није успео да покрене позадински задатак!","ui.task.failedDescription1":"Нешто је кренуло погрешно приликом извршавања операција у позадини.","ui.task.failedDescription2":"Ако се ово деси поново, Ваш сервер можда не подржава инсталацију.","ui.task.reportProblem":"Пријави проблем","ui.task.sponsor":"Composer Cloud је подржан од {sponsor}","ui.task.buttonAudit":"Ажурирај базу података","ui.task.buttonClose":"Затвори","ui.task.buttonConfirm":"Потврди и затвори","ui.task.buttonCancel":"Откажи","ui.task.confirmCancel":"Да ли сте сигурни да желите да откажете задатак? Ово ће можда довести до тога да Contao инсталација не буде комплетна.","ui.task.autoclose":"Затвори детаље задатка након успешног завршетка.","ui.console.toggle":"Прикажи/Сакриј конзолу","ui.console.showLog":"Прикажи сав лог конзоле","ui.console.copyLog":"Копирај лог у привремену меморију.","ui.migrate.headline":"Ажурирања базе података","ui.migrate.migrationsOnly":"(само миграције)","ui.migrate.schemaOnly":"(само шема)","ui.migrate.loading":"Молимо да сачекате док проверимо вашу базу података ...","ui.migrate.empty":"Нису пронађене миграције или ажурирања шеме базе података на чекању. Ваша база података је ажурна.","ui.migrate.emptyMigrations":"Нису пронађене миграције на чекању. Не заборавите да проверите и ажурирања шеме.","ui.migrate.emptySchema":"Нису пронађена ажурирања шеме на чекању. Не заборавите да проверите и миграције.","ui.migrate.pending":"Ваша база података није ажурна. Проучите испис конзоле и извршите захтеване промене.","ui.migrate.previousChanges":"Миграција претходне базе података није потврђена..\\nПроверите испис конзоле испод, а онда наставите са променама.","ui.migrate.previousComplete":"Претходна миграција базе података није потврђена, проверите испис конзоле испод.\\nНема других промена на чекању.","ui.migrate.appliedChanges":"Извршена су ажурирања базе података.\\nПроверите испис конзоле испод, а онда наставите са променама.","ui.migrate.appliedComplete":"Извршена су ажуриања базе података.\\nСада је ваша база ажурна. Нема других миграција и ажурирања шеме на чекању.","ui.migrate.problem":"Contao је пронашао проблем са вашим сервером базе података.\\nПроверите испис конзоле како бисте сазнали шта треба да се поправи. | Contao је пронашао проблем са вашим сервером базе података. \\nПроверите испис конзоле како бисте сазнали шта треба да се поправи.","ui.migrate.warning":"Contao је пронашао грешку у подешавању сервера базе података.\\nУпозорења за сада можете да занемарите, али би било добро да их поправите како бисте добили оптималне перформансе и интегритет података.","ui.migrate.error":"Промене не могу да се сачувају. Изгледа да је дошло до промена у вашој бази података, освежите податке и покушајте поново.","ui.migrate.execute":"Изврши","ui.migrate.close":"Затвори","ui.migrate.confirm":"Потврди и затвори","ui.migrate.cancel":"Откажи","ui.migrate.continue":"Настави","ui.migrate.setup":"Покретање инсталације","ui.migrate.skip":"ПрескочиПрескочи","ui.migrate.retry":"Провери поново","ui.migrate.retryAll":"Провери све","ui.migrate.withDeletes":"Изврши све промене у бази података, укључујучи DROP упите.","ui.migrate.migrationTitle":"Миграције базе података","ui.migrate.schemaTitle":"Ажурирања шема","ui.migrate.problemTitle":"Проблеми базе података","ui.migrate.warningTitle":"Упозорења базе података","ui.migrate.addTable":"Додај табелу {table}","ui.migrate.dropTable":"Обриши табелу {table}","ui.migrate.addField":"Додај колону {table}.{field}","ui.migrate.changeField":"Промени колону {table}.{field}","ui.migrate.dropField":"Обриши колону {table}.{field}","ui.migrate.createIndex":"Креирај индекс \\"{name}\\" над табелом {table}","ui.migrate.dropIndex":"Обриши индекс \\"{name}\\" над табелом {table}","ui.widget.mandatory":"Ово поље не сме бити празно.","ui.widget.blankOption":"Одаберите...","ui.widget.showPassword":"Прикажи лозинку","ui.widget.hidePassword":"Сакриј лозинку","ui.error.title":"HTTP захтев за \\"{method} {url}\\" није успео.","ui.error.server500":" Изгледа да се десила нека неочекивана грешка на серверу. Проверите логове на Вашем серверу (Apache/Nginx) и логове Contao Manager на локацији \\"contao-manager/logs\\".","ui.error.response":"Сервер је договорио са кодом {status}.","ui.error.moreLink":"Више информација","ui.error.support":"Подршка за Contao","ui.error.permission":"You do not have permission to use this feature.","ui.footer.help":"Помоћ","ui.footer.reportProblem":"Пријави проблем","ui.navigation.discover":"Истражи","ui.navigation.packages":"Пакети","ui.navigation.tools":"Алати","ui.navigation.installTool":"Алат за инсталацију","ui.navigation.backend":"Contao БекЕнд","ui.navigation.debug":"Contao мод за дебаговање","ui.navigation.logViewer":"Преглед логова","ui.navigation.phpinfo":"Информације о PHP","ui.navigation.phpinfoLoading":"Учитавање информација о PHP...","ui.navigation.maintenance":"Одржавање","ui.navigation.rebuildCache":"Поновно креирај кеш","ui.navigation.users":"Accounts","ui.navigation.systemCheck":"Провера система","ui.navigation.advanced":"Напредно","ui.navigation.logout":"Одјава","ui.maintenance.database.title":"Миграције и резервне копије базе података","ui.maintenance.database.description":"Миграције базе података осигуравају конзистентност података и табела у оквиру шема.","ui.maintenance.database.migrations":"Једна миграција базе података на чекању | {count} миграција базе података на чекању","ui.maintenance.database.schemaUpdates":"Једно ажурирање шеме на чекању | {count} ажурирања шеме на чекању","ui.maintenance.database.error":"Пронађен је проблем у бази података.","ui.maintenance.database.warning":"Пронађена су упозорења за базу података.","ui.maintenance.database.button":"Провери базу података","ui.maintenance.database.migrationOnly":"Провери само миграције","ui.maintenance.database.schemaOnly":"Провери само шеме","ui.maintenance.database.installTool":"Отвори Инсталациони алат","ui.maintenance.database.createBackup":"Креирај резервну копију","ui.maintenance.database.backupUnsupported":"Резервне копије базе података нису подржане у оквиру ваше верзије Contao.","ui.maintenance.database.backupList":"Имате једну резервну копију базе података, креирану {date}. | Имате {count} резервних копија базе података, а последња је креирана {date}.","ui.maintenance.database.backupEmpty":"Тренутно немате резервне копије базе података.","ui.maintenance.rebuildCache.title":"Апликативни cache","ui.maintenance.rebuildCache.description":"Поновно креирање апликативног cache-a је потребно сваки пут када мењате било који конфигурациони фајл.","ui.maintenance.rebuildCache.rebuildProd":"Обнови продукциони Cache","ui.maintenance.rebuildCache.rebuildDev":"Обнови развојни Cache","ui.maintenance.rebuildCache.clearProd":"Обриши продукциони Cache","ui.maintenance.rebuildCache.clearDev":"Обриши развојни Cache","ui.maintenance.installTool.title":"Инсталациони алат за Contao","ui.maintenance.installTool.description":"Инсталациони алат за Contao је аутоматски закључан ако три пута заредом погрешите лозинку.","ui.maintenance.installTool.unlock":"Откључај Инсталациони алат","ui.maintenance.installTool.lock":"Закључај Инсталациони алат","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"The Composer autoloader је одговоран за учитавање PHP класа. Аutoloader мора бити испражњен након додавања властитих namespaces у root composer.json.","ui.maintenance.dumpAutoload.button":"Испразни Autoloader","ui.maintenance.composerInstall.title":"Композер зависности - dependencies","ui.maintenance.composerInstall.description":"Композер зависности су смештене у фолдер {vendor} у root фолдеру ваше апликације. Реинсталирање зависности ће можда бити неопходно након измене или ручног копирања на сервер фајла {composerLock}.","ui.maintenance.composerInstall.button":"Покрени Инсталер","ui.maintenance.composerInstall.update":"Покрени ажурирање Композера","ui.maintenance.composerCache.title":"Композер Cache","ui.maintenance.composerCache.description":"Композер кешира преузете пакете како би побољшао перформансе. Ако имате проблеме са непотпуним фајловима, покушајте да обришете cache Композера како бисте га присилили на поновно преузимање читавог пакета.","ui.maintenance.composerCache.button":"Обриши Cache","ui.maintenance.maintenanceMode.title":"Мод одржавања","ui.maintenance.maintenanceMode.description":"Када Contao пребаците у Мод одржавања, сајт ће да приказује шаблон за \\"503 Service Unavailable\\".","ui.maintenance.maintenanceMode.enable":"Омогући","ui.maintenance.maintenanceMode.disable":"Онемогући","ui.maintenance.debugMode.title":"Мод за дебаговање","ui.maintenance.debugMode.description":"Активирајте мод за дебаговање тако што ћете поставити корисничко име и лозинку за улазну тачку {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Активирајте debug мод тако што ћете поставити debug колачић за тренутни домен.","ui.maintenance.debugMode.activate":"Активирај","ui.maintenance.debugMode.deactivate":"Деактивирај","ui.maintenance.debugMode.credentials":"Креденцијали","ui.maintenance.debugMode.user":"Унесите корисничко име за Мод за дебаговање.","ui.maintenance.debugMode.password":"Унесите лозинку за Мод за дебаговање.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode кешира PHP фајлове ради бржег извршавања. У неким околностима мора бити обрисан ако фајлови нису препознати након измене.","ui.maintenance.opcodeCache.button":"Испразни Cache","ui.maintenance.safeMode":"Није доступно у Safe Mode","ui.maintenance.unsupported":"Није подржан у вашој верзији Contao","ui.packages.updateButton":"Ажурирај Пакете","ui.packages.searchButton":"Претрага пакета","ui.packages.searchPlaceholder":"Претрага Пакета...","ui.packages.uploadOverlay":"Превуците & пустите фајлове да бисте их пренели на сервер","ui.packages.uploadButton":"Постави пакете","ui.packages.uploadMessage":"Имате непотврђено пребацивање на сервер. | Имате {count} непотврђених пребацивања на сервер.","ui.packages.uploadApply":"Потврди преносе","ui.packages.uploadReset":"Обриши преносе","ui.packages.uploadIncomplete":"Фајл није пренесен у потпуности. Уклоните га и пробајте поново.","ui.packages.uploadDuplicate":"Изгледа да је овај фајл пренесен неколико пута. Уклоните дупликате.","ui.packages.uploadInstalled":"Овај фајл је већ инсталиран. Уклоните дупликате.","ui.packages.uploadUnsupported":"Учитавања нису подржана у вашој инсталацији. Проверите да је инсталирана екстензија PHP ZIP и ажурирајте зависности.","ui.packages.changesMessage":"Имате једну непотврђену промену. | Имате {count} непотврђених промена.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"Примени промене","ui.packages.changesApplyAll":"Ажурирај све пакете","ui.packages.changesDryrunAll":"Обави \\"dry-run\\" симулацију свих пакета.","ui.packages.changesReset":"Врати на почетно стање","ui.packages.changesReview":"Прегледај промене","ui.packagelist.loading":"Учитавам ...","ui.packagelist.uploads":"Преноси","ui.packagelist.added":"Нови пакети","ui.packagelist.installed":"Инсталирани пакети","ui.package.hintRevert":"Опозови измене","ui.package.hintNoupdate":"Не ажурирај","ui.package.hintConstraint":"Када сачувате измене, овај пакет ће бити инсталиран са ограничењима {constraint}.","ui.package.hintConstraintBest":"Када сачувате измене, овај пакет ће бити инсталиран са најбољом доступном верзијом.","ui.package.hintConstraintChange":"Када сачувате измене, ограничење овог пакета биће промењено из \\"{from}\\" у \\"{to}\\" .","ui.package.hintConstraintUpdate":"Ови пакети ће бити ажурирани када потврдите измене.","ui.package.hintAdded":"Ови пакети ће бити инсталирани када потврдите измене.","ui.package.hintRemoved":"Када сачувате измене, овај пакет ће бити уклоњен.","ui.package.requiredTitle":"ручно додати","ui.package.requiredText":"Овај пакет је захтеван у Вашем composer.json али није инсталиран.","ui.package.removedTitle":"ручно уклоњено","ui.package.removedText":"Овај пакет је уклоњен из вашег composer.json.","ui.package.installed":"Тренутно инсталирано:","ui.package.version":"Верзија {version}","ui.package.additionalDownloads":"{count} Преузимање | {count} Преузимања","ui.package.additionalStars":"{count} Звезда | {count} Звезде","ui.package.editConstraint":"Уреди","ui.package.uploadConstraint":"Ова зависности је дефинисана од пренесеног пакета.","ui.package.updateButton":"Ажурирај","ui.package.removeButton":"Уклони","ui.package.installButton":"Додај пакет","ui.package.installButtonShort":"Додавање","ui.package.detailsButton":"Детаљи","ui.package.latestConstraint":"последња верзија","ui.package.update":"Доступно је ажурирање","ui.package.updateLatest":"последња верзија","ui.package.updateAvailable":"{version} доступна","ui.package.updateUnknown":"непозната верзија","ui.package.updateConstraint":"Новија верзија изван вашег опсега верзија је доступна.","ui.package.incompatible":"{package} does not work with Contao {constraint}.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Верзија {version}","ui.cloudStatus.waitingTime":"Време чекања","ui.cloudStatus.jobs":"Тренутни задаци","ui.cloudStatus.workers":"Радници","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"нема","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sec","ui.cloudStatus.error":"Није могуће проверити стање сервиса Composer Resolver Cloud. Можда је у току одржавање или постоје проблеми.","ui.cloudStatus.button":"Статус Cloud-а","ui.cloudStatus.refresh":"Освежи статус Cloud-а","ui.log-viewer.loading":"Учитавам ...","ui.log-viewer.empty":"Нема лог фајлова на вашем серверу. ","ui.log-viewer.reload":"Поново учитај","ui.log-viewer.file":"Лог фајл","ui.log-viewer.channel":"Канал","ui.log-viewer.channelTitle":"Канал у ком је ова порука забиљежена.","ui.log-viewer.level":"Ниво","ui.log-viewer.levelTitle":"Озбиљност лог поруке.","ui.log-viewer.timeHeader":"Време","ui.log-viewer.messageHeader":"Порука","ui.log-viewer.showContext":"Прикажи контекст","ui.log-viewer.hideContext":"Сакриј контектст","ui.log-viewer.showExtra":"Прикажи додатне информације","ui.log-viewer.hideExtra":"Сакриј додатне информације","ui.log-viewer.more":"Учитај више ...","ui.log-viewer.download":"Преузми локално","ui.log-viewer.downloadTitle":"Преузми фајл \\"{file}\\"","ui.log-viewer.prodEnvironment":"Продукционо окружење","ui.log-viewer.devEnvironment":"Развојно окружење (Debug Mode)","ui.user-manager.loading":"Loading users …","ui.user-manager.changePassword":"Change Password","ui.user-manager.setupTotp":"Setup Two-Factor Authentication","ui.user-manager.disableTotp":"Disable Two-Factor Authentication","ui.user-manager.invite":"Invite User","ui.user-manager.delete":"Delete","ui.user-manager.deleteConfirm":"Do you really want to delete user \\"{username}\\"?","ui.user-manager.deleted":"User {username} deleted successfully","ui.user-manager.passwordHeadline":"Change Password","ui.user-manager.passwordText":"To change your password, please enter the current and a new password in the respective fields.","ui.user-manager.currentPassword":"Current password","ui.user-manager.newPassword":"New password","ui.user-manager.passwordPlaceholder":"мин. 8 знакова","ui.user-manager.submitPassword":"Submit","ui.user-manager.passwordChanged":"Your password has been changed successfully.","ui.user-manager.passwordError":"This password is incorrect.","ui.user-manager.inviteHeadline":"Invite User","ui.user-manager.inviteText":"If you need multiple logins for the Contao Manager, you can create an invitation link here. Share this link with someone or use it on another device to create a new account with the given permissions.","ui.user-manager.inviteSuccess1":"A new invitation link was created. The URL below can be used to create a new user account for this Contao Manager. The invitation expires on {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Please copy the link to your clipboard. It will only work once and you will not be able to see it again after closing this dialog.","ui.user-manager.createInvitation":"Create Invitation Link","ui.user-manager.clipboard":"Copy to clipboard","ui.user-manager.permissions":"Learn about permissions","ui.user-manager.cancel":"Откажи","ui.user-manager.close":"Затвори","ui.user-manager.you":"You","ui.totp.headline":"Two-Factor Authentication","ui.totp.setupQr":"Please scan the QR code with your 2FA/TOTP app.","ui.totp.setupCode":"If you cannot scan the QR code, enter this key instead:","ui.totp.codeLabel":"Verification code","ui.totp.codeDescription":"Please enter the verification code generated by your 2FA/TOTP app.","ui.totp.disableText":"Please enter the verification code to disable two-factor authentication.","ui.totp.invalid":"The verification code is invalid.","ui.totp.enable":"Омогући","ui.totp.disable":"Онемогући","ui.totp.cancel":"Откажи","ui.totp.enabled":"Two-factor authentication was enabled successfully.","ui.totp.disabled":"Two-factor authentication was disabled successfully.","ui.totp.setup":"Setup Two-Factor Authentication","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[542],{7542:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao 扩展","ui.app.loading":"扩展列表加载中 …","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"加载 …","ui.discover.offline":"无法获取任何结果","ui.discover.offlineExplain":"检查网络连接并在浏览器中禁用JavaScript拦截器。","ui.discover.offlineButton":"重试","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"No results for {query}","ui.discover.more":"更多","ui.discover.sortBy":"排序","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"已更新","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"下载","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"评级","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"详情","ui.discover.latestPackages":"最新和已更新扩展","ui.discover.faversPackages":"最高评级扩展","ui.discover.downloadsPackages":"下载最多扩展","ui.package.homepage":"项目网站","ui.package.private":"私有包","ui.package.privateTitle":"私有包仅可从提供商获取 (e.g. ZIP 下载)。请访问网站获取更多信息。","ui.package.abandoned":"放弃","ui.package.abandonedText":"该程序包已放弃不再维护。","ui.package.abandonedReplace":"该程序包已放弃不再维护。作者建议使用 {replacement} 包替代.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"以前的扩展详细信息","ui.package-details.close":"关闭扩展详情","ui.package-details.loading":"加载 …","ui.package-details.tabDescription":"描述","ui.package-details.tabRequire":"需求","ui.package-details.tabFeatures":"特征","ui.package-details.tabSuggest":"建议","ui.package-details.tabConflict":"冲突","ui.package-details.tabDependents":"依赖","ui.package-details.linkRequires":"需要","ui.package-details.linkReplaces":"替换","ui.package-details.linkProvides":"提供","ui.package-details.linkConflicts":"冲突","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"最新版","ui.package-details.released":"发布于","ui.package-details.license":"许可(s)","ui.package-details.authors":"from","ui.package-details.more":"更多","ui.package-details.packagist":"包详情","ui.package-details.metadata":"编辑元数据","ui.package-details.support_docs":"文档","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"支持论坛","ui.package-details.support_issues":"问题 / 错误 报告","ui.package-details.support_source":"源代码","ui.package-details.support_irc":"IRC / 聊天","ui.package-details.support_email":"支持 E-Mail","ui.package-details.support_rss":"RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[180],{2180:function(e){e.exports=JSON.parse('{"ui.app.title":"Extensiones Contao","ui.app.loading":"Cargando lista de extensiones ...","ui.app.language":"Cambiar idioma para el Contao Manager","ui.app.colorDark":"Modo oscuro","ui.app.colorDarkTitle":"Cambiar el esquema de color a oscuro","ui.app.colorLight":"Modo claro","ui.app.colorLightTitle":"Cambiar el esquema de color a claro","ui.discover.advertisement":"Aviso en la lista de extensiones","ui.discover.loading":"Cargando ...","ui.discover.offline":"No se pudo obtener ningún resultado.","ui.discover.offlineExplain":"Verifique su conexión a Internet y desactive los bloqueadores de JavaScript en su navegador.","ui.discover.offlineButton":"Inténtelo de nuevo","ui.discover.searchPlaceholder":"Buscar en {count} extensiones…","ui.discover.empty":"No hay resultados para {query}","ui.discover.more":"Más resultados","ui.discover.sortBy":"Ordenar por","ui.discover.sortReleased":"Publicado","ui.discover.sortReleasedTitle":"Ordenar resultados por fecha de lanzamiento","ui.discover.sortLatest":"Actualizado","ui.discover.sortLatestTitle":"Ordenar resultados por última actualización","ui.discover.sortDownloads":"Descargas","ui.discover.sortDownloadsTitle":"Ordenar resultados por número de descargas","ui.discover.sortFavers":"Clasificación","ui.discover.sortFaversTitle":"Ordenar resultados por calificación","ui.discover.detailsButton":"Detalles","ui.discover.latestPackages":"Extensiones más recientes y actualizadas","ui.discover.faversPackages":"Extensiones mejor calificadas","ui.discover.downloadsPackages":"Extensiones más descargadas","ui.package.homepage":"Sitio web del proyecto","ui.package.private":"Paquete privado","ui.package.privateTitle":"Los paquetes privados solo están disponibles por parte del proveedor (por ejemplo, como descarga ZIP). Por favor, visite el sitio web para más información.","ui.package.abandoned":"abandonado","ui.package.abandonedText":"Este paquete está abandonado y ya no se mantiene.","ui.package.abandonedReplace":"su paquete es abandonado y ya no se mantiene. El autor sugiere usar el paquete {replacement} en su lugar.","ui.package.contaoVersion":"Disponible para Contao","ui.package-details.previous":"Detalles de extensiones anteriores","ui.package-details.close":"Cerrar detalles de extensión","ui.package-details.loading":"Cargando ...","ui.package-details.tabDescription":"Descripción","ui.package-details.tabRequire":"Requisitos","ui.package-details.tabFeatures":"Caracteristicas","ui.package-details.tabSuggest":"Sugerencias","ui.package-details.tabConflict":"Conflictos","ui.package-details.tabDependents":"Dependientes","ui.package-details.linkRequires":"requiere","ui.package-details.linkReplaces":"reemplaza","ui.package-details.linkProvides":"provee","ui.package-details.linkConflicts":"conflictos","ui.package-details.funding":"Mantenimiento del Fund Package!","ui.package-details.contaoVersions":"Version(es) compatible(s) de Contao","ui.package-details.latest":"Última versión","ui.package-details.released":"publicado el","ui.package-details.license":"Licencia(s)","ui.package-details.authors":"de","ui.package-details.more":"Más","ui.package-details.packagist":"Detalles del paquete","ui.package-details.metadata":"Editar metadatos","ui.package-details.support_docs":"Documentación","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Foro de sopporte","ui.package-details.support_issues":"Problemas / Informe de error","ui.package-details.support_source":"Código fuente","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Email del soporte ","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[874],{2874:function(e){e.exports=JSON.parse('{"ui.app.title":"Rozšíření Contaa","ui.app.loading":"Načítání seznamu rozšíření...","ui.app.language":"Změnit jazyk Správce Contaa","ui.app.colorDark":"Tmavé zobrazení","ui.app.colorDarkTitle":"Změnit na tmavé prostředí","ui.app.colorLight":"Světlé zobrazení","ui.app.colorLightTitle":"Změnit na světlé prostředí","ui.discover.advertisement":"Reklama v seznamu rozšíření","ui.discover.loading":"Spouštění…","ui.discover.offline":"Nemůžu načíst žádné výsledky.","ui.discover.offlineExplain":"Zkontrolujte prosím Vaše internetové připojení a deaktivujte blokování JavaScriptu ve Vašem prohlížeči.","ui.discover.offlineButton":"Zkusit znovu","ui.discover.searchPlaceholder":"Prohledat {count} rozšíření...","ui.discover.empty":"Žádné výsledky pro {query}","ui.discover.more":"Více výsledků","ui.discover.sortBy":"Seřadit podle","ui.discover.sortReleased":"Zveřejněno","ui.discover.sortReleasedTitle":"Seřadit výsledky podle zveřejnění","ui.discover.sortLatest":"Zaktualizované","ui.discover.sortLatestTitle":"Seřadit výsledky podle naposledy zaktualizovaných","ui.discover.sortDownloads":"Stažení","ui.discover.sortDownloadsTitle":"Seřadit výsledky podle počtu stažení","ui.discover.sortFavers":"Hodnocení","ui.discover.sortFaversTitle":"Seřadit výsledky podle hodnocení","ui.discover.detailsButton":"Podrobnosti","ui.discover.latestPackages":"Poslední a naposledy zaktualizovaná rozšíření","ui.discover.faversPackages":"Nejlépe hodnocená rozšíření","ui.discover.downloadsPackages":"Nejvíce stahovaná rozšíření","ui.package.homepage":"Stránka projektu","ui.package.private":"Soukromý balíček","ui.package.privateTitle":"Soukromé balíčky jsou dostupné pouze z vendoru (např. jako soubor ZIP). Více informací získáte na následujícím webu. ","ui.package.abandoned":"nepřijatý","ui.package.abandonedText":"Tento balíček je označený jako nepřijatý a již se dál vyvíjí.","ui.package.abandonedReplace":"Tento balíček je označený jako nepřijatý a již se dál vyvíjí. Autor místo něho doporučuje použít {replacement}. ","ui.package.contaoVersion":"Dostupné pro Contao","ui.package-details.previous":"Předešlé podrobné informace k rozšíření","ui.package-details.close":"Zavřít podrobné informace k rozšíření","ui.package-details.loading":"Spouštění…","ui.package-details.tabDescription":"Popis","ui.package-details.tabRequire":"Požadavky","ui.package-details.tabFeatures":"Funkce","ui.package-details.tabSuggest":"Doporučení","ui.package-details.tabConflict":"Konflikty","ui.package-details.tabDependents":"Závislosti","ui.package-details.linkRequires":"vyžaduje","ui.package-details.linkReplaces":"nahrazuje","ui.package-details.linkProvides":"poskytuje","ui.package-details.linkConflicts":"konflikty","ui.package-details.funding":"Nalezen vyvíjený balíček!","ui.package-details.contaoVersions":"Podporováno verzí Contaa","ui.package-details.latest":"Poslední verze","ui.package-details.released":"Zveřejněno","ui.package-details.license":"Licence","ui.package-details.authors":"od","ui.package-details.more":"Více","ui.package-details.packagist":"Podrobnosti k balíčku","ui.package-details.metadata":"Upravit meta informace","ui.package-details.support_docs":"Dokumentace","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Podpora ve fóru","ui.package-details.support_issues":"Chyby / nahlášení chyb","ui.package-details.support_source":"Zdrojový kód","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Mail podpory","ui.package-details.support_rss":"Kanál RSS"}')}}]);(function(){"use strict";var e={70:function(e,t){t.A={ADMIN:"admin",INSTALL:"install",UPDATE:"update",READ:"read"}},683:function(e,t,a){a.d(t,{A:function(){return g}});var s=a(641),n=a(33);const o=["for"],i=["type","id","name","placeholder","required","pattern","minlength","maxlength","disabled","autocomplete","autocapitalize","value"],l=["title"],r={key:2,class:"widget__error"};function c(e,t,a,c,u,d){return(0,s.uX)(),(0,s.CE)("div",{class:(0,n.C4)(["widget widget-text",{[`widget-text--${a.type}`]:!!a.type,"widget--error":a.error,"widget--validate":a.validate&&!a.error,"widget--required":a.required}])},[a.label?((0,s.uX)(),(0,s.CE)("label",{key:0,for:"ctrl_"+a.name},(0,n.v_)(a.label),9,o)):(0,s.Q3)("",!0),(0,s.Lk)("input",{ref:"input",type:d.inputType,id:a.label?"ctrl_"+a.name:"",name:a.name,placeholder:a.validate?a.placeholder||" ":a.placeholder,required:a.required,pattern:a.pattern,minlength:a.minlength,maxlength:a.maxlength,disabled:a.disabled,autocomplete:a.autocomplete,autocapitalize:a.autocapitalize||"none",value:a.modelValue,onInput:t[0]||(t[0]=e=>d.input(e.target.value)),onKeyup:t[1]||(t[1]=t=>e.$emit("keyup")),onFocus:t[2]||(t[2]=t=>e.$emit("focus")),onBlur:t[3]||(t[3]=t=>e.$emit("blur"))},null,40,i),"password"===a.type?((0,s.uX)(),(0,s.CE)("button",{key:1,type:"button",class:(0,n.C4)(["widget__password-toggle",{"widget__password-toggle--visible":e.showPassword,"widget__password-toggle--hidden":!e.showPassword}]),title:e.$t("ui.widget."+(e.showPassword?"hidePassword":"showPassword")),onClick:t[4]||(t[4]=function(){return d.togglePassword&&d.togglePassword(...arguments)})},t[5]||(t[5]=[(0,s.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"})],-1)]),10,l)):(0,s.Q3)("",!0),a.error?((0,s.uX)(),(0,s.CE)("p",r,(0,n.v_)(a.error),1)):(0,s.Q3)("",!0),a.description||e.$slots.description?((0,s.uX)(),(0,s.CE)("div",{key:3,class:(0,n.C4)(["widget__description",{"widget__description--disabled":a.disabled}])},[(0,s.RG)(e.$slots,"description",{},(()=>[(0,s.Lk)("p",null,(0,n.v_)(a.description),1)]))],2)):(0,s.Q3)("",!0)],2)}var u={emits:["input","keyup","focus","blur","update:modelValue"],props:{type:{type:String,validator:e=>["text","tel","email","url","password","search"].includes(e)},name:{type:String,required:!0},label:String,description:String,modelValue:String,pattern:String,placeholder:String,disabled:Boolean,required:Boolean,validate:Boolean,error:String,autocomplete:String,autocapitalize:String,minlength:String,maxlength:String},data:()=>({showPassword:!1}),computed:{inputType(){return"password"===this.type&&this.showPassword?"text":this.type?this.type:"text"}},methods:{input(e){this.$emit("input"),this.$emit("update:modelValue",e)},enter(){this.$emit("enter")},focus(){this.$refs.input.focus()},checkValidity(){return this.$refs.input.checkValidity()},togglePassword(){this.showPassword=!this.showPassword,this.focus()}},mounted(){this.$emit("update:modelValue",this.$refs.input.value)}},d=a(6262);const p=(0,d.A)(u,[["render",c]]);var g=p},707:function(e,t){t.A={INIT:"init",ACCOUNT:"account",LOGIN:"login",BOOT:"boot",CONFIG:"config",SETUP:"setup",RECOVERY:"recovery",MIGRATION:"migration",READY:"ready"}},1496:function(e,t,a){a.d(t,{A:function(){return y}});var s=a(641),n=a(33),o=a(3751);const i={key:0,class:"fragment-footer__product"},l={class:"fragment-footer__links"},r={href:"https://docs.contao.org",target:"_blank"},c={href:"https://to.contao.org/support",target:"_blank"},u={class:"fragment-footer__settings"},d={class:"fragment-footer__language"},p=["title"],g=["onClick"];function h(e,t,a,h,m,k){const v=(0,s.g2)("theme-toggle");return(0,s.uX)(),(0,s.CE)("footer",{class:(0,n.C4)("fragment-footer"+(a.display?" fragment-footer--"+a.display:""))},[k.isLogin?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("strong",i,"Contao Manager 1.9.1")),(0,s.Lk)("ul",l,[(0,s.Lk)("li",null,[(0,s.Lk)("a",r,(0,n.v_)(e.$t("ui.footer.help")),1)]),(0,s.Lk)("li",null,[(0,s.Lk)("a",c,(0,n.v_)(e.$t("ui.footer.reportProblem")),1)])]),(0,s.Lk)("div",u,[(0,s.Lk)("div",d,[(0,s.Lk)("button",{title:e.$t("ui.app.language"),onClick:t[0]||(t[0]=function(){return k.toggle&&k.toggle(...arguments)})},(0,n.v_)(k.languageOptions[k.currentLanguage]),9,p),(0,s.bo)((0,s.Lk)("ul",{class:"link-menu link-menu--contao link-menu--valign-top",ref:"menu",tabindex:"-1",onBlur:t[2]||(t[2]=function(){return k.close&&k.close(...arguments)}),onClick:t[3]||(t[3]=function(){return k.close&&k.close(...arguments)})},[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(k.languageOptions,((e,a)=>((0,s.uX)(),(0,s.CE)("li",{class:"link-menu__item",key:a},[(0,s.Lk)("a",{class:(0,n.C4)({active:a===k.currentLanguage}),onClick:e=>k.updateLanguage(a),onTouchstart:t[1]||(t[1]=(0,o.D$)((()=>{}),["stop"]))},(0,n.v_)(e),43,g)])))),128))],544),[[o.aG,e.visible]])]),(0,s.bF)(v)])],2)}var m=a(8044),k=a(9376),v=a(707),b=a(6637),_={components:{ThemeToggle:b.A},props:{display:String},data:()=>({visible:!1}),computed:{isLogin:e=>e.$store.state.view===v.A.LOGIN,currentLanguage(){return this.$i18n.locale},languageOptions(){return k.A}},methods:{updateLanguage(e){m.A.switch(e)},open(){this.visible=!0,setTimeout((()=>this.$refs.menu.focus()),0)},close(){this.$refs.menu.blur(),setTimeout((()=>{this.visible=!1}),300)},toggle(){this.visible?this.close():this.open()}}},f=a(6262);const w=(0,f.A)(_,[["render",h]]);var y=w},1909:function(e,t,a){a.d(t,{A:function(){return v}});var s=a(641),n=a(33);function o(e,t,a,o,i,l){const r=(0,s.g2)("confirm-button");return e.isGranted(l.scopes.INSTALL)?((0,s.uX)(),(0,s.Wv)(r,{key:0,color:"primary",icon:"add",small:a.small,inline:a.inline,disabled:a.disabled||e.isRootInstalled||e.isAdded||e.isRequired||!e.canBeInstalled,onClick:l.install},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(e.$t(a.small?"ui.package.installButtonShort":"ui.package.installButton")),1)])),_:1},8,["small","inline","disabled","onClick"])):(0,s.Q3)("",!0)}var i=a(6278),l=a(70),r=a(8200);const c=["disabled"];function u(e,t,a,o,i,l){return(0,s.uX)(),(0,s.CE)("button",{type:"button",class:(0,n.C4)(l.buttonClass),disabled:a.disabled,onClick:t[0]||(t[0]=function(){return l.click&&l.click(...arguments)})},[(0,s.Lk)("span",{class:(0,n.C4)(l.slotClass)},[(0,s.RG)(e.$slots,"default")],2),(0,s.Lk)("span",{class:(0,n.C4)(["confirm-button__icon",{"confirm-button__icon--confirm":e.confirm}])},t[1]||(t[1]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"})],-1)]),2)],10,c)}var d={emits:["click"],props:{color:String,icon:String,inline:Boolean,small:Boolean,disabled:Boolean},data:()=>({confirm:!1}),computed:{buttonClass:e=>({"confirm-button":!0,"widget-button":!0,"widget-button--inline":e.inline,"widget-button--small":e.small,[`widget-button--${e.color}`]:e.color}),slotClass:e=>({[`widget-button--${e.icon}`]:e.icon})},methods:{click(e){this.confirm||(e.preventDefault(),e.target.blur(),this.$emit("click",e),this.confirm=!0,setTimeout((()=>{this.confirm=!1}),1e3))}}},p=a(6262);const g=(0,p.A)(d,[["render",u]]);var h=g,m={components:{ConfirmButton:h},mixins:[r.A],props:{data:{type:Object,required:!0},small:Boolean,inline:Boolean,disabled:Boolean},computed:{...(0,i.L8)("auth",["isGranted"]),scopes:()=>l.A},methods:{install(){this.$store.commit("packages/add",{name:this.data.name})}}};const k=(0,p.A)(m,[["render",o]]);var v=k},2286:function(e,t,a){a.d(t,{A:function(){return _}});var s=a(641),n=a(33);const o={class:"setup-totp__qr"},i={class:"setup-totp__uri"},l=["disabled"];function r(e,t,a,r,c,u){const d=(0,s.g2)("qrcode-svg"),p=(0,s.g2)("text-field"),g=(0,s.g2)("loading-spinner"),h=(0,s.g2)("loading-button"),m=(0,s.g2)("popup-overlay");return(0,s.uX)(),(0,s.Wv)(m,{class:"setup-totp",headline:e.$t("ui.totp.headline"),onSubmit:u.submit,onClear:u.close},(0,s.eX)({default:(0,s.k6)((()=>[e.provisioning_uri?((0,s.uX)(),(0,s.CE)(s.FK,{key:0},[(0,s.Lk)("p",null,(0,n.v_)(e.$t("ui.totp.setupQr")),1),(0,s.Lk)("div",o,[(0,s.bF)(d,{value:e.provisioning_uri,level:"H"},null,8,["value"])]),(0,s.Lk)("p",null,(0,n.v_)(e.$t("ui.totp.setupCode")),1),(0,s.Lk)("code",i,(0,n.v_)(e.provisioning_uri),1),(0,s.bF)(p,{ref:"totp",name:"totp",label:e.$t("ui.totp.codeLabel"),description:e.$t("ui.totp.codeDescription"),required:"",pattern:"\\d+",minlength:"6",maxlength:"6",autocomplete:"one-time-code",error:e.error,onKeyup:t[0]||(t[0]=t=>e.error=""),modelValue:e.totp,"onUpdate:modelValue":t[1]||(t[1]=t=>e.totp=t)},null,8,["label","description","error","modelValue"])],64)):((0,s.uX)(),(0,s.Wv)(g,{key:1}))])),_:2},[e.provisioning_uri?{name:"actions",fn:(0,s.k6)((()=>[(0,s.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[2]||(t[2]=function(){return u.close&&u.close(...arguments)})},(0,n.v_)(e.$t("ui.totp.cancel")),9,l),(0,s.bF)(h,{submit:"",color:"primary",loading:e.loading},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(e.$t("ui.totp.enable")),1)])),_:1},8,["loading"])])),key:"0"}:void 0]),1032,["headline","onSubmit","onClear"])}var c=a(4335),u=a(6278),d=a(3170),p=a(4999),g=a(6966),h=a(683),m=a(7944),k={components:{PopupOverlay:d.A,LoadingSpinner:p.A,LoadingButton:g.A,TextField:h.A,QrcodeSvg:m.dv},data:()=>({loading:!1,provisioning_uri:null,totp:null,error:""}),computed:{...(0,u.aH)("auth",["username"])},methods:{submit(){this.loading=!0,this.$request.put(`api/users/${this.username}/totp`,{provisioning_uri:this.provisioning_uri,totp:this.totp},null,{201:async()=>{await this.$store.dispatch("auth/status"),this.$notify.success(this.$t("ui.totp.enabled")),this.close()},422:()=>{this.loading=!1,this.error=this.$t("ui.totp.invalid"),this.$refs.totp.focus()}})},close(){this.$store.commit("modals/close","setup-totp")}},async mounted(){const e=await c.A.get(`api/users/${this.username}/totp`);this.provisioning_uri=e.data.provisioning_uri,setTimeout((()=>{this.$refs.totp.focus()}),0)}},v=a(6262);const b=(0,v.A)(k,[["render",r]]);var _=b},2880:function(e,t,a){a.d(t,{A:function(){return g}});var s=a(641),n=a(33),o=a(3751);const i={class:"button-group"},l=["disabled"];function r(e,t,a,r,c,u){const d=(0,s.g2)("loading-button");return(0,s.uX)(),(0,s.CE)("div",i,[(0,s.bF)(d,{href:a.href,to:a.to,class:(0,n.C4)(u.primaryClass),onClick:t[0]||(t[0]=t=>e.$emit("click",t)),disabled:a.disabled,loading:a.loading,submit:a.submit},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.label),1)])),_:1},8,["href","to","class","disabled","loading","submit"]),(0,s.Lk)("button",{type:"button",class:(0,n.C4)(u.moreClass),onClick:t[1]||(t[1]=function(){return u.toggle&&u.toggle(...arguments)}),disabled:a.moreDisabled},t[4]||(t[4]=[(0,s.Lk)("svg",{fill:"#FFF",height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("path",{d:"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"}),(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)]),10,l),(0,s.bo)((0,s.Lk)("div",{ref:"group",class:(0,n.C4)({"button-group__group":!0,["button-group__group--top"]:a.alignTop}),tabindex:"-1",onBlur:t[2]||(t[2]=function(){return u.close&&u.close(...arguments)}),onClick:t[3]||(t[3]=function(){return u.close&&u.close(...arguments)})},[(0,s.RG)(e.$slots,"default")],34),[[o.aG,e.showGroup]])])}var c=a(6966),u={components:{LoadingButton:c.A},emits:["click"],props:{label:{type:String,required:!0},type:String,href:String,to:[String,Object],icon:String,color:String,disabled:Boolean,loading:Boolean,submit:Boolean,moreDisabled:Boolean,alignTop:Boolean},data:()=>({showGroup:!1}),computed:{primaryClass(){let e="widget-button button-group__primary";return this.type&&(e+=` widget-button--${this.type}`),this.icon&&(e+=` widget-button--${this.icon}`),this.color&&(e+=` widget-button--${this.color}`),e},moreClass(){let e="widget-button button-group__more";return this.type&&(e+=` widget-button--${this.type}`),this.color&&(e+=` widget-button--${this.color}`),e}},methods:{open(){this.showGroup=!0,setTimeout((()=>this.$refs.group?.focus()),0)},close(){this.$refs.group?.blur(),setTimeout((()=>{this.showGroup=!1}),300)},toggle(){this.showGroup?this.close():this.open()}}},d=a(6262);const p=(0,d.A)(u,[["render",r]]);var g=p},3018:function(e,t,a){a.d(t,{A:function(){return d}});var s=a(641),n=a(33);const o=["id","name","disabled","required","checked"],i=["for"];function l(e,t,a,l,r,c){return(0,s.uX)(),(0,s.CE)("div",null,[(0,s.Lk)("div",{class:(0,n.C4)(["widget widget-checkbox",{"widget--required":a.required}])},[(0,s.Lk)("input",{ref:"input",type:"checkbox",id:a.label?"ctrl_"+a.name:"",name:a.name,disabled:a.disabled,required:a.required,checked:a.modelValue||null,onChange:t[0]||(t[0]=e=>c.toggle(e.target.checked))},null,40,o),a.label?((0,s.uX)(),(0,s.CE)("label",{key:0,for:"ctrl_"+a.name},(0,n.v_)(a.label),9,i)):(0,s.Q3)("",!0)],2),a.description||e.$slots.description?((0,s.uX)(),(0,s.CE)("div",{key:0,class:(0,n.C4)(["widget__description",{"widget__description--disabled":a.disabled}])},[(0,s.RG)(e.$slots,"description",{},(()=>[(0,s.Lk)("p",null,(0,n.v_)(a.description),1)]))],2)):(0,s.Q3)("",!0)])}var r={emits:["input","update:modelValue"],props:{name:{type:String,required:!0},label:{type:String,required:!0},description:String,modelValue:Boolean,disabled:Boolean,required:Boolean},methods:{toggle(e){this.$emit("input"),this.$emit("update:modelValue",!!e)}}},c=a(6262);const u=(0,c.A)(r,[["render",l]]);var d=u},3629:function(e,t,a){a.d(t,{A:function(){return v}});var s=a(641),n=a(33),o=a(3751);const i={key:0,class:"package-constraint"},l=["placeholder","title","disabled"],r=["title","disabled"];function c(e,t,a,c,u,d){return!e.isFeature&&e.isVisible?((0,s.uX)(),(0,s.CE)("fieldset",i,[(0,s.bo)((0,s.Lk)("input",{ref:"constraint",type:"text",placeholder:d.inputPlaceholder,title:d.inputTitle,"onUpdate:modelValue":t[0]||(t[0]=e=>d.inputValue=e),class:(0,n.C4)({disabled:!a.emit&&(e.willBeRemoved||!e.isInstalled&&!e.willBeInstalled&&!e.isRequired||e.isUpload||!e.isGranted(d.scopes.UPDATE)),error:e.constraintError}),disabled:!e.constraintEditable||e.willBeRemoved||!a.emit&&!e.isInstalled&&!e.willBeInstalled&&!e.isRequired||e.isUpload||!e.isGranted(d.scopes.UPDATE),onKeypress:[t[1]||(t[1]=(0,o.jR)((0,o.D$)((function(){return d.saveConstraint&&d.saveConstraint(...arguments)}),["prevent"]),["enter"])),t[2]||(t[2]=(0,o.jR)((0,o.D$)((function(){return d.resetConstraint&&d.resetConstraint(...arguments)}),["prevent"]),["esc"]))],onBlur:t[3]||(t[3]=function(){return d.saveConstraint&&d.saveConstraint(...arguments)})},null,42,l),[[o.Jo,d.inputValue]]),(0,s.Lk)("button",{class:(0,n.C4)({"widget-button widget-button--gear":!0,rotate:e.constraintValidating}),title:d.buttonTitle,onClick:t[4]||(t[4]=function(){return d.editConstraint&&d.editConstraint(...arguments)}),disabled:!a.emit&&(e.willBeRemoved||!e.isInstalled&&!e.willBeInstalled&&!e.isRequired||e.isUpload||!e.isGranted(d.scopes.UPDATE))},(0,n.v_)(d.buttonValue),11,r)])):(0,s.Q3)("",!0)}var u=a(6278),d=a(4335),p=a(70),g=a(8200),h={mixins:[g.A],props:{data:{type:Object,required:!0},emit:{type:Boolean,default:!1},value:{type:String,default:""}},data:()=>({constraint:"",constraintEditable:!1,constraintValidating:!1,constraintError:!1}),computed:{...(0,u.L8)("auth",["isGranted"]),scopes:()=>p.A,buttonTitle:e=>e.isUpload?e.$t("ui.package.uploadConstraint"):"",buttonValue:e=>e.isUpload?e.$t("ui.package.editConstraint"):e.$t("ui.package.private"),inputTitle:e=>e.isUpload?e.$t("ui.package.privateTitle"):e.constraint,inputPlaceholder:e=>e.isUpload||e.$store.state.packages.root&&Object.keys(e.$store.state.packages.root.require).includes(e.data.name)?"":e.$t("ui.package.latestConstraint"),inputValue:{get:e=>e.isUpload?e.$t("ui.package.private"):e.constraint,set(e){this.isUpload||(this.constraint=e)}}},methods:{editConstraint(){this.constraintValidating||(this.constraintEditable=!0,setTimeout((()=>{this.$refs.constraint.focus()}),0))},saveConstraint(){if(this.constraintEditable){if(this.constraintEditable=!1,this.constraintError=!1,!this.emit&&(this.isInstalled&&(!this.constraint||this.constraintInstalled===this.constraint)||this.isRequired&&(!this.constraint||this.constraintRequired===this.constraint)))return this.$store.commit("packages/restore",this.data.name),this.$store.dispatch("packages/uploads/unconfirm",this.data.name),void this.resetConstraint();if(!this.emit&&!this.isRequired&&this.willBeInstalled&&!this.constraint)return this.$store.commit("packages/add",Object.assign({},this.data,{constraint:null})),void this.resetConstraint();if(this.emit&&!this.constraint)return this.$emit("input",this.constraint),void this.resetConstraint();this.$refs.constraint.blur(),this.constraintValidating=!0,d.A.post("api/constraint",{constraint:this.constraint}).then((e=>{this.constraintValidating=!1,e.data.valid?this.emit?this.$emit("input",this.constraint):this.isRootInstalled||this.isRequired?this.$store.commit("packages/change",{name:this.data.name,version:this.constraint}):this.$store.commit("packages/add",Object.assign({},this.data,{constraint:this.constraint})):(this.constraintError=!0,setTimeout((()=>this.editConstraint()),0))}))}},resetConstraint(){this.emit?this.constraint=this.value:this.willBeInstalled?this.constraint=this.constraintAdded:this.isChanged?this.constraint=this.constraintChanged:this.isInstalled?this.constraint=this.constraintInstalled:this.isRequired&&(this.constraint=this.constraintRequired),this.constraintEditable&&(this.constraintEditable=!1,this.constraintError=!1,this.constraintValidating=!1)}},watch:{value(e){this.constraint=e},constraintAdded(e){this.constraint=e},constraintChanged(e){this.constraint=e||this.constraintInstalled||this.constraintRequired}},mounted(){this.resetConstraint()}},m=a(6262);const k=(0,m.A)(h,[["render",c],["__scopeId","data-v-1e421d04"]]);var v=k},3723:function(e,t){t.A={discover:{name:"discover"},packages:{name:"packages"},oauth:{name:"oauth"},maintenance:{name:"maintenance"},userManager:{name:"users"},logViewer:{name:"logs"}}},4141:function(e,t,a){var s=a(4335),n=a(4405),o=a(5633),i=a(3192),l=a(5220),r=a(3723),c=a(641),u=a(33);const d={key:0},p=["href"];function g(e,t,a,s,n,o){const i=(0,c.g2)("install-button"),l=(0,c.g2)("discover-list");return(0,c.uX)(),(0,c.Wv)(l,{wrapper:o.wrapper,"hide-themes":""},{"package-hint":(0,c.k6)((t=>{let{data:a}=t;return[e.contaoSupported(a.contaoConstraint)?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("p",d,(0,u.v_)(e.$t("ui.package.incompatible",{package:a.name,constraint:e.packageConstraint("contao/manager-bundle")})),1))]})),"package-actions":(0,c.k6)((t=>{let{data:a}=t;return[a&&a.private&&!e.packageSuggested(a.name)?((0,c.uX)(),(0,c.CE)("a",{key:0,class:"widget-button widget-button--small widget-button--primary widget-button--link",target:"_blank",href:a.homepage},(0,u.v_)(e.$t("ui.package.homepage")),9,p)):((0,c.uX)(),(0,c.Wv)(i,{key:1,small:"",inline:"",data:a},null,8,["data"]))]})),_:1},8,["wrapper"])}var h=a(6278),m=a(6894);const k={class:"layout-main"},v={class:"layout-main__logo"},b={class:"layout-main__title"},_={key:0,class:"layout-main__badge-title"},f={key:0,class:"layout-main__subheader"},w={class:"layout-main__subheader-inside"},y={key:0,class:"layout-main__news"},C=["href","title"],$=["src","alt"],L={class:"layout-main__content"};function A(e,t,a,s,n,o){const i=(0,c.g2)("navigation-fragment"),l=(0,c.g2)("footer-fragment");return(0,c.uX)(),(0,c.CE)("div",k,[(0,c.Lk)("header",{class:(0,u.C4)(["layout-main__header",{"layout-main__header--margin":!e.$slots.search,"layout-main__has-badge-title":e.badgeTitle}])},[(0,c.Lk)("div",v,[t[1]||(t[1]=(0,c.Lk)("img",{src:m,width:"40",height:"40",alt:"Contao Logo"},null,-1)),(0,c.Lk)("span",b,[t[0]||(t[0]=(0,c.Lk)("span",{class:"layout-main__manager-title"},"Contao Manager",-1)),e.badgeTitle?((0,c.uX)(),(0,c.CE)("span",_,(0,u.v_)(e.badgeTitle),1)):(0,c.Q3)("",!0)])]),(0,c.bF)(i)],2),e.$slots.search?((0,c.uX)(),(0,c.CE)("div",f,[(0,c.Lk)("div",w,[o.currentNews?((0,c.uX)(),(0,c.CE)("div",y,[(0,c.Lk)("a",{href:o.currentNews.url,title:o.currentNews.title,target:"_blank",rel:"noreferrer noopener"},[(0,c.Lk)("img",{src:o.currentNews.image,width:"320",height:"50",alt:o.currentNews.title},null,8,$)],8,C)])):(0,c.Q3)("",!0),(0,c.RG)(e.$slots,"search")])])):(0,c.Q3)("",!0),(0,c.Lk)("main",L,[(0,c.RG)(e.$slots,"default")]),(0,c.bF)(l,{display:"main"})])}var E=a(3751);const X={role:"navigation",class:"navigation"},S={class:"navigation__group navigation__group--main"},M={key:0,class:"navigation__item-badge"},T={key:0,class:"navigation__item-badge"},x={class:"navigation__item navigation__item--main"},O={tabindex:"0","aria-haspopup":"true"},P={class:"navigation__group navigation__group--sub"},B={key:0,class:"navigation__item navigation__item--sub"},I=["href"],F={key:1,class:"navigation__item navigation__item--sub"},R={href:"/app_dev.php/",target:"_blank"},q={key:2,class:"navigation__item navigation__item--sub"},U=["href"],j={key:3,class:"navigation__item navigation__item--sub"},D=["href"],W={class:"navigation__item navigation__item--sub"},V={class:"navigation__item navigation__item--main navigation__item--icon"},Q={tabindex:"0","aria-haspopup":"true",onclick:""},H={class:"navigation__group navigation__group--sub navigation__group--right"},G={class:"navigation__item navigation__item--sub"},z={class:"navigation__item navigation__item--sub"};function N(e,t,a,s,n,o){const i=(0,c.g2)("navigation-item");return(0,c.uX)(),(0,c.CE)("nav",X,[(0,c.Lk)("a",{class:"navigation__toggle",onClick:t[0]||(t[0]=(0,E.D$)((function(){return o.toggleNavigation&&o.toggleNavigation(...arguments)}),["prevent"]))},t[4]||(t[4]=[(0,c.Lk)("span",null,null,-1)])),(0,c.Lk)("ul",S,[(0,c.bF)(i,{to:e.routes.discover},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.navigation.discover")),1)])),_:1},8,["to"]),(0,c.bF)(i,{to:e.routes.packages},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.navigation.packages")),1),o.packageChanges>0?((0,c.uX)(),(0,c.CE)("span",M,(0,u.v_)(o.packageChanges),1)):(0,c.Q3)("",!0)])),_:1},8,["to"]),e.isGranted(o.scopes.UPDATE)?((0,c.uX)(),(0,c.Wv)(i,{key:0,to:e.routes.maintenance},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.navigation.maintenance")),1),e.hasDatabaseChanges||e.hasDatabaseWarning||e.hasDatabaseError?((0,c.uX)(),(0,c.CE)("span",T,"1")):(0,c.Q3)("",!0)])),_:1},8,["to"])):(0,c.Q3)("",!0),(0,c.Lk)("li",x,[(0,c.Lk)("a",O,(0,u.v_)(e.$t("ui.navigation.tools")),1),(0,c.Lk)("ul",P,[e.safeMode?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("li",B,[(0,c.Lk)("a",{href:o.backendUrl},(0,u.v_)(e.$t("ui.navigation.backend")),9,I)])),!e.safeMode&&e.showAppDev?((0,c.uX)(),(0,c.CE)("li",F,[(0,c.Lk)("a",R,(0,u.v_)(e.$t("ui.navigation.debug")),1)])):(0,c.Q3)("",!0),!e.safeMode&&e.showPreview?((0,c.uX)(),(0,c.CE)("li",q,[(0,c.Lk)("a",{href:o.previewUrl,target:"_blank"},(0,u.v_)(e.$t("ui.navigation.debug")),9,U)])):(0,c.Q3)("",!0),!e.safeMode&&e.showInstallTool?((0,c.uX)(),(0,c.CE)("li",j,[(0,c.Lk)("a",{href:o.installToolUrl,target:"_blank"},(0,u.v_)(e.$t("ui.navigation.installTool")),9,D)])):(0,c.Q3)("",!0),(0,c.bF)(i,{to:e.routes.logViewer,sub:""},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.navigation.logViewer")),1)])),_:1},8,["to"]),(0,c.Lk)("li",W,[(0,c.Lk)("a",{href:"#",onClick:t[1]||(t[1]=(0,E.D$)((function(){return o.phpinfo&&o.phpinfo(...arguments)}),["prevent"]))},(0,u.v_)(e.$t("ui.navigation.phpinfo")),1)])])]),(0,c.Lk)("li",V,[(0,c.Lk)("a",Q,[t[5]||(t[5]=(0,c.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 204.993 204.993"},[(0,c.Lk)("path",{d:"M113.711 202.935H92.163c-3.242 0-4.373.007-15.421-27.364l-8.532-3.468c-23.248 10.547-26 10.547-26.92 10.547h-1.779l-1.517-1.303-15.275-14.945c-2.323-2.319-3.128-3.124 8.825-30.137l-3.479-8.231C0 117.977 0 116.81 0 113.496V92.37c0-3.31 0-4.355 27.972-15.171l3.479-8.249c-12.644-26.602-11.774-27.428-9.28-29.776l16.427-16.105 2.04-.064c2.48 0 11.681 3.357 27.371 9.981l8.507-3.454C86.758 2.054 88.015 2.058 91.246 2.058h21.548c3.228 0 4.363.004 15.411 27.382l8.546 3.443c23.212-10.533 26-10.533 26.927-10.533h1.768l1.517 1.281 15.275 14.92c2.323 2.344 3.117 3.146-8.836 30.17l3.489 8.278c28.101 10.014 28.101 11.177 28.101 14.498v21.101c0 3.232 0 4.37-28.008 15.192l-3.457 8.256c12.58 26.487 11.749 27.317 9.394 29.69l-16.552 16.205-2.051.057c-2.469 0-11.649-3.361-27.317-9.992l-8.557 3.457c-10.27 27.472-11.437 27.472-14.733 27.472zm-19.308-8.722h16.996c1.95-3.976 6.166-14.516 9.541-23.595l.68-1.807 15.475-6.249 1.664.705c9.223 3.933 20.124 8.292 24.372 9.631l11.943-11.681c-1.517-4.205-6.116-14.494-10.264-23.173l-.837-1.764 6.403-15.285 1.743-.673c9.316-3.586 20.11-8.013 24.143-10.032V93.88c-4.08-1.918-14.831-6.009-24.096-9.294l-1.814-.648-6.445-15.3.769-1.725c3.965-8.947 8.375-19.501 9.788-23.753l-11.975-11.706c-3.865 1.349-14.688 5.987-23.817 10.153l-1.7.78-15.475-6.238-.691-1.721c-3.658-9.13-8.203-19.716-10.253-23.635H93.569c-1.961 3.965-6.163 14.509-9.53 23.585l-.669 1.797-15.432 6.27-1.664-.712c-9.244-3.926-20.167-8.278-24.429-9.616L29.923 43.805c1.496 4.198 6.109 14.48 10.243 23.159l.848 1.768-6.435 15.278-1.732.669c-9.301 3.582-20.077 8.006-24.111 10.017v16.431c4.08 1.925 14.82 6.027 24.079 9.326l1.8.655 6.446 15.249-.769 1.721c-3.965 8.94-8.371 19.48-9.788 23.724l12 11.742c3.854-1.36 14.663-5.998 23.803-10.168l1.711-.784 15.443 6.277.691 1.721c3.669 9.133 8.2 19.701 10.251 23.623zm8.092-56.56c-19.759 0-35.849-15.772-35.849-35.159 0-19.372 16.087-35.134 35.849-35.134 19.748 0 35.799 15.765 35.799 35.134 0 19.387-16.051 35.159-35.799 35.159zm0-61.563c-14.956 0-27.113 11.846-27.113 26.405 0 14.569 12.154 26.426 27.113 26.426 14.931 0 27.078-11.857 27.078-26.426-.004-14.559-12.147-26.405-27.078-26.405z"})],-1)),(0,c.Lk)("span",null,(0,u.v_)(e.$t("ui.navigation.advanced")),1)]),(0,c.Lk)("ul",H,[(0,c.bF)(i,{to:e.routes.userManager,sub:""},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.navigation.users")),1)])),_:1},8,["to"]),(0,c.Lk)("li",G,[(0,c.Lk)("a",{href:"#",onClick:t[2]||(t[2]=(0,E.D$)((function(){return o.systemCheck&&o.systemCheck(...arguments)}),["prevent"]))},(0,u.v_)(e.$t("ui.navigation.systemCheck")),1)]),(0,c.Lk)("li",z,[(0,c.Lk)("a",{href:"#",onClick:t[3]||(t[3]=(0,E.D$)((function(){return e.logout&&e.logout(...arguments)}),["prevent"]))},(0,u.v_)(e.$t("ui.navigation.logout")),1)])])])])])}var K=a(707);const J=["href","onClick","onKeypress"];function Z(e,t,a,s,n,o){const i=(0,c.g2)("router-link");return(0,c.uX)(),(0,c.Wv)(i,{to:a.to,custom:""},{default:(0,c.k6)((t=>{let{isActive:s,href:n,navigate:o}=t;return[(0,c.Lk)("li",{class:(0,u.C4)({["navigation__item navigation__item--"+(a.sub?"sub":"main")]:!0,"router-link-active":s})},[(0,c.Lk)("a",{href:n,onClick:o,onKeypress:(0,E.jR)(o,["enter"])},[(0,c.RG)(e.$slots,"default")],40,J)],2)]})),_:3},8,["to"])}var Y={props:{to:Object,sub:Boolean}},ee=a(6262);const te=(0,ee.A)(Y,[["render",Z]]);var ae=te,se=a(70),ne={components:{NavigationItem:ae},data:()=>({routes:r.A,databaseChanges:0}),computed:{...(0,h.aH)(["safeMode"]),...(0,h.aH)("contao/install-tool",{showInstallTool:"isSupported"}),...(0,h.aH)("contao/access-key",{showAppDev:"isEnabled"}),...(0,h.aH)("contao/jwt-cookie",{showPreview:"isDebugEnabled"}),...(0,h.aH)("server/contao",["contaoConfig"]),...(0,h.L8)("auth",["isGranted"]),...(0,h.L8)("packages",["totalChanges"]),...(0,h.L8)("packages/uploads",["totalUploads"]),...(0,h.L8)("server/database",{hasDatabaseChanges:"hasChanges",hasDatabaseWarning:"hasWarning",hasDatabaseError:"hasError"}),scopes:()=>se.A,packageChanges:e=>e.totalChanges+e.totalUploads,backendUrl:e=>e.contaoConfig?.backend?.route_prefix||"/contao",previewUrl:e=>`${e.contaoConfig?.backend?.preview_script||"/preview.php"}/`,installToolUrl:e=>`${e.contaoConfig?.backend?.route_prefix||"/contao"}/install`},methods:{...(0,h.i0)("auth",["logout"]),toggleNavigation(){document.body.classList.toggle("nav-active")},phpinfo(){const e=window.open();e&&(e.document.open(),e.document.write('

'),e.document.write(this.$t("ui.navigation.phpinfoLoading")),e.document.write("

"),this.$store.dispatch("server/phpinfo/get").then((t=>{e.document.write(t),e.document.close(),e.document.body.removeChild(e.document.querySelector(".phpinfo__loading"))})))},systemCheck(){window.localStorage.removeItem("contao_manager_booted"),this.$store.commit("setView",K.A.BOOT)}},mounted(){this.isGranted(se.A.UPDATE)&&(this.$store.dispatch("contao/install-tool/fetch"),this.$store.dispatch("contao/jwt-cookie/get").catch((()=>{})),this.$store.dispatch("contao/access-key/get").catch((()=>{})),this.$store.dispatch("server/database/get"))}};const oe=(0,ee.A)(ne,[["render",N]]);var ie=oe,le=a(1496),re={components:{NavigationFragment:ie,FooterFragment:le.A},computed:{...(0,h.aH)("algolia",["news"]),...(0,h.L8)("server/contao",["badgeTitle"]),currentNews:e=>e.news.length?e.news[0]:null},mounted(){this.$store.dispatch("server/contao/get")}};const ce=(0,ee.A)(re,[["render",A]]);var ue=ce,de=a(5039),pe=a(1909),ge={components:{DiscoverList:de.A,InstallButton:pe.A},computed:{...(0,h.L8)("packages",["packageSuggested","contaoSupported","packageConstraint"]),wrapper:()=>ue}};const he=(0,ee.A)(ge,[["render",g]]);var me=he;const ke={class:"package-list"},ve={key:1,class:"package-list__headline"},be={key:2,class:"package-list__headline"},_e={key:0,class:"package-actions__inner"},fe={class:"package-actions__text"},we=["disabled"],ye={key:1,class:"package-actions__inner"},Ce={class:"package-actions__text"},$e=["disabled"];function Le(e,t,a,s,n,o){const i=(0,c.g2)("package-uploads"),l=(0,c.g2)("composer-package"),r=(0,c.g2)("loading-button"),d=(0,c.g2)("cloud-status"),p=(0,c.g2)("link-menu"),g=(0,c.g2)("button-group"),h=(0,c.g2)("package-base");return(0,c.uX)(),(0,c.Wv)(h,{onStartUpload:t[3]||(t[3]=e=>o.openFileSelector())},{actions:(0,c.k6)((()=>[e.hasUploads&&!e.uploading?((0,c.uX)(),(0,c.CE)("div",_e,[(0,c.Lk)("p",fe,(0,u.v_)(e.$tc("ui.packages.uploadMessage",e.totalUploads)),1),(0,c.Lk)("button",{class:"package-actions__button widget-button widget-button--primary",disabled:!e.canConfirmUploads||o.removingUploads,onClick:t[0]||(t[0]=function(){return o.confirmUploads&&o.confirmUploads(...arguments)})},(0,u.v_)(e.$t("ui.packages.uploadApply")),9,we),(0,c.bF)(r,{class:"package-actions__button",color:"alert",loading:o.removingUploads,onClick:o.removeUploads},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.packages.uploadReset")),1)])),_:1},8,["loading","onClick"])])):e.totalChanges&&!e.uploading?((0,c.uX)(),(0,c.CE)("div",ye,[(0,c.bF)(d,{"button-class":"package-actions__button package-actions__button--cloud"}),(0,c.Lk)("p",Ce,(0,u.v_)(e.$tc("ui.packages.changesMessage",e.totalChanges)),1),(0,c.bF)(g,{class:"package-actions__button-group","align-top":"",type:"primary",icon:"update",loading:e.cloudLoading,disabled:e.cloudError,"more-disabled":e.cloudLoading||e.cloudError,label:e.$t("ui.packages.changesApply"),onClick:t[1]||(t[1]=t=>e.hasLockFile?o.applyChanges():o.applyChangesAll())},{default:(0,c.k6)((()=>[(0,c.bF)(p,{align:"right",valign:"top",items:o.applyActions,color:"primary"},null,8,["items"])])),_:1},8,["loading","disabled","more-disabled","label"]),(0,c.Lk)("button",{class:"package-actions__button widget-button widget-button--alert",disabled:!e.canResetChanges&&!e.confirmed.length,onClick:t[2]||(t[2]=function(){return o.resetChanges&&o.resetChanges(...arguments)})},(0,u.v_)(e.$t("ui.packages.changesReset")),9,$e)])):(0,c.Q3)("",!0)])),default:(0,c.k6)((()=>[(0,c.Lk)("div",ke,[!1!==e.uploads&&e.isGranted(o.scopes.INSTALL)?((0,c.uX)(),(0,c.Wv)(i,{key:0,ref:"uploader"},null,512)):(0,c.Q3)("",!0),o.hasAdded?((0,c.uX)(),(0,c.CE)("h2",ve,(0,u.v_)(e.$t("ui.packagelist.added")),1)):(0,c.Q3)("",!0),((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(o.addedPackages,(e=>((0,c.uX)(),(0,c.Wv)(l,{data:e,key:e.name},null,8,["data"])))),128)),o.showHeadline?((0,c.uX)(),(0,c.CE)("h2",be,(0,u.v_)(e.$t("ui.packagelist.installed")),1)):(0,c.Q3)("",!0),((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(o.installedPackages,(e=>((0,c.uX)(),(0,c.Wv)(l,{data:e,key:e.name},null,8,["data"])))),128))])])),_:1})}a(8111),a(2489);const Ae={key:0,class:"package-tools"},Ee=["disabled"],Xe=["disabled","title"];function Se(e,t,a,s,n,o){const i=(0,c.g2)("main-layout");return(0,c.uX)(),(0,c.Wv)(i,null,{default:(0,c.k6)((()=>[e.isGranted(o.scopes.UPDATE)?((0,c.uX)(),(0,c.CE)("section",Ae,[(0,c.RG)(e.$slots,"search",{},(()=>[(0,c.Lk)("button",{class:"package-tools__button widget-button widget-button--update",disabled:e.totalChanges>0||e.uploading,onClick:t[0]||(t[0]=function(){return e.updateAll&&e.updateAll(...arguments)})},(0,u.v_)(e.$t("ui.packages.updateButton")),9,Ee),(0,c.Lk)("button",{class:"package-tools__button widget-button widget-button--upload",disabled:!e.uploads||e.uploading||!e.isGranted(o.scopes.INSTALL),title:o.uploadError,onClick:t[1]||(t[1]=(0,E.D$)((t=>e.$emit("start-upload")),["prevent"]))},(0,u.v_)(e.$t("ui.packages.uploadButton")),9,Xe)]))])):(0,c.Q3)("",!0),(0,c.RG)(e.$slots,"default"),(0,c.Lk)("div",{class:(0,u.C4)({"package-actions":!0,"package-actions--active":!o.slotEmpty(e.$slots.actions)})},[(0,c.RG)(e.$slots,"actions")],2)])),_:3})}var Me=a(9451),Te={components:{MainLayout:ue},computed:{...(0,h.L8)("auth",["isGranted"]),...(0,h.L8)("packages",["totalChanges"]),...(0,h.aH)("packages/uploads",["uploads","uploading"]),scopes:()=>se.A,uploadError:e=>!1===e.uploads?e.$t("ui.packages.uploadUnsupported"):e.isGranted(se.A.INSTALL)?"":e.$t("ui.error.permission")},methods:{slotEmpty:Me.A,...(0,h.i0)("packages",["updateAll"])}};const xe=(0,ee.A)(Te,[["render",Se]]);var Oe=xe,Pe=a(7591);const Be={key:0},Ie={class:"package-uploads__overlay"},Fe={key:0,class:"package-list__headline"};function Re(e,t,a,s,n,o){const i=(0,c.g2)("file-upload"),l=(0,c.g2)("uploading-package"),r=(0,c.g2)("uploaded-package");return null!==e.uploads?((0,c.uX)(),(0,c.CE)("div",Be,[(0,c.bo)((0,c.Lk)("div",Ie,[(0,c.Lk)("div",null,[t[0]||(t[0]=(0,c.Lk)("img",{src:Pe,alt:"",width:"128",height:"128"},null,-1)),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.packages.uploadOverlay")),1)])],512),[[E.aG,e.$refs.uploader&&e.$refs.uploader.dropActive]]),(0,c.bF)(i,{name:"package",ref:"uploader","post-action":"api/packages/uploads",multiple:!0,drop:!0,"drop-directory":!1,"chunk-enabled":!0,chunk:{action:"api/packages/uploads"},onInput:e.setFiles,onInputFile:o.updateFile,onInputFilter:o.filterFile},null,8,["onInput","onInputFile","onInputFilter"]),e.$refs.uploader?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[e.hasUploads||e.files.length?((0,c.uX)(),(0,c.CE)("h2",Fe,(0,u.v_)(e.$t("ui.packagelist.uploads")),1)):(0,c.Q3)("",!0),((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(e.files,(t=>((0,c.uX)(),(0,c.Wv)(l,{file:t,uploader:e.$refs.uploader,key:t.id},null,8,["file","uploader"])))),128)),((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(e.unconfirmedUploads,(t=>((0,c.uX)(),(0,c.Wv)(r,{upload:t,uploader:e.$refs.uploader,key:t.id},null,8,["upload","uploader"])))),128))],64)):(0,c.Q3)("",!0)])):(0,c.Q3)("",!0)}var qe=a(8568),Ue=a.n(qe);const je={class:"package__version package__version--release"};function De(e,t,a,s,n,o){const i=(0,c.g2)("progress-bar"),l=(0,c.g2)("base-package");return(0,c.uX)(),(0,c.Wv)(l,{title:a.file.name},{release:(0,c.k6)((()=>[(0,c.bF)(i,{amount:a.file.progress},null,8,["amount"]),(0,c.Lk)("div",je,[(0,c.Lk)("p",null,[(0,c.Lk)("strong",null,(0,u.v_)(o.filesize),1)])])])),_:1},8,["title"])}const We={key:0,class:"package__hint"},Ve={class:"package__inside"},Qe={class:"package__details"},He={class:"package__about"},Ge=["title"],ze={class:"package__title"},Ne={class:"package__description"},Ke={class:"package__additional"},Je={class:"package__release"},Ze={class:"package__actions"};function Ye(e,t,a,s,n,o){const i=(0,c.g2)("package-logo");return(0,c.uX)(),(0,c.CE)("article",{class:(0,u.C4)(["package",a.hint||!o.slotEmpty(e.$slots.hint)?"is--hint":""])},[a.hint||!o.slotEmpty(e.$slots.hint)?((0,c.uX)(),(0,c.CE)("div",We,[(0,c.RG)(e.$slots,"hint",{},(()=>[a.hintClose?((0,c.uX)(),(0,c.CE)("a",{key:0,href:"#",class:"package__hint-close",onClick:t[0]||(t[0]=(0,E.D$)((t=>e.$emit("close-hint")),["prevent"]))},(0,u.v_)(a.hintClose),1)):(0,c.Q3)("",!0),(0,c.Lk)("p",null,(0,u.v_)(a.hint),1)]))])):(0,c.Q3)("",!0),(0,c.Lk)("div",Ve,[(0,c.bF)(i,{class:"package__icon",src:a.logo},null,8,["src"]),(0,c.Lk)("div",Qe,[(0,c.Lk)("div",He,[(0,c.Lk)("h1",{class:(0,u.C4)({package__headline:!0,"package__headline--badge":a.badge})},[a.badge?((0,c.uX)(),(0,c.CE)("span",{key:0,class:"package__badge",title:a.badge.title},(0,u.v_)(a.badge.text),9,Ge)):(0,c.Q3)("",!0),(0,c.Lk)("span",ze,(0,u.v_)(a.title),1)],2),(0,c.Lk)("p",Ne,(0,u.v_)(a.description),1),(0,c.Lk)("p",Ke,[(0,c.RG)(e.$slots,"additional")])]),(0,c.Lk)("div",Je,[(0,c.RG)(e.$slots,"release",{},(()=>[t[1]||(t[1]=(0,c.Lk)("div",null,null,-1))]))]),(0,c.Lk)("fieldset",Ze,[(0,c.RG)(e.$slots,"actions",{},(()=>[t[2]||(t[2]=(0,c.Lk)("div",null,null,-1))]))])])]),(0,c.RG)(e.$slots,"features")],2)}var et=a(5951),tt={components:{PackageLogo:et.A},props:{title:String,logo:String,badge:Object,description:String,hint:String,hintClose:String},methods:{slotEmpty:Me.A}};const at=(0,ee.A)(tt,[["render",Ye]]);var st=at;const nt={class:"progress-bar"};function ot(e,t,a,s,n,o){return(0,c.uX)(),(0,c.CE)("div",nt,[(0,c.Lk)("div",{class:"progress-bar__label",ref:"bar"},(0,u.v_)(a.label?a.label:`${o.progress}%`),513),(0,c.Lk)("div",{class:"progress-bar__bar",style:(0,u.Tr)(`width:${o.progress}%`)},[(0,c.Lk)("span",{style:(0,u.Tr)(`width:${e.width}px`)},(0,u.v_)(a.label?a.label:`${o.progress}%`),5)],4)])}var it={props:{amount:[String,Number],label:String},data:()=>({width:0}),computed:{progress(){return Math.floor(this.amount)}},methods:{updateWidth(){this.$refs.bar&&(this.width=this.$refs.bar.clientWidth)}},mounted(){setTimeout(this.updateWidth,0)}};const lt=(0,ee.A)(it,[["render",ot]]);var rt=lt,ct={components:{ProgressBar:rt,BasePackage:st},props:{file:{type:Object,required:!0},uploader:{type:Object,required:!0}},computed:{filesize(){let e=["KB","MB","GB"],t="Bytes",a=this.file.size;while(a>1024)a/=1024,t=e.shift();return`${Math.round(100*a)/100} ${t}`}}};const ut=(0,ee.A)(ct,[["render",De]]);var dt=ut;const pt={class:"package__version package__version--release"},gt={key:0},ht={key:1},mt={key:2},kt=["disabled"];function vt(e,t,a,s,n,o){const i=(0,c.g2)("progress-bar"),l=(0,c.g2)("loading-button"),r=(0,c.g2)("base-package"),d=(0,c.g2)("composer-package");return!a.upload.success||a.upload.error?((0,c.uX)(),(0,c.Wv)(r,{key:0,title:a.upload.name,hint:o.hintUploading},(0,c.eX)({release:(0,c.k6)((()=>[(0,c.bF)(i,{amount:o.progress},null,8,["amount"]),(0,c.Lk)("div",pt,[(0,c.Lk)("p",null,[(0,c.Lk)("strong",null,(0,u.v_)(o.filesize(a.upload.size)),1)])])])),actions:(0,c.k6)((()=>[(0,c.bF)(l,{color:"alert",icon:"trash",loading:o.removing,onClick:o.removeUpload},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.package.removeButton")),1)])),_:1},8,["loading","onClick"])])),_:2},[a.upload.error?{name:"hint",fn:(0,c.k6)((()=>[(0,c.Lk)("p",null,[(0,c.eW)((0,u.v_)(a.upload.error)+" ",1),a.upload.exception?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[(0,c.eW)((0,u.v_)(a.upload.exception),1)],64)):(0,c.Q3)("",!0)])])),key:"0"}:void 0]),1032,["title","hint"])):((0,c.uX)(),(0,c.Wv)(d,{key:1,"uncloseable-hint":"",data:o.pkg},{hint:(0,c.k6)((()=>[e.isDuplicate(a.upload.id,o.pkg.name)?((0,c.uX)(),(0,c.CE)("p",gt,(0,u.v_)(e.$t("ui.packages.uploadDuplicate")),1)):e.versionInstalled(o.pkg.name,o.pkg.version)?((0,c.uX)(),(0,c.CE)("p",ht,(0,u.v_)(e.$t("ui.packages.uploadInstalled")),1)):o.isCompatible?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("p",mt,(0,u.v_)(e.$t("ui.package.incompatible",{package:o.pkg.name,constraint:e.packageConstraint("contao/manager-bundle")})),1))])),actions:(0,c.k6)((()=>[(0,c.Lk)("button",{class:"widget-button widget-button--primary widget-button--add",disabled:!o.canBeInstalled,onClick:t[0]||(t[0]=function(){return o.addPackage&&o.addPackage(...arguments)})},(0,u.v_)(e.$t("ui.package.installButton")),9,kt),(0,c.bF)(l,{color:"alert",icon:"trash",loading:o.removing,onClick:o.removeUpload},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.package.removeButton")),1)])),_:1},8,["loading","onClick"])])),_:1},8,["data"]))}a(4114);var bt=a(4960),_t=a(416);const ft={key:0,class:"package__version package__version--additional"},wt=["title"],yt={key:0,class:"package__version-update package__version-update--error"},Ct={key:1,class:"package__version-update package__version-update--available"},$t={key:2,class:"package__version-update package__version-update--none"},Lt=["title"],At={key:1,class:"composer-package__stats composer-package__stats--license"},Et=["title"],Xt={key:0,class:"package__version package__version--release"},St=["title"],Mt={key:0,class:"package__version-update package__version-update--error"},Tt={key:1,class:"package__version-update package__version-update--available"},xt={key:2,class:"package__version-update package__version-update--none"},Ot=["title"],Pt=["disabled"],Bt=["disabled"],It=["disabled"],Ft=["disabled"],Rt={class:"package__features"};function qt(e,t,a,s,n,o){const i=(0,c.g2)("router-link"),l=(0,c.g2)("package-constraint"),r=(0,c.g2)("details-button"),d=(0,c.g2)("button-group"),p=(0,c.g2)("feature-package"),g=(0,c.g2)("base-package");return(0,c.uX)(),(0,c.Wv)(g,{class:(0,u.C4)({"package--contao":e.isContao}),title:o.packageData.title||a.data.name,logo:o.packageData.logo,badge:o.badge,description:o.packageData.description,hint:o.packageHint,"hint-close":o.packageHintClose,onCloseHint:o.restore},(0,c.eX)({additional:(0,c.k6)((()=>[o.packageData.version?((0,c.uX)(),(0,c.CE)("div",ft,[(0,c.Lk)("strong",{title:o.packageData.time?o.datimFormat(o.packageData.time):""},(0,u.v_)(e.$t("ui.package.version",{version:o.packageData.version})),9,wt),o.packageData.update?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[o.packageData.update.valid?o.packageData.update.latest?((0,c.uX)(),(0,c.CE)("div",$t,[(0,c.eW)((0,u.v_)(e.$t("ui.package.updateLatest"))+" ",1),o.packageData.latest&&!o.packageData.latest.active?((0,c.uX)(),(0,c.CE)("span",{key:0,class:"package__version-latest",title:e.$t("ui.package.updateConstraint")},null,8,Lt)):(0,c.Q3)("",!0)])):((0,c.uX)(),(0,c.CE)("div",Ct,(0,u.v_)(e.$t("ui.package.updateAvailable",{version:o.packageData.update.version})),1)):((0,c.uX)(),(0,c.CE)("div",yt,(0,u.v_)(e.$t("ui.package.updateUnknown")),1))],64)):(0,c.Q3)("",!0)])):(0,c.Q3)("",!0),o.license?((0,c.uX)(),(0,c.CE)("span",At,(0,u.v_)(o.license),1)):(0,c.Q3)("",!0),o.packageData.contaoVersions&&!e.isContao?((0,c.uX)(),(0,c.CE)("ul",{key:2,class:"composer-package__stats composer-package__stats--versions",title:`${e.$t("ui.package.contaoVersion")} ${o.packageData.contaoVersions.join(", ")}`},[((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(o.packageData.contaoVersions,((e,t)=>((0,c.uX)(),(0,c.CE)("li",{class:"composer-package__stats--version",key:t},(0,u.v_)(e),1)))),128))],8,Et)):(0,c.Q3)("",!0),o.packageData.funding?((0,c.uX)(),(0,c.Wv)(i,{key:3,class:"composer-package__stats composer-package__stats--funding",to:{query:{p:a.data.name}}},{default:(0,c.k6)((()=>t[4]||(t[4]=[(0,c.eW)(" ")]))),_:1},8,["to"])):(0,c.Q3)("",!0)])),release:(0,c.k6)((()=>[(0,c.RG)(e.$slots,"release",{},(()=>[(0,c.bF)(l,{class:"package__constraint",data:a.data},null,8,["data"]),o.packageData.version?((0,c.uX)(),(0,c.CE)("div",Xt,[(0,c.Lk)("strong",{title:o.packageData.time?o.datimFormat(o.packageData.time):""},(0,u.v_)(e.$t("ui.package.version",{version:o.packageData.version})),9,St),o.packageData.update?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[o.packageData.update.valid?o.packageData.update.latest?((0,c.uX)(),(0,c.CE)("div",xt,[(0,c.eW)((0,u.v_)(e.$t("ui.package.updateLatest"))+" ",1),o.packageData.latest&&!o.packageData.latest.active?((0,c.uX)(),(0,c.CE)("span",{key:0,class:"package__version-latest",title:e.$t("ui.package.updateConstraint")},null,8,Ot)):(0,c.Q3)("",!0)])):((0,c.uX)(),(0,c.CE)("div",Tt,(0,u.v_)(e.$t("ui.package.updateAvailable",{version:o.packageData.update.version})),1)):((0,c.uX)(),(0,c.CE)("div",Mt,(0,u.v_)(e.$t("ui.package.updateUnknown")),1))],64)):(0,c.Q3)("",!0)])):(0,c.Q3)("",!0)]))])),actions:(0,c.k6)((()=>[(0,c.RG)(e.$slots,"actions",{},(()=>[a.data.name?((0,c.uX)(),(0,c.Wv)(r,{key:0,name:a.data.name},null,8,["name"])):(0,c.Q3)("",!0),e.isGranted(o.scopes.UPDATE)?((0,c.uX)(),(0,c.CE)(c.FK,{key:1},[e.isContao?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[e.isRequired?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("button",{key:0,class:"widget-button widget-button--update",disabled:e.isModified,onClick:t[0]||(t[0]=function(){return e.update&&e.update(...arguments)})},(0,u.v_)(e.$t("ui.package.updateButton")),9,Pt))],64)):((0,c.uX)(),(0,c.CE)(c.FK,{key:1},[e.isMissing?((0,c.uX)(),(0,c.CE)("button",{key:0,class:"widget-button widget-button--primary widget-button--add",onClick:t[1]||(t[1]=function(){return e.install&&e.install(...arguments)}),disabled:e.willBeInstalled},(0,u.v_)(e.$t("ui.package.installButton")),9,Bt)):e.isRequired?((0,c.uX)(),(0,c.CE)("button",{key:1,class:"widget-button widget-button--alert widget-button--trash",onClick:t[2]||(t[2]=function(){return e.uninstall&&e.uninstall(...arguments)}),disabled:e.willBeRemoved},(0,u.v_)(e.$t("ui.package.removeButton")),9,It)):e.isRootInstalled?((0,c.uX)(),(0,c.Wv)(d,{key:2,label:e.$t("ui.package.updateButton"),icon:"update",disabled:e.isModified,onClick:e.update},{default:(0,c.k6)((()=>[(0,c.Lk)("button",{class:"widget-button widget-button--alert widget-button--trash",onClick:t[3]||(t[3]=function(){return e.uninstall&&e.uninstall(...arguments)}),disabled:e.willBeRemoved},(0,u.v_)(e.$t("ui.package.removeButton")),9,Ft)])),_:1},8,["label","disabled","onClick"])):(0,c.Q3)("",!0)],64))],64)):(0,c.Q3)("",!0)]))])),_:2},[o.slotEmpty(e.$slots.hint)?void 0:{name:"hint",fn:(0,c.k6)((()=>[(0,c.RG)(e.$slots,"hint")])),key:"0"},e.packageFeatures(a.data.name)?.length?{name:"features",fn:(0,c.k6)((()=>[(0,c.Lk)("section",Rt,[((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(e.packageFeatures(a.data.name),(e=>((0,c.uX)(),(0,c.Wv)(p,{key:e,name:e},null,8,["name"])))),128))])])),key:"1"}:void 0]),1032,["class","title","logo","badge","description","hint","hint-close","onCloseHint"])}var Ut=a(4210),jt=a(266),Dt=a(8200);const Wt={key:0,class:"feature-package"},Vt={class:"feature-package__name"},Qt={key:0,class:"feature-package__hint"},Ht=["title"],Gt=["title"],zt={class:"feature-package__actions"},Nt=["title"];function Kt(e,t,a,s,n,o){const i=(0,c.g2)("details-button");return e.isRequired||e.isMissing||e.isRootInstalled||e.willBeInstalled?((0,c.uX)(),(0,c.CE)("article",Wt,[(0,c.Lk)("p",{class:(0,u.C4)(["feature-package__text",{"feature-package__text--hint":this.packageHint}])},[(0,c.Lk)("strong",Vt,(0,u.v_)(o.packageTitle),1),this.packageHint?((0,c.uX)(),(0,c.CE)("span",Qt,(0,u.v_)(o.packageHint),1)):e.isMissing?((0,c.uX)(),(0,c.CE)("span",{key:1,class:"feature-package__badge",title:e.$t("ui.package.removedText")},(0,u.v_)(e.$t("ui.package.removedTitle")),9,Ht)):e.isRequired?((0,c.uX)(),(0,c.CE)("span",{key:2,class:"feature-package__badge",title:e.$t("ui.package.requiredText")},(0,u.v_)(e.$t("ui.package.requiredTitle")),9,Gt)):((0,c.uX)(),(0,c.CE)(c.FK,{key:3},[(0,c.eW)((0,u.v_)(e.metadata.description),1)],64))],2),(0,c.Lk)("div",zt,[o.packageHint&&e.isGranted(o.scopes.INSTALL)?((0,c.uX)(),(0,c.CE)("button",{key:0,class:"feature-package__restore",onClick:t[0]||(t[0]=function(){return o.restore&&o.restore(...arguments)})},(0,u.v_)(e.$t("ui.package.hintRevert")),1)):(0,c.Q3)("",!0),(0,c.bF)(i,{small:"",name:a.name},null,8,["name"]),(e.isRequired||e.isRootInstalled)&&!e.willBeRemoved&&e.isGranted(o.scopes.INSTALL)?((0,c.uX)(),(0,c.CE)("button",{key:1,title:e.$t("ui.package.removeButton"),class:"widget-button widget-button--alert widget-button--trash widget-button--small",onClick:t[1]||(t[1]=function(){return e.uninstall&&e.uninstall(...arguments)})},null,8,Nt)):(0,c.Q3)("",!0)])])):(0,c.Q3)("",!0)}var Jt=a(9071),Zt={mixins:[Dt.A],components:{DetailsButton:Jt.A},props:{name:String,reason:String},computed:{...(0,h.L8)("auth",["isGranted"]),scopes:()=>se.A,data:e=>({name:e.name}),packageTitle(){return this.metadata?.name?this.metadata.title||this.metadata.name:this.data.name},packageHint(){return this.willBeRemoved?this.$t("ui.package.hintRemoved"):this.willBeInstalled?this.$t("ui.package.hintAdded"):null}},methods:{restore(){this.$store.commit("packages/restore",this.data.name)}}};const Yt=(0,ee.A)(Zt,[["render",Kt]]);var ea=Yt,ta=a(3629),aa=a(2880),sa={mixins:[Dt.A],components:{BasePackage:st,FeaturePackage:ea,PackageConstraint:ta.A,ButtonGroup:aa.A,DetailsButton:Jt.A},props:{data:{type:Object,required:!0},hint:String,uncloseableHint:Boolean},computed:{...(0,h.L8)("auth",["isGranted"]),...(0,h.L8)("packages",["packageFeatures"]),scopes:()=>se.A,packageData:e=>Object.assign({},e.data,e.installed[e.data.name]||{},e.metadata||{}),license:e=>e.packageData.license instanceof Array?e.packageData.license.join("/"):e.packageData.license,packageHint(){return this.hint?this.hint:this.willBeRemoved||this.isMissing&&!this.willBeInstalled?this.$t("ui.package.hintRemoved"):this.isRequired?this.$t("ui.package.hintConstraint",{constraint:this.constraintRequired}):this.willBeInstalled?this.constraintAdded?this.$t("ui.package.hintConstraint",{constraint:this.constraintAdded}):this.$t("ui.package.hintConstraintBest"):this.isChanged?this.$t("ui.package.hintConstraintChange",{from:this.constraintInstalled,to:this.constraintChanged}):this.isUpdated?this.$t("ui.package.hintConstraintUpdate"):null},packageHintClose(){return this.uncloseableHint||this.isRequired&&!this.willBeRemoved&&!this.isChanged||this.isMissing&&!this.willBeInstalled?null:this.isUpdated?this.$t("ui.package.hintNoupdate"):this.$t("ui.package.hintRevert")},packageUpdates(){return this.isInstalled&&(Object.keys(this.$store.state.packages.add).length>0||Object.keys(this.$store.state.packages.change).length>0||this.$store.state.packages.update.length>0||this.$store.state.packages.remove.length>0)},badge(){return this.isRequired?{title:this.$t("ui.package.requiredText"),text:this.$t("ui.package.requiredTitle")}:this.isMissing?{title:this.$t("ui.package.removedText"),text:this.$t("ui.package.removedTitle")}:this.packageData.abandoned?{title:!0===this.packageData.abandoned?this.$t("ui.package.abandonedText"):this.$t("ui.package.abandonedReplace",{replacement:this.packageData.abandoned}),text:this.$t("ui.package.abandoned")}:null}},methods:{datimFormat:Ut.A,numberFormat:jt.A,slotEmpty:Me.A,restore(){this.$store.commit("packages/restore",this.data.name),this.$store.dispatch("packages/uploads/unconfirm",this.data.name)}}};const na=(0,ee.A)(sa,[["render",qt]]);var oa=na,ia=a(6966),la={mixins:[_t.A],components:{ProgressBar:rt,BasePackage:st,ComposerPackage:oa,LoadingButton:ia.A},props:{upload:{type:Object,required:!0},uploader:{type:Object,required:!0}},computed:{...(0,h.L8)("packages",["packageRemoved","versionInstalled","contaoSupported","packageConstraint"]),...(0,h.L8)("packages/uploads",["isDuplicate","isRemoving"]),removing:e=>e.isRemoving(e.upload.id),progress:e=>100/e.upload.size*e.upload.filesize,isTheme:e=>"contao-theme"===e.data.type||e.metadata&&"contao-theme"===e.metadata.type,isCompatible:e=>!e.data.require||e.contaoSupported(e.data.require["contao/core-bundle"]||e.data.require["contao/manager-bundle"]||null),canBeInstalled:e=>!e.isDuplicate(e.upload.id,e.pkg.name)&&!e.versionInstalled(e.pkg.name,e.pkg.version)&&!e.removing&&!e.packageRemoved(e.pkg.name)&&!e.isTheme&&e.isCompatible,data:e=>e.upload.package||{name:""},pkg:e=>Object.assign({name:e.upload.name,version:null},e.upload.package||{}),hintUploading(){return this.upload.error?this.upload.error:this.upload.size!==this.upload.filesize?this.$t("ui.packages.uploadIncomplete"):""},additional(){const e=[];return this.pkg.license&&(this.pkg.license instanceof Array?e.push(this.pkg.license.join("/")):e.push(this.pkg.license)),this.pkg.downloads&&e.push(this.$tc("ui.package.additionalDownloads",this.pkg.downloads)),this.pkg.favers&&e.push(this.$tc("ui.package.additionalStars",this.pkg.favers)),e}},methods:{filesize:bt.A,addPackage(){this.$store.dispatch("packages/uploads/confirm",this.upload.id)},removeUpload(){this.$store.dispatch("packages/uploads/remove",this.upload.id)}}};const ra=(0,ee.A)(la,[["render",vt]]);var ca=ra,ua={components:{FileUpload:Ue(),UploadingPackage:dt,UploadedPackage:ca},computed:{...(0,h.aH)("packages/uploads",["uploads","files"]),...(0,h.L8)("packages/uploads",["hasUploads","unconfirmedUploads"])},methods:{...(0,h.PY)("packages/uploads",["setUploading","setFiles"]),openFileSelector(){this.$refs.uploader&&this.$refs.uploader.$el.querySelector("input").click()},async filterFile(e,t,a){if(e&&!t&&!/\.zip$/i.test(e.name))return a()},async updateFile(e,t){this.setUploading(!this.$refs.uploader.uploaded),!t||e?(e.error&&e.xhr&&(401===e.xhr.status?this.$store.commit("setView",K.A.LOGIN):"application/problem+json"===e.xhr.getResponseHeader("Content-Type")&&this.$store.commit("setError",JSON.parse(e.response))),Boolean(e)===Boolean(t)&&t.error===e.error||this.$refs.uploader.active||(this.$refs.uploader.active=!0),this.$refs.uploader.uploaded&&e&&t&&!e.active&&t.active&&(await this.$store.dispatch("packages/uploads/load"),this.$refs.uploader.remove(e))):this.$refs.uploader.uploaded&&!this.$refs.uploader.active&&this.setFiles([])}}};const da=(0,ee.A)(ua,[["render",Re]]);var pa=da;const ga={key:0,class:"cloud-status"},ha={class:"cloud-status__headline"},ma={class:"cloud-status__version"},ka={class:"widget-button widget-button--info widget-button--link widget-button--small cloud-status__link",href:"https://composer-resolver-cloud.statuspage.io/",target:"_blank",rel:"noreferrer noopener"},va={key:1,class:"cloud-status__popup cloud-status__popup--error",tabindex:"-1"},ba={class:"cloud-status__headline cloud-status__headline--error"},_a={class:"cloud-status__error"},fa={class:"widget-button widget-button--info widget-button--link widget-button--small cloud-status__link",href:"https://composer-resolver-cloud.statuspage.io/",target:"_blank",rel:"noreferrer noopener"},wa=["title"];function ya(e,t,a,s,n,o){const i=(0,c.g2)("loading-button");return e.enabled?((0,c.uX)(),(0,c.CE)("div",ga,[(0,c.bF)(i,{class:(0,u.C4)(`cloud-status__button ${a.buttonClass}`),color:"info",icon:e.hasError?"cloud-off":"cloud",loading:e.isLoading,disabled:e.hasError,onMouseover:o.open,onMouseout:o.close,onClick:o.open},{default:(0,c.k6)((()=>[e.isReady?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[(0,c.eW)((0,u.v_)(e.$t("ui.cloudStatus.approx",{minutes:o.approxMinutes})),1)],64)):(0,c.Q3)("",!0)])),_:1},8,["class","icon","loading","disabled","onMouseover","onMouseout","onClick"]),e.isReady?(0,c.bo)(((0,c.uX)(),(0,c.CE)("div",{key:0,class:"cloud-status__popup",tabindex:"-1",onBlur:t[0]||(t[0]=function(){return o.close&&o.close(...arguments)}),onMouseover:t[1]||(t[1]=function(){return o.open&&o.open(...arguments)}),onMouseout:t[2]||(t[2]=function(){return o.close&&o.close(...arguments)}),onClick:t[3]||(t[3]=function(){return o.open&&o.open(...arguments)})},[(0,c.Lk)("h2",ha,(0,u.v_)(e.$t("ui.cloudStatus.headline")),1),(0,c.Lk)("p",ma,(0,u.v_)(e.$t("ui.cloudStatus.version",{version:e.status.appVersion})),1),(0,c.Lk)("table",null,[(0,c.Lk)("tbody",null,[(0,c.Lk)("tr",null,[(0,c.Lk)("th",null,(0,u.v_)(e.$t("ui.cloudStatus.waitingTime"))+":",1),(0,c.Lk)("td",null,(0,u.v_)(o.waitingLabel),1)]),(0,c.Lk)("tr",null,[(0,c.Lk)("th",null,(0,u.v_)(e.$t("ui.cloudStatus.jobs"))+":",1),(0,c.Lk)("td",null,(0,u.v_)(e.status.numberOfJobsInQueue>0?e.status.numberOfJobsInQueue+e.status.numberOfWorkers:`≤ ${e.status.numberOfWorkers}`),1)]),(0,c.Lk)("tr",null,[(0,c.Lk)("th",null,(0,u.v_)(e.$t("ui.cloudStatus.workers"))+":",1),(0,c.Lk)("td",null,(0,u.v_)(e.status.numberOfWorkers),1)])])]),(0,c.Lk)("a",ka,(0,u.v_)(e.$t("ui.cloudStatus.button")),1)],544)),[[E.aG,e.visible]]):e.hasError?((0,c.uX)(),(0,c.CE)("div",va,[(0,c.Lk)("h2",ba,(0,u.v_)(e.$t("ui.cloudStatus.headline")),1),(0,c.Lk)("p",_a,(0,u.v_)(e.$t("ui.cloudStatus.error")),1),(0,c.Lk)("a",fa,(0,u.v_)(e.$t("ui.cloudStatus.button")),1),(0,c.Lk)("button",{class:"widget-button widget-button--update widget-button--small",onClick:t[4]||(t[4]=function(){return o.refreshCloud&&o.refreshCloud(...arguments)}),title:e.$t("ui.cloudStatus.approxError")},null,8,wa)])):(0,c.Q3)("",!0)])):(0,c.Q3)("",!0)}var Ca={components:{LoadingButton:ia.A},props:{buttonClass:String},data:()=>({visible:!1,timeout:null,mouseout:null}),computed:{...(0,h.aH)("cloud",["enabled","status"]),...(0,h.L8)("cloud",["isLoading","isReady","hasError"]),waitingTime:e=>Math.round(e.status.numberOfJobsInQueue*(e.status.averageProcessingTimeInMs/1e3)/Math.max(e.status.numberOfWorkers,1)),waitingMinutes:e=>Math.floor(e.waitingTime/60),waitingSeconds:e=>e.waitingTime-60*e.waitingMinutes,approxMinutes:e=>Math.round(e.waitingTime/60),waitingLabel(){return this.waitingTime?this.waitingSeconds?this.$t("ui.cloudStatus.long",{minutes:this.waitingMinutes,seconds:this.waitingSeconds}):this.$t("ui.cloudStatus.short",{minutes:this.waitingMinutes}):this.$t("ui.cloudStatus.none")}},methods:{open(){clearTimeout(this.mouseout),this.visible=!0},close(){this.mouseout=setTimeout((()=>{this.visible=!1}),300)},refreshCloud(){this.$store.commit("cloud/setStatus",null),this.fetchCloud()},async fetchCloud(){await this.$store.dispatch("cloud/fetch"),this.enabled&&!this.hasError&&(this.timeout=setTimeout(this.fetchCloud,6e4))}},async mounted(){this.fetchCloud()},beforeUnmount(){clearTimeout(this.timeout)}};const $a=(0,ee.A)(Ca,[["render",ya]]);var La=$a,Aa=a(5529);const Ea=(e,t)=>"contao/manager-bundle"===e.name?-1:"contao/manager-bundle"===t.name?1:0;var Xa={components:{PackageBase:Oe,PackageUploads:pa,ComposerPackage:oa,LoadingButton:ia.A,CloudStatus:La,ButtonGroup:aa.A,LinkMenu:Aa.A},data:()=>({hasLockFile:!0}),computed:{...(0,h.L8)("auth",["isGranted"]),...(0,h.L8)("cloud",{cloudLoading:"isLoading",cloudError:"hasError"}),...(0,h.aH)("packages",{requiredPackages:"required"}),...(0,h.aH)("packages/uploads",["uploads","uploading","files","removing","confirmed"]),...(0,h.L8)("packages",["totalChanges","packageMissing","canResetChanges","visibleRequired","visibleInstalled","visibleAdded"]),...(0,h.L8)("packages/uploads",["hasUploads","totalUploads","canConfirmUploads"]),scopes:()=>se.A,addedPackages:e=>e.visibleRequired.concat(e.visibleAdded).filter((t=>!e.packageMissing(t.name))).sort(Ea),installedPackages:e=>e.visibleRequired.filter((t=>e.packageMissing(t.name))).concat(e.visibleInstalled).sort(Ea),removingUploads:e=>e.removing.length>0,showHeadline:e=>e.installedPackages.length>0&&(e.hasAdded||e.hasUploads||e.files.length),hasAdded:e=>e.addedPackages.length,applyActions(){return this.hasLockFile?[{label:this.$t("ui.packages.changesDryrun"),action:this.dryrunChanges},{label:this.$t("ui.packages.changesDryrunAll"),action:this.dryrunChangesAll},{label:this.$t("ui.packages.changesApplyAll"),action:this.applyChangesAll}]:[{label:this.$t("ui.packages.changesDryrun"),action:this.dryrunChanges}]}},methods:{openFileSelector(){this.$refs.uploader&&this.isGranted(se.A.INSTALL)&&this.$refs.uploader.openFileSelector()},confirmUploads(){this.$store.dispatch("packages/uploads/confirmAll")},async removeUploads(){await this.$store.dispatch("packages/uploads/removeAll")},dryrunChanges(){this.$store.dispatch("packages/apply",{dry_run:!0})},dryrunChangesAll(){this.$store.dispatch("packages/apply",{dry_run:!0,update_all:!0})},async applyChanges(){await this.$store.dispatch("packages/apply"),await this.$store.dispatch("packages/load")},async applyChangesAll(){await this.$store.dispatch("packages/apply",{update_all:!0}),await this.$store.dispatch("packages/load")},resetChanges(){this.$store.commit("packages/reset"),this.$store.dispatch("packages/uploads/unconfirmAll")}},mounted(){this.$store.dispatch("server/composer/get").then((e=>{this.hasLockFile=e.lock.found}))}};const Sa=(0,ee.A)(Xa,[["render",Le]]);var Ma=Sa,Ta=a.p+"img/oauth.1243e742.svg";const xa={class:"view-oauth__header"},Oa={class:"view-oauth__product"},Pa={class:"view-oauth__form"},Ba={class:"view-oauth__description"},Ia={class:"view-oauth__client"},Fa={class:"view-oauth__warning"},Ra=["disabled"],qa={class:"view-oauth__warning"},Ua=["disabled"];function ja(e,t,a,s,n,o){const i=(0,c.g2)("user-scope"),l=(0,c.g2)("loading-button"),r=(0,c.g2)("boxed-layout");return(0,c.uX)(),(0,c.Wv)(r,{slotClass:"view-oauth"},{default:(0,c.k6)((()=>[(0,c.Lk)("header",xa,[t[4]||(t[4]=(0,c.Lk)("img",{src:Ta,width:"80",height:"80",alt:"",class:"view-oauth__icon"},null,-1)),(0,c.Lk)("p",Oa,(0,u.v_)(e.$t("ui.oauth.headline")),1)]),(0,c.Lk)("main",Pa,[(0,c.Lk)("p",Ba,(0,u.v_)(e.$t("ui.oauth.description")),1),(0,c.Lk)("p",Ia,(0,u.v_)(o.hostname),1),o.scopes.length?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[(0,c.bF)(i,{class:"view-oauth__scopes",allowed:o.scopes,modelValue:e.scope,"onUpdate:modelValue":t[0]||(t[0]=t=>e.scope=t)},null,8,["allowed","modelValue"]),(0,c.Lk)("p",Fa,(0,u.v_)(e.$t("ui.oauth.domain")),1),(0,c.bF)(l,{class:"view-oauth__button",color:"primary",disabled:!e.valid,loading:e.authenticating,onClick:o.allowAccess},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.oauth.allow")),1)])),_:1},8,["disabled","loading","onClick"]),(0,c.Lk)("button",{class:"view-oauth__button widget-button",onClick:t[1]||(t[1]=(0,E.D$)((function(){return o.denyAccess&&o.denyAccess(...arguments)}),["prevent"])),disabled:!e.valid||e.authenticating},(0,u.v_)(e.$t("ui.oauth.deny")),9,Ra)],64)):((0,c.uX)(),(0,c.CE)(c.FK,{key:1},[(0,c.Lk)("p",qa,(0,u.v_)(e.$t("ui.oauth.outOfScope")),1),(0,c.Lk)("button",{class:"view-oauth__button widget-button",onClick:t[2]||(t[2]=(0,E.D$)((function(){return o.denyAccess&&o.denyAccess(...arguments)}),["prevent"])),disabled:!e.valid},(0,u.v_)(e.$t("ui.oauth.deny")),9,Ua),(0,c.Lk)("button",{class:"view-oauth__button widget-button widget-button--anchor",onClick:t[3]||(t[3]=(0,E.D$)((function(){return e.logout&&e.logout(...arguments)}),["prevent"]))},(0,u.v_)(e.$t("ui.oauth.switchUser")),1)],64))])])),_:1})}a(4603),a(7566),a(8721);var Da=a(5404);const Wa={class:"user-scope"},Va={key:0,class:"user-scope__label"};function Qa(e,t,a,s,n,o){const i=(0,c.g2)("check-box");return(0,c.uX)(),(0,c.CE)("fieldset",Wa,[a.label?((0,c.uX)(),(0,c.CE)("legend",Va,(0,u.v_)(a.label),1)):(0,c.Q3)("",!0),((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(o.all,(t=>((0,c.uX)(),(0,c.Wv)(i,{key:t,class:(0,u.C4)(["user-scope__item",{"user-scope__item--required":a.readonly||o.isRequired(t)}]),name:`${t}_${e.randomKey}`,label:e.$t(`ui.scope.${t}`),disabled:a.readonly||!o.isRequested(t)||o.isRequired(t),"model-value":e.model[t],"onUpdate:modelValue":e=>o.setEnabled(t,e)},null,8,["class","name","label","disabled","model-value","onUpdate:modelValue"])))),128))])}a(116),a(7588);var Ha=a(3018),Ga={components:{CheckBox:Ha.A},props:{allowed:Array,label:String,modelValue:String,readonly:Boolean},data:()=>({randomKey:(Math.random()+1).toString(36).substring(7),model:{admin:!1,install:!1,update:!1,read:!1}}),computed:{all:()=>Object.values(se.A).reverse(),scopes:e=>e.all.filter((t=>!e.allowed||e.allowed.includes(t))),isRequested:e=>t=>e.scopes.includes(t),isRequired:e=>t=>e.all.indexOf(t)<=e.all.indexOf(e.all.find((t=>e.scopes.includes(t))))},methods:{init(){this.all.forEach((e=>{this.model[e]=!1})),this.setEnabled(this.modelValue||this.scopes[this.scopes.length-1],!0)},setEnabled(e,t){this.all.forEach((a=>{this.isRequired(a)?this.model[a]=!0:this.model[a]=t?this.all.indexOf(a)<=this.all.indexOf(e):this.isRequested(a)&&this.all.indexOf(a)this.model[e])))}},watch:{scopes:{handler(){this.init()},deep:!0}},mounted(){this.init()}};const za=(0,ee.A)(Ga,[["render",Qa]]);var Na=za,Ka={components:{BoxedLayout:Da.A,LoadingButton:ia.A,UserScope:Na},data:()=>({valid:!1,authenticating:!1,scope:null}),computed:{...(0,h.L8)("auth",["isGranted"]),hostname:e=>e.$route.query.redirect_uri?new URL(e.$route.query.redirect_uri).hostname:"???",scopes:e=>e.$route.query.scope.split(" ").filter((t=>e.isGranted(t)))},methods:{...(0,h.i0)("auth",["logout"]),async allowAccess(){this.authenticating=!0;try{const e=await s.A.post(`api/users/${encodeURIComponent(this.$store.state.auth.username)}/tokens`,{client_id:this.$route.query.client_id,scope:this.scope});this.redirect({access_token:e.data.token,token_type:"bearer",scope:this.scope,endpoint:`${location.origin}${location.pathname}`})}catch(e){this.redirect({error:"server_error"})}},denyAccess(){this.redirect({error:"access_denied"})},redirect(e){const t=[];for(let n in e)t.push(encodeURIComponent(n)+"="+encodeURIComponent(e[n]));this.$route.query.state&&t.push(encodeURIComponent("state")+"="+encodeURIComponent(this.$route.query.state));const a=t.join("&"),s=this.$route.query.redirect_uri;s.includes("#")?document.location.href=`${s}&${a}`:document.location.href=`${s}#${a}`}},async mounted(){await this.$router.isReady();let e=!1;try{const t=new URL(this.$route.query.redirect_uri);"https:"!==t.protocol&&"localhost"!==t.hostname&&(e=!0)}catch(t){e=!0}if(!e)return"token"!==this.$route.query.response_type?this.redirect({error:"unsupported_response_type"}):this.scopes.length?this.$route.query.client_id?void(this.valid=!0):this.redirect({error:"invalid_request"}):this.redirect({error:"invalid_scope"});this.$store.commit("setError",{title:this.$t("ui.oauth.error"),detail:this.$t("ui.oauth.https"),type:"https://tools.ietf.org/html/rfc6749#section-3.1.2.1",status:400})}};const Ja=(0,ee.A)(Ka,[["render",ja]]);var Za=Ja;function Ya(e,t,a,s,n,o){const i=(0,c.g2)("rebuild-cache"),l=(0,c.g2)("database-status"),r=(0,c.g2)("maintenance-mode"),u=(0,c.g2)("install-tool"),d=(0,c.g2)("debug-mode"),p=(0,c.g2)("dump-autoload"),g=(0,c.g2)("composer-install"),h=(0,c.g2)("composer-cache"),m=(0,c.g2)("opcode-cache"),k=(0,c.g2)("main-layout");return(0,c.uX)(),(0,c.Wv)(k,null,{default:(0,c.k6)((()=>[(0,c.bF)(i),(0,c.bF)(l),(0,c.bF)(r),(0,c.bF)(u),(0,c.bF)(d),(0,c.bF)(p),(0,c.bF)(g),(0,c.bF)(h),(0,c.bF)(m)])),_:1})}const es={class:"maintenance"},ts={class:"maintenance__inside"},as={class:"maintenance__about"},ss={key:0,class:"maintenance__error"},ns={key:1,class:"maintenance__warning"},os={key:2,class:"maintenance__warning"},is={key:3,class:"maintenance__warning"},ls={key:0},rs={key:1},cs={key:2},us={class:"maintenance__actions"},ds={key:1,class:"widget-button widget-button--alert",href:"/contao/install"};function ps(e,t,a,s,n,o){const i=(0,c.g2)("loading-spinner"),l=(0,c.g2)("link-menu"),r=(0,c.g2)("button-group"),d=(0,c.g2)("loading-button"),p=(0,c.g2)("message-overlay");return(0,c.uX)(),(0,c.Wv)(p,{message:o.overlayMessage,active:e.safeMode||!1===e.supported},{default:(0,c.k6)((()=>[(0,c.Lk)("section",es,[(0,c.Lk)("div",ts,[t[2]||(t[2]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:m,alt:""})],-1)),(0,c.Lk)("div",as,[(0,c.Lk)("h1",null,[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.database.title"))+" ",1),e.hasError?((0,c.uX)(),(0,c.CE)("span",ss,(0,u.v_)(e.$t("ui.maintenance.database.error")),1)):(0,c.Q3)("",!0),e.hasWarning?((0,c.uX)(),(0,c.CE)("span",ns,(0,u.v_)(e.$t("ui.maintenance.database.warning")),1)):e.totalMigrations?((0,c.uX)(),(0,c.CE)("span",os,(0,u.v_)(e.$tc("ui.maintenance.database.migrations",e.totalMigrations)),1)):e.totalSchemaUpdates?((0,c.uX)(),(0,c.CE)("span",is,(0,u.v_)(e.$tc("ui.maintenance.database.schemaUpdates",e.totalSchemaUpdates)),1)):(0,c.Q3)("",!0)]),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.maintenance.database.description")),1),t[1]||(t[1]=(0,c.Lk)("br",null,null,-1)),e.supportsBackups||e.loadingBackups?e.supportsBackups&&e.backupFiles.length?((0,c.uX)(),(0,c.CE)("p",rs,(0,u.v_)(e.$tc("ui.maintenance.database.backupList",e.backupFiles.length,{date:o.datimFormat(e.backupFiles[0].createdAt)})),1)):e.supportsBackups?((0,c.uX)(),(0,c.CE)("p",cs,(0,u.v_)(e.$t("ui.maintenance.database.backupEmpty")),1)):(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("p",ls,(0,u.v_)(e.$t("ui.maintenance.database.backupUnsupported")),1))]),(0,c.Lk)("fieldset",us,[e.loading?((0,c.uX)(),(0,c.Wv)(i,{key:0,class:"maintenance__loader"})):e.hasError&&!e.supported?((0,c.uX)(),(0,c.CE)("a",ds,(0,u.v_)(e.$t("ui.maintenance.database.installTool")),1)):e.hasError?((0,c.uX)(),(0,c.CE)("button",{key:2,class:"widget-button widget-button--alert",onClick:t[0]||(t[0]=function(){return o.checkMigrations&&o.checkMigrations(...arguments)})},(0,u.v_)(e.$t("ui.maintenance.database.button")),1)):((0,c.uX)(),(0,c.Wv)(r,{key:3,label:e.$t("ui.maintenance.database.button"),type:e.hasChanges||e.hasWarning?"warning":"primary",icon:"database",onClick:o.checkMigrations},{default:(0,c.k6)((()=>[(0,c.bF)(l,{align:"right",items:o.advancedActions(),color:e.hasChanges?"warning":"primary"},null,8,["items","color"])])),_:1},8,["label","type","onClick"])),(0,c.bF)(d,{class:"widget-button",onClick:o.createBackup,disabled:!e.supportsBackups,loading:e.loadingBackups},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.database.createBackup")),1)])),_:1},8,["onClick","disabled","loading"])])])])])),_:1},8,["message","active"])}const gs={class:"message-overlay"},hs={key:0,class:"message-overlay__overlay"},ms={class:"message-overlay__message"};function ks(e,t,a,s,n,o){return(0,c.uX)(),(0,c.CE)("div",gs,[(0,c.Lk)("div",{class:(0,u.C4)({"message-overlay__blur":a.active})},[(0,c.RG)(e.$slots,"default")],2),a.active?((0,c.uX)(),(0,c.CE)("div",hs,[(0,c.Lk)("span",ms,(0,u.v_)(a.message),1)])):(0,c.Q3)("",!0)])}var vs={props:{message:{type:String,required:!0},active:{type:Boolean,required:!0}}};const bs=(0,ee.A)(vs,[["render",ks]]);var _s=bs,fs=a(4999),ws={components:{MessageOverlay:_s,LoadingSpinner:fs.A,ButtonGroup:aa.A,LinkMenu:Aa.A,LoadingButton:ia.A},computed:{...(0,h.aH)(["safeMode"]),...(0,h.aH)("server/database",["loading","supported","status"]),...(0,h.aH)("contao/backup",{supportsBackups:"supported",backupFiles:"files",loadingBackups:"loading"}),...(0,h.L8)("server/database",["hasError","hasChanges","hasWarning","totalMigrations","totalSchemaUpdates"]),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{datimFormat(e){return(0,Ut.A)(e,"short","long")},checkMigrations(){this.$store.commit("checkMigrations")},advancedActions(){return[{label:this.$t("ui.maintenance.database.migrationOnly"),action:()=>{this.$store.commit("checkMigrations","migrations-only")}},{label:this.$t("ui.maintenance.database.schemaOnly"),action:()=>{this.$store.commit("checkMigrations","schema-only")}}]},async createBackup(){await this.$store.dispatch("tasks/execute",{name:"contao/backup-create"}),await this.$store.dispatch("contao/backup/fetch",!1)}},mounted(){this.$store.dispatch("server/database/get"),this.$store.dispatch("contao/backup/fetch")}};const ys=(0,ee.A)(ws,[["render",ps]]);var Cs=ys,$s=a.p+"img/symfony-logo.5c162c73.svg",Ls=a.p+"img/symfony-logo--dark.ea265042.svg";const As={class:"maintenance"},Es={class:"maintenance__inside"},Xs={class:"maintenance__about"},Ss={class:"maintenance__actions"};function Ms(e,t,a,s,n,o){const i=(0,c.g2)("link-menu"),l=(0,c.g2)("button-group");return(0,c.uX)(),(0,c.CE)("section",As,[(0,c.Lk)("div",Es,[t[0]||(t[0]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{class:"color-scheme--light",src:$s,alt:""}),(0,c.Lk)("img",{class:"color-scheme--dark",src:Ls,alt:""})],-1)),(0,c.Lk)("div",Xs,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.rebuildCache.title")),1),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.maintenance.rebuildCache.description")),1)]),(0,c.Lk)("fieldset",Ss,[(0,c.bF)(l,{label:e.$t("ui.maintenance.rebuildCache.rebuildProd"),type:"primary",icon:"update",onClick:o.rebuildProd},{default:(0,c.k6)((()=>[(0,c.bF)(i,{align:"right",items:o.advancedActions(),color:"primary"},null,8,["items"])])),_:1},8,["label","onClick"])])])])}var Ts={components:{ButtonGroup:aa.A,LinkMenu:Aa.A},methods:{advancedActions(){return[{label:this.$t("ui.maintenance.rebuildCache.rebuildDev"),action:this.rebuildDev},{label:this.$t("ui.maintenance.rebuildCache.clearProd"),action:this.clearProd},{label:this.$t("ui.maintenance.rebuildCache.clearDev"),action:this.clearDev}]},rebuildProd(){this.execute("prod",!0)},rebuildDev(){this.execute("dev",!0)},clearProd(){this.execute("prod",!1)},clearDev(){this.execute("dev",!1)},execute(e,t){const a={name:"contao/rebuild-cache",config:{environment:e,warmup:t}};this.$store.dispatch("tasks/execute",a)}}};const xs=(0,ee.A)(Ts,[["render",Ms]]);var Os=xs;const Ps={class:"maintenance"},Bs={class:"maintenance__inside"},Is={class:"maintenance__about"},Fs={key:0,class:"maintenance__actions"};function Rs(e,t,a,s,n,o){const i=(0,c.g2)("loading-spinner"),l=(0,c.g2)("loading-button"),r=(0,c.g2)("message-overlay");return(0,c.uX)(),(0,c.Wv)(r,{message:o.overlayMessage,active:e.safeMode||!1===e.isSupported},{default:(0,c.k6)((()=>[(0,c.Lk)("section",Ps,[(0,c.Lk)("div",Bs,[t[0]||(t[0]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:m,alt:""})],-1)),(0,c.Lk)("div",Is,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.installTool.title")),1),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.maintenance.installTool.description")),1)]),e.safeMode||!1===e.isSupported?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("fieldset",Fs,[null===e.isLocked?((0,c.uX)(),(0,c.Wv)(i,{key:0,class:"maintenance__loader"})):e.isLocked?((0,c.uX)(),(0,c.Wv)(l,{key:1,class:"widget-button widget-button--primary widget-button--unlock",loading:e.loading,disabled:!e.isSupported,onClick:o.unlock},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.installTool.unlock")),1)])),_:1},8,["loading","disabled","onClick"])):((0,c.uX)(),(0,c.Wv)(l,{key:2,class:"widget-button widget-button--primary widget-button--lock",loading:e.loading,disabled:!e.isSupported,onClick:o.lock},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.installTool.lock")),1)])),_:1},8,["loading","disabled","onClick"]))]))])])])),_:1},8,["message","active"])}var qs={components:{MessageOverlay:_s,LoadingSpinner:fs.A,LoadingButton:ia.A},data:()=>({loading:!1}),computed:{...(0,h.aH)(["safeMode"]),...(0,h.aH)("contao/install-tool",["isLocked","isSupported"]),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{async unlock(){this.loading=!0,await this.$store.dispatch("contao/install-tool/unlock"),this.loading=!1},async lock(){this.loading=!0,await this.$store.dispatch("contao/install-tool/lock"),this.loading=!1}},mounted(){this.$store.dispatch("contao/install-tool/fetch")}};const Us=(0,ee.A)(qs,[["render",Rs]]);var js=Us;const Ds={class:"maintenance"},Ws={class:"maintenance__inside"},Vs={class:"maintenance__about"},Qs={key:0},Hs={key:0,class:"maintenance__actions"},Gs={key:1,class:"maintenance__actions"},zs={key:2,class:"maintenance__actions"};function Ns(e,t,a,s,n,o){const i=(0,c.g2)("i18n-t"),l=(0,c.g2)("loading-spinner"),r=(0,c.g2)("loading-button"),d=(0,c.g2)("message-overlay");return(0,c.uX)(),(0,c.Wv)(d,{message:o.overlayMessage,active:e.safeMode||!e.loading&&!e.supportsJwtCookie&&!e.supportsAccessKey},{default:(0,c.k6)((()=>[(0,c.Lk)("section",Ds,[(0,c.Lk)("div",Ws,[t[1]||(t[1]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:m,alt:""})],-1)),(0,c.Lk)("div",Vs,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.debugMode.title")),1),e.supportsJwtCookie?((0,c.uX)(),(0,c.CE)("p",Qs,(0,u.v_)(e.$t("ui.maintenance.debugMode.descriptionJwt")),1)):e.supportsAccessKey?((0,c.uX)(),(0,c.Wv)(i,{key:1,tag:"p",keypath:"ui.maintenance.debugMode.description"},{appDevPhp:(0,c.k6)((()=>t[0]||(t[0]=[(0,c.Lk)("code",null,"app_dev.php",-1)]))),_:1})):(0,c.Q3)("",!0)]),!e.loading||e.supportsJwtCookie||e.supportsAccessKey?e.supportsJwtCookie?((0,c.uX)(),(0,c.CE)("fieldset",Gs,[e.hasJwtDebug?((0,c.uX)(),(0,c.Wv)(r,{key:1,class:"widget-button widget-button--alert widget-button--hide",loading:e.loading,onClick:o.removeJwtCookie},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.debugMode.deactivate")),1)])),_:1},8,["loading","onClick"])):((0,c.uX)(),(0,c.Wv)(r,{key:0,class:"widget-button widget-button--primary widget-button--show",loading:e.loading,onClick:o.enableJwtDebugMode},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.debugMode.activate")),1)])),_:1},8,["loading","onClick"]))])):e.supportsAccessKey?((0,c.uX)(),(0,c.CE)("fieldset",zs,[e.hasAccessKey?((0,c.uX)(),(0,c.Wv)(r,{key:1,class:"widget-button widget-button--alert widget-button--hide",loading:e.loading,onClick:o.removeAccessKey},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.debugMode.deactivate")),1)])),_:1},8,["loading","onClick"])):((0,c.uX)(),(0,c.Wv)(r,{key:0,class:"widget-button widget-button--primary widget-button--show",loading:e.loading,onClick:o.setAccessKey},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.debugMode.activate")),1)])),_:1},8,["loading","onClick"])),e.hasAccessKey?((0,c.uX)(),(0,c.Wv)(r,{key:2,class:"widget-button widget-button--edit",loading:e.loading,onClick:o.setAccessKey},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.debugMode.credentials")),1)])),_:1},8,["loading","onClick"])):(0,c.Q3)("",!0)])):(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("fieldset",Hs,[(0,c.bF)(l,{class:"maintenance__loader"})]))])])])),_:1},8,["message","active"])}var Ks={components:{MessageOverlay:_s,LoadingSpinner:fs.A,LoadingButton:ia.A},data:()=>({supportsJwtCookie:!1,supportsAccessKey:!1,loading:!0}),computed:{...(0,h.aH)(["safeMode"]),...(0,h.aH)("contao/access-key",{hasAccessKey:"isEnabled"}),...(0,h.aH)("contao/jwt-cookie",{hasJwtDebug:"isDebugEnabled"}),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{async enableJwtDebugMode(){this.loading=!0,await this.$store.dispatch("contao/jwt-cookie/enableDebug"),this.loading=!1},async removeJwtCookie(){this.loading=!0,await this.$store.dispatch("contao/jwt-cookie/delete"),this.loading=!1},async setAccessKey(){const e=prompt(this.$t("ui.maintenance.debugMode.user"));if(!e)return;const t=prompt(this.$t("ui.maintenance.debugMode.password"));t&&(this.loading=!0,await this.$store.dispatch("contao/access-key/set",{user:e,password:t}),this.loading=!1)},async removeAccessKey(){this.loading=!0,await this.$store.dispatch("contao/access-key/delete"),this.loading=!1}},mounted(){this.$store.dispatch("contao/jwt-cookie/get").then((()=>{this.supportsJwtCookie=!0,this.supportsAccessKey=!1,this.loading=!1}),(()=>this.$store.dispatch("contao/access-key/get").then((()=>{this.supportsJwtCookie=!1,this.supportsAccessKey=!0,this.loading=!1}),(()=>{this.supportsJwtCookie=!1,this.supportsAccessKey=!1,this.loading=!1}))))}};const Js=(0,ee.A)(Ks,[["render",Ns]]);var Zs=Js,Ys="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAMAAAAPdrEwAAABgFBMVEX///94Xz5KNyUGBQX15cxyWjucYTRqVDgAAACJVjD//+oXFxb8/PwdHRz5+fkICg709PR9ZEH///IoJyYQERMtLS2UXDI4LCBbPiciISH/+d5hTzVWRjAuJBvV1dX77dPOzs+mZzb//uNubnBLTEw4Myz04snv8PD/9No5ODY+PTqWl5cUCwPa2tump6eDVC9IRkP15Mvs7Oz+8daHbEnHyMlBQT+xp5abnJ3///je39/m5udYWFXCwsNWU0uRkZKJiotySitpRSosHA766c+hoaLEuKN1dnjz4chnZ2e6sJ2ysrN8fH1HKRJbXF6NhHZybWMfEwj35s2jm4phYWNSUlTj4+NTTUO8vLzp4crp6eqTjH18UC62t7h7dWn46tGPj4+sra2flIJiW1BmYlrKv6pwaV3a0LrVybOBgoOFfG/89d7k1b3LxrXo3MXz4Mbv5s7Rw6xhNhaSkonv69Ssd0/e1MGSVyqGSh3KnXt4RB1ocXqDTyiBhHz6+ebw7uYmf38+AAAM/0lEQVRYw61ZB1viWtc9JAY2CSEhBQhVmtJFQRBF7Nh7772Xabe+9a9/+4DM6Nx3BO8353miecLJysrea5dzQsi7h8329dROfuqwF2dvtxqnWWP4ZyLbNqBWEiPd9Dx2thr4idARIZJ4JMvpETxPzX1kbT8PekEg8+kc4bfVDLHp5Pz2J9I2YuQ/OntNasIAmVrn2e6/adj52Lc7+5/1oE4QsgL7JJwcHbogy5t/SwvzqXNo6ktOGjJeikQHSSVWJiWo4gNylSdFHGoHqukSGUFIZrRY2k027xuAFP03AuvCiT2yrZBdI1c+BiiR5Wgb0DHx2QwA/dlYcp/sCs8C3hLUhmFkfZlcJYY3jxSeTx49redWlLjQ2tq2KDtQP0ksn0H1WiFzxeebpuH066zZJHmMFdkzJR6sxcv5m2PlKtWa9W0pQS0xIhCSTBD+DjrrlzNaUn4xa0rkyRELJSUY7+rCw/Mp1xo6e/ZpCd8ZHsKee6F4frc8Sh2wADuvpw3DLnmoQincUR+TnlhriwzmSGyP6Ffl3jh6SCfxGCpOgtzod1moE64Jv3/maUD3KtX+Nvx4/ylyKITD14kbsqvuk+WBBTBqJB35bl4AdnlS7pppYPPLA23khzNShRteuQOjRO5zp1cgrsfJJfwlB92K/6klj4LHdWjPXBvBfrhNano8eL9+OSes/PcIxDkPX/70GtneObCxGQUJNZRvsM7fzLaGlvW8crXMz3g8JKwBJHfLQc9HeGXJjFG9uDur3SyXlPizQfLX7QRNcU75tH/f5VEec8LKo8czc6z4s69mRP0fFUJ4Dx/u7W0gdwRnYm1Um4FzJR8MKh8vQH0s88GurvJd4ru4CgxUc0cdylpXR3PEr/U2knafGs8rnn2AfZ5HVl2eXZD/GrX9S+J6uWkOVMhRW8kPVTcnwPZHJUhZrSnJ6f85bU/c9ijxyWfofa0d6OHtC9DmlHAXNWQXfwm2H1VI4ctuWMl/oLa+T3e2kfoXAI48ymTdkL2TxLXww6mdOogrx3Gk0KVcVdqABjgj+YaHuibJOrzl+swtnBNqOM+D1IZEbKkY3zDhTLhcghbpMgBX8SDNIrFG0u1+Wykwp1DWvfndKrSMsoA0x6OQ+JqOrp3S4W3yo+IvQZoqw7rQhnMWcnwwrPAPQiUBQk5/e3I31DAR93oetHaaly0I85dHBrDixnC33MKb/fo9JrQ1fnukraLPJg0A/RZfsB82pt+YiMfGPrV1/EFtw+eZWwOkaHavUdjUyI+lSqJ6qt+4weQzyS+/nmbb6p9PTfX3vUrBLBjTwy/MNh/5MbS6MJpT9eLdZZxsv/ShLSuw6YnFxVW22P/SzlOv7h5ST96AHsQ/pxsJQ92GzAt6wupnq5mOnkVY+iawhReK2BuILgV+7HhZsGUTtKRsDVSSam4kUEfpLrL/CJmt9eEMWVlJ/ha7z0VRzi6pE2zizZRKdFhqlvfUppCkF2HC/AxMh9mcjg4NTw3XG7Ys1FvODTW96jY50rkfsx4skhHt9EVfgm7Zg8WQ9cXoMfew7MRiGgS61pCmA9M6m2ZMDs7LOeDwx1VXfd2rLPUj588U2Yl2duIfJ56H/P5Q6PfClLhEOxIJGIuJs+DgvC/985eMIEQj0yPzgWeNqWhN5Ow0W8fcjMvvdzHuHrPV7DacVufvf27pRXypyGrB0himQvr0jRjo0yDNspqYiP7zZGd0liRXQ07zgUs0XAzjxsG43E7zuL+n56Dnj19/Y7Fx05k6ZQvnc3lXs28FmOBDq7ldE2kAFvpP2bOQ1aX53Q3pUfUxjLNHZNwM41oMlaB7GJ5Jc17GgM43E7AJZ3Emh8PhE2xDUinkloSxFwpBzu5xP3XnuEsbZ9TuKGN6Nkih4H8rvQ+Bz9FkIZHU/p8TEvNSelR9Y5rLXH9IYckPgUFoQnMO5s28M886mjON6NTDqnTwSnpUIWbRT6F7Dqx/TunRW6F5g8U08WYXlWGbJEwu2LlgrS8pO51jFJoRUdx4Mrb46x379TXxDjh9s6FkOW9joiMmqpqzjvE1EP3I13ngHnNZnXjdeRDzC6LlKxff/2iHXvYhX1k7fJLwDZmGy5jAjpmtIcYVcvtR39Ye568jmsg1STvYt0tpJzSnOmISfW8nDUKz9WDMLbKolZ7QgcSEzOPGOPXBH7VD8Jmafoeh9qA5L8tguFgPxmmkMH6JFTBarKEDEdL4tAOxrpw/Pv1TbEpqItGiMoIFsdHcJlUImRETh8tvYJCPI7DT7BYgVkmb8VwU8crvv95pDdac5fvV1F9ZN30i9Ixh1NXBkfcBTU+hz35VwvZKBWso5HQJfmb8X2OixcE1BGVrBe3lKAVHzM+IY24XpqTxHnMoFDI7/7W4ur1gwFVY2RWBoeDj9KF+NcYhcVN6ulU7BF76gpzJ0CQGwRHzH58/Ly4uTky4cqNzRb0Ujn/gg7iWwUc6e8bRE4ua5nVYuDcy6nM1AF/99XySoUqu0MFE2l+9uFg5+veX0o2H1Eq7HmzZZ8L8FxY0v2EYmqbGVE3yoVRbdUR7z9AuySeKZj+o/34M4hKR/lQOl1dqn6rl+ORaV1D5bZtdXRyzjouqyeJldIer2Kpr6QaayTiLxJgkZpFdDyue+PG5mNhe2Z97WobroHbmCfM4FM/ceWxVmBA0lXOYOG61lamJzLqpG30CxwkClPh8x9r9sl7N6RrLAqzz/BkI0dx5pXp+ScK7j+LFCoCKyjax861ZeznOwjGMg1Ml9jKxrvR+eAg+hZVwbfncyHs6+OsYnOcq649fLuMepVKr+pMQwxeFlns53WlUkpfzejmTqsHVsv5LMP/xKiHosdzscfWc7+otH+srpcu56spT0FOrzYG34NIsnFto2deiG70urDOcpcBIGjys7/PHT9e7R+r5zUd+2UAXrnme9isCHPH5D2H+QURxOMRkYTHZuqndAEw4VCQcZ4hpg+fDH9aCeT5MW8w54UOcD87ElfDTTPj4Az9XFEDE9/MlCxNLbXTM8qbL8ZwVDJ+QTD3cY0+8NrmGLfdVklcuLjyTvWv5+Bou5DX2s2bQ6PUVVkfb6cYz4GtUaTR6gYGkEmwsxj2XkCBH8Jhfq6/PwuUqHIyJYj0xmFrGYmOkgHE0+iG0uA/TUX3l23Ec/E0Eun8TxHjMK79UJC/jjgkU2uHS29w67ASqkwbz7VV2XwnP9M54+K7a+kXpl9LRTb4jf72ig8Phd3kFGr0maHuzWc5hNa0TNyXH/JDbVXo96zHVSC6vVC8Sl56O+8svF0LBJIoFEaMXG4t37JGnwN9Iwz6Xi0tLj8p96bxEnpK5Wpkusz/ESdRvMsVEB4PQJp/xnv3UALAWGsCM5Cs4/PDIx8vls0Tlqnj1MUiX5SUJg9aiehvPLxI50P5Gtj0KNA3rMby5MAG/8fwRXNzEn9avg7gU5nUXysgUo8nMVHBJUeh8D/EpcHGWOi2HC/T7sHRHPJP5cLCrd5LcwbbDi7R9nMMywc7uwN77NpkDzcD0wmFkm1RvPFThvV0ess5uilRDJodvIj09SPpkknnXFnmmXt6pwQVsj0uExs5anleCK7g+0hiTyeFOiwO0ZQocRrPtiMQe6JO3+nCmbdZlavQkYob0q3dxBVPK8SU2ereERNIFho0dovNsw7Narj3O9ltgO4dPItPDI2DCCkK7OboSjURX9leSKkCCLi93sAbQzqP7BGsEdA4F5PbAU1kbkTtTEYNNu3wOr5Yl8sD0QlEDMVLUpyOVzXkyK9C6MhhBXC3SPyS3bebB5wVz3+mmtJpW6aozuzOqQ6KyaURGUrPCziyqLaADGCeB936ussuyvX6PPbPE0gVhZlOYHrLJtu6RSvRkEFd+QxLA6OD7UPuyqY3NoiBoaEVJHd2hm+OBxLeNqCVhMxrB36KBd39Ksvf19XXLOLqHMp0DUSQ3m4LZ09R8XQa2RIJ+8BCnZPL/H/ahw4VEZQMfEekjdiwI5DS68/fhujN1Q8ud3/atsydYCk5gg/QlErZX3xrtnSftx+IIWpJGOjoKbT+CZhigmxSigBbfqP+WApqR5jVBCmzhSr3ttHoCmb0+sgVZ9B4hGh46Vr+NBAKSipqZgr5B2DpJkaw2MDJlL8ZIBNqVSKOKwgLSZ8kpLOGtrI2A3Q5ZugdiB9sexZKxcKFdICB/t1f0xua73iiRaFFp3oZGGWFnNXxgBbIEMAjnEXcJj0O0xDQukXUYbVcRiDCYHMoaFJ7k1CUJ5CkdjTHajUQpzYguE3WBRKOdOzYyoA2jb9usuiCyoNtSmr0f5B2QNXRYUeuDSH2bbKtbihADMgOQ0cRZYZMkRGTQZuojESkySBmDtDeI9SOyQ7+wZVnqABtbFw2ZYuEkoCUjI8M2QAGdArwrkwwGCNl83ruzyaQR1XLnM4bclLbcnPveT7B/P+r+D5q++1kip6P4AAAAAElFTkSuQmCC";const en={class:"maintenance"},tn={class:"maintenance__inside"},an={class:"maintenance__about"},sn={class:"maintenance__actions"};function nn(e,t,a,s,n,o){return(0,c.uX)(),(0,c.CE)("section",en,[(0,c.Lk)("div",tn,[t[1]||(t[1]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:Ys,alt:""})],-1)),(0,c.Lk)("div",an,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.dumpAutoload.title")),1),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.maintenance.dumpAutoload.description")),1)]),(0,c.Lk)("fieldset",sn,[(0,c.Lk)("button",{class:"widget-button widget-button--primary widget-button--update",onClick:t[0]||(t[0]=function(){return o.execute&&o.execute(...arguments)})},(0,u.v_)(e.$t("ui.maintenance.dumpAutoload.button")),1)])])])}var on={methods:{execute(){this.$store.dispatch("tasks/execute",{name:"composer/dump-autoload"})}}};const ln=(0,ee.A)(on,[["render",nn]]);var rn=ln;const cn={class:"maintenance"},un={class:"maintenance__inside"},dn={class:"maintenance__about"},pn={class:"maintenance__actions"};function gn(e,t,a,s,n,o){const i=(0,c.g2)("i18n-t"),l=(0,c.g2)("link-menu"),r=(0,c.g2)("button-group");return(0,c.uX)(),(0,c.CE)("section",cn,[(0,c.Lk)("div",un,[t[2]||(t[2]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:Ys,alt:""})],-1)),(0,c.Lk)("div",dn,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.composerInstall.title")),1),(0,c.bF)(i,{tag:"p",keypath:"ui.maintenance.composerInstall.description"},{vendor:(0,c.k6)((()=>t[0]||(t[0]=[(0,c.Lk)("code",null,"/vendor",-1)]))),composerLock:(0,c.k6)((()=>t[1]||(t[1]=[(0,c.Lk)("code",null,"composer.lock",-1)]))),_:1})]),(0,c.Lk)("fieldset",pn,[(0,c.bF)(r,{label:e.$t("ui.maintenance.composerInstall.button"),type:"primary",icon:"run",onClick:o.composerInstall},{default:(0,c.k6)((()=>[(0,c.bF)(l,{align:"right",items:o.advancedActions,color:"primary"},null,8,["items"])])),_:1},8,["label","onClick"])])])])}var hn={components:{ButtonGroup:aa.A,LinkMenu:Aa.A},computed:{advancedActions(){return[{label:this.$t("ui.maintenance.composerInstall.update"),action:this.composerUpdate}]}},methods:{composerInstall(){this.$store.dispatch("tasks/execute",{name:"composer/install"})},composerUpdate(){this.$store.dispatch("tasks/execute",{name:"composer/update"})}}};const mn=(0,ee.A)(hn,[["render",gn]]);var kn=mn;const vn={class:"maintenance"},bn={class:"maintenance__inside"},_n={class:"maintenance__about"},fn={class:"maintenance__actions"};function wn(e,t,a,s,n,o){return(0,c.uX)(),(0,c.CE)("section",vn,[(0,c.Lk)("div",bn,[t[1]||(t[1]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:Ys,alt:""})],-1)),(0,c.Lk)("div",_n,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.composerCache.title")),1),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.maintenance.composerCache.description")),1)]),(0,c.Lk)("fieldset",fn,[(0,c.Lk)("button",{class:"widget-button widget-button--primary widget-button--trash",onClick:t[0]||(t[0]=function(){return o.execute&&o.execute(...arguments)})},(0,u.v_)(e.$t("ui.maintenance.composerCache.button")),1)])])])}var yn={methods:{execute(){this.$store.dispatch("tasks/execute",{name:"composer/clear-cache"})}}};const Cn=(0,ee.A)(yn,[["render",wn]]);var $n=Cn,Ln=a.p+"img/php-logo.7376e212.svg";const An={key:0,class:"maintenance"},En={class:"maintenance__inside"},Xn={class:"maintenance__about"},Sn={class:"maintenance__actions"};function Mn(e,t,a,s,n,o){const i=(0,c.g2)("loading-spinner");return e.status.opcache_enabled?((0,c.uX)(),(0,c.CE)("section",An,[(0,c.Lk)("div",En,[t[1]||(t[1]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:Ln,alt:""})],-1)),(0,c.Lk)("div",Xn,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.opcodeCache.title")),1),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.maintenance.opcodeCache.description")),1)]),(0,c.Lk)("fieldset",Sn,[e.loading?((0,c.uX)(),(0,c.Wv)(i,{key:0,class:"maintenance__loader"})):((0,c.uX)(),(0,c.CE)("button",{key:1,class:"widget-button widget-button--primary widget-button--trash",onClick:t[0]||(t[0]=function(){return o.execute&&o.execute(...arguments)})},(0,u.v_)(e.$t("ui.maintenance.opcodeCache.button")),1))])])])):(0,c.Q3)("",!0)}var Tn={components:{LoadingSpinner:fs.A},data:()=>({opcodeEnabled:!1,loading:!1,status:{opcache_enabled:!1}}),methods:{execute(){this.loading=!0,this.$store.dispatch("server/opcache/delete",this.status.reset_token).then((e=>{this.loading=!1,this.status=e}))}},mounted(){this.$store.dispatch("server/opcache/get").then((e=>{this.status=e}),(()=>{this.status={opcache_enabled:!1}}))}};const xn=(0,ee.A)(Tn,[["render",Mn]]);var On=xn;const Pn={class:"maintenance"},Bn={class:"maintenance__inside"},In={class:"maintenance__about"},Fn={class:"maintenance__actions"};function Rn(e,t,a,s,n,o){const i=(0,c.g2)("loading-spinner"),l=(0,c.g2)("loading-button"),r=(0,c.g2)("message-overlay");return(0,c.uX)(),(0,c.Wv)(r,{message:o.overlayMessage,active:e.safeMode||!e.loading&&!e.supported},{default:(0,c.k6)((()=>[(0,c.Lk)("section",Pn,[(0,c.Lk)("div",Bn,[t[0]||(t[0]=(0,c.Lk)("figure",{class:"maintenance__image"},[(0,c.Lk)("img",{src:m,alt:""})],-1)),(0,c.Lk)("div",In,[(0,c.Lk)("h1",null,(0,u.v_)(e.$t("ui.maintenance.maintenanceMode.title")),1),(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.maintenance.maintenanceMode.description")),1)]),(0,c.Lk)("fieldset",Fn,[e.loading&&!e.supported?((0,c.uX)(),(0,c.Wv)(i,{key:0,class:"maintenance__loader"})):e.enabled?((0,c.uX)(),(0,c.Wv)(l,{key:2,class:"widget-button widget-button--alert widget-button--maintenance",loading:e.loading,disabled:!e.supported,onClick:o.disableMaintenanceMode},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.maintenanceMode.disable")),1)])),_:1},8,["loading","disabled","onClick"])):((0,c.uX)(),(0,c.Wv)(l,{key:1,class:"widget-button widget-button--primary widget-button--maintenance",loading:e.loading,disabled:!e.supported,onClick:o.enableMaintenanceMode},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.maintenance.maintenanceMode.enable")),1)])),_:1},8,["loading","disabled","onClick"]))])])])])),_:1},8,["message","active"])}var qn={components:{MessageOverlay:_s,LoadingSpinner:fs.A,LoadingButton:ia.A},data:()=>({loading:!0,supported:!1,enabled:!1}),computed:{...(0,h.aH)(["safeMode"]),overlayMessage:e=>e.safeMode?e.$t("ui.maintenance.safeMode"):e.$t("ui.maintenance.unsupported")},methods:{async enableMaintenanceMode(){this.loading=!0,this.enabled=await this.$store.dispatch("contao/maintenance-mode/enable"),this.loading=!1},async disableMaintenanceMode(){this.loading=!0,this.enabled=await this.$store.dispatch("contao/maintenance-mode/disable"),this.loading=!1}},async mounted(){const e=await this.$store.dispatch("server/contao/get");if(200===e.status){const t=Object.keys(e.data?.cli?.commands);this.supported=t.includes("contao:maintenance-mode")||t.includes("lexik:maintenance:lock")&&t.includes("lexik:maintenance:unlock"),this.supported&&(this.enabled=await this.$store.dispatch("contao/maintenance-mode/isEnabled"))}this.loading=!1}};const Un=(0,ee.A)(qn,[["render",Rn]]);var jn=Un,Dn={components:{MainLayout:ue,DatabaseStatus:Cs,RebuildCache:Os,InstallTool:js,MaintenanceMode:jn,DebugMode:Zs,DumpAutoload:rn,ComposerInstall:kn,ComposerCache:$n,OpcodeCache:On},computed:{...(0,h.L8)("auth",["isGranted"])},mounted(){this.isGranted(se.A.UPDATE)||this.$router.push("/")}};const Wn=(0,ee.A)(Dn,[["render",Ya]]);var Vn=Wn;const Qn={class:"log-viewer__title"},Hn={key:1,class:"log-viewer__status log-viewer__status--empty"},Gn={class:"log-viewer__title"},zn={key:2},Nn={class:"log-viewer__filters"},Kn={class:"log-viewer__file"},Jn=["title"],Zn=["href","download","title"],Yn={class:"log-viewer__list",ref:"list"},eo={class:"log-viewer__line log-viewer__line--header"},to={class:"log-viewer__meta log-viewer__meta--header"},ao={class:"log-viewer__content log-viewer__content--header"},so={class:"log-viewer__meta"},no=["datetime"],oo=["title"],io=["title"],lo={class:"log-viewer__content"},ro={class:"log-viewer__message"},co={class:"log-viewer__details"},uo=["title"],po=["title"],go=["onClick"],ho=["onClick"],mo={key:1,class:"log-viewer__line log-viewer__more"},ko={key:2,class:"log-viewer__loading"};function vo(e,t,a,s,n,o){const i=(0,c.g2)("loading-spinner"),l=(0,c.g2)("select-menu"),r=(0,c.g2)("vue-json-pretty"),d=(0,c.g2)("main-layout");return(0,c.uX)(),(0,c.Wv)(d,null,{default:(0,c.k6)((()=>[null===e.files?((0,c.uX)(),(0,c.Wv)(i,{key:0,class:"log-viewer__status log-viewer__status--loader"},{default:(0,c.k6)((()=>[(0,c.Lk)("p",Qn,(0,u.v_)(e.$t("ui.log-viewer.loading")),1)])),_:1})):e.files&&0===e.files.length?((0,c.uX)(),(0,c.CE)("div",Hn,[(0,c.Lk)("p",Gn,(0,u.v_)(e.$t("ui.log-viewer.empty")),1),(0,c.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",onClick:t[0]||(t[0]=function(){return o.load&&o.load(...arguments)})},(0,u.v_)(e.$t("ui.log-viewer.reload")),1)])):((0,c.uX)(),(0,c.CE)("div",zn,[(0,c.Lk)("div",Nn,[(0,c.Lk)("div",null,[(0,c.Lk)("div",Kn,[(0,c.bF)(l,{options:o.fileOptions,name:"file",label:e.$t("ui.log-viewer.file"),modelValue:e.file,"onUpdate:modelValue":t[1]||(t[1]=t=>e.file=t)},null,8,["options","label","modelValue"]),(0,c.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",title:e.$t("ui.log-viewer.reload"),onClick:t[2]||(t[2]=function(){return o.load&&o.load(...arguments)})},null,8,Jn)]),(0,c.Lk)("a",{href:`api/logs/${encodeURIComponent(e.file)}`,download:`${e.file}.log`,target:"_blank",class:(0,u.C4)(["widget-button widget-button--inline widget-button--download",{disabled:!e.file}]),title:e.$t("ui.log-viewer.downloadTitle",{file:`${e.file}.log`})},(0,u.v_)(e.$t("ui.log-viewer.download")),11,Zn)]),(0,c.Lk)("div",null,[(0,c.bF)(l,{options:o.channelOptions,name:"channel",label:e.$t("ui.log-viewer.channel"),modelValue:e.channel,"onUpdate:modelValue":t[3]||(t[3]=t=>e.channel=t)},null,8,["options","label","modelValue"]),(0,c.bF)(l,{options:o.levelOptions,name:"level",label:e.$t("ui.log-viewer.level"),modelValue:e.level,"onUpdate:modelValue":t[4]||(t[4]=t=>e.level=t)},null,8,["options","label","modelValue"])])]),(0,c.Lk)("div",Yn,[(0,c.Lk)("div",eo,[(0,c.Lk)("div",to,(0,u.v_)(e.$t("ui.log-viewer.timeHeader")),1),(0,c.Lk)("div",ao,(0,u.v_)(e.$t("ui.log-viewer.messageHeader")),1)]),o.lines?((0,c.uX)(!0),(0,c.CE)(c.FK,{key:0},(0,c.pI)(o.lines,((t,a)=>((0,c.uX)(),(0,c.CE)(c.FK,{key:a},["string"===typeof t?((0,c.uX)(),(0,c.CE)("div",{class:"log-viewer__line log-viewer__line--raw",key:a},(0,u.v_)(t),1)):((0,c.uX)(),(0,c.CE)("div",{key:1,class:(0,u.C4)(`log-viewer__line log-viewer__line--${t.level.toLowerCase()}`)},[(0,c.Lk)("div",so,[(0,c.Lk)("time",{class:"log-viewer__datetime",datetime:t.datetime},(0,u.v_)(o.datimFormat(t.datetime,"medium")),9,no),(0,c.Lk)("span",{class:(0,u.C4)(`log-viewer__badge log-viewer__badge--desktop log-viewer__badge--level-${t.level.toLowerCase()}`),title:e.$t("ui.log-viewer.levelTitle")},(0,u.v_)(t.level),11,oo),(0,c.Lk)("span",{class:"log-viewer__badge log-viewer__badge--desktop log-viewer__badge--channel",title:e.$t("ui.log-viewer.channelTitle")},(0,u.v_)(t.channel),9,io)]),(0,c.Lk)("div",lo,[(0,c.Lk)("div",ro,[((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(o.pieces(t.message),((e,t)=>((0,c.uX)(),(0,c.CE)("span",{key:t},(0,u.v_)(e),1)))),128))]),(0,c.Lk)("div",co,[(0,c.Lk)("span",{class:(0,u.C4)(`log-viewer__badge log-viewer__badge--mobile log-viewer__badge--level-${t.level.toLowerCase()}`),title:e.$t("ui.log-viewer.levelTitle")},(0,u.v_)(t.level),11,uo),(0,c.Lk)("span",{class:"log-viewer__badge log-viewer__badge--mobile log-viewer__badge--channel",title:e.$t("ui.log-viewer.channelTitle")},(0,u.v_)(t.channel),9,po),o.canShow(t.context)?((0,c.uX)(),(0,c.CE)("button",{key:0,class:(0,u.C4)(["log-viewer__toggle",{"log-viewer__toggle--active":e.showContext[a]}]),onClick:e=>o.toggleContext(a)},(0,u.v_)(e.$t(`ui.log-viewer.${e.showContext[a]?"hide":"show"}Context`)),11,go)):(0,c.Q3)("",!0),o.canShow(t.extra)?((0,c.uX)(),(0,c.CE)("button",{key:1,class:(0,u.C4)(["log-viewer__toggle",{"log-viewer__toggle--active":e.showExtra[a]}]),onClick:e=>o.toggleExtra(a)},(0,u.v_)(e.$t(`ui.log-viewer.${e.showExtra[a]?"hide":"show"}Extra`)),11,ho)):(0,c.Q3)("",!0)]),o.canShow(t.context)&&e.showContext[a]?((0,c.uX)(),(0,c.Wv)(r,{key:0,data:t.context,deep:1,class:"log-viewer__json"},null,8,["data"])):(0,c.Q3)("",!0),o.canShow(t.extra)&&e.showExtra[a]?((0,c.uX)(),(0,c.Wv)(r,{key:1,data:t.extra,deep:1,class:"log-viewer__json"},null,8,["data"])):(0,c.Q3)("",!0)])],2))],64)))),128)):(0,c.Q3)("",!0),o.current&&0!==e.offset?((0,c.uX)(),(0,c.CE)("div",mo,[(0,c.Lk)("button",{class:"widget-button widget-button--inline widget-button--add",onClick:t[5]||(t[5]=function(){return o.next&&o.next(...arguments)})},(0,u.v_)(e.$t("ui.log-viewer.more")),1)])):(0,c.Q3)("",!0),e.loading?((0,c.uX)(),(0,c.CE)("div",ko,[(0,c.bF)(i)])):(0,c.Q3)("",!0)],512)]))])),_:1})}a(1701);var bo=a(4144);const _o=["for"],fo=["id","name","disabled","required"],wo={key:0,value:""},yo=["label"],Co=["value","disabled","selected"],$o=["value","disabled","selected"],Lo={key:1,class:"widget__error"};function Ao(e,t,a,s,n,o){return(0,c.uX)(),(0,c.CE)("div",{class:(0,u.C4)(["widget widget-select",{"widget--error":a.error,"widget--required":a.required}])},[a.label?((0,c.uX)(),(0,c.CE)("label",{key:0,for:"ctrl_"+a.name},(0,u.v_)(a.label),9,_o)):(0,c.Q3)("",!0),(0,c.Lk)("select",{ref:"input",id:a.label?"ctrl_"+a.name:"",name:a.name,disabled:a.disabled,required:a.required,onChange:t[0]||(t[0]=e=>o.input(e.target.value))},[a.includeBlank?((0,c.uX)(),(0,c.CE)("option",wo,(0,u.v_)(e.$t("ui.widget.blankOption")),1)):(0,c.Q3)("",!0),((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(a.options,((e,t)=>((0,c.uX)(),(0,c.CE)(c.FK,null,[e.options?((0,c.uX)(),(0,c.CE)("optgroup",{label:e.label,key:t},[((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(e.options,(e=>((0,c.uX)(),(0,c.CE)("option",{value:e.value,disabled:e.disabled,selected:e.value===a.modelValue,key:e.value},(0,u.v_)(e.label),9,Co)))),128))],8,yo)):((0,c.uX)(),(0,c.CE)("option",{value:e.value,disabled:e.disabled,selected:e.value===a.modelValue,key:e.value},(0,u.v_)(e.label),9,$o))],64)))),256))],40,fo),a.error?((0,c.uX)(),(0,c.CE)("p",Lo,(0,u.v_)(a.error),1)):(0,c.Q3)("",!0)],2)}var Eo={emits:["input","update:modelValue"],props:{name:{type:String,required:!0},options:{type:Array,required:!0},label:String,modelValue:String,disabled:Boolean,required:Boolean,error:String,includeBlank:Boolean},methods:{input(e){this.$emit("input"),this.$emit("update:modelValue",e)}},mounted(){this.$emit("update:modelValue",this.$refs.input.value)},updated(){this.$emit("update:modelValue",this.$refs.input.value)}};const Xo=(0,ee.A)(Eo,[["render",Ao]]);var So=Xo,Mo={components:{MainLayout:ue,LoadingSpinner:fs.A,SelectMenu:So,VueJsonPretty:bo.A},data:()=>({files:null,loading:!1,file:null,offset:0,limit:100,content:[],channel:"",level:"",showContext:{},showExtra:{}}),computed:{channelOptions:e=>e.countOptions("channel"),levelOptions:e=>e.countOptions("level",{emergency:0,alert:0,critical:0,error:0,warning:0,notice:0,info:0,debug:0}),fileOptions(){if(!this.files)return[];const e={},t=[];return this.files.forEach((a=>{const s=a.name.match(/^([a-z]+)-(\d{4}-\d{2}-\d{2})$/i);s?(e[s[1]]||(e[s[1]]={label:this.$te(`ui.log-viewer.${s[1]}Environment`)?this.$t(`ui.log-viewer.${s[1]}Environment`):s[1],options:[]}),e[s[1]].options.push({value:a.name,label:`${(0,Ut.A)(s[2],null,"long")} (${(0,bt.A)(a.size)})`})):t.push({value:a.name,label:`${a.name} (${(0,bt.A)(a.size)})`})})),[...Object.values(e),...t]},current:e=>e.files?.find((t=>t.name===e.file)),lines:e=>e.content?.filter((t=>"string"===typeof t||(!e.channel||t.channel===e.channel)&&(!e.level||t.level.toLowerCase()===e.level))).reverse()},methods:{datimFormat:Ut.A,canShow:e=>e&&(!Array.isArray(e)||e.length),pieces:e=>{let t=[];const a=e.split(' "'),s=a.length-1;let n=0;for(let o=0;o<=s;o++){let e=a[o];if(0!==n)while(n>0){while(!a[o].includes('"')&&o!==s)e=`${e} "${a[o+1]}`,n++,o++;if(n--,0===n){t[t.length-1]+=' "';const a=e.indexOf('" ')||e.lastIndexOf('"');t.push(e.slice(0,a)),t.push(e.slice(a)),n++;break}}else t.push(e),n++}return t},toggleContext(e){this.$set(this.showContext,e,!this.showContext[e])},toggleExtra(e){this.$set(this.showExtra,e,!this.showExtra[e])},countOptions(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return this.content.forEach((a=>{"string"!==typeof a&&(t[a[e].toLowerCase()]||(t[a[e].toLowerCase()]=0),t[a[e].toLowerCase()]+=1)})),[{label:"all",value:""}].concat(Object.keys(t).map((e=>({value:e,label:`${e.at(0).toUpperCase()}${e.slice(1)} (${t[e]})`}))))},next(){this.limit=Math.min(this.offset,100),this.offset=Math.max(this.offset-100,0)},async load(){const e=this.file;this.files=null,this.file=null,this.files=(await s.A.get("api/logs")).data,this.file=this.files.find((t=>t.name===e))?.name||(this.files.length?this.files[0].name:null)},async fetch(){if(!this.current)return;this.loading=!0;const e=(await s.A.get(`api/logs/${encodeURIComponent(this.current.name)}?offset=${this.offset}&limit=${this.limit}`)).data;this.content=this.content.concat(Array.from(e.content.reverse())),this.loading=!1}},watch:{async file(){this.content=[],this.channel="",this.level="",this.showContext={},this.showExtra={},this.limit=100,this.offset=this.current?Math.max(this.current.lines-100,0):0,await this.fetch()},async offset(){await this.fetch()}},async created(){await this.load()}};const To=(0,ee.A)(Mo,[["render",vo]]);var xo=To;const Oo={key:1},Po={class:"user-manager__list"},Bo={key:0,class:"user-manager__you"},Io={class:"user-manager__username"},Fo=["onClick"],Ro={class:"user-manager__new"};function qo(e,t,a,s,n,o){const i=(0,c.g2)("loading-spinner"),l=(0,c.g2)("user-scope"),r=(0,c.g2)("main-layout");return(0,c.uX)(),(0,c.Wv)(r,{class:"user-manager"},{default:(0,c.k6)((()=>[null===e.users?((0,c.uX)(),(0,c.Wv)(i,{key:0,class:"user-manager__loading"},{default:(0,c.k6)((()=>[(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.user-manager.loading")),1)])),_:1})):((0,c.uX)(),(0,c.CE)("div",Oo,[(0,c.Lk)("div",Po,[((0,c.uX)(!0),(0,c.CE)(c.FK,null,(0,c.pI)(e.users,((a,s)=>((0,c.uX)(),(0,c.CE)("div",{key:s,class:"user-manager__item"},[e.currentUser===a.username?((0,c.uX)(),(0,c.CE)("div",Bo,(0,u.v_)(e.$t("ui.user-manager.you")),1)):(0,c.Q3)("",!0),(0,c.Lk)("div",Io,(0,u.v_)(a.username),1),(0,c.bF)(l,{readonly:"",label:"Permissions","model-value":a.scope,class:"user-manager__scope"},null,8,["model-value"]),t[4]||(t[4]=(0,c.Lk)("div",{class:"user-manager__spacer"},null,-1)),e.currentUser!==a.username||e.hasPasskey?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("button",{key:1,class:"widget-button",onClick:t[0]||(t[0]=function(){return o.changePassword&&o.changePassword(...arguments)})},(0,u.v_)(e.$t("ui.user-manager.changePassword")),1)),e.currentUser!==a.username||e.hasPasskey||e.hasTotp?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.CE)("button",{key:2,class:"widget-button",onClick:t[1]||(t[1]=function(){return o.setupTotp&&o.setupTotp(...arguments)})},(0,u.v_)(e.$t("ui.user-manager.setupTotp")),1)),e.currentUser===a.username&&!e.hasPasskey&&e.hasTotp?((0,c.uX)(),(0,c.CE)("button",{key:3,class:"widget-button",onClick:t[2]||(t[2]=function(){return o.disableTotp&&o.disableTotp(...arguments)})},(0,u.v_)(e.$t("ui.user-manager.disableTotp")),1)):(0,c.Q3)("",!0),e.currentUser!==a.username?((0,c.uX)(),(0,c.CE)("button",{key:4,class:"widget-button widget-button--alert widget-button--trash",onClick:e=>o.deleteUser(a.username)},(0,u.v_)(e.$t("ui.user-manager.delete")),9,Fo)):(0,c.Q3)("",!0)])))),128))]),(0,c.Lk)("div",Ro,[e.isGranted(o.scopes.ADMIN)?((0,c.uX)(),(0,c.CE)("button",{key:0,class:"widget-button widget-button--inline widget-button--add",onClick:t[3]||(t[3]=function(){return o.addUser&&o.addUser(...arguments)})},(0,u.v_)(e.$t("ui.user-manager.invite")),1)):(0,c.Q3)("",!0)])]))])),_:1})}const Uo={class:"invite-user__text"},jo={class:"invite-user__url"},Do={class:"invite-user__text"},Wo=["href"],Vo=["disabled"];function Qo(e,t,a,s,n,o){const i=(0,c.g2)("i18n-t"),l=(0,c.g2)("user-scope"),r=(0,c.g2)("loading-button"),d=(0,c.g2)("popup-overlay"),p=(0,c.gN)("clipboard");return(0,c.uX)(),(0,c.Wv)(d,{class:"invite-user",headline:e.$t("ui.user-manager.inviteHeadline"),onSubmit:o.submit,onClear:o.close},{actions:(0,c.k6)((()=>[(0,c.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[2]||(t[2]=function(){return o.close&&o.close(...arguments)})},(0,u.v_)(e.token?e.$t("ui.user-manager.close"):e.$t("ui.user-manager.cancel")),9,Vo),e.token?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.Wv)(r,{key:0,submit:"",color:"primary",loading:e.loading},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.user-manager.createInvitation")),1)])),_:1},8,["loading"]))])),default:(0,c.k6)((()=>[e.token?((0,c.uX)(),(0,c.CE)(c.FK,{key:0},[t[3]||(t[3]=(0,c.Lk)("div",{class:"invite-user__check"},[(0,c.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,c.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})])],-1)),(0,c.bF)(i,{tag:"p",keypath:"ui.user-manager.inviteSuccess1",class:"invite-user__text"},{expires:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(o.datimFormat(1e3*e.token.expires,"short","long")),1)])),_:1}),(0,c.Lk)("p",Uo,(0,u.v_)(e.$t("ui.user-manager.inviteSuccess2")),1),(0,c.Lk)("code",jo,(0,u.v_)(e.token.url),1),(0,c.bo)(((0,c.uX)(),(0,c.CE)("button",{type:"button",class:(0,u.C4)(["widget-button widget-button--small invite-user__clipboard",{"widget-button--clipboard":!e.copied,"widget-button--check":e.copied}]),onClick:t[0]||(t[0]=function(){return o.markCopy&&o.markCopy(...arguments)})},[(0,c.eW)((0,u.v_)(e.$t("ui.user-manager.clipboard")),1)],2)),[[p,e.token.url]])],64)):((0,c.uX)(),(0,c.CE)(c.FK,{key:1},[(0,c.Lk)("p",Do,(0,u.v_)(e.$t("ui.user-manager.inviteText")),1),(0,c.bF)(l,{modelValue:e.scope,"onUpdate:modelValue":t[1]||(t[1]=t=>e.scope=t)},null,8,["modelValue"]),(0,c.Lk)("a",{class:"invite-user__help",href:`https://to.contao.org/docs/manager-users?lang=${e.$i18n.locale}`,target:"_blank"},(0,u.v_)(e.$t("ui.user-manager.permissions")),9,Wo)],64))])),_:1},8,["headline","onSubmit","onClear"])}var Ho=a(3170),Go={components:{PopupOverlay:Ho.A,LoadingButton:ia.A,UserScope:Na},data:()=>({loading:!1,scope:"admin",token:null,copied:!1}),methods:{datimFormat:Ut.A,markCopy(){this.copied=!0,setTimeout((()=>{this.copied=!1}),1e3)},async submit(){this.loading=!0,this.$request.post("api/invitations",{scope:this.scope},null,{201:e=>{this.token=e.data,this.loading=!1}})},close(){this.$store.commit("modals/close","invite-user")}}};const zo=(0,ee.A)(Go,[["render",Qo]]);var No=zo,Ko=a(2286);const Jo={class:"disable-totp__text"},Zo=["disabled"];function Yo(e,t,a,s,n,o){const i=(0,c.g2)("text-field"),l=(0,c.g2)("loading-button"),r=(0,c.g2)("popup-overlay");return(0,c.uX)(),(0,c.Wv)(r,{class:"disable-totp",headline:e.$t("ui.totp.headline"),onSubmit:o.submit,onClear:o.close},{actions:(0,c.k6)((()=>[(0,c.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[2]||(t[2]=function(){return o.close&&o.close(...arguments)})},(0,u.v_)(e.$t("ui.totp.cancel")),9,Zo),(0,c.bF)(l,{submit:"",color:"primary",loading:e.loading},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.totp.disable")),1)])),_:1},8,["loading"])])),default:(0,c.k6)((()=>[(0,c.Lk)("p",Jo,(0,u.v_)(e.$t("ui.totp.disableText")),1),(0,c.bF)(i,{ref:"totp",name:"totp",required:"",pattern:"\\d+",minlength:"6",maxlength:"6",autocomplete:"one-time-code",error:e.error,onKeyup:t[0]||(t[0]=t=>e.error=""),modelValue:e.totp,"onUpdate:modelValue":t[1]||(t[1]=t=>e.totp=t)},null,8,["error","modelValue"])])),_:1},8,["headline","onSubmit","onClear"])}var ei=a(683),ti={components:{PopupOverlay:Ho.A,LoadingButton:ia.A,TextField:ei.A},data:()=>({loading:!1,error:"",totp:null}),computed:{...(0,h.aH)("auth",["username"])},methods:{submit(){this.loading=!0,this.$request.delete(`api/users/${this.username}/totp`,{data:{totp:this.totp}},null,{200:async()=>{await this.$store.dispatch("auth/status"),this.$notify.success(this.$t("ui.totp.disabled")),this.close()},422:()=>{this.loading=!1,this.error=this.$t("ui.totp.invalid"),this.$refs.totp.focus()}})},close(){this.$store.commit("modals/close","disable-totp")}},mounted(){setTimeout((()=>{this.$refs.totp.focus()}),0)}};const ai=(0,ee.A)(ti,[["render",Yo]]);var si=ai;const ni=["disabled"];function oi(e,t,a,s,n,o){const i=(0,c.g2)("text-field"),l=(0,c.g2)("loading-button"),r=(0,c.g2)("popup-overlay");return(0,c.uX)(),(0,c.Wv)(r,{class:"change-password",headline:e.$t("ui.user-manager.passwordHeadline"),onSubmit:o.submit,onClear:o.close},{actions:(0,c.k6)((()=>[(0,c.Lk)("button",{type:"button",class:"widget-button",disabled:e.loading,onClick:t[3]||(t[3]=function(){return o.close&&o.close(...arguments)})},(0,u.v_)(e.$t("ui.user-manager.cancel")),9,ni),(0,c.bF)(l,{submit:"",color:"primary",loading:e.loading,disabled:!o.inputValid},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.user-manager.submitPassword")),1)])),_:1},8,["loading","disabled"])])),default:(0,c.k6)((()=>[(0,c.Lk)("p",null,(0,u.v_)(e.$t("ui.user-manager.passwordText")),1),(0,c.bF)(i,{ref:"password",name:"current-password",type:"password",label:e.$t("ui.user-manager.currentPassword"),required:"",minlength:"8",autocomplete:"current-password",error:e.error,onKeyup:t[0]||(t[0]=t=>e.error=""),modelValue:e.currentPassword,"onUpdate:modelValue":t[1]||(t[1]=t=>e.currentPassword=t),disabled:e.loading},null,8,["label","error","modelValue","disabled"]),(0,c.bF)(i,{name:"new-password",type:"password",label:e.$t("ui.user-manager.newPassword"),placeholder:e.$t("ui.user-manager.passwordPlaceholder"),required:"",minlength:"8",autocomplete:"new-password",modelValue:e.newPassword,"onUpdate:modelValue":t[2]||(t[2]=t=>e.newPassword=t),disabled:e.loading},null,8,["label","placeholder","modelValue","disabled"])])),_:1},8,["headline","onSubmit","onClear"])}var ii={components:{PopupOverlay:Ho.A,LoadingButton:ia.A,TextField:ei.A},data:()=>({loading:!1,currentPassword:"",newPassword:"",error:""}),computed:{...(0,h.aH)("auth",["username"]),inputValid:e=>e.currentPassword.length>=8&&e.newPassword.length>=8},methods:{async submit(){this.loading=!0,await this.$request.put(`api/users/${this.username}/password`,{current_password:this.currentPassword,new_password:this.newPassword},null,{200:()=>{this.$notify.success(this.$t("ui.user-manager.passwordChanged")),this.close()},422:()=>{this.error=this.$t("ui.user-manager.passwordError"),setTimeout((()=>{this.$refs.password.focus()}),0)}}),this.loading=!1},close(){this.$store.commit("modals/close","change-password")}},mounted(){this.$refs.password.focus()}};const li=(0,ee.A)(ii,[["render",oi]]);var ri=li,ci={components:{MainLayout:ue,LoadingSpinner:fs.A,UserScope:Na},data:()=>({users:null}),computed:{...(0,h.aH)("auth",{currentUser:"username",hasTotp:"totpEnabled",hasPasskey:"passkey"}),...(0,h.L8)("auth",["isGranted"]),scopes:()=>se.A},methods:{load(){this.$request.get("api/users",null,{200:e=>{this.users=e.data}})},changePassword(){this.$store.commit("modals/open",{id:"change-password",component:ri})},setupTotp(){this.$store.commit("modals/open",{id:"setup-totp",component:Ko.A})},disableTotp(){this.$store.commit("modals/open",{id:"disable-totp",component:si})},addUser(){this.$store.commit("modals/open",{id:"invite-user",component:No})},async deleteUser(e){confirm(this.$t("ui.user-manager.deleteConfirm",{username:e}))&&(await this.$request.delete(`api/users/${e}`),this.$notify.success(this.$t("ui.user-manager.deleted")),this.load())}},async mounted(){this.load()}};const ui=(0,ee.A)(ci,[["render",qo]]);var di=ui;const pi=(0,l.aE)({history:(0,l.Bt)(),routes:[{name:r.A.discover.name,path:"/discover",component:me},{name:r.A.packages.name,path:"/packages",component:Ma},{name:r.A.oauth.name,path:"/oauth",component:Za,props:!0},{name:r.A.maintenance.name,path:"/maintenance",component:Vn},{name:r.A.logViewer.name,path:"/logs",component:xo},{name:r.A.userManager.name,path:"/users",component:di},{path:"/:pathMatch(.*)*",redirect:"/discover"}]});var gi=pi,hi=a(7008),mi=a(8044),ki=a(4710);const vi={id:"app"},bi={key:0,class:"app-hint app-hint--alert"},_i={class:"app-hint__headline"},fi={class:"app-hint__description"},wi={key:1,class:"app-hint"},yi={class:"app-hint__headline"},Ci={class:"app-hint__description"},$i={key:2,class:"app-hint app-hint--warning"},Li={class:"app-hint__headline"},Ai={class:"app-hint__description"},Ei=["href"],Xi={key:3,class:"app-hint app-hint--warning"},Si={class:"app-hint__headline"},Mi={class:"app-hint__description"},Ti={key:0,class:"view-init"},xi={class:"view-init__cell animate-initializing"},Oi={class:"view-init__message"},Pi={key:3};function Bi(e,t,a,s,n,o){const i=(0,c.g2)("Notification"),l=(0,c.g2)("Notivue"),r=(0,c.g2)("error-view"),d=(0,c.g2)("task-view"),p=(0,c.g2)("router-view");return(0,c.uX)(),(0,c.CE)("div",vi,[(0,c.bF)(l,null,{default:(0,c.k6)((e=>[(0,c.bF)(i,{item:e},null,8,["item"])])),_:1}),e.safeMode&&"ready"===e.view?((0,c.uX)(),(0,c.CE)("div",bi,[(0,c.Lk)("strong",_i,(0,u.v_)(e.$t("ui.app.safeModeHeadline")),1),t[3]||(t[3]=(0,c.eW)("  ")),(0,c.Lk)("span",fi,(0,u.v_)(e.$t("ui.app.safeModeDescription")),1),t[4]||(t[4]=(0,c.eW)("  ")),(0,c.Lk)("button",{class:"app-hint__link",onClick:t[0]||(t[0]=()=>e.window.location.reload())},(0,u.v_)(e.$t("ui.app.safeModeExit")),1)])):(0,c.Q3)("",!0),e.limited?((0,c.uX)(),(0,c.CE)("div",wi,[(0,c.Lk)("strong",yi,(0,u.v_)(e.$t("ui.app.limitedHeadline")),1),t[5]||(t[5]=(0,c.eW)("  ")),(0,c.Lk)("span",Ci,(0,u.v_)(e.$t("ui.app.limitedDescription")),1),t[6]||(t[6]=(0,c.eW)("  ")),(0,c.Lk)("button",{class:"app-hint__link",onClick:t[1]||(t[1]=function(){return e.logout&&e.logout(...arguments)})},(0,u.v_)(e.$t("ui.app.limitedLogout")),1)])):o.isInsecure?((0,c.uX)(),(0,c.CE)("div",$i,[(0,c.Lk)("strong",Li,(0,u.v_)(e.$t("ui.app.httpsHeadline")),1),t[7]||(t[7]=(0,c.eW)("  ")),(0,c.Lk)("span",Ai,(0,u.v_)(e.$t("ui.app.httpsDescription")),1),t[8]||(t[8]=(0,c.eW)("  ")),(0,c.Lk)("a",{href:e.$t("ui.app.httpsHref"),target:"_blank",class:"app-hint__link"},(0,u.v_)(e.$t("ui.app.httpsLink")),9,Ei)])):e.loaded&&e.username&&!e.totpEnabled?((0,c.uX)(),(0,c.CE)("div",Xi,[(0,c.Lk)("strong",Si,(0,u.v_)(e.$t("ui.app.totpHeadline")),1),t[9]||(t[9]=(0,c.eW)("  ")),(0,c.Lk)("span",Mi,(0,u.v_)(e.$t("ui.app.totpDescription")),1),t[10]||(t[10]=(0,c.eW)("  ")),(0,c.Lk)("button",{class:"app-hint__link",onClick:t[2]||(t[2]=function(){return o.setupTotp&&o.setupTotp(...arguments)})},(0,u.v_)(e.$t("ui.app.totpSetup")),1)])):(0,c.Q3)("",!0),e.error?((0,c.uX)(),(0,c.Wv)(r,{key:4})):(0,c.Q3)("",!0),(0,c.bF)(E.eB,{name:"animate-fade",mode:"out-in",style:{height:"100%"}},{default:(0,c.k6)((()=>[o.isInitializing||o.isReady?((0,c.uX)(),(0,c.CE)("div",Ti,[(0,c.Lk)("div",xi,[t[11]||(t[11]=(0,c.Lk)("img",{src:m,width:"100",height:"100",alt:"Contao Logo"},null,-1)),(0,c.Lk)("p",Oi,(0,u.v_)(e.$t("ui.app.loading")),1)])])):e.username&&e.taskStatus?((0,c.uX)(),(0,c.Wv)(d,{key:1,class:(0,u.C4)(e.hasModal?"animate-blur-in":"animate-blur-out")},null,8,["class"])):o.currentView?((0,c.uX)(),(0,c.Wv)((0,c.$y)(o.currentView),{key:2,class:(0,u.C4)(e.hasModal?"animate-blur-in":"animate-blur-out")},null,8,["class"])):((0,c.uX)(),(0,c.CE)("div",Pi,[(0,c.bF)(p,{class:(0,u.C4)(e.hasModal?"animate-blur-in":"animate-blur-out")},null,8,["class"])]))])),_:1}),e.hasModal?((0,c.uX)(),(0,c.Wv)((0,c.$y)(e.currentModal),{key:5})):(0,c.Q3)("",!0)])}a(3609);var Ii=a(953);const Fi={class:"view-error"},Ri={class:"view-error__content"},qi={class:"view-error__status"},Ui=["href"],ji={class:"view-error__headline"},Di={key:0,class:"view-error__details"},Wi={key:1,class:"view-error__debug"},Vi={class:"view-error__actions"},Qi=["href"],Hi=["href"];function Gi(e,t,a,s,n,o){return(0,c.uX)(),(0,c.CE)("div",Fi,[o.isDebug?((0,c.uX)(),(0,c.CE)("button",{key:0,type:"button",class:"view-error__close",onClick:t[0]||(t[0]=function(){return o.close&&o.close(...arguments)})},t[1]||(t[1]=[(0,c.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",fill:"#fff",xmlns:"http://www.w3.org/2000/svg"},[(0,c.Lk)("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"}),(0,c.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)]))):(0,c.Q3)("",!0),(0,c.Lk)("div",Ri,[t[3]||(t[3]=(0,c.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",class:"view-error__icon"},[(0,c.Lk)("path",{d:"M473.7 73.8l-2.4-2.5c-46-47-118-51.7-169.6-14.8L336 159.9l-96 64 48 128-144-144 96-64-28.6-86.5C159.7 19.6 87 24 40.7 71.4l-2.4 2.4C-10.4 123.6-12.5 202.9 31 256l212.1 218.6c7.1 7.3 18.6 7.3 25.7 0L481 255.9c43.5-53 41.4-132.3-7.3-182.1z"})],-1)),(0,c.Lk)("div",qi,[t[2]||(t[2]=(0,c.eW)("ERROR ")),e.error.status?((0,c.uX)(),(0,c.CE)("a",{key:0,href:`https://developer.mozilla.org/${e.$i18n.locale}/docs/Web/HTTP/Status/${e.error.status}`,target:"_blank"},(0,u.v_)(e.error.status),9,Ui)):(0,c.Q3)("",!0)]),(0,c.Lk)("h1",ji,(0,u.v_)(o.title),1),o.detail?((0,c.uX)(),(0,c.CE)("div",Di,(0,u.v_)(o.detail),1)):(0,c.Q3)("",!0),o.debug?((0,c.uX)(),(0,c.CE)("div",Wi,(0,u.v_)(o.debug),1)):(0,c.Q3)("",!0),(0,c.Lk)("div",Vi,["about:blank"!==e.error.type?((0,c.uX)(),(0,c.CE)("a",{key:0,href:e.error.type,target:"_blank",class:"view-error__link"},(0,u.v_)(e.$t("ui.error.moreLink")),9,Qi)):(0,c.Q3)("",!0),(0,c.Lk)("a",{href:`https://to.contao.org/support?lang=${e.$i18n.locale}`,target:"_blank",class:"view-error__link view-error__link--support"},(0,u.v_)(e.$t("ui.error.support")),9,Hi)])])])}var zi={computed:{...(0,h.aH)(["error"]),response:e=>e.error.response,isDebug:()=>!1,title(){return this.error.title?this.error.title:this.response?this.$t("ui.error.title",{method:(this.response.config.headers["X-HTTP-Method-Override"]||this.response.config.method).toUpperCase(),url:this.response.config.url}):this.$t("ui.app.apiError")},detail(){return this.error.detail?this.error.detail:this.error.debug?"":500===this.error.status?this.$t("ui.error.server500"):this.response?this.$t("ui.error.response",this.error):""},debug(){return this.error.debug?this.error.debug:this.response&&this.response.data?this.response.data:""}},methods:{close(){this.$store.commit("setError",null)}}};const Ni=(0,ee.A)(zi,[["render",Gi]]);var Ki=Ni,Ji=a.p+"img/task.e9e5333f.svg",Zi=a(3382);const Yi={class:"view-task__header"},el={class:"view-task__headline"},tl={key:0,class:"view-task__description"},al={class:"view-task__text"},sl={class:"view-task__text"},nl={href:"https://github.com/contao/contao-manager/issues/new",target:"_blank"},ol={class:"view-task__actions"},il={key:2,class:"view-task__actions"},ll={key:3,class:"view-task__loading"},rl={key:1,class:"view-task__sponsor"},cl=["href"];function ul(e,t,a,s,n,o){const i=(0,c.g2)("loading-button"),l=(0,c.g2)("check-box"),r=(0,c.g2)("loading-spinner"),d=(0,c.g2)("console-output"),p=(0,c.g2)("i18n-t"),g=(0,c.g2)("boxed-layout");return(0,c.uX)(),(0,c.Wv)(g,{wide:!0,slotClass:"view-task"},{default:(0,c.k6)((()=>[(0,c.Lk)("header",Yi,[t[3]||(t[3]=(0,c.Lk)("img",{src:Ji,width:"80",height:"80",alt:"",class:"view-task__icon"},null,-1)),(0,c.Lk)("h1",el,(0,u.v_)(e.$t("ui.task.headline")),1),e.taskStatus?((0,c.uX)(),(0,c.CE)("p",tl,(0,u.v_)(e.$t(`ui.task.${e.taskStatus}`)),1)):(0,c.Q3)("",!0),e.isFailed&&!e.awaitTask?((0,c.uX)(),(0,c.CE)(c.FK,{key:1},[(0,c.Lk)("p",al,[(0,c.eW)((0,u.v_)(e.$t("ui.task.failedDescription1")),1),t[1]||(t[1]=(0,c.Lk)("br",null,null,-1)),(0,c.eW)(" "+(0,u.v_)(e.$t("ui.task.failedDescription2")),1)]),(0,c.Lk)("p",sl,[t[2]||(t[2]=(0,c.Lk)("br",null,null,-1)),(0,c.Lk)("a",nl,(0,u.v_)(e.$t("ui.task.reportProblem")),1)]),(0,c.Lk)("div",ol,[(0,c.bF)(i,{class:"view-task__action",loading:e.deletingTask,onClick:o.deleteTask},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.task.buttonClose")),1)])),_:1},8,["loading","onClick"])])],64)):e.hasTask&&!e.awaitTask?((0,c.uX)(),(0,c.CE)("div",il,[e.allowCancel&&(e.isActive||e.isAborting)?((0,c.uX)(),(0,c.Wv)(i,{key:0,class:"view-task__action",color:"alert",loading:e.isAborting,onClick:o.cancelTask},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.task.buttonCancel")),1)])),_:1},8,["loading","onClick"])):(0,c.Q3)("",!0),e.requiresAudit?((0,c.uX)(),(0,c.Wv)(i,{key:1,class:"view-task__action",color:"primary",loading:e.loadingMigrations,disabled:e.supportsMigrations&&!e.hasDatabaseChanges||e.deletingTask,onClick:o.updateDatabase},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.task.buttonAudit")),1)])),_:1},8,["loading","disabled","onClick"])):(0,c.Q3)("",!0),e.isActive||e.isAborting?(0,c.Q3)("",!0):((0,c.uX)(),(0,c.Wv)(i,{key:2,class:"view-task__action",loading:e.deletingTask,onClick:o.deleteTask},{default:(0,c.k6)((()=>[(0,c.eW)((0,u.v_)(e.$t("ui.task.buttonConfirm")),1)])),_:1},8,["loading","onClick"])),e.isActive&&e.allowAutoClose?((0,c.uX)(),(0,c.Wv)(l,{key:3,name:"autoclose",label:e.$t("ui.task.autoclose"),modelValue:e.autoClose,"onUpdate:modelValue":t[0]||(t[0]=t=>e.autoClose=t)},null,8,["label","modelValue"])):(0,c.Q3)("",!0)])):((0,c.uX)(),(0,c.CE)("div",ll,[(0,c.bF)(r)]))]),e.hasTask?((0,c.uX)(),(0,c.Wv)(d,{key:0,class:"view-task__main",title:e.hasTask?e.currentTask.title:e.$t("ui.task.loading"),operations:e.currentTask.operations,"console-output":e.currentTask.console},null,8,["title","operations","console-output"])):(0,c.Q3)("",!0),e.currentTask&&e.currentTask.sponsor?((0,c.uX)(),(0,c.CE)("div",rl,[(0,c.bF)(p,{keypath:"ui.task.sponsor"},{sponsor:(0,c.k6)((()=>[t[4]||(t[4]=(0,c.Lk)("br",null,null,-1)),(0,c.Lk)("a",{href:e.currentTask.sponsor.link,target:"_blank",rel:"noreferrer noopener"},(0,u.v_)(e.currentTask.sponsor.name),9,cl)])),_:1}),t[5]||(t[5]=(0,c.Lk)("a",{href:"https://to.contao.org/donate",target:"_blank",rel:"noreferrer noopener",class:"view-task__donate"},[(0,c.Lk)("img",{src:Zi,alt:"",width:"20",height:"20"})],-1))])):(0,c.Q3)("",!0)])),_:1})}var dl={computed:{...(0,h.aH)("tasks",{taskStatus:"status",currentTask:"current",deletingTask:"deleting",awaitTask:"await"}),hasTask:e=>e.currentTask&&e.currentTask.status,isActive:e=>e.hasTask&&"active"===e.taskStatus,isComplete:e=>e.hasTask&&"complete"===e.taskStatus,isAborting:e=>e.hasTask&&"aborting"===e.taskStatus,isFailed:e=>"failed"===e.taskStatus,isError:e=>e.hasTask&&("error"===e.taskStatus||"stopped"===e.taskStatus||"failed"===e.taskStatus),allowAutoClose:e=>e.hasTask&&e.currentTask.autoclose,allowCancel:e=>e.hasTask&&e.currentTask.cancellable,requiresAudit:e=>e.isComplete&&e.currentTask.audit}},pl=a(6774),gl={name:"TaskView",mixins:[dl],components:{BoxedLayout:Da.A,LoadingSpinner:fs.A,LoadingButton:ia.A,ConsoleOutput:pl.A,CheckBox:Ha.A},data:()=>({autoClose:!1,favicons:null,faviconInterval:null}),computed:{...(0,h.aH)("server/database",{supportsMigrations:"supported",loadingMigrations:"loading"}),...(0,h.L8)("server/database",{hasDatabaseChanges:"hasChanges"})},methods:{cancelTask(){confirm(this.$t("ui.task.confirmCancel"))&&this.$store.dispatch("tasks/abort")},async deleteTask(){const e=this.isError;await this.$store.dispatch("tasks/deleteCurrent"),e&&window.location.reload()},async updateDatabase(){this.supportsMigrations?(await this.$store.dispatch("tasks/deleteCurrent"),this.$store.commit("checkMigrations")):window.open("/contao/install")},updateFavicon(){let e;this.faviconInterval&&clearInterval(this.faviconInterval);const t=e=>{this.favicons.forEach((t=>{t.href=`${e}/${t.href.split("/").pop()}`}))};switch(this.taskStatus){case"active":e="icons/task-active";break;case"complete":e="icons/task-success";break;case"error":case"failed":case"stopped":e="icons/task-error";break;default:return void setTimeout(t.bind(this,"icons"),2e3)}let a=!1;this.faviconInterval=setInterval((()=>{a=!a,t(a?e:"icons")}),2e3)}},watch:{taskStatus(){this.updateFavicon()},autoClose(e){window.localStorage.setItem("contao_manager_autoclose",e?"1":"0")},isComplete(){this.isComplete&&this.$store.dispatch("server/database/get",!1)}},mounted(){this.favicons=document.querySelectorAll('link[class="favicon"]'),this.updateFavicon(),this.autoClose="1"===window.localStorage.getItem("contao_manager_autoclose"),this.$store.dispatch("server/database/get")},beforeUnmount(){this.updateFavicon()}};const hl=(0,ee.A)(gl,[["render",ul]]);var ml=hl,kl={components:{ErrorView:Ki,TaskView:ml,Notivue:o.Bx,Notification:o.Eg},data:()=>({views:{[K.A.ACCOUNT]:(0,Ii.IG)((0,c.$V)((()=>Promise.all([a.e(60),a.e(612)]).then(a.bind(a,5612))))),[K.A.LOGIN]:(0,Ii.IG)((0,c.$V)((()=>Promise.all([a.e(60),a.e(479)]).then(a.bind(a,4479))))),[K.A.BOOT]:(0,Ii.IG)((0,c.$V)((()=>a.e(212).then(a.bind(a,300))))),[K.A.CONFIG]:(0,Ii.IG)((0,c.$V)((()=>a.e(82).then(a.bind(a,6222))))),[K.A.SETUP]:(0,Ii.IG)((0,c.$V)((()=>Promise.all([a.e(500),a.e(531)]).then(a.bind(a,763))))),[K.A.RECOVERY]:(0,Ii.IG)((0,c.$V)((()=>a.e(306).then(a.bind(a,3385))))),[K.A.MIGRATION]:(0,Ii.IG)((0,c.$V)((()=>a.e(139).then(a.bind(a,3139)))))},loaded:!1}),computed:{...(0,h.aH)(["safeMode"]),...(0,h.aH)(["view","error"]),...(0,h.aH)("auth",["username","limited","totpEnabled"]),...(0,h.aH)("tasks",{taskStatus:"status"}),...(0,h.L8)("modals",["hasModal","currentModal"]),isInitializing:e=>e.view===K.A.INIT,isReady:e=>!e.isInitializing&&!e.currentView&&!e.loaded,isInsecure:()=>"https:"!==location.protocol&&"localhost"!==location.hostname,currentView:e=>e.views[e.view]||null},methods:{...(0,h.i0)("auth",["logout"]),initColorMode(){let e=localStorage.getItem("contao--prefers-dark");null===e&&(e=String(window.matchMedia("(prefers-color-scheme: dark)").matches)),document.documentElement.dataset.colorScheme="true"===e?"dark":"light"},async checkPublicConfig(){const e=location.pathname.split("/").filter((e=>""!==e));e.unshift("");while(void 0!==e.pop()&&e.length){let a;try{a=(await s.A.get(`${e.join("/")}/contao-manager/users.json`)).data}catch(t){continue}if(a.users||a.version)throw this.$store.commit("setError",{title:this.$t("ui.app.configSecurity1"),type:"about:blank",status:"500",detail:this.$t("ui.app.configSecurity2")}),new Error(this.$t("ui.app.configSecurity1"))}},setupTotp(){this.$store.commit("modals/open",{id:"setup-totp",component:Ko.A})}},watch:{async isReady(e){if(e){try{await this.$store.dispatch("packages/uploads/load"),await this.$store.dispatch("packages/load"),await this.$store.dispatch("algolia/discover")}catch(t){}this.loaded=!0,this.$store.dispatch("packages/details/init",{vue:this,component:(0,c.$V)((()=>Promise.all([a.e(500),a.e(496)]).then(a.bind(a,9500))))})}},username(e){null===e&&(this.$store.commit("tasks/setCurrent",null),this.$store.commit("tasks/setInitialized",!1))}},async mounted(){if(this.initColorMode(),await this.checkPublicConfig(),await this.$router.isReady(),this.$route.query.invitation)return void this.$store.commit("setView",K.A.ACCOUNT);if(this.$route.query.token){try{await s.A.post("api/session",{token:this.$route.query.token})}catch(t){}this.$router.replace({name:this.$route.name,query:null})}const e=await this.$store.dispatch("auth/status");200===e?this.$store.commit("setView",K.A.BOOT):204===e?this.$store.commit("setView",K.A.ACCOUNT):401===e||403===e?this.$store.commit("setView",K.A.LOGIN):this.$store.commit("setError",{type:"about:blank",status:e})},created(){document.title=`Contao Manager | ${location.hostname}`}};const vl=(0,ee.A)(kl,[["render",Bi]]);var bl=vl;s.A.defaults.headers.common["Accept"]="application/json",s.A.interceptors.request.use((function(e){return"api/"===e.url.slice(0,4)&&(e.headers["Accept-Language"]=mi.A.plugin.global.locale,["PUT","PATCH","DELETE"].includes(e.method)&&(e.headers["X-HTTP-Method-Override"]=e.method,e.method="POST")),e})),s.A.interceptors.response.use((e=>(hi.A.commit("auth/renewCountdown"),e)),(function(e){if(!e.response)return Promise.reject(e);const t=e.response,a=t.config.url;return 401===t.status&&"api/session"!==a?(hi.A.commit("auth/reset"),hi.A.commit("setView",K.A.LOGIN),t):"application/problem+json"===t.headers["content-type"]?(500===t.status&&hi.A.commit("setError",t.data),Promise.reject(e)):"api/session"===a&&200!==t.status?t:"api/"===a.substring(0,4)&&"application/json"!==t.headers["content-type"]&&t.status>=400&&t.status<=599?(hi.A.commit("setError",{type:"about:blank",status:t.status,response:t}),Promise.reject(e)):Promise.reject(e)}));const _l=(0,o.FD)({position:"bottom-right",limit:4,enqueue:!0});(0,i.A)(bl,mi.A,[hi.A,gi,n.A,_l],(e=>{e.config.globalProperties.$notify=o.VC,e.config.globalProperties.$request=ki.A}))},4710:function(e,t,a){var s=a(4335),n=a(7008);const o=new Proxy(s.A,{get(e,t){const a={request:1,get:2,delete:2,head:2,options:2,post:3,put:3,patch:3};return Object.keys(a).includes(t)?async function(){let s,o={};for(var i=arguments.length,l=new Array(i),r=0;ra[t]&&(o=l.pop());try{s=await e[t](...l)}catch(c){s=c.response}return o[s.status]?o[s.status](s):(s.status>=400&&s.status<=599&&n.A.commit("apiError",s),s)}:Reflect.get(...arguments)}});t.A=o},4960:function(e,t){t.A=e=>{let t=["KB","MB","GB"],a="Bytes";while(e>1024)e/=1024,a=t.shift();return`${Math.round(100*e)/100} ${a}`}},5404:function(e,t,a){a.d(t,{A:function(){return p}});var s=a(641),n=a(33);const o={class:"layout-boxed"},i={class:"layout-boxed__cell"};function l(e,t,a,l,r,c){const u=(0,s.g2)("footer-fragment");return(0,s.uX)(),(0,s.CE)("div",o,[(0,s.Lk)("div",i,[(0,s.Lk)("div",{class:(0,n.C4)("layout-boxed__container "+(a.wide?" layout-boxed__container--wide ":"")+a.slotClass)},[(0,s.RG)(e.$slots,"default"),(0,s.bF)(u,{display:a.wide?"boxed":""},null,8,["display"])],2)])])}var r=a(1496),c={components:{FooterFragment:r.A},props:{slotClass:String,wide:Boolean}},u=a(6262);const d=(0,u.A)(c,[["render",l]]);var p=d},6774:function(e,t,a){a.d(t,{A:function(){return R}});var s=a(641),n=a(33);const o={class:"console"},i={class:"console__header"},l={class:"console__headline"},r={key:0,class:"console__description"},c={class:"console__actions"},u=["title"],d={class:"console__operations"};function p(e,t,a,p,g,h){const m=(0,s.g2)("button-menu"),k=(0,s.g2)("console-operation"),v=(0,s.gN)("clipboard");return(0,s.uX)(),(0,s.CE)("div",o,[(0,s.Lk)("section",i,[(0,s.Lk)("div",null,[(0,s.Lk)("h1",l,(0,n.v_)(a.title),1),a.description?((0,s.uX)(),(0,s.CE)("p",r,(0,n.v_)(a.description),1)):(0,s.Q3)("",!0)]),(0,s.Lk)("div",c,[a.forceConsole?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("button",{key:0,class:(0,n.C4)(["widget-button widget-button--transparent widget-button--console console__action",{"console__action--active":e.showConsole}]),title:e.$t("ui.console.toggle"),onClick:t[0]||(t[0]=function(){return h.toggleConsole&&h.toggleConsole(...arguments)})},null,10,u)),(0,s.bF)(m,{transparent:"","button-class":"console__action"},{default:(0,s.k6)((()=>[(0,s.Lk)("button",{onClick:t[1]||(t[1]=function(){return h.showLog&&h.showLog(...arguments)})},(0,n.v_)(e.$t("ui.console.showLog")),1),(0,s.bo)(((0,s.uX)(),(0,s.CE)("button",null,[(0,s.eW)((0,n.v_)(e.$t("ui.console.copyLog")),1)])),[[v,a.consoleOutput]])])),_:1})])]),(0,s.Lk)("div",d,[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(a.operations,((t,n)=>((0,s.uX)(),(0,s.Wv)(k,(0,s.v6)({key:n,ref_for:!0},t,{"show-console":e.showConsole,"force-console":a.forceConsole}),null,16,["show-console","force-console"])))),128))])])}var g=a(3751);const h={class:"button-menu"};function m(e,t,a,o,i,l){return(0,s.uX)(),(0,s.CE)("div",h,[(0,s.Lk)("button",{class:(0,n.C4)(l.classes),onClick:t[0]||(t[0]=function(){return l.toggle&&l.toggle(...arguments)})},null,2),(0,s.bo)((0,s.Lk)("div",{ref:"menu",class:"button-menu__menu",tabindex:"-1",onBlur:t[1]||(t[1]=function(){return l.close&&l.close(...arguments)}),onClick:t[2]||(t[2]=function(){return l.close&&l.close(...arguments)})},[(0,s.RG)(e.$slots,"default")],544),[[g.aG,e.showMenu]])])}var k={name:"ButtonMenu",props:{buttonClass:String,type:String,icon:{type:String,default:"more"},transparent:Boolean,disabled:Boolean},data:()=>({showMenu:!1}),computed:{classes(){let e=`widget-button widget-button--${this.icon} button-menu__button ${this.buttonClass}`;return this.type&&(e+=` widget-button--${this.type}`),this.transparent&&(e+=" widget-button--transparent"),e}},methods:{open(){this.showMenu=!0,setTimeout((()=>this.$refs.menu.focus()),0)},close(){this.$refs.menu.blur(),setTimeout((()=>{this.showMenu=!1}),300)},toggle(){this.showMenu?this.close():this.open()}}},v=a(6262);const b=(0,v.A)(k,[["render",m]]);var _=b;const f={class:"console-operation__status"},w={key:0,class:"console-operation__icon console-operation__icon--active",width:"18",height:"18",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"#dbab0a"},y={key:1,class:"console-operation__icon console-operation__icon--success",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},C={key:2,class:"console-operation__icon console-operation__icon--error",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},$={key:3,class:"console-operation__icon console-operation__icon--skipped",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},L={key:4,class:"console-operation__icon console-operation__icon--pending",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},A={class:"console-operation__label"},E={key:0,class:"console-operation__description"},X={class:"console-operation__lines"},S=["data-index"],M={class:"console-operation__line-number"},T={class:"console-operation__line-content"};function x(e,t,a,o,i,l){return(0,s.uX)(),(0,s.Wv)((0,s.$y)(console&&!a.forceConsole?"details":"div"),{ref:"details",class:"console-operation",onToggle:l.toggleConsole},{default:(0,s.k6)((()=>[((0,s.uX)(),(0,s.Wv)((0,s.$y)(console&&!a.forceConsole?"summary":"div"),{class:(0,n.C4)(["console-operation__summary",{"console-operation__summary--console":!!console}])},{default:(0,s.k6)((()=>[(0,s.Lk)("div",f,[l.isActive?((0,s.uX)(),(0,s.CE)("svg",w,t[3]||(t[3]=[(0,s.Lk)("g",{fill:"none",fillrule:"evenodd"},[(0,s.Lk)("g",{transform:"translate(1 1)","stroke-width":"2"},[(0,s.Lk)("circle",{opacity:".5",cx:"8",cy:"8",r:"7"}),(0,s.Lk)("path",{d:" M 15 8 A 7 7 0 0 1 8 15"})])],-1),(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M9 5a4 4 0 100 8 4 4 0 000-8z"},null,-1)]))):l.isSuccess?((0,s.uX)(),(0,s.CE)("svg",y,t[4]||(t[4]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"},null,-1)]))):l.isError||l.isStopped?((0,s.uX)(),(0,s.CE)("svg",C,t[5]||(t[5]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z"},null,-1)]))):l.isSkipped?((0,s.uX)(),(0,s.CE)("svg",$,t[6]||(t[6]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8z"},null,-1)]))):((0,s.uX)(),(0,s.CE)("svg",L,t[7]||(t[7]=[(0,s.Lk)("path",{"fill-rule":"evenodd",d:"M8 4a4 4 0 100 8 4 4 0 000-8z"},null,-1)])))]),(0,s.Lk)("div",A,[Array.isArray(a.summary)?((0,s.uX)(!0),(0,s.CE)(s.FK,{key:0},(0,s.pI)(a.summary,((e,o)=>((0,s.uX)(),(0,s.CE)(s.FK,{key:`${o}_title`},[(0,s.Lk)("h2",{class:(0,n.C4)(["console-operation__title",{"console-operation__title--disabled":e.match(/^~.+~$/)}])},(0,n.v_)(e.replace(/^~(.+)~$/,"$1")),3),a.details[o]?((0,s.uX)(),(0,s.CE)("p",{class:"console-operation__description",key:`${o}_details`},(0,n.v_)(a.details[o]),1)):(0,s.Q3)("",!0),t[8]||(t[8]=(0,s.Lk)("br",null,null,-1))],64)))),128)):((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.Lk)("h2",{class:(0,n.C4)(["console-operation__title",{"console-operation__title--disabled":a.summary.match(/^~.+~$/)}])},(0,n.v_)(a.summary.replace(/^~(.+)~$/,"$1")),3),a.details?((0,s.uX)(),(0,s.CE)("p",E,(0,n.v_)(a.details),1)):(0,s.Q3)("",!0)],64))])])),_:1})),a.console?((0,s.uX)(),(0,s.CE)("div",{key:0,class:"console-operation__console",ref:"console",onScroll:t[2]||(t[2]=function(){return l.scrolled&&l.scrolled(...arguments)})},[(0,s.bo)((0,s.Lk)("button",{class:"console-operation__scroll console-operation__scroll--top",onClick:t[0]||(t[0]=function(){return l.scrollToTop&&l.scrollToTop(...arguments)})},t[9]||(t[9]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24",viewBox:"0 0 24 24",width:"24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"})],-1)]),512),[[g.aG,!e.isScrolledTop]]),(0,s.Lk)("div",X,[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(l.consoleLines,((e,t)=>((0,s.uX)(),(0,s.CE)("div",{key:t,class:"console-operation__line","data-index":t},[(0,s.Lk)("span",M,(0,n.v_)(t+1),1),(0,s.Lk)("span",T,(0,n.v_)(e),1)],8,S)))),128))]),(0,s.bo)((0,s.Lk)("button",{class:"console-operation__scroll console-operation__scroll--bottom",onClick:t[1]||(t[1]=function(){return l.scrollToBottom&&l.scrollToBottom(...arguments)})},t[10]||(t[10]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24",viewBox:"0 0 24 24",width:"24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"})],-1)]),512),[[g.aG,!e.isScrolledBottom]])],544)):(0,s.Q3)("",!0)])),_:1},40,["onToggle"])}a(9348);var O={name:"ConsoleOperation",props:{status:String,summary:[String,Array],details:[String,Array],console:String,showConsole:Boolean,forceConsole:Boolean},data:()=>({openConsole:!0,isScrolledTop:!0,isScrolledBottom:!0,autoScroll:!0,swallowScroll:!0}),computed:{isPending:e=>"pending"===e.status,isActive:e=>"active"===e.status,isSuccess:e=>"complete"===e.status,isError:e=>"error"===e.status,isStopped:e=>"stopped"===e.status,isSkipped:e=>"skipped"===e.status,consoleLines:e=>e.console.trim().split("\n")},methods:{toggleConsole(){this.openConsole=this.$refs.details.open,this.openConsole&&this.$refs.console&&(this.autoScroll=!0,this.$refs.console.scrollTop=this.$refs.console.scrollHeight,this.updatePosition())},scrolled(){this.swallowScroll||this.updatePosition(),this.swallowScroll=!1},updatePosition(){const e=this.$refs.console,t=e.scrollTop+e.clientHeight;this.autoScroll=t===e.scrollHeight,this.isScrolledTop=e.clientHeight<=250||e.scrollHeight>250&&e.scrollTop<16,this.isScrolledBottom=e.clientHeight<=250||e.scrollHeight>250&&t>=e.scrollHeight-16},scrollToTop(){this.$refs.console.scrollTop=0},scrollToBottom(){this.$refs.console.scrollTop=this.$refs.console.scrollHeight},updateConsole(){let e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.isError&&(e=!0),this.$refs.details&&(this.$refs.details.open=e)}},watch:{console(e){e&&(this.updateConsole(this.openConsole),this.autoScroll&&setTimeout((()=>{this.swallowScroll=!0,this.$refs.console.scrollTop=this.$refs.console.scrollHeight}),0))},showConsole(e){this.openConsole=e,this.updateConsole(e)}},mounted(){this.openConsole=this.showConsole,this.updateConsole(this.openConsole)}};const P=(0,v.A)(O,[["render",x]]);var B=P,I={components:{ConsoleOperation:B,ButtonMenu:_},props:{title:{type:String,required:!0},description:String,operations:{type:Array,required:!0},forceConsole:{type:Boolean,default:!1},consoleOutput:String},data:()=>({showConsole:!1}),methods:{toggleConsole(){this.showConsole=!this.showConsole,window.localStorage.setItem("contao_manager_console",this.showConsole?"1":"0")},showLog(){const e=window.open();e&&(e.document.open(),e.document.write(`
${this.consoleOutput}
`),e.document.close())}},mounted(){this.showConsole="1"===window.localStorage.getItem("contao_manager_console")}};const F=(0,v.A)(I,[["render",p]]);var R=F},6894:function(e,t,a){e.exports=a.p+"img/logo.d9707286.svg"},7008:function(e,t,a){a.d(t,{A:function(){return ke}});var s=a(6278),n=a(707),o=a(4335),i=a(4710),l=a(70),r=a(641),c=a(33);const u={class:"logout-warning__text"},d={class:"logout-warning__countdown"},p={key:1,class:"logout-warning__text"};function g(e,t,a,s,n,o){const i=(0,r.g2)("loading-button"),l=(0,r.g2)("popup-overlay");return(0,r.uX)(),(0,r.Wv)(l,{class:"logout-warning",headline:e.$t("ui.logout.headline"),headlineType:0===this.countdown?"alert":null},{actions:(0,r.k6)((()=>[e.countdown>0?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[(0,r.bF)(i,{color:"primary",loading:e.renew,disabled:e.logout,onClick:o.keepAlive},{default:(0,r.k6)((()=>[(0,r.eW)((0,c.v_)(e.$t("ui.logout.renew")),1)])),_:1},8,["loading","disabled","onClick"]),(0,r.bF)(i,{onClick:o.doLogout,loading:e.logout,disabled:e.renew},{default:(0,r.k6)((()=>[(0,r.eW)((0,c.v_)(e.$t("ui.logout.logout")),1)])),_:1},8,["onClick","loading","disabled"])],64)):((0,r.uX)(),(0,r.Wv)(i,{key:1,onClick:o.close},{default:(0,r.k6)((()=>[(0,r.eW)((0,c.v_)(e.$t("ui.logout.login")),1)])),_:1},8,["onClick"]))])),default:(0,r.k6)((()=>[e.countdown>0?((0,r.uX)(),(0,r.CE)(r.FK,{key:0},[(0,r.Lk)("p",u,(0,c.v_)(e.$t("ui.logout.warning")),1),(0,r.Lk)("p",d,(0,c.v_)(o.minutes)+":"+(0,c.v_)(o.seconds),1)],64)):((0,r.uX)(),(0,r.CE)("p",p,(0,c.v_)(e.$t("ui.logout.expired")),1))])),_:1},8,["headline","headlineType"])}var h=a(3170),m=a(6966),k={components:{PopupOverlay:h.A,LoadingButton:m.A},data:()=>({renew:!1,logout:!1}),computed:{...(0,s.aH)("auth",["countdown"]),minutes(){return Math.floor(this.countdown/60)},seconds(){const e=this.countdown%60;return e<10?`0${e}`:e}},methods:{async keepAlive(){this.renew=!0,await this.$store.dispatch("auth/status"),this.renew=!1},async doLogout(){this.logout=!0,await this.$store.dispatch("auth/logout"),this.logout=!1},close(){this.$store.commit("auth/resetCountdown")}}},v=a(6262);const b=(0,v.A)(k,[["render",g]]);var _=b;let f,w,y,C;const $=function(){clearTimeout(f),y=Date.now()+18e5,w=1800,f=setInterval(A,1e3),C.commit("setCountdown",w),C.commit("modals/close","logout-warning",{root:!0})},L=function(){y=null,w=null,clearInterval(f),f=void 0,C.commit("setCountdown",w),C.commit("modals/close","logout-warning",{root:!0})},A=function(){w>0&&(w=Math.floor(Math.max(y-Date.now(),0)/1e3)),w<=300&&C.commit("modals/open",{id:"logout-warning",component:_,priority:255},{root:!0}),0===w&&(C.dispatch("logout"),clearInterval(f)),C.commit("setCountdown",w)};var E={namespaced:!0,state:{username:null,scope:null,limited:!1,totpEnabled:!1,passkey:!1,countdown:null},getters:{isGranted:e=>t=>{const a=Object.values(l.A);return e.scope&&a.indexOf(e.scope)<=a.indexOf(t)}},mutations:{setUser(e,t){e.username=t?.username||null,e.scope=t?.scope||null,e.limited=t?.limited||!1,e.totpEnabled=t?.totp_enabled||t?.passkey||!1,e.passkey=t?.passkey||!1},setCountdown(e,t){e.countdown=t},renewCountdown(){C&&$()},resetCountdown(){C&&L()}},actions:{status(e){return C=e,o.A.get("api/session").then((t=>(t.data.username?(e.commit("setUser",t.data),$()):(e.commit("setUser",null),L()),t.status))).catch((t=>(e.commit("setUser",null),L(),403===t.response?.status&&e.commit("setLocked",null,{root:!0}),t.response?.status)))},async login(e,t){return C=e,await i.A.post("api/session",t,null,{201:t=>(e.commit("setUser",t.data),$(),t),401:e=>e,403:t=>(e.commit("setLocked",null,{root:!0}),t),422:e=>e})},logout(e){let{commit:t}=e;return o.A.delete("api/session").then((()=>!0),(e=>401===e.status)).then((e=>(e&&(t("setUser",null),t("setView",n.A.LOGIN,{root:!0}),L()),e)))}}},X=a(7943),S={namespaced:!0,state:{enabled:null,status:null},getters:{isLoading:e=>null===e.enabled||null===e.status,isReady:e=>e.enabled&&null!==e.status&&!!e.status.appVersion,hasError:(e,t)=>e.enabled&&!t.isLoading&&!t.isReady},mutations:{setEnabled(e,t){e.enabled=t},setStatus(e,t){e.status=t}},actions:{async fetch(e){let{state:t,commit:a,dispatch:s}=e,n=t.enabled;if(null===t.enabled){try{const e=await s("server/config/get",null,{root:!0});n=!!e.cloud?.enabled}catch(i){n=!1}a("setEnabled",n)}if(n)try{const e=await o.A.get("https://www.composer-resolver.cloud/",{timeout:2500,responseType:"json",headers:{"Composer-Resolver-Client":"contao"}});if(!e.data?.appVersion)return void a("setStatus",{});a("setStatus",e.data)}catch(i){a("setStatus",{})}else a("setStatus",{})}}},M={namespaced:!0,actions:{get(){return o.A.get("api/config/composer").then((e=>e.data))},put(e,t){return o.A.put("api/config/composer",t).then((e=>e.data))},patch(e,t){return o.A.patch("api/config/composer",t).then((e=>e.data))},writeDefaults(e){let{dispatch:t}=e;return t("patch",{config:{"preferred-install":"dist","store-auths":!1,"optimize-autoloader":!0,"sort-packages":!0,"discard-changes":!0}}).then((e=>e.data))}}},T={namespaced:!0,modules:{composer:M}},x=a(156),O=(a(4114),a(8111),a(2489),a(116),a(7588),a(9589)),P=a(950),B=a(9997);a(1701),a(8237);const I=e=>{const t=Object.values(e).reduce(((e,t)=>(e[t.hash]=(e[t.hash]||0)+1,e)),{});return!!Object.values(t).find((e=>e>1))};var F={namespaced:!0,state:{uploads:null,uploading:!1,files:[],confirmed:[],removing:[]},getters:{hasUploads:(e,t)=>t.totalUploads>0,isDuplicate:e=>(t,a)=>Object.values(e.uploads).find((s=>s.id!==t&&(s.hash===e.uploads[t].hash||e.uploads[s.id]?.package?.name===a))),isRemoving:e=>t=>e.removing.includes(t),totalUploads:(e,t)=>e.uploads?t.unconfirmedUploads.length:0,unconfirmedUploads:e=>Object.values(e.uploads).filter((t=>!e.confirmed.includes(t.id))),canConfirmUploads:(e,t,a,s)=>!!e.uploads&&(void 0===Object.values(e.uploads).find((e=>!e.success||e.error||Object.keys(a.packages.installed).includes(e.package.name)&&a.packages.installed[e.package.name].version===e.package.version||e.package.require&&!s["packages/contaoSupported"](e.package.require["contao/core-bundle"]||e.package.require["contao/manager-bundle"])))&&!I(e.uploads))},mutations:{setUploads(e,t){e.uploads=t},setUploading(e,t){e.uploading=!!t},setFiles(e,t){e.files=t},setConfirmed(e,t){e.confirmed.push(t)},setUnconfirmed(e,t){o.A.delete(e.confirmed,e.confirmed.indexOf(t))},setRemoving(e,t){e.removing.push(t)},setRemoved(e,t){e.removing=e.removing.filter((e=>e!==t))}},actions:{async load(e){let{commit:t}=e;try{t("setUploads",(await o.A.get("api/packages/uploads")).data)}catch(a){if(501!==a.status)throw a;t("setUploads",!1)}},async confirm(e,t){let{state:a,commit:s}=e;const n=a.uploads[t].package;n&&(this.getters["packages/packageInstalled"](n.name)?this.commit("packages/change",n):this.commit("packages/add",Object.assign({},n,{constraint:n.version})),n.suggest&&await Promise.all(Object.keys(n.suggest).map((async e=>{if(!this.getters["packages/packageInstalled"](e)){const t=await this.dispatch("packages/metadata",{name:e});t.contaoConstraint&&!this.getters["packages/contaoSupported"](t.contaoConstraint)||this.commit("packages/add",{name:e})}}))),s("setConfirmed",t))},confirmAll(e){let{state:t,dispatch:a}=e;Object.keys(t.uploads).forEach((e=>a("confirm",e)))},unconfirm(e,t){let{state:a,commit:s}=e;const n=a.confirmed.includes(t)?t:Object.keys(a.uploads).find((e=>a.uploads[e].package&&a.uploads[e].package.name===t&&a.confirmed.includes(e)));if(!n)return;s("setUnconfirmed",n);const o=a.uploads[n].package;o&&o.suggest&&Object.keys(o.suggest).forEach((e=>{this.getters["packages/packageAdded"](e)&&this.commit("packages/restore",e)}))},unconfirmAll(e){let{state:t,dispatch:a}=e;Object.keys(t.uploads).forEach((e=>a("unconfirm",e)))},async remove(e,t){let{commit:a,dispatch:s}=e;a("setRemoving",t),await o.A.delete(`api/packages/uploads/${t}`),await s("load"),a("setRemoved",t),await s("unconfirm",t)},async removeAll(e){let{state:t,commit:a,dispatch:s}=e;await Promise.all(Object.keys(t.uploads).map((async e=>{t.confirmed.includes(e)||(a("setRemoving",e),await o.A.delete(`api/packages/uploads/${e}`),a("setRemoved",e))}))),await s("load")}}};const R=["contao/core-bundle","contao/installation-bundle","contao/conflicts"],q=e=>e.includes("/")&&!R.includes(e),U=(e,t)=>q(e)&&!t.packageFeature(e);var j={namespaced:!0,modules:{details:P.A,uploads:F},state:{root:null,local:null,installed:null,required:{},add:{},change:{},update:[],remove:[]},getters:{hasRoot:e=>!!e.root,packageInstalled:(e,t)=>a=>Object.keys(e.installed).includes(a)&&!t.packageMissing(a),versionInstalled:e=>(t,a)=>Object.keys(e.installed).includes(t)&&e.installed[t].version===a,packageRoot:e=>t=>!!e.root&&Object.keys(e.root.require).includes(t),packageRequired:e=>t=>Object.keys(e.required).includes(t)&&!!e.required[t].constraint,packageMissing:e=>t=>Object.keys(e.required).includes(t)&&!e.required[t].constraint,packageAdded:e=>t=>Object.keys(e.add).includes(t),packageChanged:e=>t=>Object.keys(e.change).includes(t),packageUpdated:e=>t=>e.update.includes(t),packageRemoved:e=>t=>e.remove.includes(t),packageFeatures:()=>e=>B.A[e]?B.A[e]:[],packageFeature:(e,t)=>e=>!!Object.keys(B.A).find((a=>B.A[a].includes(e)&&(t.packageInstalled(a)||t.packageRequired(a)))),packageVisible:(e,t)=>e=>U(e,t),packageSuggested:e=>t=>!!Object.values(e.local||{}).concat(Object.values(e.add||{})).find((e=>e.type&&("contao-"===e.type.substr(0,7)||"contao/"===e.name.substr(0,7))&&e.suggest&&Object.prototype.hasOwnProperty.call(e.suggest,t))),totalChanges:e=>Object.keys(e.add).filter(q).length+Object.keys(e.required).filter(q).length+Object.keys(e.change).filter(q).length+e.update.length+e.remove.length-Object.values(e.add).filter((t=>Object.keys(e.required).includes(t.name))).length-Object.values(e.change).filter((t=>Object.keys(e.required).includes(t.name))).length-e.remove.filter((t=>Object.keys(e.required).includes(t))).length,totalRequired:e=>Object.keys(e.required).length-Object.values(e.add).filter((t=>Object.keys(e.required).includes(t.name))).length-Object.values(e.change).filter((t=>Object.keys(e.required).includes(t.name))).length-e.remove.filter((t=>Object.keys(e.required).includes(t))).length,canResetChanges:(e,t)=>t.totalChanges>t.totalRequired,visibleRequired:(e,t)=>Object.values(e.required).filter((e=>U(e.name,t))),visibleInstalled:(e,t)=>Object.values(t.installed).filter((e=>U(e.name,t))),visibleAdded:(e,t)=>Object.values(e.add).filter((e=>U(e.name,t))),installed:e=>{if(!e.root||!e.installed)return{};const t={};return Object.keys(e.root.require).forEach((a=>{a.includes("/")&&e.installed[a]&&(t[a]={name:a,version:!1,constraint:e.root.require[a]},t[a]=Object.assign(t[a],e.installed[a]))})),t},packageConstraint:(e,t)=>e=>t.packageConstraintAdded(e)||t.packageConstraintChanged(e)||t.packageConstraintInstalled(e)||t.packageConstraintRequired(e),packageConstraintAdded:(e,t)=>a=>t.packageAdded(a)?e.add[a].constraint:null,packageConstraintChanged:(e,t)=>a=>t.packageChanged(a)?e.change[a]:null,packageConstraintInstalled:(e,t)=>e=>t.packageInstalled(e)&&t.packageRoot(e)?t.installed[e].constraint:null,packageConstraintRequired:(e,t)=>a=>t.packageRequired(a)?t.packageChanged(a)?t.constraintChanged(a):e.required[a].constraint:null,contaoConstraint:(e,t)=>(0,O.coerce)(t.packageConstraint("contao/manager-bundle"),{includePrerelease:!0}).toString(),contaoSupported:(e,t)=>e=>!e||(0,O.intersects)(e,t.contaoConstraint,!0)},mutations:{setInstalled(e,t){let{root:a,local:s,missing:n}=t;const o={},i={};s&&Object.keys(s).forEach((e=>{!1===s[e].version?i[e]=s[e]:o[e]=s[e]})),a&&Object.keys(a.require).forEach((e=>{e.includes("/")&&(Object.prototype.hasOwnProperty.call(o,e)||Object.prototype.hasOwnProperty.call(i,e)||(i[e]={name:e,constraint:a.require[e]}))})),n&&n.forEach((e=>{i[e]={name:e,constraint:null}})),e.root=a,e.local=s,e.installed=o,e.required=i},clearInstalled(e){e.root=null,e.local=null,e.installed=null,e.required={}},add(e,t){e.add[t.name]=t},change(e,t){let{name:a,version:s}=t;this.commit("packages/restore",a),e.change[a]=s},update(e,t){this.commit("packages/restore",t),e.update.push(t)},remove(e,t){this.commit("packages/restore",t),e.remove.push(t)},restore(e,t){delete e.add[t],delete e.change[t],e.remove.includes(t)&&e.remove.splice(e.remove.indexOf(t),1),e.update.includes(t)&&e.update.splice(e.update.indexOf(t),1)},reset(e){e.add={},e.change={},e.update=[],e.remove=[]}},actions:{async metadata(e,t){let{state:a,dispatch:s}=e;const n=t.name;if(t&&!t.source&&t.extra&&t.extra["contao-metadata-url"])return t;const o=await s("algolia/getPackage",n,{root:!0});if(!o)return t;const i=e=>e.version&&(0,O.valid)(e.version)?(0,O.parse)(e.version):e.version_normalized?(0,O.coerce)(e.version_normalized,{loose:!0}):null,l=a.change[n]||a.root?.require[n],r=a.installed?i(t):null;if(o.update=null,o.versions&&l&&"dev-"!==l.substr(0,4)&&"-dev"!==l.substr(-4)){let e;o.update={valid:!0,latest:!0,version:null,time:null},l&&r&&(e=o.versions.filter((e=>e.version===r.version||(0,O.satisfies)(i(e),l))).pop(),e?(o.update.version=e.version,o.update.time=e.time,o.update.latest=(0,O.eq)(i(e),r),o.latest&&o.latest.version&&(o.latest.active=(0,O.eq)(i(e),o.latest.version))):o.update.valid=!1)}const c=Object.assign({},o,{dependents:t.dependents||o.dependents,conflict:t.conflict||o.conflict,require:t.require||o.require,"require-dev":t["require-dev"]||o["require-dev"],suggest:o.suggest});return t.suggest&&(c.suggest={},Object.keys(t.suggest).forEach((e=>{c.suggest[e]=o.suggest&&o.suggest[e]||t.suggest[e]}))),c},async load(e){let{commit:t}=e;t("clearInstalled"),t("reset"),t("algolia/reset",null,{root:!0});const a={},s=[o.A.get("api/packages/root"),o.A.get("api/packages/local"),o.A.get("api/packages/missing")];return t("setInstalled",{root:(await s[0]).data,local:(await s[1]).data,missing:(await s[2]).data}),a},apply(e){let{state:t,dispatch:a}=e,s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{dry_run:!1,update_all:!1};const n=t.change,o=t.remove,i=t.update.concat(Object.keys(t.required),Object.keys(t.change).filter((e=>!Object.keys(t.required).includes(e))),t.remove.filter((e=>!Object.keys(t.required).includes(e))));Object.keys(t.add).forEach((e=>{n[t.add[e].name]=t.add[e].constraint||null,i.push(t.add[e].name)})),Object.keys(B.A).forEach((e=>{B.A[e].forEach((a=>{if(t.root&&Object.keys(t.root.require).includes(a)||t.installed&&Object.keys(t.installed).includes(a))return i.includes(e)&&i.push(a),void(n[e]?n[a]=n[e]:o.includes(e)&&o.push(a));Object.prototype.hasOwnProperty.call(n,a)&&(i.includes(a)||i.push(a),!Object.prototype.hasOwnProperty.call(n,e)&&t.root?.require[e]?n[a]=t.root.require[e]:Object.prototype.hasOwnProperty.call(n,e)&&(n[a]=n[e]))}))}));const l={require:n,remove:o,uploads:!0,dry_run:!!s.dry_run};s.update_all||(l.update=i);const r={name:"composer/update",config:l};return a("tasks/execute",r,{root:!0})},updateAll(e){let{state:t,getters:a,commit:s}=e;Object.keys(t.root.require).forEach((e=>{U(e,a)&&s("update",e)}))}}};const D=(e,t)=>{let{commit:a}=t;return new Promise(((t,s)=>{e.then((e=>{a("setCache",e.data["access-key"]),a("setIsEnabled",""!==e.data["access-key"]),t(e.data["access-key"])})).catch((()=>{a("setIsEnabled",!1),s()}))}))};var W={namespaced:!0,state:{cache:null,isEnabled:null},mutations:{setCache(e,t){e.cache=t},setIsEnabled(e,t){e.isEnabled=t}},actions:{get(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return t&&e.state.cache?Promise.resolve(e.state.cache):e.rootState.safeMode||e.rootState.server.contao.contaoApi.version<1||!e.rootState.server.contao.contaoApi.features?.["contao/manager-bundle"]?.["dot-env"]?.includes("APP_DEV_ACCESSKEY")?Promise.reject():D(o.A.get("api/contao/access-key"),e)},set(e,t){return D(o.A.put("api/contao/access-key",t),e)},delete(e){return D(o.A.delete("api/contao/access-key"),e)}}},V={namespaced:!0,state:{cache:null,isSupported:null,isLocked:null},mutations:{setCache(e,t){e.cache=t,e.isSupported=!t&&null,e.isLocked=null,t&&200===t.status&&(e.isSupported=!0,e.isLocked=!0===t.data.locked)}},actions:{fetch(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(t&&e.state.cache)return Promise.resolve(e.state.cache);if(e.rootState.safeMode)return e.commit("setCache"),Promise.resolve();const a=t=>(e.commit("setCache",t),Promise.resolve(t));return o.A.get("api/contao/install-tool/lock").then(a).catch((e=>a(e.response)))},lock(e){const t=t=>(e.commit("setCache",t),Promise.resolve(t));return o.A.put("api/contao/install-tool/lock").then(t).catch((e=>t(e.response)))},unlock(e){const t=t=>(e.commit("setCache",t),Promise.resolve(t));return o.A.delete("api/contao/install-tool/lock").then(t).catch((e=>t(e.response)))}}};const Q=(e,t)=>{let{commit:a}=t;return new Promise(((t,s)=>{e.then((e=>{a("setCache",e.data),a("setIsDebugEnabled",204!==e.status&&e.data.debug),t(e.data)})).catch((()=>{a("setIsDebugEnabled",!1),s()}))}))};var H={namespaced:!0,state:{cache:null,isDebugEnabled:null},mutations:{setCache(e,t){e.cache=t},setIsDebugEnabled(e,t){e.isDebugEnabled=t}},actions:{get(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return t&&e.state.cache?Promise.resolve(e.state.cache):e.rootState.safeMode||e.rootState.server.contao.contaoApi.version<2||!e.rootState.server.contao.contaoApi.features?.["contao/manager-bundle"]?.["jwt-cookie"]?.includes("debug")?Promise.reject():Q(o.A.get("api/contao/jwt-cookie"),e)},enableDebug(e){return Q(o.A.put("api/contao/jwt-cookie",{debug:!0}),e)},disableDebug(e){return Q(o.A.put("api/contao/jwt-cookie",{debug:!1}),e)},delete(e){return Q(o.A.delete("api/contao/jwt-cookie"),e)}}};const G=(e,t)=>{let{commit:a}=t;return new Promise(((t,s)=>{e.then((e=>{a("setCache",e.data.enabled),a("setIsEnabled",!0===e.data.enabled),t(e.data.enabled)})).catch((()=>{a("setIsEnabled",!1),s()}))}))};var z={namespaced:!0,state:{cache:null,isEnabled:null},mutations:{setCache(e,t){e.cache=t},setIsEnabled(e,t){e.isEnabled=t}},actions:{isEnabled(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return t&&e.state.cache?Promise.resolve(e.state.cache):e.rootState.safeMode?Promise.reject():G(o.A.get("api/contao/maintenance-mode"),e)},enable(e){return G(o.A.put("api/contao/maintenance-mode"),e)},disable(e){return G(o.A.delete("api/contao/maintenance-mode"),e)}}},N={namespaced:!0,state:{cache:null,loading:!1,supported:!1,files:[],restore:!1,restored:!1},getters:{hasBackups:e=>e.supported&&e.files&&e.files.length>0},mutations:{setLoading(e,t){e.loading=!!t},setCache(e,t){e.cache=t,e.loading=!1,e.supported=!t&&null,e.files=[],t&&200===t.status&&(e.supported=!0,e.files=t.data)},setRestore(e,t){e.restore=t},setRestored(e){e.restored=!0}},actions:{fetch(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(s&&t.cache)return new Promise((e=>{e(t.cache)}));const n=e=>(a("setCache",e),e);return a("setLoading",!0),o.A.get("api/contao/backup").then(n).catch((e=>n(e.response)))}}},K={namespaced:!0,modules:{"access-key":W,backup:N,"install-tool":V,"jwt-cookie":H,"maintenance-mode":z},state:{package:null,version:null},mutations:{installTheme(e,t){let{package:a,version:s}=t;e.package=a,e.version=s}},actions:{install(e,t){let{dispatch:a}=e;const s={name:"contao/install",config:t};return a("config/composer/writeDefaults",null,{root:!0}).then((()=>a("tasks/execute",s,{root:!0})))}}},J={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return s&&t.cache?new Promise((e=>{e(t.cache)})):o.A.get("api/server/composer").then((e=>e.data)).then((e=>(a("setCache",e),e)))}}},Z={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{async get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(s&&t.cache)return t.cache;const n=(await o.A.get("api/server/config")).data;return a("setCache",n),n},async set(e,t){let{commit:a}=e;try{const e=(await o.A.put("api/server/config",t)).data;return a("setCache",e),e}catch(s){if(!s.response)throw s;return s.response.data}}}},Y={namespaced:!0,state:{cache:null,contaoVersion:null,contaoApi:null,contaoConfig:null},getters:{badgeTitle:e=>e.contaoConfig?.backend?.badge_title},mutations:{setCache(e,t){e.cache=t,e.contaoVersion=null,e.contaoApi=null,e.contaoConfig=null,t&&(e.contaoVersion=t.data.version,e.contaoApi=t.data.api,e.contaoConfig=t.data.config)}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(s&&t.cache)return new Promise((e=>{e(t.cache)}));const n=e=>(a("setCache",e),e);return o.A.get("api/server/contao").then(n).catch((e=>n(e.response)))},documentRoot(e,t){let{directory:a,usePublicDir:s=!1}=t;const n={usePublicDir:s};return a&&(n.directory=a),o.A.post("api/server/contao",n).catch((e=>e))}}},ee={namespaced:!0,state:{cache:null,loading:!1,supported:null,status:null,pattern:null,url:null},getters:{totalMigrations:e=>e.status&&"migration"===e.status.type?e.status.total:0,totalSchemaUpdates:e=>e.status&&"schema"===e.status.type?e.status.total:0,hasError:e=>!!e.status&&("error"===e.status.type||"problem"===e.status.type),hasWarning:e=>!!e.status&&e.status.warnings>0,hasChanges:(e,t)=>!!t.totalMigrations||!!t.totalSchemaUpdates,totalChanges:(e,t)=>t.totalMigrations+t.totalSchemaUpdates,accessProblem:e=>!!e.status&&"error"===e.status.type&&e.status.message.toLowerCase().includes("access denied")},mutations:{setLoading(e,t){e.loading=!!t},setCache(e,t){e.cache=t,e.loading=!1,e.supported=!t&&null,e.status=null,e.url=null,t&&200===t.status&&(e.supported=!0,e.status=t.data.status,e.pattern=t.data.pattern,e.url=t.data.url)}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(s&&t.cache)return new Promise((e=>{e(t.cache)}));const n=e=>(a("setCache",e),e);return a("setLoading",!0),o.A.get("api/server/database").then(n).catch((e=>n(e.response)))},set(e,t){let{commit:a}=e;const s=e=>(a("setCache",e),e);return a("setLoading",!0),o.A.post("api/server/database",{url:t}).then(s).catch((e=>s(e.response)))}}},te={namespaced:!0,state:{cache:null,supported:!1,hasUser:null},mutations:{setCache(e,t){e.cache=t,e.supported=!1,e.hasUser=null,!t||200!==t.status&&201!==t.status||(e.supported=!0,e.hasUser=!!t.data.hasUser)}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(s&&t.cache)return new Promise((e=>{e(t.cache)}));const n=e=>(a("setCache",e),e);return o.A.get("api/server/admin-user").then(n).catch((e=>n(e.response)))},set(e,t){let{commit:a}=e;const s=e=>(a("setCache",e),e);return o.A.post("api/server/admin-user",t).then(s).catch((e=>s(e.response)))}}},ae={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return s&&t.cache?new Promise((e=>{e(t.cache)})):o.A.get("api/server/opcache").then((e=>e.data)).then((e=>(a("setCache",e),e)))},delete(e,t){let{commit:a}=e;return o.A.delete(`api/server/opcache?opcache_reset=${encodeURIComponent(t)}`).then((e=>e.data)).then((e=>(a("setCache",e),e)))}}},se={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return s&&t.cache?new Promise((e=>{e(t.cache)})):o.A.get("api/server/php-cli").then((e=>e.data)).then((e=>(a("setCache",e),e)))}}},ne={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{async get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(s&&t.cache)return t.cache;const n=(await o.A.get("api/server/phpinfo",{responseType:"text"})).data;return a("setCache",n),n}}},oe={namespaced:!0,state:{cache:null,phpVersion:null,phpVersionId:null},mutations:{setCache(e,t){e.cache=t,e.phpVersion=null,e.phpVersionId=null,t&&200===t.status&&(e.phpVersion=t.data.version,e.phpVersionId=t.data.version_id)}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(s&&t.cache)return new Promise((e=>{e(t.cache)}));const n=e=>(a("setCache",e),Promise.resolve(e));return o.A.get("api/server/php-web").then(n).catch((e=>n(e.response)))}}},ie={namespaced:!0,state:{cache:null},mutations:{setCache(e,t){e.cache=t}},actions:{get(e){let{state:t,commit:a}=e,s=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return s&&t.cache?new Promise((e=>{e(t.cache)})):o.A.get("api/server/self-update").then((e=>e.data)).catch((e=>{if(501===e.response?.status)return{current_version:null,latest_version:null,channel:"dev",supported:!1,error:null};throw e})).then((e=>(a("setCache",e),e)))},async latest(){const e=await o.A.get("https://download.contao.org/contao-manager/stable/contao-manager.version");return e.data.version}}},le={namespaced:!0,modules:{composer:J,config:Z,contao:Y,database:ee,adminUser:te,opcache:ae,phpinfo:ne,"php-cli":se,"php-web":oe,"self-update":ie}};let re,ce,ue,de=0,pe=!1;const ge=function(e,t,a){let s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3,n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1;setTimeout((()=>{o.A.get("api/task",{timeout:5e3*n}).then((s=>re(s,e,t,a))).catch((s=>ce(s,e,t,a)))}),s)};re=(e,t,a,s)=>{if(de=0,204===e.status)return void a();if(!(e.data instanceof Object))return pe||t.commit("apiError",e,{root:!0}),void s();const n=e.data;switch(t.commit("setCurrent",n),n.status){case"active":case"aborting":ge(t,a,s);break;case"terminated":case"complete":n.autoclose&&"1"===window.localStorage.getItem("contao_manager_autoclose")&&t.dispatch("deleteCurrent"),a(n);break;case"stopped":case"error":s(n);break;default:s(n);break}},ce=(e,t,a,s)=>{e.request&&!e.response&&(de+=1,de<=5)?ge(t,a,s,5e3,de+1):(pe||t.commit("setStatus","failed"),s())};var he={namespaced:!0,state:{status:null,current:null,deleting:!1,initialized:!1},mutations:{setStatus(e,t){e.status=t},setCurrent(e,t){e.deleting=!1,e.current=t,e.status=t?t.status:null},setDeleting(e,t){e.deleting=!!t},setInitialized(e,t){e.initialized=!!t,t||(ue=null)}},actions:{async init(e){return ue||(ue=new Promise((t=>{const a=()=>{e.commit("setInitialized",!0),t()};ge(e,a,a)}))),ue},execute(e,t){return new Promise(((a,s)=>{null!==e.state.status&&s(),pe=!!t.ignoreErrors,delete t.ignoreErrors,e.commit("setCurrent",t),e.commit("setStatus","created"),o.A.put("api/task",t).then((t=>re(t,e,a,s))).catch((t=>ce(t,e,a,s)))}))},abort(e){return null===e.state.status?new Promise(((e,t)=>{t()})):(e.commit("setStatus","aborting"),new Promise(((t,a)=>{o.A.patch("api/task",{status:"aborting"}).then((s=>re(s,e,t,a))).catch((s=>ce(s,e,t,a)))})))},async deleteCurrent(e){let{commit:t,dispatch:a}=e,s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;t("setDeleting",!0);try{await o.A.delete("api/task"),t("setCurrent",null),await a("server/contao/get",!1,{root:!0})}catch(n){if(400===n.status)return void t("setCurrent",null);if(403===n.status&&s>0)return new Promise((e=>{setTimeout((()=>{e(a("deleteCurrent",s-1))}),5e3)}));throw"application/problem+json"===n.headers.get("Content-Type")?t("setError",n.data,{root:!0}):t("setError",{type:"about:blank",status:n.status,response:n},{root:!0}),n}}}};const me=(0,s.y$)({modules:{auth:E,algolia:X.A,cloud:S,config:T,modals:x.A,packages:j,contao:K,server:le,tasks:he},state:{view:n.A.INIT,setupStep:0,migrationsType:"",error:null,locked:!1,safeMode:!1},mutations:{setView(e,t){e.view=t,t===n.A.READY&&(e.setupStep=0)},setLocked(e){e.view=n.A.LOGIN,e.locked=!0},setError(e,t){t&&e.error||(e.error=t)},setSafeMode(e,t){e.safeMode=!!t},setup(e,t){e.view=n.A.SETUP,e.setupStep=t},checkMigrations(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e.view=n.A.MIGRATION,e.migrationsType=t},apiError:(e,t)=>{if(!e.error)if("application/problem+json"===t.headers["content-type"]){const a=t.data;a.response=t,e.error=a}else e.error={type:"about:blank",status:t.status||"",response:t}}},actions:{reset(e){let{commit:t}=e;t("server/composer/setCache"),t("server/config/setCache"),t("server/contao/setCache"),t("server/database/setCache"),t("server/adminUser/setCache"),t("server/opcache/setCache"),t("server/phpinfo/setCache"),t("server/php-cli/setCache"),t("server/php-web/setCache"),t("server/self-update/setCache"),t("contao/install-tool/setCache"),t("contao/backup/setCache"),t("tasks/setInitialized",!1),t("cloud/setStatus",null),t("setSafeMode",!1)}}});var ke=me},7591:function(e,t,a){e.exports=a.p+"img/button-upload.ca8e9cfc.svg"},8044:function(e,t,a){var s=a(6992),n=a(7008),o=a(4210);const i=async function(){let e,t={};for(var a=arguments.length,s=new Array(a),n=0;ni(a.e(219).then(a.t.bind(a,3219,19)),a.e(553).then(a.t.bind(a,5553,19))),de:()=>i(a.e(523).then(a.t.bind(a,523,19)),a.e(477).then(a.t.bind(a,6477,19))),br:()=>i(a.e(140).then(a.t.bind(a,1140,19)),a.e(958).then(a.t.bind(a,2958,19))),cs:()=>i(a.e(874).then(a.t.bind(a,2874,19)),a.e(540).then(a.t.bind(a,4540,19))),es:()=>i(a.e(180).then(a.t.bind(a,2180,19)),a.e(706).then(a.t.bind(a,2706,19))),fa:()=>i(a.e(669).then(a.t.bind(a,9669,19)),a.e(520).then(a.t.bind(a,4139,19))),fr:()=>i(a.e(120).then(a.t.bind(a,8120,19)),a.e(554).then(a.t.bind(a,4554,19))),it:()=>i(a.e(769).then(a.t.bind(a,4769,19)),a.e(851).then(a.t.bind(a,6851,19))),ja:()=>i(a.e(721).then(a.t.bind(a,9721,19)),a.e(551).then(a.t.bind(a,2551,19))),lv:()=>i(a.e(194).then(a.t.bind(a,194,19)),a.e(560).then(a.t.bind(a,1560,19))),nl:()=>i(a.e(518).then(a.t.bind(a,2518,19)),a.e(164).then(a.t.bind(a,6164,19))),pl:()=>i(a.e(716).then(a.t.bind(a,3716,19)),a.e(638).then(a.t.bind(a,3638,19))),pt:()=>i(a.e(52).then(a.t.bind(a,9052,19)),a.e(606).then(a.t.bind(a,2225,19))),ru:()=>i(a.e(557).then(a.t.bind(a,1557,19)),a.e(715).then(a.t.bind(a,3715,19))),sr:()=>i(a.e(581).then(a.t.bind(a,4581,19)),a.e(367).then(a.t.bind(a,8367,19))),sv:()=>i(a.e(953).then(a.t.bind(a,3953,19)),a.e(643).then(a.t.bind(a,6643,19))),tr:()=>i(a.e(486).then(a.t.bind(a,8486,19)),a.e(44).then(a.t.bind(a,44,19))),zh:()=>i(a.e(542).then(a.t.bind(a,7542,19)),a.e(28).then(a.t.bind(a,4028,19)))},r=(0,s.hU)(),c=e=>{r.global.locale=e,(0,o.x)(e),n.A.commit("algolia/setLanguage",e),document.querySelector("html").setAttribute("lang",e)};t.A={plugin:r,async init(){r.global.fallbackLocale="en",await this.load("en");const e=localStorage.getItem("contao_manager_locale");if(e&&l[e])return this.load(e);const t=Array.from(navigator.languages);for(let a=0;ae.packageInstalled(e.data.name),isRootInstalled:e=>e.isInstalled&&e.packageRoot(e.data.name),isRequired:e=>e.packageRequired(e.data.name),isAdded:e=>e.packageAdded(e.data.name),isMissing:e=>e.packageMissing(e.data.name),isChanged:e=>e.packageChanged(e.data.name),isUpdated:e=>e.packageUpdated(e.data.name),willBeRemoved:e=>e.packageRemoved(e.data.name),willBeInstalled:e=>e.packageAdded(e.data.name),isModified:e=>e.isUpdated||e.isChanged||e.willBeRemoved||e.willBeInstalled,isSuggested:e=>e.packageSuggested(e.data.name),isPrivate:e=>e.metadata&&!!e.metadata.private,isDependency:e=>e.metadata&&!!e.metadata.dependency,isFeature:e=>e.packageFeature(e.data.name),isVisible:e=>e.packageVisible(e.data.name),isTheme:e=>"contao-theme"===e.data.type||e.metadata&&"contao-theme"===e.metadata.type,isContao:e=>"contao/manager-bundle"===e.data.name,isUpload:e=>e.metadata&&"dist"===e.metadata["installation-source"]&&e.metadata.dist&&new RegExp("/contao-manager/packages/[^/]+.zip$","i").test(e.metadata.dist.url),installedVersion:e=>e.installed[e.data.name]?e.installed[e.data.name].version:null,installedTime:e=>e.installed[e.data.name]?e.installed[e.data.name].time:null,isCompatible:e=>e.contaoSupported(e.metadata.contaoConstraint),canBeInstalled:e=>(!e.isPrivate||e.isSuggested)&&!e.isTheme&&(!e.isDependency||e.isSuggested)&&e.isCompatible,constraintInstalled:e=>e.packageConstraintInstalled(e.data.name),constraintRequired:e=>e.packageConstraintRequired(e.data.name),constraintAdded:e=>e.packageConstraintAdded(e.data.name),constraintChanged:e=>e.packageConstraintChanged(e.data.name),targetConstraint:e=>e.$store.state.packages?.change[e.data.name]||e.$store.state.packages?.root?.require[e.data.name]},methods:{install(){this.$store.commit("packages/add",{name:this.data.name})},update(){this.$store.commit("packages/update",this.data.name)},uninstall(){this.willBeInstalled&&!this.isInstalled?this.$store.commit("packages/restore",this.data.name):(this.$store.commit("packages/restore",this.data.name),this.$store.dispatch("packages/uploads/unconfirm",this.data.name),this.$store.commit("packages/remove",this.data.name))}},watch:{targetConstraint(){this.$store.commit("algolia/uncache",this.data.name),this.loadMetadata()}}}}},t={};function a(s){var n=t[s];if(void 0!==n)return n.exports;var o=t[s]={exports:{}};return e[s].call(o.exports,o,o.exports,a),o.exports}a.m=e,function(){var e=[];a.O=function(t,s,n,o){if(!s){var i=1/0;for(u=0;u=o)&&Object.keys(a.O).every((function(e){return a.O[e](s[r])}))?s.splice(r--,1):(l=!1,o0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[s,n,o]}}(),function(){a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,{a:t}),t}}(),function(){var e,t=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__};a.t=function(s,n){if(1&n&&(s=this(s)),8&n)return s;if("object"===typeof s&&s){if(4&n&&s.__esModule)return s;if(16&n&&"function"===typeof s.then)return s}var o=Object.create(null);a.r(o);var i={};e=e||[null,t({}),t([]),t(t)];for(var l=2&n&&s;"object"==typeof l&&!~e.indexOf(l);l=t(l))Object.getOwnPropertyNames(l).forEach((function(e){i[e]=function(){return s[e]}}));return i["default"]=function(){return s},a.d(o,i),o}}(),function(){a.d=function(e,t){for(var s in t)a.o(t,s)&&!a.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})}}(),function(){a.f={},a.e=function(e){return Promise.all(Object.keys(a.f).reduce((function(t,s){return a.f[s](e,t),t}),[]))}}(),function(){a.u=function(e){return"js/"+e+"."+{28:"ceef267d",44:"aa3a6943",52:"53a6eeda",60:"15d99754",82:"4d867f71",120:"ad9ecc53",139:"a9db33f9",140:"9f138779",164:"1bf38df2",180:"25fde044",194:"1e21e427",212:"82f9b333",219:"c00b841d",306:"7db13eb6",367:"b1973e97",477:"b60ba150",479:"98674663",486:"dbfe136b",500:"d95d38df",518:"16da88f4",520:"015d305f",523:"14592c65",531:"d9917883",540:"9222434f",542:"a77d6afc",551:"3fd69aa4",553:"9a474b92",554:"6793dc25",557:"9a8ca5d7",560:"bf496880",581:"34ad7ec7",606:"c408386b",612:"ba8a2b90",638:"9d60aca3",643:"f898abfb",669:"deb99932",706:"fa5ca273",710:"aa0213da",715:"39edc453",716:"a21c458e",721:"92ab0b05",769:"46cebc27",851:"800f4cc3",874:"cb764366",953:"cfd6dc8d",958:"7fdd57a1"}[e]+".js"}}(),function(){a.miniCssF=function(e){return"css/"+e+"."+{82:"e18cb2b2",139:"11002f25",212:"44f2aba0",306:"25211792",479:"5c4f2539",496:"10f7bb83",531:"fa97fb72",612:"3a60e65a"}[e]+".css"}}(),function(){a.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){var e={},t="contao-manager:";a.l=function(s,n,o,i){if(e[s])e[s].push(n);else{var l,r;if(void 0!==o)for(var c=document.getElementsByTagName("script"),u=0;u[(0,i.Lk)("header",n,[c[4]||(c[4]=(0,i.Lk)("img",{src:t,width:"80",height:"80",class:"config-check__icon",alt:""},null,-1)),(0,i.Lk)("h1",r,(0,l.v_)(e.$t("ui.server.config.title")),1),(0,i.Lk)("p",a,(0,l.v_)(e.$t("ui.server.config.description")),1)]),(0,i.Lk)("main",d,[(0,i.Lk)("form",{onSubmit:c[3]||(c[3]=(0,o.D$)((function(){return L.save&&L.save(...arguments)}),["prevent"]))},[(0,i.Lk)("fieldset",u,[(0,i.Lk)("legend",g,(0,l.v_)(e.$t("ui.server.config.formTitle")),1),(0,i.Lk)("p",f,(0,l.v_)(e.$t("ui.server.config.formText")),1),(0,i.bF)($,{ref:"cli",name:"php_cli",label:e.$t("ui.server.config.cli"),required:"",disabled:e.processing,error:e.error,modelValue:e.php_cli,"onUpdate:modelValue":c[0]||(c[0]=c=>e.php_cli=c)},null,8,["label","disabled","error","modelValue"])]),(0,i.Lk)("fieldset",h,[(0,i.Lk)("legend",_,(0,l.v_)(e.$t("ui.server.config.cloudTitle")),1),(0,i.Lk)("p",p,(0,l.v_)(e.$t("ui.server.config.cloudText")),1),e.cloudIssues&&e.cloudIssues.length?((0,i.uX)(),(0,i.CE)("div",k,[(0,i.Lk)("p",null,(0,l.v_)(e.$t("ui.server.config.stateErrorCloud")),1),(0,i.Lk)("ul",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.cloudIssues,((e,c)=>((0,i.uX)(),(0,i.CE)("li",{key:c},(0,l.v_)(e),1)))),128))])])):(0,i.Q3)("",!0),(0,i.bF)(w,{name:"cloud",label:e.$t("ui.server.config.cloud"),disabled:e.processing,modelValue:e.cloud,"onUpdate:modelValue":c[1]||(c[1]=c=>e.cloud=c)},null,8,["label","disabled","modelValue"])]),(0,i.bF)(C,{submit:"",color:"primary",disabled:!e.php_cli,loading:e.processing},{default:(0,i.k6)((()=>[(0,i.eW)((0,l.v_)(e.$t("ui.server.config.save")),1)])),_:1},8,["disabled","loading"]),(0,i.Lk)("button",{type:"button",class:"widget-button",disabled:e.processing,onClick:c[2]||(c[2]=function(){return L.cancel&&L.cancel(...arguments)})},(0,l.v_)(e.$t("ui.server.config.cancel")),9,v)],32)])])),_:1})}var m=s(5404),L=s(683),$=s(3018),w=s(6966),C=s(707),x={components:{BoxedLayout:m.A,TextField:L.A,CheckBox:$.A,LoadingButton:w.A},data:()=>({processing:!0,error:"",php_cli:"",cloud:!0,cloudIssues:[]}),methods:{async save(){this.processing=!0,this.error="";const e={php_cli:this.php_cli,cloud:this.cloud},c=await this.$store.dispatch("server/config/set",e);400===c.status&&c.detail?(this.error=c.detail,this.processing=!1,setTimeout((()=>{this.$refs.cli.focus()}),0)):window.location.reload(!0)},cancel(){this.$store.commit("setView",C.A.BOOT)}},async mounted(){const e=await this.$store.dispatch("server/config/get");this.php_cli=e.php_cli,this.cloud=e.cloud.enabled,this.cloudIssues=e.cloud.issues,this.processing=!1}},y=s(6262);const T=(0,y.A)(x,[["render",b]]);var V=T}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[500],{9500:function(a,e,t){t.r(e),t.d(e,{default:function(){return qa}});var s=t(641),n=t(33);const i={class:"package-popup__installed"},l=["dateTime","title"],o=["href"],p={key:3},r={class:"package-popup__update"},c={class:"package-popup__incompatible"};function u(a,e,t,u,d,k){const g=(0,s.g2)("package-constraint"),m=(0,s.g2)("install-button"),h=(0,s.g2)("package-details",!0);return(0,s.uX)(),(0,s.Wv)(h,{local:k.data,dependents:k.dependents},(0,s.eX)({"package-actions":(0,s.k6)((()=>[(0,s.RG)(a.$slots,"package-actions",{},(()=>[a.isInstalled?((0,s.uX)(),(0,s.CE)(s.FK,{key:0},[!a.isFeature&&a.isVisible?((0,s.uX)(),(0,s.Wv)(g,{key:0,data:k.data},null,8,["data"])):(0,s.Q3)("",!0),(0,s.Lk)("p",i,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package.installed")),1),a.installedTime?((0,s.uX)(),(0,s.CE)("time",{key:0,dateTime:a.installedTime,title:k.datimFormat(a.installedTime)},(0,n.v_)(a.$t("ui.package.version",{version:a.installedVersion})),9,l)):((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.eW)((0,n.v_)(a.$t("ui.package.version",{version:a.installedVersion})),1)],64))])],64)):a.canBeInstalled||a.isRequired?((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.bF)(m,{data:k.data},null,8,["data"]),a.isAdded||a.isRequired?((0,s.uX)(),(0,s.Wv)(g,{key:0,data:k.data},null,8,["data"])):(0,s.Q3)("",!0)],64)):a.isPrivate?((0,s.uX)(),(0,s.CE)("a",{key:2,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:a.metadata.homepage},(0,n.v_)(a.$t("ui.package.homepage")),9,o)):((0,s.uX)(),(0,s.CE)("div",p))]))])),"suggest-actions":(0,s.k6)((e=>{let{name:t}=e;return[a.packageSuggested(t)?((0,s.uX)(),(0,s.Wv)(m,{key:0,inline:"",small:"",data:{name:t}},null,8,["data"])):(0,s.Q3)("",!0)]})),"features-actions":(0,s.k6)((e=>{let{name:t}=e;return[!a.hasRoot||a.packageInstalled(t)||a.packageRoot(t)?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.Wv)(m,{key:0,inline:"",small:"",data:{name:t}},null,8,["data"]))]})),_:2},[a.metadata.update&&a.metadata.update.valid&&!a.metadata.update.latest?{name:"package-update",fn:(0,s.k6)((()=>[(0,s.Lk)("p",r,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package.update"))+":",1),(0,s.eW)(" "+(0,n.v_)(a.$t("ui.package.version",{version:a.metadata.update.version}))+" ("+(0,n.v_)(a.$t("ui.package-details.released"))+" "+(0,n.v_)(k.datimFormat(a.metadata.update.time,"short","long"))+")",1)])])),key:"0"}:a.isCompatible?void 0:{name:"package-update",fn:(0,s.k6)((()=>[(0,s.Lk)("p",c,(0,n.v_)(a.$t("ui.package.incompatible",{package:k.data.name,constraint:a.packageConstraint("contao/manager-bundle")})),1)])),key:"1"}]),1032,["local","dependents"])}t(8111),t(7588);var d=t(6278),k=t(4210),g=t(8200),m=t(3751);const h={class:"package-popup__headline"},_=["title"],v=["title"],b={key:0,class:"package-popup__loader"},f={class:"package-popup__summary"},y={class:"package-popup__text"},$={class:"package-popup__title"},C={key:0,class:"package-popup__authors"},X=["href"],E={class:"package-popup__statistics"},L=["title"],w={key:1,class:"package-popup__stats package-popup__stats--updated"},F={key:2,class:"package-popup__stats package-popup__stats--downloads"},A={key:3,class:"package-popup__stats package-popup__stats--favers"},W={class:"package-popup__actions"},Q=["href"],x=["href"],T={class:"package-popup__tabs"},G={class:"package-popup__tabs-list"},P={key:0,class:"package-popup__abandoned"},R={key:2},q={key:3},B={key:4},O={class:"package-popup__description"};function I(a,e,t,i,l,o){const p=(0,s.g2)("loading-spinner"),r=(0,s.g2)("package-logo"),c=(0,s.g2)("more-links"),u=(0,s.g2)("details-tab"),d=(0,s.g2)("router-link"),k=(0,s.g2)("i18n-t"),g=(0,s.g2)("package-funding"),I=(0,s.g2)("details-content"),S=(0,s.g2)("popup-overlay");return(0,s.uX)(),(0,s.Wv)(S,{fixed:!0,"popup-class":"package-popup",onClear:e[8]||(e[8]=e=>a.clearCurrent())},{content:(0,s.k6)((()=>[(0,s.Lk)("div",h,[a.hasPrevious?((0,s.uX)(),(0,s.CE)("button",{key:0,class:"package-popup__button package-popup__button--previous",title:a.$t("ui.package-details.previous"),onClick:e[0]||(e[0]=e=>a.$router.go(-1))},e[9]||(e[9]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"#fff",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,s.Lk)("path",{d:"M21 11H6.83l3.58-3.59L9 6l-6 6 6 6 1.41-1.41L6.83 13H21z"})],-1)]),8,_)):(0,s.Q3)("",!0),(0,s.eW)(" "+(0,n.v_)(o.data.name)+" ",1),(0,s.Lk)("button",{class:"package-popup__button package-popup__button--close",title:a.$t("ui.package-details.close"),onClick:e[1]||(e[1]=e=>a.clearCurrent())},e[10]||(e[10]=[(0,s.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",fill:"#fff",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"}),(0,s.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"})],-1)]),8,v)]),a.metadata&&a.metadata.hasOwnProperty("name")?((0,s.uX)(),(0,s.CE)(s.FK,{key:1},[(0,s.Lk)("div",f,[(0,s.bF)(r,{class:"package-popup__logo","component-class":"package-popup__icon",src:a.metadata.logo},null,8,["src"]),(0,s.Lk)("div",y,[(0,s.Lk)("h1",$,(0,n.v_)(a.metadata.title||o.data.name),1),o.authors?((0,s.uX)(),(0,s.CE)("p",C,[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.authors"))+" ",1),((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(o.authors,((a,e)=>((0,s.uX)(),(0,s.CE)(s.FK,null,[a.homepage?((0,s.uX)(),(0,s.CE)("a",{class:"package-popup__author",key:e,href:a.homepage,target:"_blank",rel:"noreferrer noopener"},(0,n.v_)(a.name),9,X)):((0,s.uX)(),(0,s.CE)("span",{class:"package-popup__author",key:e},(0,n.v_)(a.name),1))],64)))),256))])):(0,s.Q3)("",!0),(0,s.Lk)("p",E,[a.metadata.private?((0,s.uX)(),(0,s.CE)("span",{key:0,class:"package-popup__stats package-popup__stats--private",title:a.$t("ui.package.privateTitle")},(0,n.v_)(a.$t("ui.package.private")),9,L)):(0,s.Q3)("",!0),a.metadata.updated?((0,s.uX)(),(0,s.CE)("span",w,(0,n.v_)(o.datimFormat(a.metadata.updated,!1)),1)):(0,s.Q3)("",!0),a.metadata.downloads>0?((0,s.uX)(),(0,s.CE)("span",F,(0,n.v_)(o.numberFormat(a.metadata.downloads)),1)):(0,s.Q3)("",!0),a.metadata.favers>0?((0,s.uX)(),(0,s.CE)("span",A,(0,n.v_)(o.numberFormat(a.metadata.favers)),1)):(0,s.Q3)("",!0),(0,s.bF)(c,{name:a.metadata.name,homepage:a.metadata.homepage,support:Object.assign({},a.metadata.support),metadata:a.metadata.metadata,"hide-packagist":a.metadata.private},null,8,["name","homepage","support","metadata","hide-packagist"])])]),(0,s.Lk)("div",W,[(0,s.RG)(a.$slots,"package-actions",(0,n._B)((0,s.Ng)({data:a.metadata})),(()=>[a.metadata&&a.metadata.homepage?((0,s.uX)(),(0,s.CE)("a",{key:0,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:a.metadata.homepage},(0,n.v_)(a.$t("ui.package.homepage")),9,Q)):a.metadata.private?(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("a",{key:1,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:`https://packagist.org/packages/${o.data.name}`},(0,n.v_)(a.$t("ui.package-details.packagist")),9,x))]))])]),(0,s.Lk)("div",T,[(0,s.Lk)("ul",G,[(0,s.bF)(u,{"show-empty":"",links:!1,active:""===o.tab,onClick:e[2]||(e[2]=a=>o.setTab(""))},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabDescription")),1)])),_:1},8,["active"]),a.metadata.features?((0,s.uX)(),(0,s.Wv)(u,{key:0,highlight:"",links:a.metadata.features,active:"features"===o.tab,onClick:e[3]||(e[3]=a=>o.setTab("features"))},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabFeatures")),1)])),_:1},8,["links","active"])):(0,s.Q3)("",!0),(0,s.bF)(u,{highlight:"",active:"suggest"===o.tab,links:a.metadata.suggest,onClick:e[4]||(e[4]=a=>o.setTab("suggest"))},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabSuggest")),1)])),_:1},8,["active","links"]),(0,s.bF)(u,{"show-empty":"",active:"require"===o.tab,links:a.metadata.require,onClick:e[5]||(e[5]=a=>o.setTab("require"))},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabRequire")),1)])),_:1},8,["active","links"]),(0,s.bF)(u,{"show-empty":"",active:"conflict"===o.tab,links:a.metadata.conflict,onClick:e[6]||(e[6]=a=>o.setTab("conflict"))},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabConflict")),1)])),_:1},8,["active","links"]),t.dependents?((0,s.uX)(),(0,s.Wv)(u,{key:1,active:"dependents"===o.tab,links:t.dependents,onClick:e[7]||(e[7]=a=>o.setTab("dependents"))},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.$t("ui.package-details.tabDependents")),1)])),_:1},8,["active","links"])):(0,s.Q3)("",!0)])]),(0,s.bo)((0,s.bF)(I,null,{default:(0,s.k6)((()=>[a.metadata.abandoned?((0,s.uX)(),(0,s.CE)("div",P,[!0===a.metadata.abandoned?((0,s.uX)(),(0,s.CE)(s.FK,{key:0},[(0,s.eW)((0,n.v_)(a.$t("ui.package.abandonedText")),1)],64)):((0,s.uX)(),(0,s.Wv)(k,{key:1,keypath:"ui.package.abandonedReplace"},{replacement:(0,s.k6)((()=>[(0,s.bF)(d,{to:{query:{p:a.metadata.abandoned}}},{default:(0,s.k6)((()=>[(0,s.eW)((0,n.v_)(a.metadata.abandoned),1)])),_:1},8,["to"])])),_:1}))])):(0,s.Q3)("",!0),a.metadata.funding?((0,s.uX)(),(0,s.Wv)(g,{key:1,class:"package-popup__funding",items:a.metadata.funding},null,8,["items"])):(0,s.Q3)("",!0),(0,s.RG)(a.$slots,"package-update"),a.metadata.contaoVersions?((0,s.uX)(),(0,s.CE)("p",R,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package-details.contaoVersions"))+":",1),(0,s.eW)(" "+(0,n.v_)(a.metadata.contaoVersions.join(", ")),1)])):(0,s.Q3)("",!0),a.metadata.latest?((0,s.uX)(),(0,s.CE)("p",q,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package-details.latest"))+":",1),(0,s.eW)(" "+(0,n.v_)(a.metadata.latest.version)+" ("+(0,n.v_)(a.$t("ui.package-details.released"))+" "+(0,n.v_)(o.datimFormat(a.metadata.latest.time,"short","long"))+")",1)])):(0,s.Q3)("",!0),a.metadata.license?((0,s.uX)(),(0,s.CE)("p",B,[(0,s.Lk)("strong",null,(0,n.v_)(a.$t("ui.package-details.license"))+":",1),(0,s.eW)(" "+(0,n.v_)(o.license),1)])):(0,s.Q3)("",!0),(0,s.Lk)("p",O,(0,n.v_)(a.metadata.description),1)])),_:3},512),[[m.aG,""===o.tab]]),a.metadata.features?(0,s.bo)(((0,s.uX)(),(0,s.Wv)(I,{key:0,links:a.metadata.features},{actions:(0,s.k6)((({name:e})=>[(0,s.RG)(a.$slots,"features-actions",(0,n._B)((0,s.Ng)({name:e})))])),_:3},8,["links"])),[[m.aG,"features"===o.tab]]):(0,s.Q3)("",!0),(0,s.bo)((0,s.bF)(I,{links:a.metadata.suggest},{actions:(0,s.k6)((({name:e})=>[(0,s.RG)(a.$slots,"suggest-actions",(0,n._B)((0,s.Ng)({name:e})))])),_:3},8,["links"]),[[m.aG,"suggest"===o.tab]]),(0,s.bo)((0,s.bF)(I,{links:a.metadata.require},{actions:(0,s.k6)((({name:e})=>[(0,s.RG)(a.$slots,"require-actions",(0,n._B)((0,s.Ng)({name:e})))])),_:3},8,["links"]),[[m.aG,"require"===o.tab]]),(0,s.bo)((0,s.bF)(I,{links:a.metadata.conflict},{actions:(0,s.k6)((({name:e})=>[(0,s.RG)(a.$slots,"conflict-actions",(0,n._B)((0,s.Ng)({name:e})))])),_:3},8,["links"]),[[m.aG,"conflict"===o.tab]]),t.dependents?(0,s.bo)(((0,s.uX)(),(0,s.Wv)(I,{key:1,links:t.dependents},{actions:(0,s.k6)((({name:e})=>[(0,s.RG)(a.$slots,"dependents-actions",(0,n._B)((0,s.Ng)({name:e})))])),_:3},8,["links"])),[[m.aG,"dependents"===o.tab]]):(0,s.Q3)("",!0)],64)):((0,s.uX)(),(0,s.CE)("div",b,[(0,s.bF)(p,{horizontal:""}),(0,s.Lk)("p",null,(0,n.v_)(a.$t("ui.package-details.loading")),1)]))])),_:3})}var S=t(9376),j=t(416),K=t(266),V=t(5951),D=t(4999);const H={key:0,ref:"menu",class:"link-more"};function M(a,e,t,i,l,o){const p=(0,s.g2)("link-menu");return o.linkItems.length?((0,s.uX)(),(0,s.CE)("div",H,[(0,s.Lk)("button",{onClick:e[0]||(e[0]=(...a)=>o.toggle&&o.toggle(...a))},(0,n.v_)(a.$t("ui.package-details.more")),1),a.visible?((0,s.uX)(),(0,s.CE)("div",{key:0,class:"link-more__menu",tabindex:"-1",onClick:e[1]||(e[1]=(...a)=>o.close&&o.close(...a))},[(0,s.bF)(p,{items:o.linkItems,color:"contao"},null,8,["items"])])):(0,s.Q3)("",!0)],512)):(0,s.Q3)("",!0)}var N=t(5529),z={components:{LinkMenu:N.A},props:{name:String,homepage:String,support:Object,metadata:String,hidePackagist:Boolean},data:()=>({visible:!1}),computed:{linkItems(){const a=[];return this.homepage&&a.push({label:this.$t("ui.package.homepage"),href:this.homepage,target:"_blank"}),this.name&&!this.hidePackagist&&a.push({label:this.$t("ui.package-details.packagist"),href:`https://packagist.org/packages/${this.name}`,target:"_blank"}),this.support&&Object.keys(this.support).forEach((e=>{const t=`ui.package-details.support_${e}`;let s=this.$t(`ui.package-details.support_${e}`);s===t&&(s=e),"email"===e?a.push({label:s,href:`mailto:${this.support[e]}`}):a.push({label:s,href:this.support[e],target:"_blank"})})),this.metadata&&a.push({label:this.$t("ui.package-details.metadata"),href:this.metadata,target:"_blank"}),a}},methods:{open(){this.visible=!0,window.addEventListener("click",this.closeOutside)},close(){this.visible=!1,window.removeEventListener("click",this.closeOutside)},closeOutside(a){this.$refs.menu&&!this.$refs.menu.contains(a.target)&&this.close()},toggle(){this.visible?this.close():this.open()}}},U=t(6262);const Y=(0,U.A)(z,[["render",M]]);var J=Y;const Z=["disabled"];function aa(a,e,t,i,l,o){return t.showEmpty||o.count>0?((0,s.uX)(),(0,s.CE)("li",{key:0,class:(0,n.C4)(["package-popup__tab",{"package-popup__tab--active":t.active}])},[(0,s.Lk)("button",{onClick:e[0]||(e[0]=e=>a.$emit("click")),disabled:0===o.count&&!1!==t.links},[(0,s.RG)(a.$slots,"default"),!1!==t.links?((0,s.uX)(),(0,s.CE)("span",{key:0,class:(0,n.C4)({"package-popup__pill":!0,"package-popup__pill--highlight":t.highlight&&o.count>0})},(0,n.v_)(o.count),3)):(0,s.Q3)("",!0)],8,Z)],2)):(0,s.Q3)("",!0)}var ea={emits:["click"],props:{active:Boolean,showEmpty:Boolean,highlight:Boolean,links:[Object,Array,Boolean]},computed:{count(){return this.links?this.links instanceof Array?this.links.length:Object.values(this.links).length:0}}};const ta=(0,U.A)(ea,[["render",aa]]);var sa=ta;const na={class:"package-popup__tabcontent"},ia={key:0,class:"package-popup__packagelist"};function la(a,e,t,n,i,l){const o=(0,s.g2)("package-link");return(0,s.uX)(),(0,s.CE)("div",na,[(0,s.RG)(a.$slots,"default",{},(()=>[t.links?((0,s.uX)(),(0,s.CE)("div",ia,[((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(l.iterableLinks,((e,t)=>(0,s.RG)(a.$slots,"links",(0,s.v6)({ref_for:!0},{name:t,text:e}),(()=>[((0,s.uX)(),(0,s.Wv)(o,{name:t,key:t,text:e},{default:(0,s.k6)((()=>[(0,s.RG)(a.$slots,"actions",(0,s.v6)({ref_for:!0},{name:t}))])),_:2},1032,["name","text"]))])))),256))])):(0,s.Q3)("",!0)]))])}const oa={class:"package-link__details"},pa=["title"],ra={class:"package-link__text"},ca={class:"package-link__actions"};function ua(a,e,t,i,l,o){const p=(0,s.g2)("details-button");return(0,s.uX)(),(0,s.CE)("article",{class:(0,n.C4)(["package-link",{"package-link--limit":!t.text}])},[(0,s.Lk)("div",oa,[(0,s.Lk)("p",{class:"package-link__name",title:t.name},(0,n.v_)(a.metadata&&a.metadata.title||t.name),9,pa),(0,s.Lk)("p",ra,(0,n.v_)(t.text||a.metadata&&a.metadata.description),1)]),(0,s.Lk)("div",ca,[(0,s.RG)(a.$slots,"default"),(0,s.bF)(p,{small:"",name:t.name},null,8,["name"])])],2)}var da=t(9071),ka={mixins:[j.A],components:{DetailsButton:da.A},props:{name:String,text:String},computed:{data:a=>({name:a.name})}};const ga=(0,U.A)(ka,[["render",ua]]);var ma=ga,ha={components:{PackageLink:ma},props:{links:[Object,Array]},computed:{iterableLinks(){if(this.links instanceof Array){const a={};return this.links.forEach((e=>{a[e]=null})),a}return this.links}}};const _a=(0,U.A)(ha,[["render",la]]);var va=_a,ba=t(3170);const fa={key:0,class:"package-funding"},ya=["href"],$a=["href"],Ca=["href"],Xa=["href"],Ea=["href"];function La(a,e,t,i,l,o){return t.items&&t.items.length?((0,s.uX)(),(0,s.CE)("div",fa,[(0,s.Lk)("div",null,[(0,s.Lk)("span",null,(0,n.v_)(a.$t("ui.package-details.funding")),1),((0,s.uX)(!0),(0,s.CE)(s.FK,null,(0,s.pI)(t.items,((a,e)=>((0,s.uX)(),(0,s.CE)(s.FK,null,["github"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:o.githubUrl(a),target:"_blank",rel:"noreferrer noopener",key:e},"GitHub",8,ya)):"tidelift"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},"Tidelift",8,$a)):"patreon"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},"Patreon",8,Ca)):"opencollective"===a.type?((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},"OpenCollective",8,Xa)):((0,s.uX)(),(0,s.CE)("a",{href:a.url,target:"_blank",rel:"noreferrer noopener",key:e},(0,n.v_)(a.url.replace(/^https?:\/\/(www.)?([^/]+).*$/,"$2")),9,Ea))],64)))),256))])])):(0,s.Q3)("",!0)}var wa={name:"PackageFunding",props:{items:{type:Array,required:!0}},computed:{githubUrl:()=>a=>a.url.replace(/^https:\/\/github.com\/([^/]+)$/,"https://github.com/sponsors/$1")}};const Fa=(0,U.A)(wa,[["render",La],["__scopeId","data-v-5a8fd14b"]]);var Aa=Fa,Wa={mixins:[j.A],components:{PopupOverlay:ba.A,MoreLinks:J,LoadingSpinner:D.A,PackageLogo:V.A,PackageFunding:Aa,DetailsTab:sa,DetailsContent:va},props:{local:{type:Object},dependents:{type:Object}},data:()=>({appTitle:"",links:[],hasPrevious:!1}),computed:{current:a=>a.$route.query.p,tab:a=>String(a.$route.hash).substring(1),exists:a=>a.metadata,data:a=>a.local||{name:a.current},authors:a=>a.metadata.authors&&a.metadata.authors.length?a.metadata.authors.filter((a=>!!a.name)):null,license:a=>a.metadata.license?a.metadata.license instanceof Array?a.metadata.license.join(", "):a.metadata.license:"–",contaoVersions:a=>a.metadata.contaoVersions||null},methods:{datimFormat:k.A,numberFormat:K.A,...(0,d.PY)("packages/details",["clearCurrent"]),setTab(a){this.$router.replace({query:this.$route.query,hash:`#${a}`,append:!0})},updatePage(){let a=`${this.current} - ${this.appTitle}`,e="";this.metadata&&(this.metadata.title&&(a=`${this.metadata.title} (${this.current}) - ${this.appTitle}`),e=this.metadata.description||""),document.title=a,document.head.querySelector('meta[name="description"]').setAttribute("content",e)},addLink(a,e,t=null){const s=new URL(location.pathname,location);s.search=a;const n=document.createElement("link");n.setAttribute("rel",e),n.setAttribute("href",s.toString()),t&&n.setAttribute("hrefLang",t),document.head.appendChild(n),this.links.push(n)}},watch:{current(){this.updatePage(),this.hasPrevious=/[?&]p=/.test(window.history.state?.back)},exists(a){a||this.clearCurrent()},metadata(){this.updatePage()}},created(){this.appTitle=document.title},mounted(){document.head.querySelector('meta[name="robots"]').setAttribute("content","index,follow"),this.updatePage(),this.addLink(`?p=${this.current}&_locale=${this.$i18n.locale}`,"canonical"),Object.keys(S.A).forEach((a=>{this.addLink(`?p=${this.current}&_locale=${a}`,"alternate",a)}))},beforeUnmount(){document.title=this.appTitle,document.head.querySelector('meta[name="description"]').setAttribute("content",""),this.links.forEach((a=>{document.head.removeChild(a)}))}};const Qa=(0,U.A)(Wa,[["render",I]]);var xa=Qa,Ta=t(1909),Ga=t(3629),Pa={mixins:[g.A],components:{PackageConstraint:Ga.A,PackageDetails:xa,InstallButton:Ta.A},computed:{...(0,d.aH)("packages",{allInstalled:"installed"}),...(0,d.L8)("packages",["packageConstraint"]),current:a=>a.$route.query.p,data:a=>a.add[a.current]||a.allInstalled[a.current]||{name:a.current},dependents(){if(!this.allInstalled[this.data.name]?.dependents)return null;const a={},e=["requires","replaces","provides","conflicts"];return Object.values(this.allInstalled[this.data.name].dependents).forEach((t=>{if("__root__"===t.source||!e.includes(t.description)||t.source===this.data.name&&"replaces"===t.description)return;const s=this.$t(`ui.package-details.link${t.description[0].toUpperCase()}${t.description.slice(1)}`);let n=t.target;n===this.data.name&&this.metadata&&this.metadata.title&&(n=this.metadata.title),a[t.source]=`${s} ${n} ${t.constraint}`})),a}},methods:{datimFormat:k.A}};const Ra=(0,U.A)(Pa,[["render",u]]);var qa=Ra}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[28],{4028:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! 不安全连接 !!","ui.app.httpsDescription":"没有HTTPS情况下,机密数据将会未加密传输。","ui.app.httpsLink":"更多信息","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Safe Mode enabled !!","ui.app.safeModeDescription":"Some features of the Contao Manager are not available.","ui.app.safeModeExit":"Exit Safe Mode","ui.app.loading":"加载 Contao 管理器 …","ui.app.apiError":"意外的API状态","ui.app.configSecurity1":"安全警报 !!! 检测到未受保护的配置目录","ui.app.configSecurity2":"Contao管理器检测到其配置文件可以公开访问。目录受到保护之前会禁止所有操作,否则攻击者可以访问安装的敏感数据。\\n\\n为了修复这个问题,请确保阻止访问服务器上的\\"contao-manager\\"目录。要了解如何执行此操作,请参阅您的网络服务器手册或联系您的托管服务提供商。","ui.account.welcome":"欢迎","ui.account.intro1":"Welcome to the Contao Manager, a universal tool to install and manage Contao Open Source CMS. If you are new to it, please {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} to get started","ui.account.introManual":"read the manual","ui.account.intro2":"If you encounter any problems, check {ourGithubIssues} and feel free to create new one for anything that has not been reported yet.","ui.account.introIssues":"our GitHub issues","ui.account.headline":"用户账户","ui.account.description":"为了管理安装,请为Contao管理器创建一个账号。请注意该账号和Contao后台和前端没有关联。","ui.account.username":"用户名","ui.account.password":"密码","ui.account.passwordPlaceholder":"最少8个字符","ui.account.passwordLength":"请输入最少8个字符","ui.account.submit":"创建账号","ui.account.contribute1":"Contao and the Contao Manager are sponsored by the non-profit Contao Association.","ui.account.contribute2":"Please consider contributing to open source by {donate}.","ui.account.contributeDonate":"making a donation","ui.login.headline":"登录","ui.login.description":"登录来管理安装。","ui.login.username":"用户名","ui.login.password":"密码","ui.login.forgotPassword":"忘记密码","ui.login.button":"登录","ui.login.locked":"Access has been denied because the Contao Manager is locked. To unlock, delete the {lockFile} file in your Contao root directory.","ui.logout.headline":"会话超时","ui.logout.warning":"超过25分钟没有活动。安全原因您的会话将很快被终止。","ui.logout.expired":"由于超过30分钟没有活动,您的会话已自动终止。","ui.logout.renew":"保持登入","ui.logout.logout":"注销","ui.logout.login":"返回登录","ui.oauth.error":"无效的OAuth尝试。检查请求参数。","ui.oauth.https":"The redirect URI MUST use a secure protocol (https:) to prevent the authentication token from being transmitted in clear-text.","ui.oauth.headline":"Remote Authentication","ui.oauth.description":"以下应用程序或者服务正在请求对您的Contao Manager实例远程访问。","ui.oauth.domain":"Before allowing access, make sure you know this URL and trust its owner!","ui.oauth.allow":"允许访问","ui.oauth.deny":"拒绝访问","ui.boot.headline":"系统检查","ui.boot.description":"请稍等,正在分析您的服务器 …","ui.boot.issue1":"监测到安装问题","ui.boot.issue2":"Your installation has issues that have to be fixed before the Contao Manager can be used.","ui.boot.run":"运行Contao管理器","ui.boot.safeMode":"安全模式下运行","ui.recovery.headline":"系统恢复","ui.recovery.description":"The Contao Manager detected files that look like Contao, but the Command Line Interface does not work as expected.","ui.recovery.console":"Console Output","ui.recovery.repairOptions":"Please choose an option to repair your installation.","ui.recovery.repairHeadline":"自动修复","ui.recovery.repairDescription":"尝试通过重建应用缓存并重新安装Composer包来自动修复安装。","ui.recovery.repairWarning":"此过程可能会删除vendor中文件的任何修改!","ui.recovery.repairFailed":"自动修复没有成功。请尝试安全模式手动修复安装。","ui.recovery.repairButton":"运行系统修复","ui.recovery.safeModeHeadline":"安全模式","ui.recovery.safeModeDescription":"安全模式下运行Contao管理器允许管理包并运行某些维护任务,但依赖于正在运行的Contao安装的功能将不可用。","ui.recovery.safeModeButton":"安全模式下运行","ui.server.pending":"等待 …","ui.server.running":"分析中 …","ui.server.error":"由于服务器的意外响应,检查失败。","ui.server.details":"详情","ui.server.prerequisite":"由于缺少必要的条件,检查已取消。","ui.server.selfUpdate.title":"Contao管理器更新","ui.server.selfUpdate.update":"新的Contao管理器版本 {latest} .","ui.server.selfUpdate.manualUpdate":"新版本的Contao管理器 {latest} 可用。服务器不支持自动更新,请从{download}下载新版本。","ui.server.selfUpdate.latest":"正在使用最新版本 {current}。","ui.server.selfUpdate.dev":"开发版不支持自动更新。","ui.server.selfUpdate.unsupported":"有新版本,但您的PHP版本不支持。","ui.server.selfUpdate.button":"运行自更新","ui.server.selfUpdate.continue":"继续","ui.server.config.title":"服务器配置","ui.server.config.setup":"配置","ui.server.config.change":"更改","ui.server.config.save":"保存","ui.server.config.cancel":"取消","ui.server.config.customOption":"其他 …","ui.server.config.description":"To correctly run background tasks, the Contao Manager needs to know where to find the PHP command line binary and how to run commands separated from the web process.","ui.server.config.formTitle":"服务器配置","ui.server.config.formText":"请输入PHP二进制文件位置。确认二进制文件和服务器web进程是相同的PHP版本。","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud 允许安装Composer依赖即使服务器无法提供足够的内存。您的包信息将被传输到由Contao Association运营的云服务器。","ui.server.config.cloud":"使用Composer Resolver Cloud","ui.server.config.cli":"PHP二进制","ui.server.config.stateErrorCli":"服务器中没有发现有效的PHP二进制文件。","ui.server.config.stateErrorCloud":"不支持Composer Resolver Cloud。","ui.server.config.stateSuccess":"PHP 二进制文件在 {php_cli}.","ui.server.php_web.title":"PHP Web 进程","ui.server.php_web.below7":"发现 PHP 版本 {version}。请尽快切换到PHP 7!","ui.server.php_web.success":"发现PHP版本 {version}, 没有发现已知问题。","ui.server.php_cli.title":"PHP命令行接口","ui.server.php_cli.success":"发现PHP版本 {version}, 没有发现已知问题。","ui.server.composer.title":"Composer环境","ui.server.composer.success":"没有发现已知问题","ui.server.composer.install":"没有安装Composer依赖。","ui.server.composer.button":"Install","ui.server.contao.title":"Contao 安装","ui.server.contao.setup":"安装","ui.server.contao.check":"Check database","ui.server.contao.empty":"没有发现安装Contao。","ui.server.contao.old":"Contao版本 {version}不兼容Contao Manager,请手动更新当前安装的系统。","ui.server.contao.found":"发现Contao {version} (API 版本 {api}).","ui.server.contao.connectionError":"Unable to connect to the database server.","ui.server.contao.connectionProblem":"Database problem found.","ui.server.contao.missingUser":"Admin account not found.","ui.setup.continue":"继续","ui.setup.manager":"运行Contao管理器","ui.setup.cancel":"取消","ui.setup.welcome":"欢迎","ui.setup.welcome1":"This wizard will take you through the necessary steps to set up your Contao Open Source CMS installation.","ui.setup.welcome2":"If you have any questions, please find documentation, forums, a Slack channel and more on the {support} page.","ui.setup.support":"community support","ui.setup.start":"Get started","ui.setup.complete":"Congratulations!","ui.setup.complete1":"Contao {version} has been installed successfully.","ui.setup.complete2":"To finish the setup process, please open the install tool to configure the database connection and create a back end user.","ui.setup.complete3":"You can now start to create your website in the Contao back end. If you need additional extensions, continue to the Contao Manager.","ui.setup.installTool":"Open the Install Tool","ui.setup.login":"Login to Contao","ui.setup.funding":"Free software is \\"free\\" as in \\"free speech\\", not as in \\"free beer\\". An Open Source project like Contao requires amounts of money that can\'t be raised by a single person or company.\\nIf you have a website or sell websites built with Contao, we would love to see you contribute back financially to the product your business relies upon.","ui.setup.fundingLink":"Learn more","ui.setup.document-root.headline":"Webserver Setup","ui.setup.document-root.warning":"To install Contao through the Contao Manager, you have to fix the document root on the web server.","ui.setup.document-root.description1":"Contao uses a separate folder for public files, application files are installed in its parent folder. Contao cannot be installed if the folder structure is not correct or the folders are not empty.","ui.setup.document-root.description2":"If you don\'t know how to configure your document root, please read the Contao documentation or contact your hosting provider.","ui.setup.document-root.documentation":"Read the Documentation","ui.setup.document-root.conflictsTitle":"Installation directory not empty","ui.setup.document-root.conflictsDirectory":"The root directory of your future Contao installation is not empty, we have found {count} file(s) that might be overwritten by the installation process. It is recommended to create an empty directory structure for Contao, but you can also remove the following files and check again if you are sure they are unused.","ui.setup.document-root.ignoreConflicts":"I want to install Contao into the non-empty directory. I understand that this might overwrite any existing files on my webspace.","ui.setup.document-root.check":"Check again","ui.setup.document-root.create":"Create directories","ui.setup.document-root.change":"Change directories","ui.setup.document-root.formTitle":"Directory Setup","ui.setup.document-root.formText1":"The Contao Manager can automatically create a new directory structure on the server.","ui.setup.document-root.formText2":"You will need to manually configure the new document root (e.g. through a hosting admin panel).","ui.setup.document-root.autoconfig":"I understand that I have to change my server configuration. Not configuring the document root will break the Contao Manager and expose configuration files (including account details and passwords)!","ui.setup.document-root.directory":"New Directory","ui.setup.document-root.currentRoot":"Current Document Root","ui.setup.document-root.newRoot":"New Document Root","ui.setup.document-root.finish":"Setup Directories","ui.setup.document-root.publicDir":"Use {dir} for public files (for Contao {version})","ui.setup.document-root.directoryInvalid":"Please enter a valid directory name.","ui.setup.document-root.directoryExists":"The target directory already exists. Please enter a different name.","ui.setup.document-root.confirmation":"The Contao Manager has successfully created the necessary directory for your Contao installation. You now have to configure the document root on your web server. Do not reload this page until then.","ui.setup.document-root.reload":"Reload Page","ui.setup.document-root.success":"The directory structure on your web server is set up correctly!","ui.setup.document-root.installingProjectDir":"Application files will be installed to {dir}.","ui.setup.document-root.installingPublicDir":"Public files will be installed to {dir}.","ui.setup.document-root.installedProjectDir":"Application files are installed in {dir}.","ui.setup.document-root.installedPublicDir":"Public files are installed in {dir}.","ui.setup.create-project.headline":"Contao 安装","ui.setup.create-project.description":"Contao development follows the principle of {semver}, a new minor version is released every six months. The currently supported releases are:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"最新","ui.setup.create-project.ltsTitle":"长期支持","ui.setup.create-project.latestQ1":"Our latest version, offers the most features with support until February {year}.","ui.setup.create-project.latestQ3":"Our latest version, offers the most features with support until August {year}.","ui.setup.create-project.ltsText":"Our current LTS version, if you focus on stability. Offers long term support until February {year}.","ui.setup.create-project.pltsText":"The previous LTS version, still has long term support until February {year}.","ui.setup.create-project.requiresPHP":"Requires at least PHP {version}, you have PHP {current}.","ui.setup.create-project.requiresDocroot":"The document root must be \\"{folder}\\".","ui.setup.create-project.releaseplan":"See the {contaoReleasePlan} for detailed information.","ui.setup.create-project.releaseplanLink":"Contao Release Plan","ui.setup.create-project.formTitle":"Select a distribution","ui.setup.create-project.formText":"Please choose which version should be installed.","ui.setup.create-project.version":"版本","ui.setup.create-project.coreOnly":"初始化安装","ui.setup.create-project.coreOnlyNo":"全部安装 (新闻, 日历, 等.)","ui.setup.create-project.coreOnlyYes":"最小化安装 (仅核心)","ui.setup.create-project.coreOnlyFeatures":"What\'s the difference?","ui.setup.create-project.noUpdate":"跳过安装 (仅限专家!)","ui.setup.create-project.install":"Install","ui.setup.database-connection.headline":"Database Connection","ui.setup.database-connection.description":"Contao requires a MySQL database (or a compatible fork like MariaDB) to store pages, content, users and other relational data. Connection parameters are stored in the {env} file in the project root of your Contao installation.","ui.setup.database-connection.formTitle":"Connection Parameters","ui.setup.database-connection.formText":"Enter a database URL or fill in the username, password, server and database fields separately.","ui.setup.database-connection.url":"Database URL","ui.setup.database-connection.validUrl":"Database URL is invalid or connection to server failed.","ui.setup.database-connection.or":"or","ui.setup.database-connection.user":"用户名","ui.setup.database-connection.password":"密码","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Database Name","ui.setup.database-connection.serverVersion":"Server Version","ui.setup.database-connection.oldVersion":"Older MySQL or MariaDB","ui.setup.database-connection.connected":"Successfully connected to database {database} on {server} {version}.","ui.setup.database-connection.error":"Error connecting to the database.","ui.setup.database-connection.problem":"Contao has detected a problem with your database server.","ui.setup.database-connection.migration":"There is one pending migration. | There are {count} pending migrations.","ui.setup.database-connection.schema":"There is one pending schema update. | There are {count} pending schema updates.","ui.setup.database-connection.noChanges":"Your database schema is up to date.","ui.setup.database-connection.check":"Check database","ui.setup.database-connection.save":"保存","ui.setup.database-connection.change":"Change credentials","ui.setup.backend-user.success":"An admin account for the Contao back end was found in your database. Use the Contao back end to add more users.","ui.setup.backend-user.error":"Unable to retrieve user list. Check the console output for details.","ui.setup.backend-user.headline":"Backend Account","ui.setup.backend-user.description":"To manage your website, you need to have at least one admin account for the Contao back end. Be aware that this account is not related to the Contao Manager.","ui.setup.backend-user.formTitle":"创建账号","ui.setup.backend-user.formText":"Please enter the details for the new back end account.","ui.setup.backend-user.username":"用户名","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-mail address","ui.setup.backend-user.emailInvalid":"Please enter a valid e-mail address","ui.setup.backend-user.password":"密码","ui.setup.backend-user.passwordPlaceholder":"最少8个字符","ui.setup.backend-user.passwordLength":"请输入最少8个字符","ui.setup.backend-user.create":"Add account","ui.task.headline":"Background Task","ui.task.loading":"Loading details …","ui.task.created":"Loading details …","ui.task.active":"Please wait while the Contao Manager is running task operations in the background.","ui.task.complete":"All operations are completed successfully. Check the console output for details.","ui.task.aborting":"Please wait while the background operations are being cancelled.","ui.task.stopped":"Some background operations were cancelled. Please check the console output.","ui.task.error":"A background operation stopped unexpectedly. Please check the console output.","ui.task.failed":"The Contao Manager failed to start a background task!","ui.task.failedDescription1":"Something went wrong while trying to execute operations in the background.","ui.task.failedDescription2":"If this happens again, your server might not be supported.","ui.task.reportProblem":"报告问题","ui.task.sponsor":"Composer Cloud sponsored by {sponsor}","ui.task.buttonAudit":"更新数据库","ui.task.buttonClose":"关闭","ui.task.buttonConfirm":"确认 & 关闭","ui.task.buttonCancel":"取消","ui.task.confirmCancel":"确认取消此任务? 将会使Contao安装处于损坏状态!","ui.task.autoclose":"Close task details on success","ui.console.toggle":"显示/隐藏命令行输出","ui.console.showLog":"Show full console log","ui.console.copyLog":"Copy log to clipboard","ui.migrate.headline":"Database Updates","ui.migrate.migrationsOnly":"(migrations only)","ui.migrate.schemaOnly":"(schema only)","ui.migrate.loading":"Please wait, we are checking your database …","ui.migrate.empty":"No pending migrations or schema updates found. Your database is up to date.","ui.migrate.emptyMigrations":"No pending migrations found. Make sure to also check for schema updates.","ui.migrate.emptySchema":"No pending schema updates found. Make sure to also check for migrations.","ui.migrate.pending":"Your database is not up to date. Please review the console output below and execute the changes.","ui.migrate.previousChanges":"A previous database migration was not confirmed.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.previousComplete":"A previous database migration was not confirmed, please review the console output below.\\nThere are no more pending changes.","ui.migrate.appliedChanges":"Database updates have been applied.\\nPlease review the console output below, then continue to see the next changes.","ui.migrate.appliedComplete":"Database updates have been applied.\\nThere are no more pending migrations or schema updates. Your database is up to date.","ui.migrate.problem":"Contao has detected a problem with your database server.\\nPlease review the console output below to find out what needs to be fixed. | Contao has detected problems with your database server.\\nPlease review the console output below to find out what needs to be fixed.","ui.migrate.warning":"Contao has detected a misconfiguration of your database server.\\nWarnings can be skipped temporarily, but should be fixed for optimal performance and data integrity.","ui.migrate.error":"The changes could not be applied. Your database might have been changed, please check again to retry.","ui.migrate.execute":"Execute","ui.migrate.close":"关闭","ui.migrate.confirm":"确认 & 关闭","ui.migrate.cancel":"取消","ui.migrate.continue":"继续","ui.migrate.setup":"安装","ui.migrate.skip":"Skip","ui.migrate.retry":"Check again","ui.migrate.retryAll":"Check all","ui.migrate.withDeletes":"Execute all database changes including DROP queries.","ui.migrate.migrationTitle":"Database Migrations","ui.migrate.schemaTitle":"Schema Updates","ui.migrate.problemTitle":"Database Problems","ui.migrate.warningTitle":"Database Warnings","ui.migrate.addTable":"Add table {table}","ui.migrate.dropTable":"Drop table {table}","ui.migrate.addField":"Add field {table}.{field}","ui.migrate.changeField":"Change field {table}.{field}","ui.migrate.dropField":"Drop field {table}.{field}","ui.migrate.createIndex":"Create index \\"{name}\\" on {table}","ui.migrate.dropIndex":"Drop index \\"{name}\\" on {table}","ui.widget.mandatory":"该字段不能为空。","ui.widget.blankOption":"请选择 …","ui.widget.showPassword":"Show password","ui.widget.hidePassword":"Hide password","ui.error.title":"HTTP request for \\"{method} {url}\\" failed.","ui.error.server500":"Looks like an unexpected error happened on your server. Please check the log files of your web server (Apache/Nginx) and the Contao Manager logs at \\"contao-manager/logs\\".","ui.error.response":"The server returned a response with status code {status}.","ui.error.moreLink":"更多信息","ui.error.support":"Contao Support","ui.footer.help":"帮助","ui.footer.reportProblem":"报告问题","ui.navigation.discover":"发现","ui.navigation.packages":"包","ui.navigation.tools":"工具","ui.navigation.installTool":"安装工具","ui.navigation.backend":"Contao 后台","ui.navigation.debug":"Contao调试模式","ui.navigation.logViewer":"Log Viewer","ui.navigation.phpinfo":"PHP信息","ui.navigation.phpinfoLoading":"Loading PHP Information…","ui.navigation.maintenance":"维护","ui.navigation.rebuildCache":"重建缓存","ui.navigation.systemCheck":"系统检查","ui.navigation.advanced":"高级","ui.navigation.logout":"注销","ui.maintenance.databaseMigration.title":"Database Migrations","ui.maintenance.databaseMigration.description":"Database migrations ensure consistent data and table schemas.","ui.maintenance.databaseMigration.migrations":"One pending database migration | {count} pending database migrations","ui.maintenance.databaseMigration.schemaUpdates":"One pending schema update | {count} pending schema updates","ui.maintenance.databaseMigration.error":"Database problem found.","ui.maintenance.databaseMigration.warning":"Database warnings found.","ui.maintenance.databaseMigration.button":"Check database","ui.maintenance.databaseMigration.migrationOnly":"Check migrations only","ui.maintenance.databaseMigration.schemaOnly":"Check schema only","ui.maintenance.databaseMigration.installTool":"Open Install Tool","ui.maintenance.rebuildCache.title":"应用缓存","ui.maintenance.rebuildCache.description":"修改任何配置文件后,必须重建应用程序缓存。","ui.maintenance.rebuildCache.rebuildProd":"重建生产环境缓存","ui.maintenance.rebuildCache.rebuildDev":"重建开发环境缓存","ui.maintenance.rebuildCache.clearProd":"清除生产环境缓存","ui.maintenance.rebuildCache.clearDev":"清除开发环境缓存","ui.maintenance.installTool.title":"Contao安装工具","ui.maintenance.installTool.description":"连续输入3次错误密码会自动锁定Contao安装工具。","ui.maintenance.installTool.unlock":"解锁安装工具","ui.maintenance.installTool.lock":"锁定安装工具","ui.maintenance.dumpAutoload.title":"Composer类加载器","ui.maintenance.dumpAutoload.description":"Composer的自动加载器负责PHP类加载。添加自定义命名空间到根下的composer.json后必须转储自动加载器。","ui.maintenance.dumpAutoload.button":"打印Autoloader","ui.maintenance.composerInstall.title":"Composer依赖","ui.maintenance.composerInstall.description":"Composer dependencies are located in the {vendor} folder in your application root. Reinstalling the dependencies can be necessary after manipulation or manually uploading the {composerLock} file.","ui.maintenance.composerInstall.button":"运行安装器","ui.maintenance.composerInstall.update":"运行Composer更新","ui.maintenance.composerCache.title":"Composer缓存","ui.maintenance.composerCache.description":"Composer缓存下载的软件包以提高性能。 如果您遇到文件损坏等问题,请尝试删除Composer缓存以强制进行新的下载。","ui.maintenance.composerCache.button":"清楚缓存","ui.maintenance.maintenanceMode.title":"Maintenance Mode","ui.maintenance.maintenanceMode.description":"Putting Contao in maintenance mode will display a \\"503 Service Unavailable\\" template for the website.","ui.maintenance.maintenanceMode.enable":"Enable","ui.maintenance.maintenanceMode.disable":"Disable","ui.maintenance.debugMode.title":"调试模式","ui.maintenance.debugMode.description":"Activate the debug mode by setting a user and password for the {appDevPhp} entry point.","ui.maintenance.debugMode.descriptionJwt":"通过对于当前域名设置调试cookie来激活调试模式。","ui.maintenance.debugMode.activate":"激活","ui.maintenance.debugMode.deactivate":"未激活","ui.maintenance.debugMode.credentials":"证书","ui.maintenance.debugMode.user":"请输入用于调试模式的用户名。","ui.maintenance.debugMode.password":"请输入用于调试模式的密码。","ui.maintenance.opcodeCache.title":"Opcode缓存","ui.maintenance.opcodeCache.description":"Opcode在Web进程上缓存PHP文件以加快执行速度。 如果文件在更改后无法识别,则在某些情况下必须将其删除。","ui.maintenance.opcodeCache.button":"清除缓存","ui.maintenance.safeMode":"安装模式下无效","ui.maintenance.unsupported":"您的Contao版本不支持","ui.packages.updateButton":"更新包","ui.packages.searchButton":"搜索包","ui.packages.searchPlaceholder":"搜索包","ui.packages.uploadOverlay":"拖拽文件上传","ui.packages.uploadButton":"上传包","ui.packages.uploadMessage":"You have one unconfirmed upload. | You have {count} unconfirmed uploads.","ui.packages.uploadApply":"确认上传","ui.packages.uploadReset":"删除上传","ui.packages.uploadIncomplete":"此文件未完全上传。 请将其删除,然后重试。","ui.packages.uploadDuplicate":"此文件似乎多次上传。 请删除重复项。","ui.packages.uploadInstalled":"此文件已安装。请移除重复项。","ui.packages.uploadUnsupported":"Uploads are not supported in your installation. Please make sure that the PHP ZIP extension is installed and update your dependencies.","ui.packages.changesMessage":"You have one unconfirmed change. | You have {count} unconfirmed changes.","ui.packages.changesDryrun":"Dry Run","ui.packages.changesApply":"应用更改","ui.packages.changesApplyAll":"Update all packages","ui.packages.changesDryrunAll":"Dry run all packages","ui.packages.changesReset":"重置更改","ui.packages.changesReview":"预览更改","ui.packagelist.loading":"加载 …","ui.packagelist.uploads":"上传","ui.packagelist.added":"新包","ui.packagelist.installed":"已安装的包","ui.package.hintRevert":"恢复更改","ui.package.hintNoupdate":"不要更新","ui.package.hintConstraint":"应用更改时,此包将会带约束 {constraint} 安装。","ui.package.hintConstraintBest":"应用更改时,此包将会安装最佳版本。","ui.package.hintConstraintChange":"应用更改时,此包的约束将从\\"{from}\\"更改为\\"{to}\\"。","ui.package.hintConstraintUpdate":"应用更改后此包会被更新","ui.package.hintAdded":"应用更改后此包会被安装","ui.package.hintRemoved":"应用更改时,该程序包将被移除。","ui.package.requiredTitle":"手动添加","ui.package.requiredText":"composer.json中需要此包,但是没有安装","ui.package.removedTitle":"手动移除","ui.package.removedText":"此包已从composer.json移除。","ui.package.installed":"当前已安装:","ui.package.version":"版本 {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Star | {count} Stars","ui.package.editConstraint":"编辑","ui.package.uploadConstraint":"此约束由上传的包定义。","ui.package.updateButton":"更新","ui.package.removeButton":"移除","ui.package.installButton":"添加包","ui.package.installButtonShort":"添加","ui.package.detailsButton":"详情","ui.package.latestConstraint":"最新版","ui.package.update":"Update available","ui.package.updateLatest":"最新版","ui.package.updateAvailable":"{version} available","ui.package.updateUnknown":"unknown version","ui.package.updateConstraint":"A newer version outside your version constraint is available.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"版本 {version}","ui.cloudStatus.waitingTime":"等待时间","ui.cloudStatus.jobs":"当前工作","ui.cloudStatus.workers":"工作者","ui.cloudStatus.approx":"{minutes} 分钟","ui.cloudStatus.none":"无","ui.cloudStatus.short":"ca. {minutes} 分钟","ui.cloudStatus.long":"ca. {minutes} 分钟 {seconds} 秒","ui.cloudStatus.error":"Unable to fetch the status of the Composer Resolver Cloud. It might be down for maintenance or experience issues.","ui.cloudStatus.button":"Cloud Status","ui.cloudStatus.refresh":"Refresh Cloud Status","ui.log-viewer.loading":"加载 …","ui.log-viewer.empty":"There are no log files on your server.","ui.log-viewer.reload":"Reload","ui.log-viewer.file":"Log file","ui.log-viewer.channel":"Channel","ui.log-viewer.channelTitle":"The channel this message was logged to.","ui.log-viewer.level":"Level","ui.log-viewer.levelTitle":"Severity of the log message.","ui.log-viewer.timeHeader":"Time","ui.log-viewer.messageHeader":"Message","ui.log-viewer.showContext":"Show Context","ui.log-viewer.hideContext":"Hide Context","ui.log-viewer.showExtra":"Show Extra","ui.log-viewer.hideExtra":"Hide Extra","ui.log-viewer.more":"Load more …","ui.log-viewer.download":"Download","ui.log-viewer.downloadTitle":"Download file \\"{file}\\"","ui.log-viewer.prodEnvironment":"Production Environment","ui.log-viewer.devEnvironment":"Development Environment (Debug Mode)"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[219],{3219:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensions","ui.app.loading":"Loading Extension List …","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"Loading …","ui.discover.offline":"Could not fetch any results.","ui.discover.offlineExplain":"Check your internet connection and disable JavaScript blockers in your browser.","ui.discover.offlineButton":"Try again","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"No results for {query}","ui.discover.more":"More Results","ui.discover.sortBy":"Sort by","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Updated","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Rating","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Details","ui.discover.latestPackages":"Latest and updated extensions","ui.discover.faversPackages":"Top rated extensions","ui.discover.downloadsPackages":"Most downloaded extensions","ui.package.homepage":"Project Website","ui.package.private":"Private Package","ui.package.privateTitle":"Private packages are only available from the vendor (e.g. as a ZIP download). Please visit the website for more information.","ui.package.abandoned":"abandoned","ui.package.abandonedText":"This package is abandoned and no longer maintained.","ui.package.abandonedReplace":"This package is abandoned and no longer maintained. The author suggests using the {replacement} package instead.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Previous Extension Details","ui.package-details.close":"Close Extension Details","ui.package-details.loading":"Loading …","ui.package-details.tabDescription":"Description","ui.package-details.tabRequire":"Requirements","ui.package-details.tabFeatures":"Features","ui.package-details.tabSuggest":"Suggestions","ui.package-details.tabConflict":"Conflicts","ui.package-details.tabDependents":"Dependents","ui.package-details.linkRequires":"requires","ui.package-details.linkReplaces":"replaces","ui.package-details.linkProvides":"provides","ui.package-details.linkConflicts":"conflicts","ui.package-details.funding":"Fund package maintenance!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Latest version","ui.package-details.released":"released on","ui.package-details.license":"License(s)","ui.package-details.authors":"from","ui.package-details.more":"More","ui.package-details.packagist":"Package Details","ui.package-details.metadata":"Edit Metadata","ui.package-details.support_docs":"Documentation","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Support Forum","ui.package-details.support_issues":"Issues / Bug Report","ui.package-details.support_source":"Source Code","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Support E-Mail","ui.package-details.support_rss":"RSS Feed"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[721],{9721:function(a){a.exports=JSON.parse('{"ui.app.title":"Contao機能拡張","ui.app.loading":"機能拡張の一覧を読み込み中...","ui.app.language":"Contao Managerの言語を切り替え","ui.app.colorDark":"ダークモード","ui.app.colorDarkTitle":"配色をダークモードに切り替え","ui.app.colorLight":"ライトモード","ui.app.colorLightTitle":"配色をライトモードに切り替え","ui.discover.advertisement":"機能拡張のリストに広告","ui.discover.loading":"読み込み中...","ui.discover.offline":"何も結果を取得できませんでした。","ui.discover.offlineExplain":"Internet接続を確認し、ブラウザーのJavaScriptのブロッカーを無効にしてください。","ui.discover.offlineButton":"再実行","ui.discover.searchPlaceholder":"{count}の機能拡張から検索中...","ui.discover.empty":"{query}の結果はありません。","ui.discover.more":"さらに結果を表示","ui.discover.sortBy":"並べ替え","ui.discover.sortReleased":"リリース","ui.discover.sortReleasedTitle":"リリース日で並べ替え","ui.discover.sortLatest":"更新日時","ui.discover.sortLatestTitle":"更新日時で並べ替え","ui.discover.sortDownloads":"ダウンロード","ui.discover.sortDownloadsTitle":"ダウンロード数で並べ替え","ui.discover.sortFavers":"評価","ui.discover.sortFaversTitle":"評価の結果で並べ替え","ui.discover.detailsButton":"詳細","ui.discover.latestPackages":"最新と更新された機能拡張","ui.discover.faversPackages":"最上位のレートの機能拡張","ui.discover.downloadsPackages":"もっともダウンロードされた機能拡張","ui.package.homepage":"プロジェクトのウェブサイト","ui.package.private":"私的なパッケージ","ui.package.privateTitle":"私的なパッケージはベンダーからだけ(例えば、ZIPのダウンロードで)入手できます。詳細はウェブサイトを参照してください。","ui.package.abandoned":"放棄","ui.package.abandonedText":"このパッケージは放棄され、もう保守されていません。","ui.package.abandonedReplace":"このパッケージは放棄され、もう保守されていません。代わりに{replacement}パッケージの使用を作者は推奨しています。","ui.package.contaoVersion":"Contaoで利用可能","ui.package-details.previous":"以前の機能拡張の詳細","ui.package-details.close":"機能拡張の詳細を閉じる","ui.package-details.loading":"読み込み中...","ui.package-details.tabDescription":"説明","ui.package-details.tabRequire":"必須要件","ui.package-details.tabFeatures":"機能","ui.package-details.tabSuggest":"提案","ui.package-details.tabConflict":"競合","ui.package-details.tabDependents":"依存関係","ui.package-details.linkRequires":"必要","ui.package-details.linkReplaces":"置き換え","ui.package-details.linkProvides":"提供","ui.package-details.linkConflicts":"競合","ui.package-details.funding":"パッケージの保守に資金を提供!","ui.package-details.contaoVersions":"サポートしているContaoのバージョン","ui.package-details.latest":"最新版","ui.package-details.released":"リリース日","ui.package-details.license":"ライセンス","ui.package-details.authors":"次から","ui.package-details.more":"詳細","ui.package-details.packagist":"パッケージの詳細","ui.package-details.metadata":"メタデータを編集","ui.package-details.support_docs":"ドキュメント","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"サポートフォーラム","ui.package-details.support_issues":"問題 / バグ報告","ui.package-details.support_source":"ソースコード","ui.package-details.support_irc":"IRC / チャット","ui.package-details.support_email":"サポートの電子メール","ui.package-details.support_rss":"RSSフィード"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[581],{4581:function(a){a.exports=JSON.parse('{"ui.app.title":"Contao проширења","ui.app.loading":"Учитавам листу проширења...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Оглашавање у листи екстензија","ui.discover.loading":"Учитавам ...","ui.discover.offline":"Нема пронађених резултата.","ui.discover.offlineExplain":"Проверите вашу интернет конекцију и искључите блокаду JavaScript-а у вашем прегледачу.","ui.discover.offlineButton":"Покушајте поново","ui.discover.searchPlaceholder":"Претражи у {count} екстензија ...","ui.discover.empty":"Нема резултата за {query}","ui.discover.more":"Више резултата","ui.discover.sortBy":"Сортирај по","ui.discover.sortReleased":"Објављено","ui.discover.sortReleasedTitle":"Поредај резултате по датуму објаве","ui.discover.sortLatest":"Ажурирано","ui.discover.sortLatestTitle":"Поредај резултате по датуму ажурирања","ui.discover.sortDownloads":"Преузимања","ui.discover.sortDownloadsTitle":"Поредај резултате по броју преузимања","ui.discover.sortFavers":"Оцене","ui.discover.sortFaversTitle":"Поредај резултате по оцени","ui.discover.detailsButton":"Детаљи","ui.discover.latestPackages":"Последње и ажуриране екстензије","ui.discover.faversPackages":"Најбоље оцењене екстензије","ui.discover.downloadsPackages":"Екстензије са највише преузимања","ui.package.homepage":"Вебсајт пројекта","ui.package.private":"Приватни пакети","ui.package.privateTitle":"Приватни пакети су доступни само од вендора (нпр. као ZIP преузимање). Посетите сајт ради више информација.","ui.package.abandoned":"напуштено","ui.package.abandonedText":"Овај пакет је напуштен и више се не одржава.","ui.package.abandonedReplace":"Овај пакет је напуштен и више се не одржава. Аутор предлаже да користите {replacement} као замену.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Детаљи претходне екстензије","ui.package-details.close":"Затвори детаље екстензије","ui.package-details.loading":"Учитавам ...","ui.package-details.tabDescription":"Опис","ui.package-details.tabRequire":"Захтеви","ui.package-details.tabFeatures":"Могућности","ui.package-details.tabSuggest":"Предлози","ui.package-details.tabConflict":"Конфликти","ui.package-details.tabDependents":"Зависности","ui.package-details.linkRequires":"захтева","ui.package-details.linkReplaces":"мења","ui.package-details.linkProvides":"пружа","ui.package-details.linkConflicts":"сукобљава се са","ui.package-details.funding":"Спонзорирајте одржавање пакета!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Последња верзија","ui.package-details.released":"објављено","ui.package-details.license":"Лиценца(е)","ui.package-details.authors":"од","ui.package-details.more":"Детаљније","ui.package-details.packagist":"Детаљи пакета","ui.package-details.metadata":"Уреди мета податке","ui.package-details.support_docs":"Документација","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Форум за подршку","ui.package-details.support_issues":"Пријава проблема/Баг","ui.package-details.support_source":"Изворни код","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Имејл подршке","ui.package-details.support_rss":"RSS сажетак"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[612],{5612:function(t,e,o){o.r(e),o.d(e,{default:function(){return I}});var s=o(641),a=o(33),n=o(3751),i=o(6894);const u={class:"view-account__header"},r={class:"view-account__product"},l=["href"],c={href:"https://github.com/contao/contao-manager/issues",target:"_blank"},d={key:0,class:"view-account__totp"},p={class:"view-account__headline"},h={class:"view-account__description"},g={key:1,class:"view-account__form"},m={class:"view-account__headline"},b={class:"view-account__description"},w={class:"view-account__fields"},k=["disabled"],_={class:"view-account__contribute"},v={href:"https://to.contao.org/donate",target:"_blank"};function $(t,e,o,$,f,L){const y=(0,s.g2)("i18n-t"),A=(0,s.g2)("text-field"),T=(0,s.g2)("button-group"),C=(0,s.g2)("loading-button"),P=(0,s.g2)("boxed-layout");return(0,s.uX)(),(0,s.Wv)(P,{wide:!0,slotClass:"view-account"},{default:(0,s.k6)((()=>[(0,s.Lk)("header",u,[e[11]||(e[11]=(0,s.Lk)("img",{src:i,width:"100",height:"100",alt:"Contao Logo"},null,-1)),(0,s.Lk)("p",r,[(0,s.Lk)("strong",null,(0,a.v_)(t.$t("ui.account.welcome")),1),e[8]||(e[8]=(0,s.eW)(" Contao Manager 1.9.1 "))]),(0,s.Lk)("p",null,[(0,s.bF)(y,{keypath:"ui.account.intro1"},{readTheManualToGetStarted:(0,s.k6)((()=>[(0,s.bF)(y,{tag:"strong",keypath:"ui.account.introGetStarted"},{readTheManual:(0,s.k6)((()=>[(0,s.Lk)("a",{href:`https://to.contao.org/docs/contao-manager?lang=${t.$i18n.locale}`,target:"_blank"},(0,a.v_)(t.$t("ui.account.introManual")),9,l)])),_:1})])),_:1}),e[9]||(e[9]=(0,s.Lk)("br",null,null,-1)),e[10]||(e[10]=(0,s.Lk)("br",null,null,-1)),(0,s.bF)(y,{keypath:"ui.account.intro2"},{ourGithubIssues:(0,s.k6)((()=>[(0,s.Lk)("a",c,(0,a.v_)(t.$t("ui.account.introIssues")),1)])),_:1})])]),(0,s.bF)(n.eB,{name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,s.k6)((()=>[t.currentUser&&!t.hasTotp?((0,s.uX)(),(0,s.CE)("main",d,[(0,s.Lk)("h1",p,(0,a.v_)(t.$t("ui.account.totpHeadline")),1),(0,s.Lk)("p",h,(0,a.v_)(t.$t("ui.account.totpDescription")),1),(0,s.Lk)("button",{class:"widget-button widget-button--primary",onClick:e[0]||(e[0]=function(){return L.setupTotp&&L.setupTotp(...arguments)})},(0,a.v_)(t.$t("ui.totp.setup")),1),(0,s.Lk)("button",{class:"widget-button widget-button--alert",onClick:e[1]||(e[1]=function(){return L.skipTotp&&L.skipTotp(...arguments)})},(0,a.v_)(t.$t("ui.totp.skip")),1)])):((0,s.uX)(),(0,s.CE)("main",g,[(0,s.Lk)("form",{onSubmit:e[7]||(e[7]=(0,n.D$)((function(){return L.createAccount&&L.createAccount(...arguments)}),["prevent"]))},[(0,s.Lk)("h1",m,(0,a.v_)(t.$t("ui.account.headline")),1),(0,s.Lk)("p",b,(0,a.v_)(t.$t("ui.account.description")),1),(0,s.Lk)("fieldset",w,[(0,s.bF)(A,{ref:"username",name:"username",label:t.$t("ui.account.username"),disabled:t.logging_in,required:"",error:t.errors.username,onBlur:e[2]||(e[2]=e=>t.errors.username=""),modelValue:t.username,"onUpdate:modelValue":e[3]||(e[3]=e=>t.username=e)},null,8,["label","disabled","error","modelValue"]),t.usePassword?((0,s.uX)(),(0,s.Wv)(A,{key:0,ref:"password",name:"password",type:"password",label:t.$t("ui.account.password"),placeholder:t.$t("ui.account.passwordPlaceholder"),disabled:t.logging_in,required:"",pattern:".{8,}",error:t.errors.password,onBlur:L.validatePassword,modelValue:t.password,"onUpdate:modelValue":e[4]||(e[4]=e=>t.password=e)},null,8,["label","placeholder","disabled","error","onBlur","modelValue"])):(0,s.Q3)("",!0),t.supportsWebAuthn?((0,s.uX)(),(0,s.Wv)(T,{key:1,submit:"",color:"primary",disabled:!t.valid,loading:t.logging_in,label:t.$t("ui.account.submit")},{default:(0,s.k6)((()=>[(0,s.Lk)("button",{type:"button",class:"widget-button",disabled:t.logging_in,onClick:e[5]||(e[5]=e=>t.usePassword=!t.usePassword)},(0,a.v_)(t.$t("ui.account."+(t.usePassword?"usePasskey":"usePassword"))),9,k)])),_:1},8,["disabled","loading","label"])):((0,s.uX)(),(0,s.Wv)(C,{key:2,submit:"",color:"primary",disabled:!t.valid,loading:t.logging_in},{default:(0,s.k6)((()=>[(0,s.eW)((0,a.v_)(t.$t("ui.account.submit")),1)])),_:1},8,["disabled","loading"])),L.isInvitation?((0,s.uX)(),(0,s.CE)("button",{key:3,type:"button",class:"widget-button widget-button--anchor",onClick:e[6]||(e[6]=function(){return L.gotoLogin&&L.gotoLogin(...arguments)})},(0,a.v_)(t.$t("ui.account.login")),1)):(0,s.Q3)("",!0)])],32)]))])),_:1}),(0,s.Lk)("aside",_,[(0,s.Lk)("p",null,[(0,s.eW)((0,a.v_)(t.$t("ui.account.contribute1")),1),e[12]||(e[12]=(0,s.Lk)("br",null,null,-1)),(0,s.bF)(y,{keypath:"ui.account.contribute2"},{donate:(0,s.k6)((()=>[(0,s.Lk)("a",v,(0,a.v_)(t.$t("ui.account.contributeDonate")),1)])),_:1})])])])),_:1})}var f=o(6278),L=o(60),y=o(707),A=o(5404),T=o(683),C=o(6966),P=o(2880),V=o(2286),W={components:{BoxedLayout:A.A,TextField:T.A,LoadingButton:C.A,ButtonGroup:P.A},data:()=>({username:"",password:"",errors:{username:"",password:""},valid:!1,logging_in:!1,usePassword:!1,supportsWebAuthn:!0}),computed:{...(0,f.aH)("auth",{currentUser:"username",hasTotp:"totpEnabled"}),isInvitation:t=>!!t.$route.query.invitation},methods:{validate(){this.valid=this.$refs.username.checkValidity()&&(!this.usePassword||this.$refs.password.checkValidity())},validatePassword(){this.errors.password=null,""!==this.password&&this.password.length<8&&(this.errors.password=this.$t("ui.account.passwordLength"))},async createAccount(){if(!this.valid)return;this.logging_in=!0;const t={username:this.username};if(this.isInvitation&&(t.invitation=this.$route.query.invitation),this.usePassword)t.password=this.password;else{const o=(await this.$request.post("api/session/options",t)).data;let s;try{s=await(0,L.Ct)({optionsJSON:o})}catch(e){return void(this.logging_in=!1)}if(!s)return void(this.logging_in=!1);t.passkey=JSON.stringify(s)}201!==(await this.$store.dispatch("auth/login",t)).status&&(this.logging_in=!1,this.errors.username=this.$t("ui.account.loginInvalid"),setTimeout((()=>{this.$refs.username.focus()}),0))},setupTotp(){this.$store.commit("modals/open",{id:"setup-totp",component:V.A})},skipTotp(){this.$store.commit("setView",y.A.BOOT)},gotoLogin(){this.$router.replace({name:this.$route.name,query:null}),this.$store.commit("setView",y.A.LOGIN)}},watch:{username(){this.validate()},password(){this.validate()},hasTotp(){this.$store.commit("setView",y.A.BOOT)}},mounted(){this.supportsWebAuthn="https:"===location.protocol&&(0,L.zZ)(),this.usePassword=!this.supportsWebAuthn,this.$refs.username&&this.$refs.username.focus()}},B=o(6262);const F=(0,B.A)(W,[["render",$]]);var I=F}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[716],{3716:function(e){e.exports=JSON.parse('{"ui.app.title":"Rozszerzenia Contao","ui.app.loading":"Ładowanie listy rozszerzeń …","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Reklama w liście rozszerzeń","ui.discover.loading":"Ładowanie …","ui.discover.offline":"Nie znaleziono żadnych wyników.","ui.discover.offlineExplain":"Sprawdź swoje połączenie internetowe i wyłącz narzędzia blokujące JavaScript w przeglądarce.","ui.discover.offlineButton":"Spróbuj ponownie","ui.discover.searchPlaceholder":"Szukaj w {count} rozszerzeniach ...","ui.discover.empty":"Brak wyników dla {query}","ui.discover.more":"Więcej Wyników","ui.discover.sortBy":"Sortuj według","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Data aktualizacji","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Pobrania","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Ocena","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Szczegóły","ui.discover.latestPackages":"Najnowsze i zaktualizowane rozszerzenia","ui.discover.faversPackages":"Najwyżej oceniane rozszerzenia","ui.discover.downloadsPackages":"Najczęściej pobierane rozszerzenia","ui.package.homepage":"Strona Projektu","ui.package.private":"Prywatny Pakiet","ui.package.privateTitle":"Prywatne pakiety są dostępne tylko bezpośrednio od dostawcy (np. jako plik ZIP). Odwiedź stronę po więcej informacji.","ui.package.abandoned":"porzucony","ui.package.abandonedText":"Ten pakiet jest porzucony i nie jest już wspierany.","ui.package.abandonedReplace":"Ten pakiet jest porzucony i nie jest już wspierany. Autor sugeruje użycie pakietu {replacement} zamiast niego.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Szczegóły poprzedniego rozszerzenia","ui.package-details.close":"Zamknij szczegóły rozszerzenia","ui.package-details.loading":"Ładowanie …","ui.package-details.tabDescription":"Opis","ui.package-details.tabRequire":"Wymagania","ui.package-details.tabFeatures":"Funkcjonalności","ui.package-details.tabSuggest":"Sugestie","ui.package-details.tabConflict":"Konflikty","ui.package-details.tabDependents":"Zależności","ui.package-details.linkRequires":"wymaga","ui.package-details.linkReplaces":"zastępuje","ui.package-details.linkProvides":"dostarcza","ui.package-details.linkConflicts":"koliduje","ui.package-details.funding":"Finansuj rozwój pakietu!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Ostatnia wersja","ui.package-details.released":"data wydania","ui.package-details.license":"Licencje","ui.package-details.authors":"od","ui.package-details.more":"Więcej","ui.package-details.packagist":"Szczegóły Pakietu","ui.package-details.metadata":"Edytuj metadane","ui.package-details.support_docs":"Dokumentacja","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Forum","ui.package-details.support_issues":"Issues / Bug Report","ui.package-details.support_source":"Kod źródłowy","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"Wsparcie E-mail","ui.package-details.support_rss":"Kanał RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[194],{194:function(a){a.exports=JSON.parse('{"ui.app.title":"Contao paplašinājumi","ui.app.loading":"Ielādē paplašinājumu sarakstu ...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Reklāma paplašinājumu sarakstā","ui.discover.loading":"Ielādē ...","ui.discover.offline":"Nevarēja iegūt nekādus rezultātus.","ui.discover.offlineExplain":"Pārbaudiet savu interneta savienojumu un atspējojiet JavaScript bloķētājus savā pārlūkprogrammā.","ui.discover.offlineButton":"Mēģini vēlreiz","ui.discover.searchPlaceholder":"Meklēt {count} paplašinājumos ...","ui.discover.empty":"Nav rezultātu {query}","ui.discover.more":"Vairāk rezultātu","ui.discover.sortBy":"Kārtot pēc","ui.discover.sortReleased":"Released","ui.discover.sortReleasedTitle":"Sort results by release date","ui.discover.sortLatest":"Atjaunināts","ui.discover.sortLatestTitle":"Sort results by last updated","ui.discover.sortDownloads":"Lejupielādes","ui.discover.sortDownloadsTitle":"Sort results by number of downloads","ui.discover.sortFavers":"Vērtējums","ui.discover.sortFaversTitle":"Sort results by rating","ui.discover.detailsButton":"Sīkāka informācija","ui.discover.latestPackages":"Jaunākie un atjauninātie paplašinājumi","ui.discover.faversPackages":"Visaugstāk novērtētie paplašinājumi","ui.discover.downloadsPackages":"Visvairāk lejupielādētie paplašinājumi","ui.package.homepage":"Projekta mājaslapa","ui.package.private":"Privāta pakotne","ui.package.privateTitle":"Privātās pakotnes ir pieejamas tikai pie pārdevēja (piem., kā ZIP lejupielādes). Lūdzu, apmeklējiet vietni, lai iegūtu papildinformāciju.","ui.package.abandoned":"pamests","ui.package.abandonedText":"Šī pakotne ir pamesta un vairs netiek uzturēta.","ui.package.abandonedReplace":"Šī pakotne ir pamesta un vairs netiek uzturēta. Autors iesaka tās vietā izmantot pakotni {replacement}.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Iepriekšējā paplašinājuma informācija","ui.package-details.close":"Aizvērt paplašinājuma informāciju","ui.package-details.loading":"Ielādē ...","ui.package-details.tabDescription":"Apraksts","ui.package-details.tabRequire":"Prasības","ui.package-details.tabFeatures":"Iespējas","ui.package-details.tabSuggest":"Ieteikumi","ui.package-details.tabConflict":"Konflikti","ui.package-details.tabDependents":"Atkarīgie","ui.package-details.linkRequires":"nepieciešams","ui.package-details.linkReplaces":"aizstāj","ui.package-details.linkProvides":"nodrošina","ui.package-details.linkConflicts":"konflikti","ui.package-details.funding":"Finansējiet paketes uzturēšanu!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Jaunākā versija","ui.package-details.released":"izlaists","ui.package-details.license":"Licence(s)","ui.package-details.authors":"no","ui.package-details.more":"Vairāk","ui.package-details.packagist":"Pakotnes informācija","ui.package-details.metadata":"Rediģēt metadatus","ui.package-details.support_docs":"Dokumentācija","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Atbalsta forums","ui.package-details.support_issues":"Problēmas / Kļūdu ziņojums","ui.package-details.support_source":"Avota kods","ui.package-details.support_irc":"IRC / Tērzēšana","ui.package-details.support_email":"Atbalsta e-pasts","ui.package-details.support_rss":"RSS barotne"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[479],{4479:function(e,o,t){t.r(o),t.d(o,{default:function(){return V}});var i=t(641),n=t(3751),l=t(33),s=t(6894);const a={key:0,class:"view-login__locked"},r={key:0,class:"view-login__form"},u={class:"view-login__headline"},d={class:"view-login__description"},g=["href"],p={key:1,class:"view-login__form"},c={class:"view-login__headline"},_={class:"view-login__description"};function h(e,o,t,h,m,w){const k=(0,i.g2)("i18n-t"),f=(0,i.g2)("text-field"),b=(0,i.g2)("loading-button"),v=(0,i.g2)("boxed-layout");return(0,i.uX)(),(0,i.Wv)(v,{slotClass:"view-login"},{default:(0,i.k6)((()=>[o[7]||(o[7]=(0,i.Lk)("header",{class:"view-login__header"},[(0,i.Lk)("img",{src:s,width:"80",height:"80",alt:"Contao Logo"}),(0,i.Lk)("p",{class:"view-login__product"},"Contao Manager")],-1)),e.locked?((0,i.uX)(),(0,i.CE)("main",a,[(0,i.bF)(k,{tag:"p",keypath:"ui.login.locked"},{lockFile:(0,i.k6)((()=>o[6]||(o[6]=[(0,i.Lk)("strong",null,"contao-manager/login.lock",-1),(0,i.Lk)("br",null,null,-1)]))),_:1})])):((0,i.uX)(),(0,i.Wv)(n.eB,{key:1,name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)((()=>[e.requires_totp?((0,i.uX)(),(0,i.CE)("main",p,[(0,i.Lk)("form",{onSubmit:o[5]||(o[5]=(0,n.D$)((function(){return w.login&&w.login(...arguments)}),["prevent"]))},[(0,i.Lk)("h1",c,(0,l.v_)(e.$t("ui.login.totpHeadline")),1),(0,i.Lk)("p",_,(0,l.v_)(e.$t("ui.login.totpDescription")),1),(0,i.bF)(f,{name:"totp",required:"",minlength:"6",maxlength:"6",autocomplete:"one-time-code",label:e.$t("ui.login.totp"),placeholder:e.$t("ui.login.totp"),class:(0,l.C4)(["view-login__totp",e.login_failed?"widget--error":""]),disabled:e.logging_in,modelValue:e.totp,"onUpdate:modelValue":o[3]||(o[3]=o=>e.totp=o),onInput:w.reset},null,8,["label","placeholder","class","disabled","modelValue","onInput"]),(0,i.bF)(b,{submit:"",class:"view-login__button",color:"primary",disabled:!w.totpValid||e.login_failed,loading:e.logging_in},{default:(0,i.k6)((()=>[(0,i.eW)((0,l.v_)(e.$t("ui.login.button")),1)])),_:1},8,["disabled","loading"]),(0,i.Lk)("button",{class:"widget-button view-login__button",onClick:o[4]||(o[4]=function(){return w.cancelTotp&&w.cancelTotp(...arguments)})},(0,l.v_)(e.$t("ui.login.cancel")),1)],32)])):((0,i.uX)(),(0,i.CE)("main",r,[(0,i.Lk)("form",{onSubmit:o[2]||(o[2]=(0,n.D$)((function(){return w.login&&w.login(...arguments)}),["prevent"]))},[(0,i.Lk)("h1",u,(0,l.v_)(e.$t("ui.login.headline")),1),(0,i.Lk)("p",d,(0,l.v_)(e.$t("ui.login.description")),1),(0,i.bF)(f,{ref:"username",name:"username",autocomplete:"username webauthn",label:e.$t("ui.login.username"),placeholder:e.$t("ui.login.username"),class:(0,l.C4)(["view-login__user",e.login_failed?"widget--error":""]),disabled:e.logging_in,modelValue:e.username,"onUpdate:modelValue":o[0]||(o[0]=o=>e.username=o),onInput:w.reset},null,8,["label","placeholder","class","disabled","modelValue","onInput"]),(0,i.bF)(f,{type:"password",name:"password",autocomplete:"current-password",label:e.$t("ui.login.password"),placeholder:e.$t("ui.login.password"),minlength:"8",class:(0,l.C4)(["view-login__password",e.login_failed?"widget--error":""]),disabled:e.logging_in,modelValue:e.password,"onUpdate:modelValue":o[1]||(o[1]=o=>e.password=o),onInput:w.reset},null,8,["label","placeholder","class","disabled","modelValue","onInput"]),(0,i.bF)(b,{submit:"",class:"view-login__button",color:"primary",disabled:!w.inputValid||e.login_failed,loading:e.logging_in},{default:(0,i.k6)((()=>[(0,i.eW)((0,l.v_)(e.$t("ui.login.button")),1)])),_:1},8,["disabled","loading"]),e.showPasskey?((0,i.uX)(),(0,i.Wv)(b,{key:0,class:"view-login__button",color:"primary",loading:e.logging_in,onClick:(0,n.D$)(w.passkeyLogin,["prevent"])},{default:(0,i.k6)((()=>[(0,i.eW)((0,l.v_)(e.$t("ui.login.passkey")),1)])),_:1},8,["loading","onClick"])):(0,i.Q3)("",!0),(0,i.Lk)("a",{href:`https://to.contao.org/docs/manager-password?lang=${e.$i18n.locale}`,target:"_blank",class:"view-login__link"},(0,l.v_)(e.$t("ui.login.forgotPassword")),9,g)],32)]))])),_:1}))])),_:1})}var m=t(6278),w=t(60),k=t(707),f=t(5404),b=t(683),v=t(6966),y={components:{BoxedLayout:f.A,TextField:b.A,LoadingButton:v.A},data:()=>({username:"",password:"",totp:"",logging_in:!1,requires_totp:!1,login_failed:!1,showPasskey:!1}),computed:{...(0,m.aH)(["locked"]),inputValid(){return""!==this.username&&""!==this.password&&this.password.length>=8},totpValid(){return""!==this.totp&&/^\d{6}$/.test(this.totp)}},methods:{async login(){this.inputValid&&this.doLogin({username:this.username,password:this.password,totp:this.totp})},async passkeyLogin(e){let{useBrowserAutofill:o}=e;const t=(await this.$request.get("api/session/options")).data;try{const e=await(0,w.HS)({optionsJSON:t,useBrowserAutofill:!!o});await this.doLogin({passkey:JSON.stringify(e)})}catch(i){}},async doLogin(e){this.logging_in=!0;const o=await this.$store.dispatch("auth/login",e);201===o.status?this.$store.commit("setView",k.A.BOOT):401===o.status&&o.data.totp_enabled?(this.logging_in=!1,this.requires_totp=!0,this.login_failed=!!this.totp):(this.logging_in=!1,this.login_failed=!0)},reset(){this.login_failed=!1},cancelTotp(){this.username="",this.password="",this.totp="",this.logging_in=!1,this.requires_totp=!1,this.login_failed=!1}},async mounted(){if(this.$store.commit("setError",null),this.locked)return;if(this.$refs.username&&this.$refs.username.focus(),"https:"!==location.protocol)return void(this.showPasskey=!1);const e=(0,w.zZ)(),o=await(0,w.ZF)();this.showPasskey=e,e&&o&&this.passkeyLogin({useBrowserAutofill:!0})}},$=t(6262);const L=(0,$.A)(y,[["render",h]]);var V=L}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[540],{4540:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Nezabezpečené připojení !!","ui.app.httpsDescription":"Bez HTTPS budou citlivá data přenášena nezabezpečeně.","ui.app.httpsLink":"Více informací","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Je zapnutý bezpečnostní režim !!","ui.app.safeModeDescription":"Některé funkce nejsou k dispozici ve Správci Contaa.","ui.app.safeModeExit":"Ukončit bezpečnostní režim","ui.app.limitedHeadline":"Smazat autorizaci","ui.app.limitedDescription":"Máte omezená přístupová práva kvůli přihlášení bez hesla.","ui.app.limitedLogout":"Opětovné ověření","ui.app.totpHeadline":"Bezpečnostní poznámka","ui.app.totpDescription":"Nastavte si dvoufaktorové ověření pro vyšší zabezpečení vašeho účtu. ","ui.app.totpSetup":"Nastavení","ui.app.loading":"Nahrávání Správce Contaa","ui.app.apiError":"Nečekaný status API","ui.app.configSecurity1":"BEZPEČNOSTNÍ UPOZORNĚNÍ!!! Byla objevená nechráněná konfigurační složka ","ui.app.configSecurity2":"Správce Contaa zjistil, že jsou veřejně dostupné jeho konfigurační soubory. Všechny operace byly pozastavené, dokud nebude daná složka chráněná, jinak může dojít k útoku na choulostivá data Vaší instalace.\\n\\nPro opravení této potíže zajistěte omezený přístup ke složce \\"contao-manager\\" na Vašem serveru. Jak to lze provést, se dozvíte od Vašeho hostingového poskytovatele nebo v příručce ke správě serveru.","ui.account.welcome":"Vítejte","ui.account.intro1":"Vítejte ve Správci Contaa, univerzálním nástroji k instalaci a správě Contaa Open Source CMS. Pokud jste tu poprvé, přečtěte si prosím návod {readTheManualToGetStarted}.","ui.account.introGetStarted":"Začínáme {readTheManual}.","ui.account.introManual":"přečíst návod","ui.account.intro2":"Pokud si všimnete jakýchkoli nesrovnalostí, podívejte se na seznam nahlášených chyb {ourGithubIssues}  a případně nahlaste novou, kterou ještě nikdo nenahlásil. ","ui.account.introIssues":"Chyby na GitHubu","ui.account.headline":"Uživatelský účet","ui.account.description":"Abyste mohli spravovat instalaci, vytvořte prosím uživatelský účet. Uvědomte si prosím, že tento účet není stejný pro přihlášení do Contaa. ","ui.account.username":"Uživatelské jméno","ui.account.password":"Heslo","ui.account.passwordPlaceholder":"min. 8 znaků","ui.account.passwordLength":"Zadejte prosím nejméně 8 znaků.","ui.account.loginInvalid":"Došlo k chybě při vytváření účtu. Zkuste jiné úživatelské jméno. ","ui.account.submit":"Vytvořit účet","ui.account.usePassword":"Použít heslo pro příhlášení","ui.account.usePasskey":"Použít passkey pro přihlášení","ui.account.totpHeadline":"Dvoufaktorové ověření","ui.account.totpDescription":"Aktivujte prosím dvoufaktorové ověření, které přidá vašemu uživatelskému účtu další bezpečnostní úroveň. To znamená, že budete muset navíc zadat ověřovací kód generovaný dvoufaktorovými aplikacemi jako 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator nebo jakoukoli jinou TOTP aplilkací.","ui.account.totpSetup":"Nastavit nyní","ui.account.totpSkip":"Nastavit později","ui.account.login":"Odmítnout pozvání","ui.account.contribute1":"Contao a Správce Contaa je podporovaný neziskovou Contao Association.","ui.account.contribute2":"Prosím zvažte, zda se chcete stát členem a spolupracovníkem tohoto open source projektu {becomingAMember}.","ui.account.contributeDonate":"Staňte se dárcem","ui.login.headline":"Přihlásit se","ui.login.description":"Přihlaste se, abyste mohli spravovat Vaši instalaci.","ui.login.username":"Uživatelské jméno","ui.login.password":"Heslo","ui.login.totpHeadline":"Dvoufaktorové ověření","ui.login.totpDescription":"Zadejte prosím doufaktorový kód, abyste dokončili přihlášení.","ui.login.totp":"Ověřovací kód","ui.login.forgotPassword":"Zapomněli jste heslo?","ui.login.button":"Přihlásit se","ui.login.passkey":"Přihlásit se pomocí passkey","ui.login.cancel":"Zrušit","ui.login.locked":"Přístup byl zamítnut, protože je Správce Contaa uzamčen. Pro odemknutí smažte soubor {lockFile} na Vašem serveru v kořenové složce Contaa.","ui.logout.headline":"Vypršení sezení","ui.logout.warning":"Byli jste neaktivní po dobu 25 minut. Z bezpečnostních důvodů bude Vaše sezení zakrátko ukončené. ","ui.logout.expired":"Vaše sezení bylo automaticky ukončeno, protože jste byli neaktivní více než 30 minut.","ui.logout.renew":"Zůstat přihlášený/á","ui.logout.logout":"Odhlásit","ui.logout.login":"Zpátky k přihlášení","ui.oauth.error":"Neplatný pokus o ověření totožnosti. Zkontrolujte požadované parametry.","ui.oauth.https":"Přeposílací URL musí používat zabezpečený protokol (https), aby nedošlo k přenosu autorizačního kódu v čirém textu.","ui.oauth.headline":"Smazat autorizaci","ui.oauth.description":"Následující aplikace nebo servis požadují vzdálený přístup k Vašemu Správci Contaa. ","ui.oauth.domain":"Ještě než povolíte přístup, ujistěte se, že znáte tuto URL a důvěřujete jejímu majiteli!","ui.oauth.outOfScope":"Bohužel nemáte potřebné přihlašovací práva, abyste se mohl(a) přihlásit.","ui.oauth.allow":"Povolit přístup","ui.oauth.deny":"Odmítnout přístup","ui.oauth.switchUser":"Přejít na jiného uživatele","ui.scope.admin":"Přístup správce včetně správy uživatelů","ui.scope.install":"Nainstalovat nové balíčky a změnit konfiguraci Contaa","ui.scope.update":"Aktualizovat balíčky a provést úkoly údržby","ui.scope.read":"Načíst balíčky a nastavení","ui.boot.headline":"Kontrola systému","ui.boot.description":"Prosím počkejte, analyzujeme Váš server...","ui.boot.issue1":"Byly zjištěny chyby","ui.boot.issue2":"Vaše instalace obsahuje několik chyb a je ji třeba opravit, než se bude moct použít Správce Contaa.","ui.boot.run":"Spustit Správce Contaa","ui.boot.safeMode":"Spustit v Bezpečnostním módu","ui.recovery.headline":"Záchrana systému","ui.recovery.description":"Správce Contaa našel soubory, které vypadají jako soubory Contaa, ale Příkazový řádek nepracuje tak, jak by měl.","ui.recovery.console":"Výstup konzoly","ui.recovery.repairOptions":"Vyberte prosím jednu z možností pro zotavení Vaší instalace.","ui.recovery.repairHeadline":"Automatická oprava","ui.recovery.repairDescription":"Bude provedené automatické opravení instalace tím, že se přestaví meziúložiště a přeinstalují se balíčky závislé na Composeru.","ui.recovery.repairWarning":"Veškeré úpravy provedené na souborech ve složce vendor budou ztraceny!","ui.recovery.repairFailed":"Automatická oprava neproběhla úspěšně. Pro opravení instalace se pokuste se použít Bezpečnostní mód.","ui.recovery.repairButton":"Spustit opravu systému","ui.recovery.safeModeHeadline":"Bezpečnostní mód","ui.recovery.safeModeDescription":"Spuštěním Správce Contaa v Bezpečnostním módu lze spravovat balíčky a spouštět základní příkazy/úlohy, nejsou ovšem dostupné funkce závislé na instalaci Contaa.","ui.recovery.safeModeButton":"Spustit v Bezpečnostním módu","ui.server.pending":"Čekám…","ui.server.running":"Analyzování…","ui.server.error":"Kontrola selhala kvůli neočekávané odezvě ze strany serveru.","ui.server.details":"Podrobnosti","ui.server.prerequisite":"Kontrola zrušena kvůli chybějící podmínce.","ui.server.selfUpdate.title":"Aktualizace Správce Contaa","ui.server.selfUpdate.update":"Je k dispozici nová verze Správce Contaa {latest}.","ui.server.selfUpdate.manualUpdate":"Je dostupná nová verze Správce Contaa {latest}. Váš server nepodporuje automatické instalace. Stáhněte si proto prosím novou verzi {download}.","ui.server.selfUpdate.latest":"Používáte poslední verzi {current}.","ui.server.selfUpdate.dev":"Vývojové verze nepodporují automatické aktualizace.","ui.server.selfUpdate.unsupported":"Je dostupná novější verze, ale ta nepodporuje Vaši verzi PHP.","ui.server.selfUpdate.button":"Spustit automatické aktualizace","ui.server.selfUpdate.continue":"Pokračovat","ui.server.config.title":"Nastavení serveru","ui.server.config.setup":"Nastavit","ui.server.config.change":"Změnit","ui.server.config.save":"Uložit","ui.server.config.cancel":"Zrušit","ui.server.config.customOption":"Jíné…","ui.server.config.description":"Pro správný běh úloh na pozadí potřebuje Správce Contaa vědět, kde může najít binární příkazový řádek PHP a jak spouštět příkazy odděleně od webové stránky. ","ui.server.config.formTitle":"Nastavení serveru","ui.server.config.formText":"Zadejte prosím cestu k binární PHP. Ujistěte se, že je binární soubor stejný jako Vámi používaná verze PHP. ","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud umožňuje nainstalovat na Composeru závislých rozšířeních, i když Váš server nemá dostatek paměti. Mějte na paměti, že informaci o Vaši balíčcích budou odeslané na cloudový server vlastněný Asociací Contaa.","ui.server.config.cloud":"Použít Composer Resolver Cloud","ui.server.config.cli":"Binární PHP","ui.server.config.stateErrorCli":"Na Vašem serveru nebyla nalezena žádná platná binární PHP.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud není podporován.","ui.server.config.stateSuccess":"Binární PHP na {php_cli}.","ui.server.php_web.title":"Webový proces PHP","ui.server.php_web.below7":"Byla nalezena následující verze PHP {version}. Prosím přejděte co nejdříve na PHP 7. ","ui.server.php_web.success":"Byla nalezena následující verze PHP {version}, nejsou známé žádné chyby.","ui.server.php_cli.title":"Rozhraní příkazového řádku PHP","ui.server.php_cli.success":"Byla nalezena následující verze PHP {version}, nejsou známé žádné chyby.","ui.server.composer.title":"Prostředí Composeru","ui.server.composer.success":"Nebyly nalezeny žádné chyby.","ui.server.composer.install":"Věci závislé na Composorovi nejsou nainstalované.","ui.server.composer.button":"Nainstalovat","ui.server.contao.title":"Instalace Contaa","ui.server.contao.setup":"Nastavení","ui.server.contao.check":"Zkontrolovat databázi","ui.server.contao.empty":"Nebyla nalezena žádná instalace Contaa.","ui.server.contao.old":"Verze Contaa {version} není kompatabilní se Správcem Contaa. Zaktualizujte prosím Vaši instalaci manuálně.","ui.server.contao.found":"Nalezeno Contao {version} (verze API {api})","ui.server.contao.connectionError":"Nepodařilo se připojit k serveru databáze.","ui.server.contao.connectionProblem":"Nalezen problém s databází.","ui.server.contao.missingUser":"Nebyl nalezen žádný administrační účet.","ui.setup.continue":"Pokračovat","ui.setup.manager":"Spustit Správce Contaa","ui.setup.cancel":"Zrušit","ui.setup.welcome":"Vítejte","ui.setup.welcome1":"Tento průvodce Vás provede důležitými kroky pro nastavení instalace CMS Contao.","ui.setup.welcome2":"Pokud máte jakýkoli dotaz, prohlédněte si prosím dokumentaci, fóra, kanál Slacku nebo se obraťte na stránku {podpory}.  ","ui.setup.support":"podpora komunity","ui.setup.start":"Začít","ui.setup.complete":"Blahopřejeme!","ui.setup.complete1":"Úspěšně byla nainstalována {version} Contaa.","ui.setup.complete2":"Pro ukončení tohoto procesu otevřete prosím instalační nástroj, abyste nastavili připojení k databázi a vytvořili účet administrátora.","ui.setup.complete3":"Nyní můžete začít vytvářet Vaši webovou stránku v backendu Contaa. Potřebujete-li dodatečná rozšíření, vraťte se do Správce Contaa.","ui.setup.installTool":"Otevřít instalační nástroj","ui.setup.login":"Přihlásit se do Contaa","ui.setup.funding":"Volný software je \\"volný\\" jako \\"volný projev\\", ale ne jako \\"pivo zdarma\\". Open source projekt jako Contaa vyžaduje řadu peněz a nedá se ho uskutečnit bez jediné osoby nebo firmy. \\nPokud máte vytvořenou webovou stránku pomocí Contaa nebo je prodáváte, potěšilo by nás, kdybyste nás finančně podpořili poměrně k Vašemu obchodu.","ui.setup.fundingLink":"Dozvědět se víc","ui.setup.document-root.headline":"Nastavení webového serveru","ui.setup.document-root.warning":"Abyste mohli nainstalovat Contao prostřednictvím Správce Contaa, musíte opravit kořenový dokument na webovém serveru.","ui.setup.document-root.description1":"Contao používá zvláštní složku pro veřejné soubory. Aplikační soubory jsou nainstalované v rodičovské složce. Contao právě nelze nainstalovat, protože Vaše složková struktura není správná nebo složky nejsou prázdné.","ui.setup.document-root.description2":"Pokud nevíte, jak nastavit kořenový dokument, přečtěte si prosím dokumentaci Contaa nebo se obraťte na svého poskytovatele webových služeb.","ui.setup.document-root.documentation":"Přečíst si dokumentaci","ui.setup.document-root.conflictsTitle":"Instalační složka není prázdná","ui.setup.document-root.conflictsDirectory":"Kořenová složka Vaší budoucí instalace Contaa není prázdná. Našli jsem následující počet souborů {count}, které se musí přepsat během instalace. Doporučujeme vytvořit prázdnou složku pro instalaci Contaa, nebo můžete také smazat veškeré věci, které se právě nachází ve vybrané složce, pokud jste si jistí, že je již nepotřebujete. ","ui.setup.document-root.ignoreConflicts":"Chci nainstalova Contao do nevyprázděné složky. Souhlasím s tím, že budou dané soubory přepsány. ","ui.setup.document-root.check":"Znovu zkontrolovat","ui.setup.document-root.create":"Vytvořit složky","ui.setup.document-root.change":"Změnit složky","ui.setup.document-root.formTitle":"Nastavení adresáře","ui.setup.document-root.formText1":"Správce Contaa může automaticky vytvořit novou adresářovou strukturu na tomto webovém serveru.","ui.setup.document-root.formText2":"Budete muset nastavit nový kořenový dokument (např. pomocí správního panelu ve Vašem účtu webových služeb).","ui.setup.document-root.autoconfig":"Rozumím tomu, že musím změnit nastavení serveru. Pokud se tak nestane, může dojít k poruše Správce Contaa a poničení souborů nastavení (včetně podrobností k účtu a heslu)!","ui.setup.document-root.directory":"Nový adresář","ui.setup.document-root.currentRoot":"Současný kořenový dokument","ui.setup.document-root.newRoot":"Nový kořenový dokument","ui.setup.document-root.finish":"Nastavení adresářů","ui.setup.document-root.publicDir":"Použijte {dir} pro veřejné soubory (pro Contao {version})","ui.setup.document-root.directoryInvalid":"Zadejte prosím platný název adresáře","ui.setup.document-root.directoryExists":"Cílový adresář již existuje. Zadejte prosím jiný název.","ui.setup.document-root.confirmation":"Správce Contaa úspěšně vytvořil potřebný adresář pro instalaci Contaa. Nyní musíte nastavit kořenový dokument na svém webovém serveru. Nenačítejte tuto stránku do té doby.","ui.setup.document-root.reload":"Načíst stránku znovu","ui.setup.document-root.success":"Struktura složek je nastavená na Vašem serveru správně!","ui.setup.document-root.installingProjectDir":"Aplikační soubory se nainstalují do {dir}.","ui.setup.document-root.installingPublicDir":"Veřejné soubory se nainstalují do {dir}.","ui.setup.document-root.installedProjectDir":"Aplikační soubory jsou nainstalované v {dir}.","ui.setup.document-root.installedPublicDir":"Veřejné soubory jsou nainstalované v {dir}.","ui.setup.create-project.headline":"Instalace Contaa","ui.setup.create-project.description":"Vývoj Contaa se drží principů {semver}, nová menší verze vychází každých šest měsíců. Současná verze, která se udržuje, je:","ui.setup.create-project.semver":"Sémantické číslování verzí","ui.setup.create-project.latestTitle":"Poslední","ui.setup.create-project.ltsTitle":"Několikaletá podpora - Long Term Support","ui.setup.create-project.latestQ1":"Naše poslední verze nabízí nejnovější funkce s podporou do února {year}.","ui.setup.create-project.latestQ3":"Naše poslední verze nabízí nejnovější funkce s podporou do srpna {year}.","ui.setup.create-project.ltsText":"Naše současná verze LTS, chcete-li se zaměřit na stabilitu. Nabízí dlouhodobou podporu do února {year}.","ui.setup.create-project.pltsText":"Naše předešlá verze LTS má podporu do února {year}.","ui.setup.create-project.requiresPHP":"Vyžaduje přinejmenším PHP {version}, používáte PHP {current}.","ui.setup.create-project.releaseplan":"Více informací: {contaoReleasePlan} ","ui.setup.create-project.releaseplanLink":"Plán vydávání nových verzí Contaa","ui.setup.create-project.installed":"Contao {version} je úspěšně nainstalována na vašem serveru. Pokračujte, abyste nastavili vaši databázi nebo spustili Správce Contaa pro nainstalování jiné verze.","ui.setup.create-project.formTitle":"Vyberte distribuci","ui.setup.create-project.formText":"Vyberte prosím verzi, kterou chcete nainstalovat.","ui.setup.create-project.version":"Verze","ui.setup.create-project.demo":"Nainstalovat demoverzi Contaa","ui.setup.create-project.demoDescription":"Demoverze vám pomůže se seznámit s Contaa a pochopit jeho základní fukce. Více předloh můžete najít v {store}.","ui.setup.create-project.coreOnly":"Minimální instalace (pouze jádro)","ui.setup.create-project.noUpdate":"Přeskočit instalaci (pouze pro pokročilé!)","ui.setup.create-project.theme":"Předloha Contaa","ui.setup.create-project.themeInstall":"Abyste nainstalovali předlohu Contaa, použijte vyhledávací políčko nebo načtete soubor (.cto/.zip), který podporuje instalace pomocí Správce Contaa.","ui.setup.create-project.themeBuy":"Podívejte se na další předlohy v obchodě {store}.","ui.setup.create-project.themeStore":"Obchod předloh Contaa","ui.setup.create-project.themeUpload":"Načíst soubor předlohy (.cto/.zip)","ui.setup.create-project.themeInvalid":"Načtený soubor není předloha Contaa nebo ho Správce Contaa nepodporuje.","ui.setup.create-project.themeWarning":"Správce Contaa nemůže říct, jestli je tato předloha kompatibilní s vaším serverem. Podívejte se prosím na informace předlohy pro získání dalších informací.","ui.setup.create-project.themeTitle":"Podívat se na hodnocení předlohy","ui.setup.create-project.themeDetails":"Následující závislosti a soubory se nainstalují spolu s vybranou předlohou.","ui.setup.create-project.themeRequire":"{count} závilostí | {count} závislostí","ui.setup.create-project.themeFiles":"{count} soubor | {count} souborů","ui.setup.create-project.theme.or":"nebo prohledejte veřejně dostupné předlohy","ui.setup.create-project.theme.search":"Prohledat předlohy","ui.setup.create-project.theme.more":"Více předloh","ui.setup.create-project.theme.empty":"Nenalezeny žádné předlohy pro {query}","ui.setup.create-project.theme.uploaded":"Soubory předlohy byly úspěšně nahrány.","ui.setup.create-project.theme.packageName":"Název balíčku","ui.setup.create-project.theme.version":"Verze","ui.setup.create-project.theme.authors":"Autor/Autoři","ui.setup.create-project.install":"Nainstalovat","ui.setup.create-project.cancel":"Zrušit","ui.setup.database-connection.headline":"Připojení k databázi","ui.setup.database-connection.description":"Contao vyžaduje přinejmenším jednu databázi MySQL (nebo kompatibilní druh jako MariaDB) pro ukládání stránek, obsahu, uživatelů a příslušných dat. Přihlašovací údaje jsou uložené v souboru {env} v kořenové složce instalace Contaa.","ui.setup.database-connection.formTitle":"Připojovací údaje","ui.setup.database-connection.formText":"Zadejte prosím cestu k databázi nebo vyplňte zvlášť uživatelské jméno, heslo, server a pole databáze.","ui.setup.database-connection.url":"Cesta k databázi","ui.setup.database-connection.validUrl":"Cesta k databázi je neplatná nebo selhalo spojit se se serverem.","ui.setup.database-connection.or":"nebo","ui.setup.database-connection.user":"Uživatelské jméno","ui.setup.database-connection.password":"Heslo","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Jméno databáze","ui.setup.database-connection.connected":"Došlo k úspěšnému připojení k {database} na {server}.","ui.setup.database-connection.error":"Při připojení k databázi došlo k chybě.","ui.setup.database-connection.problem":"Contao zjistil problém s Vaší serverovou databází.","ui.setup.database-connection.schemaTitle":"Databázové schéma","ui.setup.database-connection.migration":"Existuje jedna nedokončená migrace. | Existují následující nedokončené migrace: {count}.","ui.setup.database-connection.schema":"Existuje jedna nedokončená schematická aktualizace. | Existují následující nedokončené schematické aktualizace: {count}.","ui.setup.database-connection.noChanges":"Vaše databáze je aktuální. ","ui.setup.database-connection.check":"Zkontrolovat databázi","ui.setup.database-connection.skip":"Přeskočit","ui.setup.database-connection.save":"Uložit","ui.setup.database-connection.change":"Změnit pověření","ui.setup.database-connection.restoreTitle":"Import databáze","ui.setup.database-connection.restoreText":"Předlohu, kterou jste právě nainstalovali, obsahuje již připravenou databázi s definovaným obsahem. Pokud ji chcete nahrát a začít tak používat Contao s již definovaným obsahem, nahrajte danou databázi, nebo přeskočte tento krok. | Předlohu, kterou jste právě nainstalovali, obsahuje několik připravených databází s již definovaným obsahem. Pokud je chcete nahrát a začít tak používat Contao s již definovaným obsahem, nahrajte dané databázi, nebo přeskočte tento krok","ui.setup.database-connection.backup":"Uložit současnou databázi před importem.","ui.setup.database-connection.backupWarning":"Veškerá data budou v databázi přepsána! Ponejprv si uložte současnou databázi, pokud již není prázdná.","ui.setup.database-connection.restore":"Importovat předlohu databáze","ui.setup.database-connection.restoreOption":"Uložená databáze {date} ({size})","ui.setup.database-connection.restored":"Vaše databáze byla úspěšně importovaná. Pokračujte prosím, abyste provedli aktualizaci schématu databáze.","ui.setup.backend-user.success":"Ve vaší databázi byl nalezen jeden administrátorský účet pro backend Contaa. Pokud si přejete přidat další účty, přihlašte se do backendu Contaa a vytvořte je v sekci Uživatelé.","ui.setup.backend-user.error":"Nebylo možné najít jakýkoli seznam uživatelů. Zkontrolujete prosím výstup příkazového řádku.","ui.setup.backend-user.headline":"Účet backendu","ui.setup.backend-user.description":"Abyste mohli spravovat Vaši webovou stránku, musíte vytvořit alespoň jeden administrativní účet. Uvědomte si prosím, že tento účet není stejný pro přihlášení do Správce Contaa. ","ui.setup.backend-user.formTitle":"Vytvořit účet","ui.setup.backend-user.formText":"Zadejte prosím údaje pro nový účet backendu.","ui.setup.backend-user.username":"Uživatelské jméno","ui.setup.backend-user.name":"Jméno","ui.setup.backend-user.email":"Mailová adresa","ui.setup.backend-user.emailInvalid":"Zadejte prosím platnou mailovou adresu","ui.setup.backend-user.password":"Heslo","ui.setup.backend-user.passwordPlaceholder":"min. 8 znaků","ui.setup.backend-user.passwordLength":"Zadejte prosím nejméně 8 znaků.","ui.setup.backend-user.create":"Přidat účet","ui.task.headline":"Úloha na pozadí","ui.task.loading":"Načítání podrobností...","ui.task.created":"Načítání podrobností...","ui.task.active":"Počkejte prosím, zatímco Spráce Contaa na pozadí vyřizuje operační úlohy.","ui.task.complete":"Všechny operace byly úspěšně provedené. Další podrobnosti získáte v protokolu konzoly.","ui.task.aborting":"Počkejte prosím, zatímco se na pozadí zastavují operace.","ui.task.stopped":"Některé z operačních úloh byly zrušené. Zkontrolujte prosím protokol konzoly.","ui.task.error":"Příkaz na pozadí byl znenadání zastaven. Zkontrolujte prosím protokol konzoly.","ui.task.failed":"Správci Contaa se nepodařilo spustit úlohu!","ui.task.failedDescription1":"Něco se pokazilo, zatímco probíhaly úlohy na pozadí.","ui.task.failedDescription2":"Pokud se to bude opakovat, nejspíš není Váš server podporovaný.","ui.task.reportProblem":"Oznámit problém","ui.task.sponsor":"Cloud Composeru spozorován: {sponsor}","ui.task.buttonAudit":"Zaktualizovat dabázi","ui.task.buttonClose":"Zavřít","ui.task.buttonConfirm":"Potvrdit a zavřít","ui.task.buttonCancel":"Zrušit","ui.task.confirmCancel":"Jste si jistí, že chcete zrušit tuto úlohu? To může zanechat instalaci Contaa v špatném stavu!","ui.task.autoclose":"Zavřít podrobnosti o úloze po úspěšném dokončení","ui.console.toggle":"Zobrazit/skrýt výstup příkazového řádku","ui.console.showLog":"Zobrazit celý protokol konzoly","ui.console.copyLog":"Zkopírovat protokol do schránky.","ui.migrate.headline":"Aktualizace databáze","ui.migrate.migrationsOnly":"(pouze migrace)","ui.migrate.schemaOnly":"(pouze schémata)","ui.migrate.loading":"Prosím počkejte, analyzujeme Vaši databázi...","ui.migrate.empty":"Nebyl nalezené žádné aktualizace pro migraci nebo schémata. Vaši databáze je aktuální.","ui.migrate.emptyMigrations":"Nebyla nalezené žádné nedokončené migrace. Ujistěte se prosím, zda není potřeba také zaktualizovat schémata.","ui.migrate.emptySchema":"Nebyla nalezené žádné nedokončené schémata. Ujistěte se prosím, zda není potřeba také zaktualizovat migrace.","ui.migrate.pending":"Vaše databáze není aktuální. Prohlídněte si prosím níže konzolu a zaktualizujte Vaši databázi.","ui.migrate.previousChanges":"Předešlá migrace nebyla potvrzená.\\nProhlédněte si prosím níže výsledky v konzole a pak proveďte potřebné změny.","ui.migrate.previousComplete":"Předešlá migrace nebyla potvrzená. Prohlédněte si prosím níže výsledky v konzole.\\nExistuje několik nedokončených změn.","ui.migrate.appliedChanges":"Databáze byla zaktualizovaná. \\nProhlédněte si prosím níže výsledky v konzole, pak pokračujte dalšími kroky, abyste provedli další změny. ","ui.migrate.appliedComplete":"Databáze byla zaktualizovaná. \\nNeexistují žádné další nedokončené migrace nebo schémata. Vaše databáze je aktuální. ","ui.migrate.problem":"Contao zjistil problém s Vaším databázovým serverem. \\nProhlédněte si prosím níže výsledky v konzole, abyste se dozvěděli více o tom, co je potřeba opravit. | Contao zjistil problém s Vaším databázovým serverem. \\nProhlédněte si prosím níže výsledky v konzole, abyste se dozvěděli více o tom, co je potřeba opravit. ","ui.migrate.warning":"Contao zjistil nesprávné nastavení Vašeho databázového serveru. \\nVarování lze dočasně přeskočit, měly by se ale opravit, aby docházelo k dobrému výkonu a zacházení s daty. ","ui.migrate.error":"Změny nelze provést. Vaše databáze se možná změnila. Zkontrolujte to prosím ještě jednou a proveďte daný krok ještě jednou.","ui.migrate.execute":"Provést","ui.migrate.close":"Zavřít","ui.migrate.confirm":"Potvrdit a zavřít","ui.migrate.cancel":"Zrušit","ui.migrate.continue":"Pokračovat","ui.migrate.setup":"Nastavení","ui.migrate.skip":"Přeskočit","ui.migrate.retry":"Znovu zkontrolovat","ui.migrate.retryAll":"Vybrat vše","ui.migrate.withDeletes":"Provést všechny změny databáze včetně příkazu ke smazání. ","ui.migrate.migrationTitle":"Migrace databáze","ui.migrate.schemaTitle":"Schématická aktualizace","ui.migrate.problemTitle":"Problémy databáze","ui.migrate.warningTitle":"Varování databáze","ui.migrate.addTable":"Přidat tabulku {table}","ui.migrate.dropTable":"Odstranit tabulku {table}","ui.migrate.addField":"Přidat pole {table}. {field}","ui.migrate.changeField":"Změnit pole {table}.{field}","ui.migrate.dropField":"Odstranit pole {table}.{field}","ui.migrate.createIndex":"Vytvořit index \\"{name}\\" v {table}","ui.migrate.dropIndex":"Odstranit index \\"{name}\\" v {table}","ui.widget.mandatory":"Toto pole nesmí být prázdné.","ui.widget.blankOption":"Vyberte prosím…","ui.widget.showPassword":"Zobrazit heslo","ui.widget.hidePassword":"Skrýt heslo","ui.error.title":"Požadavek HTTP pro \\"{method} {url}\\" selhal.","ui.error.server500":"Vypadá to, že došlo k nečekané chybě na Vašem webovém serveru. Zkontrolujte prosím protokolové soubory na serveru (Apache/Nginx) a protokol Správce Contaa v \\"contao-manager/logs\\".","ui.error.response":"Server odpověděl statusovým kódem {status}.","ui.error.moreLink":"Více informací","ui.error.support":"Podpora Contaa","ui.error.permission":"Nemáte povolení pro použití této funkce.","ui.footer.help":"Nápověda","ui.footer.reportProblem":"Oznámit problém","ui.navigation.discover":"Prohlédnout","ui.navigation.packages":"Balíčky","ui.navigation.tools":"Nástroje","ui.navigation.installTool":"Instalační nástroj","ui.navigation.backend":"Backend Contaa","ui.navigation.debug":"Debugový mód Contaa","ui.navigation.logViewer":"Prohlížeč protokolu","ui.navigation.phpinfo":"Informace o PHP","ui.navigation.phpinfoLoading":"Načítání informací o PHP…","ui.navigation.maintenance":"Údržba","ui.navigation.rebuildCache":"Přetvoření meziúložiště","ui.navigation.users":"Účty","ui.navigation.systemCheck":"Kontrola systému","ui.navigation.advanced":"Rozšířené","ui.navigation.logout":"Odhlásit","ui.maintenance.database.title":"Migrace databáze","ui.maintenance.database.description":"Migrace databáze zajišťuje konzistentní data a tabulková schémata.","ui.maintenance.database.migrations":"Jedna nedokončená migrace databáze | Počet nedokončených migrací databáze {count} ","ui.maintenance.database.schemaUpdates":"Jedna nedokončená schématická aktualizace | Počet nedokončených schematických aktualizací {count} ","ui.maintenance.database.error":"Nalezen problém s databází.","ui.maintenance.database.warning":"Byly nalezená varování databáze.","ui.maintenance.database.button":"Zkontrolovat databázi","ui.maintenance.database.migrationOnly":"Vybrat pouze migrace","ui.maintenance.database.schemaOnly":"Vybrat pouze schémata","ui.maintenance.database.installTool":"Otevřít instalační nástroj","ui.maintenance.database.createBackup":"Vytvořit uložení databáze","ui.maintenance.database.backupUnsupported":"Ukládání databází není vaší verzí Contaa podporováno.","ui.maintenance.database.backupList":"Máte pouze jednou uloženou vaší databázi, a sice {date}. | Počet uložených databází {count}. Naposledy byla uložená {date}.","ui.maintenance.database.backupEmpty":"Momentálně nemáte žádné uložené databáze.","ui.maintenance.rebuildCache.title":"Meziúložiště aplikace","ui.maintenance.rebuildCache.description":"Přetvoření meziúložiště aplikace je nutné provést po každé změně konfiguračních souborů. ","ui.maintenance.rebuildCache.rebuildProd":"Přetvořit produktivní meziúložiště ","ui.maintenance.rebuildCache.rebuildDev":"Přetvořit vývojářské meziúložiště ","ui.maintenance.rebuildCache.clearProd":"Vyprázdnit produktivní meziúložiště ","ui.maintenance.rebuildCache.clearDev":"Vyprázdnit vývojářské meziúložiště ","ui.maintenance.installTool.title":"Instalační nástroj Contaa","ui.maintenance.installTool.description":"Instalační nástroj Contaa se automaticky uzamkne, pokud nesprávně zadáte heslo třikrát po sobě. ","ui.maintenance.installTool.unlock":"Odemknout Instalační nástroj","ui.maintenance.installTool.lock":"Uzamknout Instalační nástroj","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"Composer autoloader je zodpovědný za načítání tříd PHP. Autoloader musí být spuštěný po přidání vlastních namespace do kořenové composer.json.","ui.maintenance.dumpAutoload.button":"Spustit Autoloadera","ui.maintenance.composerInstall.title":"Na Compseru závislá rozšíření","ui.maintenance.composerInstall.description":"Na Composeru závislá rozšíření se nachází ve složce {vendor} Vaší instalace. Přeinstalování těchto závislostí může být důležité po manipulaci nebo manuálnímu přenosu souboru {composerLock}.","ui.maintenance.composerInstall.button":"Spustit instalátor","ui.maintenance.composerInstall.update":"Spustit aktualizaci Composeru","ui.maintenance.composerCache.title":"Meziúložiště Composeru","ui.maintenance.composerCache.description":"Meziúložiště Composeru stáhla balíčky, aby zlepšily výkonost. Pokud máte potíže jako poničené soubory, pokuste se smazat meziúložiště Composeru, abyste vyvolali nové stáhnutí. ","ui.maintenance.composerCache.button":"Smazat meziúložiště","ui.maintenance.maintenanceMode.title":"Mód údržby","ui.maintenance.maintenanceMode.description":"Když se spustí mód údržby, zobrazí se předloha pro \\"503 service Unavailable\\".","ui.maintenance.maintenanceMode.enable":"Aktivovat","ui.maintenance.maintenanceMode.disable":"Deaktivovat","ui.maintenance.debugMode.title":"Vývojářský mód","ui.maintenance.debugMode.description":"Aktivujte vývojářský mód zadáním uživatele a hesla pro {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Aktivujte vývojářský mód nastavením vývojářské cookie pro danou doménu.","ui.maintenance.debugMode.activate":"Aktivovat","ui.maintenance.debugMode.deactivate":"Deaktivovat","ui.maintenance.debugMode.credentials":"Uživatelské informace","ui.maintenance.debugMode.user":"Zadejte prosím uživatelské jméno pro vývojářský mód.","ui.maintenance.debugMode.password":"Zadejte prosím heslo pro uživatele vývojářského módu.","ui.maintenance.opcodeCache.title":"Operační kód mezinúložiště","ui.maintenance.opcodeCache.description":"Operační kód meziúložiště souborů PHP dokáže rychleji zpracovat data. Musí být smazán za určitých podmínek, pokud se nepodařilo rozpoznat soubory po jejich změně.","ui.maintenance.opcodeCache.button":"Zkrátit meziúložiště","ui.maintenance.safeMode":"Není to dostupné v Bezpečnostním módu","ui.maintenance.unsupported":"Nepodporované Vaší verzí Contaa. ","ui.packages.updateButton":"Zaktualizovat balíčky","ui.packages.searchButton":"Vyhledat balíčky","ui.packages.searchPlaceholder":"Hledají se balíčky…","ui.packages.uploadOverlay":"Přetáhněte a pusťte soubory, které chcete nahrát","ui.packages.uploadButton":"Nahrát balíčky","ui.packages.uploadMessage":"Máte jeden nepotvrzený přenos. | Máte celkem {count} nepotvrzených přenosů.","ui.packages.uploadApply":"Potvrdit nahrání","ui.packages.uploadReset":"Smazat nahráné soubory","ui.packages.uploadIncomplete":"Tyto soubory nebyly zcela nahrány. Smažte je prosím a zkuste to znovu.","ui.packages.uploadDuplicate":"Zdá se, že byly tyto soubory nahrány několikrát. Smažte prosím dané duplikáty.","ui.packages.uploadInstalled":"Tento soubor je již nainstalovaný. Smažte prosím daný duplikát.","ui.packages.uploadUnsupported":"Nahrávání souborů není ve Vaší instalaci podporováno. Ujistěte se prosím, zda je funkce PHP ZIP nainstalovaná a zaktualizujte veškeré závislosti.","ui.packages.changesMessage":"Máte jednu nepotvrzenou změnu. | Máte celkem {count} nepotvrzených změn.","ui.packages.changesDryrun":"Zkouška nanečisto","ui.packages.changesApply":"Provést změny","ui.packages.changesApplyAll":"Zaktualizovat všechny balíčky","ui.packages.changesDryrunAll":"Vyzkoušet všechny balíčky nanečisto","ui.packages.changesReset":"Vrátit změny","ui.packages.changesReview":"Ukázat změny","ui.packagelist.loading":"Spouštění…","ui.packagelist.uploads":"Nahrání/přenos souborů","ui.packagelist.added":"Nové balíčky","ui.packagelist.installed":"Nainstalované balíčky","ui.package.hintRevert":"Vrátit změny","ui.package.hintNoupdate":"Neaktualizovat","ui.package.hintConstraint":"Tento balíček bude nainstalovaný s omezením {constraint}, pokud provedete změny.","ui.package.hintConstraintBest":"Tento balíček bude nainstalovaný v nejnověji dostupné verzi, pokud provedete změny.","ui.package.hintConstraintChange":"Toto omezení pro tento balíček bude změněno z \\"{from}\\" na \\"{to}\\", pokud provedete změny.","ui.package.hintConstraintUpdate":"Tento balíček bude zaktualizovaný, pokud aplikujete tyto změny.","ui.package.hintAdded":"Tento balíček bude nainstalovaný, když aplikujete tyto změny.","ui.package.hintRemoved":"Tento balíček bude smazaný, pokud provedete změny.","ui.package.requiredTitle":"přidáno manuálně","ui.package.requiredText":"Tento balíček je už sice uvedený ve Vašem souboru composer.json, ale ještě není nainstalovaný.","ui.package.removedTitle":"odstaněno manuálně","ui.package.removedText":"Tento balíček byl odstraněn z Vašeho souboru composer.json.","ui.package.installed":"Momentálně nainstalováno:","ui.package.version":"Verze {version}","ui.package.additionalDownloads":"{count} Stažení | {count} Stažení","ui.package.additionalStars":"{count} Hvězda | {count} hvězd","ui.package.editConstraint":"Upravit","ui.package.uploadConstraint":"Toto omezení je nadefinováno nahraným balíčkem.","ui.package.updateButton":"Zaktualizovat","ui.package.removeButton":"Smazat","ui.package.installButton":"Přidat balíček","ui.package.installButtonShort":"Přidat","ui.package.detailsButton":"Podrobnosti","ui.package.latestConstraint":"poslední verze","ui.package.update":"Existuje nová aktualizace","ui.package.updateLatest":"poslední verze","ui.package.updateAvailable":"{version}","ui.package.updateUnknown":"neznámá verze","ui.package.updateConstraint":"Je k dispozici nová verze než ta, kterou právě používáte.","ui.package.incompatible":"{package} nefunguje s Contao {constraint}.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Verze {version}","ui.cloudStatus.waitingTime":"Doba čekání","ui.cloudStatus.jobs":"Současné úlohy","ui.cloudStatus.workers":"Účastníků","ui.cloudStatus.approx":"{minutes} min.","ui.cloudStatus.none":"ne","ui.cloudStatus.short":"ca. {minutes} min.","ui.cloudStatus.long":"ca. {minutes} min. {seconds} sek.","ui.cloudStatus.error":"Nebylo možné získat status Composer Resolver Cloud. Může být zrovna neaktivní nebo má nějaké problémy.","ui.cloudStatus.button":"Status Cloudu","ui.cloudStatus.refresh":"Znovu načíst status Cloudu","ui.log-viewer.loading":"Spouštění…","ui.log-viewer.empty":"Na Vašem serveru se nenacházejí žádné protokolové soubory.","ui.log-viewer.reload":"Načíst znovu","ui.log-viewer.file":"Protokolový soubor","ui.log-viewer.channel":"Kanál","ui.log-viewer.channelTitle":"Kanál zpráv byl přihlášen.","ui.log-viewer.level":"Úroveň","ui.log-viewer.levelTitle":"Vážnost protokolované zprávy.","ui.log-viewer.timeHeader":"Čas","ui.log-viewer.messageHeader":"Zpráva","ui.log-viewer.showContext":"Zobrazit kontext","ui.log-viewer.hideContext":"Skrýt kontext","ui.log-viewer.showExtra":"Zobrazit extra","ui.log-viewer.hideExtra":"Smazat extra","ui.log-viewer.more":"Dozvědět se víc...","ui.log-viewer.download":"Stáhnout","ui.log-viewer.downloadTitle":"Stáhnout soubor \\"{file}\\"","ui.log-viewer.prodEnvironment":"Produktivní prostředí","ui.log-viewer.devEnvironment":"Vývojářské prostředí (vychytávací mód)","ui.user-manager.loading":"Načítám uživatele...","ui.user-manager.changePassword":"Změnit heslo","ui.user-manager.setupTotp":"Nastavení dvoufaktorového ověření","ui.user-manager.disableTotp":"Deaktivovat dvoufaktorové ověření","ui.user-manager.invite":"Pozvat uživatele","ui.user-manager.delete":"Smazat","ui.user-manager.deleteConfirm":"Opravdu chcete smazat \\"{username}\\"?","ui.user-manager.deleted":"Úspěšně došlo ke smazání {username}","ui.user-manager.passwordHeadline":"Změnit heslo","ui.user-manager.passwordText":"Abyste mohli změnit heslo, zadajte nejdřív vaše stávající a pak vaše nové v odpovídajících polích. ","ui.user-manager.currentPassword":"Současné heslo","ui.user-manager.newPassword":"Nové heslo","ui.user-manager.passwordPlaceholder":"min. 8 znaků","ui.user-manager.submitPassword":"Odeslat","ui.user-manager.passwordChanged":"Vaše heslo bylo úspěšně změněno.","ui.user-manager.passwordError":"Heslo není správné.","ui.user-manager.inviteHeadline":"Pozvat uživatele","ui.user-manager.inviteText":"Pokud potřebujete více přihlášení pro Správce Contaa, můžete zde vytvořit odkaz na pozvání. Sdílejte tento odkaz s někým nebo jej použijte na jiném zařízení k vytvoření nového účtu s danými oprávněními.","ui.user-manager.inviteSuccess1":"Byl vytvořen nový odkaz na pozvání. Níže uvedenou adresu lze použít k vytvoření nového uživatelského účtu pro Správce Contaa. Pozvánka vyprší na {expires} (za týden od nynějška).","ui.user-manager.inviteSuccess2":"Zkopírujte prosím tento odkaz do vaší schránky. Platí jen jednou a již se nezobrazí po zavření tohoto dialogu.","ui.user-manager.createInvitation":"Vytvořit odkaz na pozvání","ui.user-manager.clipboard":"Zkopírovat do schránky","ui.user-manager.permissions":"Dozvědět se víc o povolení","ui.user-manager.cancel":"Zrušit","ui.user-manager.close":"Zavřít","ui.user-manager.you":"Vy","ui.totp.headline":"Dvoufaktorové ověření","ui.totp.setupQr":"Naskenujte prosím QR kód pomocí vaší 2FA/TOTP aplikace.","ui.totp.setupCode":"Nemůžete-li naskenovat QR kód, zadejte místo toho následující klíč:","ui.totp.codeLabel":"Ověřovací kód","ui.totp.codeDescription":"Zadejte prosím ověřovací kód vygenerovaný vaší 2FA/TOTP aplikací.","ui.totp.disableText":"Zadejte prosím ověřovací kód, abyste deaktivovali dvoufaktorové ověření. ","ui.totp.invalid":"Ověřovací kód není platný.","ui.totp.enable":"Aktivovat","ui.totp.disable":"Deaktivovat","ui.totp.cancel":"Zrušit","ui.totp.enabled":"Dvoufaktorové ověření bylo úspěšně aktivováno.","ui.totp.disabled":"Dvoufaktorové ověření bylo úspěšně deaktivováno.","ui.totp.setup":"Nastavení dvoufaktorového ověření","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[643],{6643:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Osäker anslutning !!","ui.app.httpsDescription":"Utan HTTPS kommer din konfidentiella data att överföras okrypterad.","ui.app.httpsLink":"Mer information","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Säkert läge aktiverat !!","ui.app.safeModeDescription":"Vissa funktioner i Contao Manager är inte tillgängliga.","ui.app.safeModeExit":"Avsluta felsäkert läge","ui.app.limitedHeadline":"Fjärrautentisering","ui.app.limitedDescription":"Du har begränsade behörigheter på grund av lösenordslös inloggning.","ui.app.limitedLogout":"Autentisera på nytt","ui.app.totpHeadline":"Säkerhetsmeddelande","ui.app.totpDescription":"Konfigurera tvåfaktorsautentisering nu för att säkra ditt konto.","ui.app.totpSetup":"Setup","ui.app.loading":"Laddar Contao Manager …","ui.app.apiError":"Oväntad API-status","ui.app.configSecurity1":"SÄKERHETSVARNING !!! Oskyddad konfigurationskatalog upptäcktes","ui.app.configSecurity2":"Contao Manager har upptäckt att dess konfigurationsfiler är offentligt tillgängliga. Alla operationer är inaktiverade tills katalogen är säker, annars kan en angripare komma åt känsliga data från din installation.\\n\\nFör att åtgärda det här problemet, se till att förhindra åtkomst till \\"contao-manager\\"-katalogen på din server. För att lära dig hur du gör detta, se manualen för din webbserver eller kontakta din värdleverantör.","ui.account.welcome":"Välkommen","ui.account.intro1":"Välkommen till Contao Manager, ett universellt verktyg för att installera och hantera Contao Open Source CMS. Om du är ny på det, vänligen {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} för att komma igång","ui.account.introManual":"läs manualen","ui.account.intro2":"Om du stöter på några problem, kolla {ourGithubIssues} och skapa gärna ett nytt för allt som inte har rapporterats ännu.","ui.account.introIssues":"våra GitHub-problem","ui.account.headline":"Användarkonto","ui.account.description":"För att hantera din installation, skapa ett konto för Contao Manager. Var medveten om att det här kontot inte är relaterat till Contao backend eller frontend.","ui.account.username":"Användarnamn","ui.account.password":"Lösenord","ui.account.passwordPlaceholder":"min. 8 tecken","ui.account.passwordLength":"Ange minst 8 tecken.","ui.account.loginInvalid":"Det uppstod ett fel när du skapade kontot. Vänligen försök med ett annat användarnamn.","ui.account.submit":"Skapa konto","ui.account.usePassword":"Använd lösenord för inloggning","ui.account.usePasskey":"Använd Passkey för inloggning","ui.account.totpHeadline":"Tvåfaktorsautentisering","ui.account.totpDescription":"Vänligen aktivera tvåfaktorsautentisering, vilket ger ditt konto ett extra säkerhetslager. Förutom ditt användarnamn och lösenord måste du ange en verifieringskod som genereras av en tvåfaktorsapp som 1Password, Authy, Google Authenticator, Microsoft Authenticator, LastPass Authenticator eller någon annan TOTP-app.","ui.account.totpSetup":"Konfigurera nu","ui.account.totpSkip":"Konfigureras senare","ui.account.login":"Avvisa inbjudan","ui.account.contribute1":"Contao och Contao Manager är sponsrade av den ideella Contao Association.","ui.account.contribute2":"Vänligen överväg att bidra till öppen källkod genom att {donate}.","ui.account.contributeDonate":"göra en donation","ui.login.headline":"Logga in","ui.login.description":"Logga in för att hantera din installation.","ui.login.username":"Användarnamn","ui.login.password":"Lösenord","ui.login.totpHeadline":"Tvåfaktorsautentisering","ui.login.totpDescription":"Ange din verifieringskod för att slutföra inloggningsprocessen.","ui.login.totp":"Verifieringskod","ui.login.forgotPassword":"Glömt ditt lösenord?","ui.login.button":"Logga in","ui.login.passkey":"Logga in med Passkey","ui.login.cancel":"Avbryt","ui.login.locked":"Åtkomst har nekats eftersom Contao Manager är låst. För att låsa upp, radera {lockFile}-filen i din Contao-rotkatalog.","ui.logout.headline":"Sessionen har gått ut","ui.logout.warning":"Du har varit inaktiv i mer än 25 minuter. Av säkerhetsskäl kommer din session att avslutas inom kort.","ui.logout.expired":"Din session avslutades automatiskt eftersom du har varit inaktiv i mer än 30 minuter.","ui.logout.renew":"Håll inloggad","ui.logout.logout":"Logga ut","ui.logout.login":"Tillbaka till login","ui.oauth.error":"Ogiltigt OAuth-försök. Kontrollera request-parametrarna.","ui.oauth.https":"Omdirigerings-URI:n MÅSTE använda ett säkert protokoll (https:) för att förhindra att autentiseringstoken sänds i klartext.","ui.oauth.headline":"Fjärrautentisering","ui.oauth.description":"Följande applikation eller tjänst begär fjärråtkomst till din Contao Manager-instans.","ui.oauth.domain":"Innan du tillåter åtkomst, se till att du känner till den här webbadressen och litar på dess ägare!","ui.oauth.outOfScope":"Tyvärr har du inte de nödvändiga behörigheterna för att bevilja denna åtkomst.","ui.oauth.allow":"Tillåta åtkomst","ui.oauth.deny":"Neka åtkomst","ui.oauth.switchUser":"Växla användare","ui.scope.admin":"Admin-åtkomst inklusive användarhantering","ui.scope.install":"Installera nya paket och ändra Contao-konfigurationen","ui.scope.update":"Uppdatera paket och utföra underhållsåtgärder","ui.scope.read":"Läs paket och konfiguration","ui.boot.headline":"Systemkontroll","ui.boot.description":"Vänta, vi analyserar din server...","ui.boot.issue1":"Installationsproblem upptäcktes","ui.boot.issue2":"Din installation har problem som måste åtgärdas innan Contao Manager kan användas.","ui.boot.run":"Starta Contao Manager","ui.boot.safeMode":"Starta i felsäkert läge Safe Mode","ui.recovery.headline":"Systemåterställning","ui.recovery.description":"Contao Manager upptäckte filer som ser ut som Contao, men kommandoradsgränssnittet fungerar inte som förväntat.","ui.recovery.console":"Konsolutgång","ui.recovery.repairOptions":"Välj ett alternativ för att reparera din installation.","ui.recovery.repairHeadline":"Automatisk reparation","ui.recovery.repairDescription":"Försöker att automatiskt reparera installationen genom att bygga om programcachen och installera om Composer-paketen.","ui.recovery.repairWarning":"Eventuella ändringar av vendor-filerna kan raderas under processen!","ui.recovery.repairFailed":"Den automatiska reparationen lyckades inte. Prova felsäkert läge Safe Mode för att manuellt reparera installationen.","ui.recovery.repairButton":"Kör systemreparation","ui.recovery.safeModeHeadline":"Säkert läge Safe Mode","ui.recovery.safeModeDescription":"Att starta Contao Manager i felsäkert läge gör det möjligt att hantera paket och köra vissa underhållsuppgifter, men funktioner som förlitar sig på en fungerande Contao-installation kommer inte att vara tillgängliga.","ui.recovery.safeModeButton":"Starta i felsäkert läge Safe Mode","ui.server.pending":"Väntar …","ui.server.running":"Analyserar …","ui.server.error":"Kontrollen misslyckades på grund av ett oväntat svar från servern.","ui.server.details":"Detaljer","ui.server.prerequisite":"Checken annullerad på grund av att förutsättning saknas.","ui.server.selfUpdate.title":"Uppdateringar av Contao Manager","ui.server.selfUpdate.update":"En ny version av Contao Manager {latest} är tillgänglig.","ui.server.selfUpdate.manualUpdate":"En ny version av Contao Manager {latest} är tillgänglig. Din server stöder inte automatiska uppdateringar, ladda ner den nya versionen från {download}.","ui.server.selfUpdate.latest":"Du använder den senaste versionen {current}.","ui.server.selfUpdate.dev":"Utvecklingsbyggen stöder inte automatiska uppdateringar.","ui.server.selfUpdate.unsupported":"En ny version är tillgänglig men den stöder inte din PHP-version.","ui.server.selfUpdate.button":"Kör självuppdatering","ui.server.selfUpdate.continue":"Fortsätta","ui.server.config.title":"Serverkonfiguration","ui.server.config.setup":"Konfigurera","ui.server.config.change":"Förändra","ui.server.config.save":"Spara","ui.server.config.cancel":"Avbryt","ui.server.config.customOption":"Övrig …","ui.server.config.description":"För att köra bakgrundsuppgifter korrekt måste Contao Manager veta var man hittar PHP-kommandoradens binära filer och hur man kör kommandon separerade från webbprocessen.","ui.server.config.formTitle":"Serverkonfiguration","ui.server.config.formText":"Ange sökvägen till din PHP-binär. Se till att binären är samma PHP-version som din webbprocess.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Composer Resolver Cloud gör det möjligt att installera Composer-beroenden även om din server inte tillhandahåller tillräckligt med lokalt minne. Var medveten om att din paketinformation kommer att överföras till en molnserver som drivs av Contao Association.","ui.server.config.cloud":"Använd Composer Resolver Cloud","ui.server.config.cli":"PHP binär","ui.server.config.stateErrorCli":"Ingen giltig PHP-binär hittades på servern.","ui.server.config.stateErrorCloud":"Composer Resolver Cloud stöds inte.","ui.server.config.stateSuccess":"PHP binär på {php_cli}.","ui.server.php_web.title":"PHP webbprocess","ui.server.php_web.below7":"Hittade PHP-versionen {version}. Byt till PHP 7 så snart som möjligt!","ui.server.php_web.success":"Hittade PHP-versionen {version}, inga kända problem hittades.","ui.server.php_cli.title":"PHP kommandoradsgränssnitt","ui.server.php_cli.success":"Hittade PHP-versionen {version}, inga kända problem hittades.","ui.server.composer.title":"Composer-Miljö","ui.server.composer.success":"Inga kända problem hittades.","ui.server.composer.install":"Composer-beroenden är inte installerade.","ui.server.composer.button":"Installera","ui.server.contao.title":"Contao installation","ui.server.contao.setup":"Setup","ui.server.contao.check":"Kontrollera databasen","ui.server.contao.empty":"Ingen Contao-installation har hittats.","ui.server.contao.old":"Contao version {version} är inte kompatibel med Contao Manager, uppdatera din installation manuellt.","ui.server.contao.found":"Hittade Contao {version} (API-version {api}).","ui.server.contao.connectionError":"Det går inte att ansluta till databasservern.","ui.server.contao.connectionProblem":"Databasproblem hittades.","ui.server.contao.missingUser":"Administratörskonto hittades inte.","ui.setup.continue":"Fortsätta","ui.setup.manager":"Starta Contao Manager","ui.setup.cancel":"Avbryt","ui.setup.welcome":"Välkommen","ui.setup.welcome1":"Den här guiden tar dig igenom de nödvändiga stegen för att konfigurera din Contao Open Source CMS-installation.","ui.setup.welcome2":"Om du har några frågor kan du hitta dokumentation, forum, en Slack-kanal och mer på sidan {support}.","ui.setup.support":"community support","ui.setup.start":"Komma igång","ui.setup.complete":"Grattis!","ui.setup.complete1":"Contao {version} har installerats.","ui.setup.complete2":"För att avsluta installationsprocessen, öppna installationsverktyget för att konfigurera databasanslutningen och skapa en backend-användare.","ui.setup.complete3":"Du kan nu börja skapa din webbplats i Contaos back end. Om du behöver ytterligare tillägg, fortsätt till Contao Manager.","ui.setup.installTool":"Öppna installationsverktyget","ui.setup.login":"Logga in på Contao","ui.setup.funding":"Fri programvara är \\"fri\\" som i \\"yttrandefritt\\", inte som i \\"gratis öl\\". Ett Open Source-projekt som Contao kräver summor pengar som inte kan samlas in av en enda person eller företag.\\nOm du har en webbplats eller säljer webbplatser byggda med Contao, skulle vi gärna se att du bidrar ekonomiskt till den produkt som ditt företag är beroende av.","ui.setup.fundingLink":"Läs mer","ui.setup.document-root.headline":"Webserverinstallation","ui.setup.document-root.warning":"För att installera Contao via Contao Manager måste du fixa dokumentroten på webbservern.","ui.setup.document-root.description1":"Contao använder en separat mapp för offentliga filer, programfiler installeras i dess överordnade mapp. Contao kan inte installeras om mappstrukturen inte är korrekt eller om mapparna inte är tomma.","ui.setup.document-root.description2":"Om du inte vet hur du konfigurerar din dokumentrot, läs Contao-dokumentationen eller kontakta din värdleverantör.","ui.setup.document-root.documentation":"Läs dokumentationen","ui.setup.document-root.conflictsTitle":"Installationskatalogen är inte tom","ui.setup.document-root.conflictsDirectory":"Rotkatalogen för din framtida Contao-installation är inte tom, vi har hittat {count} fil(er) som kan skrivas över av installationsprocessen. Det rekommenderas att skapa en tom katalogstruktur för Contao, men du kan också ta bort följande filer och kontrollera igen om du är säker på att de är oanvända.","ui.setup.document-root.ignoreConflicts":"Jag vill installera Contao i den icke-tomma katalogen. Jag förstår att detta kan skriva över alla befintliga filer på mitt webbutrymme.","ui.setup.document-root.check":"Kolla igen","ui.setup.document-root.create":"Skapa kataloger","ui.setup.document-root.change":"Byt kataloger","ui.setup.document-root.formTitle":"Kataloginställningar","ui.setup.document-root.formText1":"Contao Manager kan automatiskt skapa en ny katalogstruktur på servern.","ui.setup.document-root.formText2":"Du måste konfigurera den nya dokumentroten manuellt (t.ex. via en värdadministratörspanel).","ui.setup.document-root.autoconfig":"Jag förstår att jag måste ändra min serverkonfiguration. Att inte konfigurera dokumentroten kommer att bryta Contao Manager och exponera konfigurationsfiler (inklusive kontodetaljer och lösenord)!","ui.setup.document-root.directory":"Ny katalog","ui.setup.document-root.currentRoot":"Aktuell dokumentrot","ui.setup.document-root.newRoot":"Ny dokumentrot","ui.setup.document-root.finish":"Installera kataloger","ui.setup.document-root.publicDir":"Använd {dir} för offentliga filer (för Contao {version})","ui.setup.document-root.directoryInvalid":"Vänligen ange ett giltigt katalognamn.","ui.setup.document-root.directoryExists":"Vänligen ange ett giltigt katalognamn.","ui.setup.document-root.confirmation":"Contao Manager har skapat den nödvändiga katalogen för din Contao-installation. Du måste nu konfigurera dokumentroten på din webbserver. Ladda inte om den här sidan förrän då.","ui.setup.document-root.reload":"Ladda om sidan","ui.setup.document-root.success":"Katalogstrukturen på din webbserver är korrekt inställd!","ui.setup.document-root.installingProjectDir":"Programfiler kommer att installeras i {dir}.","ui.setup.document-root.installingPublicDir":"Offentliga filer kommer att installeras i {dir}.","ui.setup.document-root.installedProjectDir":"Programfiler installeras i {dir}.","ui.setup.document-root.installedPublicDir":"Offentliga filer installeras i {dir}.","ui.setup.create-project.headline":"Contao installation","ui.setup.create-project.description":"Contao-utvecklingen följer principen för {semver}, en ny minor version släpps var sjätte månad. De utgåvor som för närvarande stöds är:","ui.setup.create-project.semver":"Semantisk versionering","ui.setup.create-project.latestTitle":"Senast","ui.setup.create-project.ltsTitle":"Långtidssupport","ui.setup.create-project.latestQ1":"Vår senaste version erbjuder de flesta funktionerna med support fram till februari {year}.","ui.setup.create-project.latestQ3":"Vår senaste version erbjuder de flesta funktionerna med support fram till augusti {year}.","ui.setup.create-project.ltsText":"Vår nuvarande LTS-version, om du fokuserar på stabilitet. Erbjuder långsiktig support till februari {year}.","ui.setup.create-project.pltsText":"Den tidigare LTS-versionen har fortfarande långtidssupport fram till februari {year}.","ui.setup.create-project.requiresPHP":"Kräver minst PHP {version}, du har PHP {current}.","ui.setup.create-project.releaseplan":"Se {contaoReleasePlan} för detaljerad information.","ui.setup.create-project.releaseplanLink":"Contao Release Plan","ui.setup.create-project.installed":"Contao {version} har installerats på servern. Fortsätt att ställa in din databas eller starta Contao Manager för att installera en annan version.","ui.setup.create-project.formTitle":"Välj en distribution","ui.setup.create-project.formText":"Välj vilken version som ska installeras.","ui.setup.create-project.version":"Version","ui.setup.create-project.demo":"Installera Contaos demowebbplats","ui.setup.create-project.demoDescription":"Demowebbplatsen hjälper dig att bli bekant med Contao och alla dess kärnfunktioner. Fler teman finns i {butiken}.","ui.setup.create-project.coreOnly":"Minimal installation (endast kärna core)","ui.setup.create-project.noUpdate":"Hoppa över installationen (endast experter!)","ui.setup.create-project.theme":"Contao Theme","ui.setup.create-project.themeInstall":"För att installera ett Contao-tema, använd sökingången eller ladda upp en temafil (.cto/.zip) som stöder installation via Contao Manager.","ui.setup.create-project.themeBuy":"Se till att besöka den officiella {butiken}.","ui.setup.create-project.themeStore":"Contao Themes Store","ui.setup.create-project.themeUpload":"Ladda upp temafil (.cto/.zip)","ui.setup.create-project.themeInvalid":"Den uppladdade filen är inte ett Contao-tema eller stöder inte Contao Manager.","ui.setup.create-project.themeWarning":"Contao Manager kan inte avgöra om detta tema är kompatibelt med din server. Kontrollera med temaleverantören om du har några frågor.","ui.setup.create-project.themeTitle":"Granska temadetaljer","ui.setup.create-project.themeDetails":"Följande beroenden och filer kommer att installeras med detta tema.","ui.setup.create-project.themeRequire":"{count} beroenden | {count} beroenden","ui.setup.create-project.themeFiles":"{count} Fil | {count} filer","ui.setup.create-project.theme.or":"eller sök efter offentliga teman","ui.setup.create-project.theme.search":"Sök teman","ui.setup.create-project.theme.more":"Fler teman","ui.setup.create-project.theme.empty":"Inga teman matchar {query}","ui.setup.create-project.theme.uploaded":"Temafilen laddades upp.","ui.setup.create-project.theme.packageName":"Paketnamn","ui.setup.create-project.theme.version":"Version","ui.setup.create-project.theme.authors":"Författare","ui.setup.create-project.install":"Installera","ui.setup.create-project.cancel":"Avbryt","ui.setup.database-connection.headline":"Databasanslutning","ui.setup.database-connection.description":"Contao kräver en MySQL-databas (eller en kompatibel databas som MariaDB) för att lagra sidor, innehåll, användare och annan relationsdata. Anslutningsparametrar lagras i filen {env} i projektroten för din Contao-installation.","ui.setup.database-connection.formTitle":"Anslutningsparametrar","ui.setup.database-connection.formText":"Ange en databas-URL eller fyll i användarnamn, lösenord, server och databasfält separat.","ui.setup.database-connection.url":"Databas URL","ui.setup.database-connection.validUrl":"Databas-URL är ogiltig eller anslutningen till servern misslyckades.","ui.setup.database-connection.or":"eller","ui.setup.database-connection.user":"Användarnamn","ui.setup.database-connection.password":"Lösenord","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Databas namn","ui.setup.database-connection.connected":"Ansluten till databasen {database} på {server}.","ui.setup.database-connection.error":"Fel vid anslutning till databasen.","ui.setup.database-connection.problem":"Contao har upptäckt ett problem med din databasserver.","ui.setup.database-connection.schemaTitle":"Databasschema","ui.setup.database-connection.migration":"Det finns en väntande migrering. | Det finns {count} väntande migreringar.","ui.setup.database-connection.schema":"Det finns en väntande schemauppdatering. | Det finns {count} väntande schemauppdateringar.","ui.setup.database-connection.noChanges":"Ditt databasschema är uppdaterat.","ui.setup.database-connection.check":"Kontrollera databasen","ui.setup.database-connection.skip":"Hoppa över","ui.setup.database-connection.save":"Spara","ui.setup.database-connection.change":"Ändra autentiseringsuppgifter","ui.setup.database-connection.restoreTitle":"Databasimport","ui.setup.database-connection.restoreText":"Temat du just installerade innehåller en databassäkerhetskopiering. Återställ databasen för att importera temadata eller hoppa över detta steg för att börja med en tom Contao-installation. | Temat du just installerade innehåller flera säkerhetskopior av databaser. Välj en säkerhetskopia för att importera temadata eller hoppa över det här steget för att börja med en tom Contao-installation.","ui.setup.database-connection.backup":"Säkerhetskopiera aktuell databas före import","ui.setup.database-connection.backupWarning":"All data i databasen kommer att skrivas över vid import! Skapa en säkerhetskopia först om databasen inte är tom.","ui.setup.database-connection.restore":"Importera temadatabas","ui.setup.database-connection.restoreOption":"Säkerhetskopiering från {date} ({size})","ui.setup.database-connection.restored":"Din temadatabas har importerats. Fortsätt att validera ditt databasschema.","ui.setup.backend-user.success":"Ett administratörskonto för Contao backend hittades i din databas. Använd Contaos backend för att lägga till fler användare.","ui.setup.backend-user.error":"Det gick inte att hämta användarlistan. Kontrollera konsolutgången för detaljer.","ui.setup.backend-user.headline":"Backend-konto","ui.setup.backend-user.description":"För att hantera din webbplats måste du ha minst ett administratörskonto för Contaos backend. Var medveten om att detta konto inte är relaterat till Contao Manager.","ui.setup.backend-user.formTitle":"Skapa konto","ui.setup.backend-user.formText":"Vänligen ange detaljerna för det nya backend-kontot.","ui.setup.backend-user.username":"Användarnamn","ui.setup.backend-user.name":"namn","ui.setup.backend-user.email":"E-postadress","ui.setup.backend-user.emailInvalid":"Vänligen ange en giltig e-postadress","ui.setup.backend-user.password":"Lösenord","ui.setup.backend-user.passwordPlaceholder":"min. 8 tecken","ui.setup.backend-user.passwordLength":"Ange minst 8 tecken.","ui.setup.backend-user.create":"Lägg till konto","ui.task.headline":"Bakgrundsuppgift","ui.task.loading":"Läser in detaljer...","ui.task.created":"Läser in detaljer...","ui.task.active":"Vänta medan Contao Manager kör uppgiftsoperationer i bakgrunden.","ui.task.complete":"Alla operationer har slutförts framgångsrikt. Kontrollera konsolutgången för detaljer.","ui.task.aborting":"Vänta medan bakgrundsåtgärderna avbryts.","ui.task.stopped":"Vissa bakgrundsoperationer avbröts. Kontrollera konsolutgången.","ui.task.error":"En bakgrundsåtgärd avbröts oväntat. Kontrollera konsolutgången.","ui.task.failed":"Contao Manager kunde inte starta en bakgrundsuppgift!","ui.task.failedDescription1":"Något gick fel när man försökte utföra åtgärder i bakgrunden.","ui.task.failedDescription2":"Om detta händer igen kanske din server inte stöds.","ui.task.reportProblem":"Rapportera ett problem","ui.task.sponsor":"Composer Cloud sponsras av {sponsor}","ui.task.buttonAudit":"Uppdatera databas","ui.task.buttonClose":"Stänga","ui.task.buttonConfirm":"Bekräfta och stäng","ui.task.buttonCancel":"Avbryt","ui.task.confirmCancel":"Är du säker på att du avbryter den här uppgiften? Detta kan lämna din Contao-installation i ett trasigt tillstånd!","ui.task.autoclose":"Stäng uppgiftsinformation om framgång","ui.console.toggle":"Visa/dölj konsol-output","ui.console.showLog":"Visa hela konsolloggen","ui.console.copyLog":"Kopiera loggen till urklipp","ui.migrate.headline":"Databasuppdateringar","ui.migrate.migrationsOnly":"(endast migrering)","ui.migrate.schemaOnly":"(endast schema)","ui.migrate.loading":"Vänta, vi kontrollerar din databas...","ui.migrate.empty":"Inga pågående migreringar eller schemauppdateringar hittades. Din databas är uppdaterad.","ui.migrate.emptyMigrations":"Inga väntande migrering hittades. Se till att även leta efter schemauppdateringar.","ui.migrate.emptySchema":"Inga väntande schemauppdateringar hittades. Se till att även kontrollera migrering.","ui.migrate.pending":"Din databas är inte uppdaterad. Granska konsolutgången nedan och verkställ ändringarna.","ui.migrate.previousChanges":"En tidigare databasmigrering har inte bekräftats.\\nGranska konsolutgången nedan och fortsätt sedan för att se nästa ändringar.","ui.migrate.previousComplete":"En tidigare databasmigrering har inte bekräftats, vänligen granska konsolutdata nedan.\\nDet finns inga fler väntande ändringar.","ui.migrate.appliedChanges":"Databasuppdateringar har tillämpats.\\nGranska konsolutgången nedan och fortsätt sedan för att se nästa ändringar.","ui.migrate.appliedComplete":"Databasuppdateringar har tillämpats.\\nDet finns inga fler väntande migreringar eller schemauppdateringar. Din databas är uppdaterad.","ui.migrate.problem":"Contao har upptäckt ett problem med din databasserver.\\nGranska konsolutgången nedan för att ta reda på vad som behöver åtgärdas. | Contao har upptäckt problem med din databasserver.\\nGranska konsolutgången nedan för att ta reda på vad som behöver åtgärdas.","ui.migrate.warning":"Contao har upptäckt en felaktig konfiguration av din databasserver.\\nVarningar kan hoppas över tillfälligt, men bör åtgärdas för optimal prestanda och dataintegritet.","ui.migrate.error":"Ändringarna kunde inte tillämpas. Din databas kan ha ändrats, kontrollera igen för att försöka igen.","ui.migrate.execute":"Kör","ui.migrate.close":"Stänga","ui.migrate.confirm":"Bekräfta och stäng","ui.migrate.cancel":"Avbryt","ui.migrate.continue":"Fortsätta","ui.migrate.setup":"Setup","ui.migrate.skip":"Hoppa över","ui.migrate.retry":"Kolla igen","ui.migrate.retryAll":"Kontrollera alla","ui.migrate.withDeletes":"Utför alla databasändringar inklusive DROP-queries.","ui.migrate.migrationTitle":"Databasmigreringar","ui.migrate.schemaTitle":"Schemauppdateringar","ui.migrate.problemTitle":"Databasproblem","ui.migrate.warningTitle":"Databasvarningar","ui.migrate.addTable":"Lägg till tabell {table}","ui.migrate.dropTable":"Släpp tabell {table}","ui.migrate.addField":"Lägg till fält {table}.{field}","ui.migrate.changeField":"Ändra fält {table}.{field}","ui.migrate.dropField":"Släpp fältet {table}.{field}","ui.migrate.createIndex":"Skapa index \\"{name}\\" på {table}","ui.migrate.dropIndex":"Släpp index \\"{name}\\" på {table}","ui.widget.mandatory":"Detta fält får inte vara tomt.","ui.widget.blankOption":"Vänligen välj …","ui.widget.showPassword":"Visa lösenord","ui.widget.hidePassword":"Dölj lösenord","ui.error.title":"HTTP-begäran för \\"{method} {url}\\" misslyckades.","ui.error.server500":"Det verkar som att ett oväntat fel inträffade på din server. Kontrollera loggfilerna för din webbserver (Apache/Nginx) och Contao Manager-loggarna på \\"contao-manager/logs\\".","ui.error.response":"Servern returnerade ett svar med statuskoden {status}.","ui.error.moreLink":"Mer information","ui.error.support":"Contao Support","ui.error.permission":"Du har inte tillstånd att använda den här funktionen.","ui.footer.help":"Hjälp","ui.footer.reportProblem":"Rapportera ett problem","ui.navigation.discover":"Upptäck","ui.navigation.packages":"Paket","ui.navigation.tools":"Verktyg","ui.navigation.installTool":"Installera verktyg","ui.navigation.backend":"Contao Backend","ui.navigation.debug":"Contao Debug Mode Felsökningsläge","ui.navigation.logViewer":"Logg visare","ui.navigation.phpinfo":"PHP-information","ui.navigation.phpinfoLoading":"Laddar PHP-information...","ui.navigation.maintenance":"Underhåll","ui.navigation.rebuildCache":"Bygg om cachen","ui.navigation.users":"Konton","ui.navigation.systemCheck":"Systemkontroll","ui.navigation.advanced":"Avancerad","ui.navigation.logout":"Logga ut","ui.maintenance.database.title":"Databasmigreringar och säkerhetskopieringar","ui.maintenance.database.description":"Databasmigreringar säkerställer konsekventa data och tabellscheman.","ui.maintenance.database.migrations":"En väntande databasmigrering | {count} väntande databasmigreringar","ui.maintenance.database.schemaUpdates":"En väntande schemauppdatering | {count} väntande schemauppdateringar","ui.maintenance.database.error":"Databasproblem hittades.","ui.maintenance.database.warning":"Databasvarningar hittades.","ui.maintenance.database.button":"Kontrollera databasen","ui.maintenance.database.migrationOnly":"Kontrollera endast migrering","ui.maintenance.database.schemaOnly":"Kontrollera endast schemat","ui.maintenance.database.installTool":"Öppna installationsverktyget","ui.maintenance.database.createBackup":"Skapa backup","ui.maintenance.database.backupUnsupported":"Databassäkerhetskopior stöds inte av din Contao-version.","ui.maintenance.database.backupList":"Du har en databassäkerhetskopia, skapad den {date}. | Du har {count} databassäkerhetskopior, den senaste skapades den {date}.","ui.maintenance.database.backupEmpty":"Du har för närvarande inga säkerhetskopior av databasen.","ui.maintenance.rebuildCache.title":"Applikationscache","ui.maintenance.rebuildCache.description":"Att bygga om applikationscachen krävs efter att ha ändrat någon av konfigurationsfilerna.","ui.maintenance.rebuildCache.rebuildProd":"Bygg om produktionscachen","ui.maintenance.rebuildCache.rebuildDev":"Bygg om utvecklingscachen","ui.maintenance.rebuildCache.clearProd":"Rensa produktionscache","ui.maintenance.rebuildCache.clearDev":"Rensa utvecklingscache","ui.maintenance.installTool.title":"Contao installationsverktyg","ui.maintenance.installTool.description":"Contao Install Tool låses automatiskt om du anger fel lösenord tre gånger i rad.","ui.maintenance.installTool.unlock":"Lås upp installationsverktyget","ui.maintenance.installTool.lock":"Lås installationsverktyg","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"Composer autoloader ansvarar för PHP-klassladdning. Autoloadern måste dumpas efter att anpassade namnområden har lagts till i roten composer.json.","ui.maintenance.dumpAutoload.button":"Dumpa Autoloader","ui.maintenance.composerInstall.title":"Composer beroenden","ui.maintenance.composerInstall.description":"Composer-beroenden finns i mappen {vendor} i din programrot. Att installera om beroenden kan vara nödvändigt efter manipulering eller manuell uppladdning av {composerLock}-filen.","ui.maintenance.composerInstall.button":"Kör installationsprogrammet","ui.maintenance.composerInstall.update":"Kör Composer Update","ui.maintenance.composerCache.title":"Composer Cache","ui.maintenance.composerCache.description":"Composer cachar nedladdade paket för förbättrad prestanda. Om du har problem som trasiga filer, försök att ta bort Composer-cachen för att tvinga fram en ny nedladdning.","ui.maintenance.composerCache.button":"Rensa cache","ui.maintenance.maintenanceMode.title":"Underhållsläge","ui.maintenance.maintenanceMode.description":"Om du sätter Contao i underhållsläge visas en \\"503 Service Unavailable\\"-mall för webbplatsen.","ui.maintenance.maintenanceMode.enable":"Aktivera","ui.maintenance.maintenanceMode.disable":"Inaktivera","ui.maintenance.debugMode.title":"Felsökningsläge Debug Mode","ui.maintenance.debugMode.description":"Aktivera felsökningsläget genom att ställa in en användare och lösenord för ingångspunkten för {appDevPhp}.","ui.maintenance.debugMode.descriptionJwt":"Aktivera felsökningsläget genom att ställa in felsökningscookien för den aktuella domänen.","ui.maintenance.debugMode.activate":"Aktivera","ui.maintenance.debugMode.deactivate":"Avaktivera","ui.maintenance.debugMode.credentials":"Referenser","ui.maintenance.debugMode.user":"Ange ett användarnamn för felsökningsläget.","ui.maintenance.debugMode.password":"Ange ett lösenord för felsökningsläget.","ui.maintenance.opcodeCache.title":"Opcode Cache","ui.maintenance.opcodeCache.description":"Opcode cachar PHP-filer på webbprocessen för snabbare exekvering. Det måste tas bort under vissa omständigheter om filer inte känns igen efter ändring.","ui.maintenance.opcodeCache.button":"Stympa Cache","ui.maintenance.safeMode":"Ej tillgängligt i felsäkert läge Safe Mode","ui.maintenance.unsupported":"Stöds inte av din Contao-version","ui.packages.updateButton":"Uppdatera paket","ui.packages.searchButton":"Sök paket","ui.packages.searchPlaceholder":"Sök paket …","ui.packages.uploadOverlay":"Dra och släpp filer för att ladda upp","ui.packages.uploadButton":"Ladda upp paket","ui.packages.uploadMessage":"Du har en obekräftad uppladdning. | Du har {count} obekräftade uppladdningar.","ui.packages.uploadApply":"Bekräfta uppladdningar","ui.packages.uploadReset":"Ta bort uppladdningar","ui.packages.uploadIncomplete":"Den här filen laddades inte upp helt. Ta bort den och försök igen.","ui.packages.uploadDuplicate":"Den här filen verkar ha laddats upp flera gånger. Ta bort dubbletterna.","ui.packages.uploadInstalled":"Den här filen är redan installerad. Ta bort dubbletterna.","ui.packages.uploadUnsupported":"Uppladdningar stöds inte i din installation. Se till att PHP ZIP-tillägget är installerat och uppdatera dina beroenden.","ui.packages.changesMessage":"Du har en obekräftad förändring. | Du har {count} obekräftade ändringar.","ui.packages.changesDryrun":"Testkörning","ui.packages.changesApply":"Applicera förändringar","ui.packages.changesApplyAll":"Uppdatera alla paket","ui.packages.changesDryrunAll":"Testkör alla paket","ui.packages.changesReset":"Återställ ändringar","ui.packages.changesReview":"Granska ändringar","ui.packagelist.loading":"Laddning ...","ui.packagelist.uploads":"Uppladdningar","ui.packagelist.added":"Nya paket","ui.packagelist.installed":"Installerade paket","ui.package.hintRevert":"Återställ ändringar","ui.package.hintNoupdate":"Uppdatera inte","ui.package.hintConstraint":"Det här paketet kommer att installeras med begränsningen {constraint} när du tillämpar ändringarna.","ui.package.hintConstraintBest":"Det här paketet kommer att installeras i den bästa tillgängliga versionen när du tillämpar ändringarna.","ui.package.hintConstraintChange":"Begränsningen för detta paket kommer att ändras från \\"{from}\\" till \\"{to}\\" när du tillämpar ändringarna.","ui.package.hintConstraintUpdate":"Detta paket kommer att uppdateras när du tillämpar ändringarna.","ui.package.hintAdded":"Det här paketet kommer att installeras när du tillämpar ändringarna.","ui.package.hintRemoved":"Detta paket kommer att tas bort när du tillämpar ändringarna.","ui.package.requiredTitle":"manuellt lagt till","ui.package.requiredText":"Det här paketet krävs i din composer.json men är inte installerat.","ui.package.removedTitle":"tas bort manuellt","ui.package.removedText":"Det här paketet togs bort från din composer.json.","ui.package.installed":"För närvarande installerad:","ui.package.version":"Version {version}","ui.package.additionalDownloads":"{count} Nedladdning | {count} nedladdningar","ui.package.additionalStars":"{count} stjärna | {count} stjärnor","ui.package.editConstraint":"Redigera","ui.package.uploadConstraint":"Denna begränsning definieras av det uppladdade paketet.","ui.package.updateButton":"Uppdatering","ui.package.removeButton":"Ta bort","ui.package.installButton":"Lägg till paket","ui.package.installButtonShort":"Lägg till","ui.package.detailsButton":"Detaljer","ui.package.latestConstraint":"senaste versionen","ui.package.update":"Uppdatering tillgänglig","ui.package.updateLatest":"senaste versionen","ui.package.updateAvailable":"{version} tillgänglig","ui.package.updateUnknown":"okänd version","ui.package.updateConstraint":"En nyare version utanför din versionsbegränsning är tillgänglig.","ui.package.incompatible":"{package} fungerar inte med Contao {constraint}.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Version {version}","ui.cloudStatus.waitingTime":"Väntetid","ui.cloudStatus.jobs":"Aktuella jobb","ui.cloudStatus.workers":"Arbetare","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"ingen","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sek","ui.cloudStatus.error":"Det går inte att hämta status för Composer Resolver Cloud. Det kan vara nere på grund av underhåll eller upplevelseproblem.","ui.cloudStatus.button":"Molnstatus","ui.cloudStatus.refresh":"Uppdatera molnstatus","ui.log-viewer.loading":"Laddning ...","ui.log-viewer.empty":"Det finns inga loggfiler på din server.","ui.log-viewer.reload":"Ladda om","ui.log-viewer.file":"Loggfil","ui.log-viewer.channel":"Kanal","ui.log-viewer.channelTitle":"Kanalen som detta meddelande loggades på.","ui.log-viewer.level":"Nivå","ui.log-viewer.levelTitle":"Allvaret i loggmeddelandet.","ui.log-viewer.timeHeader":"Tid","ui.log-viewer.messageHeader":"Meddelande","ui.log-viewer.showContext":"Visa sammanhang","ui.log-viewer.hideContext":"Dölj sammanhang","ui.log-viewer.showExtra":"Visa extra","ui.log-viewer.hideExtra":"Dölj extra","ui.log-viewer.more":"Ladda mer …","ui.log-viewer.download":"Ladda ner","ui.log-viewer.downloadTitle":"Nedladdning fil \\"{file}\\"","ui.log-viewer.prodEnvironment":"Produktionsmiljö","ui.log-viewer.devEnvironment":"Utvecklingsmiljö (felsökningsläge)","ui.user-manager.loading":"Laddar användare ...","ui.user-manager.changePassword":"Ändra lösenord","ui.user-manager.setupTotp":"Konfigurera tvåfaktorsautentisering","ui.user-manager.disableTotp":"Inaktivera tvåfaktorsautentisering","ui.user-manager.invite":"Bjud in användare","ui.user-manager.delete":"Radera","ui.user-manager.deleteConfirm":"Vill du verkligen ta bort användaren ”{användarnamn}”?","ui.user-manager.deleted":"Användaren {användarnamn} raderades framgångsrikt","ui.user-manager.passwordHeadline":"Ändra lösenord","ui.user-manager.passwordText":"Om du vill ändra ditt lösenord anger du det nuvarande och ett nytt lösenord i respektive fält.","ui.user-manager.currentPassword":"Aktuellt lösenord","ui.user-manager.newPassword":"Nytt lösenord","ui.user-manager.passwordPlaceholder":"min. 8 tecken","ui.user-manager.submitPassword":"Skicka","ui.user-manager.passwordChanged":"Ditt lösenord har ändrats framgångsrikt.","ui.user-manager.passwordError":"Det här lösenordet är felaktigt.","ui.user-manager.inviteHeadline":"Bjud in användare","ui.user-manager.inviteText":"Om du behöver flera inloggningar för Contao Manager kan du skapa en inbjudningslänk här. Dela den här länken med någon eller använd den på en annan enhet för att skapa ett nytt konto med de angivna behörigheterna.","ui.user-manager.inviteSuccess1":"En ny inbjudningslänk har skapats. URL:en nedan kan användas för att skapa ett nytt användarkonto för denna Contao Manager. Inbjudan löper ut den {expires} (one week from now).","ui.user-manager.inviteSuccess2":"Kopiera länken till ditt urklipp. Den fungerar bara en gång och du kommer inte att kunna se den igen efter att du har stängt den här dialogen.","ui.user-manager.createInvitation":"Skapa länk till inbjudan","ui.user-manager.clipboard":"Kopiera till urklipp","ui.user-manager.permissions":"Läs mer om behörigheter","ui.user-manager.cancel":"Avbryt","ui.user-manager.close":"Stänga","ui.user-manager.you":"Du","ui.totp.headline":"Tvåfaktorsautentisering","ui.totp.setupQr":"Vänligen skanna QR-koden med din 2FA/TOTP-app.","ui.totp.setupCode":"Om du inte kan skanna QR-koden, ange den här nyckeln istället:","ui.totp.codeLabel":"Verifieringskod","ui.totp.codeDescription":"Ange verifieringskoden som genereras av din 2FA/TOTP-app.","ui.totp.disableText":"Ange verifieringskoden för att inaktivera tvåfaktorsautentisering.","ui.totp.invalid":"Verifieringskoden är ogiltig.","ui.totp.enable":"Aktivera","ui.totp.disable":"Inaktivera","ui.totp.cancel":"Avbryt","ui.totp.enabled":"Tvåfaktorsautentisering aktiverades framgångsrikt.","ui.totp.disabled":"Tvåfaktorsautentisering avaktiverades framgångsrikt.","ui.totp.setup":"Konfigurera tvåfaktorsautentisering","ui.totp.skip":"Skip Two-Factor Authentication"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[551],{2551:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! この接続は安全ではありません !!","ui.app.httpsDescription":"HTTPSでないと秘密のデータも暗号化しないで送信してしまいます。","ui.app.httpsLink":"詳細な情報","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! セーフモードが有効です !!","ui.app.safeModeDescription":"Contao Managerの一部の機能は利用できません。","ui.app.safeModeExit":"セーフモードを終了","ui.app.limitedHeadline":"リモート認証","ui.app.limitedDescription":"パスワードなしのログインのため限れた権限になっています。","ui.app.limitedLogout":"再認証","ui.app.totpHeadline":"セキュリティの注意","ui.app.totpDescription":"すぐに2ファクタ認証を構成してアカウントを安全にします。","ui.app.totpSetup":"セットアップ","ui.app.loading":"Contao Managerを読み込み中…","ui.app.apiError":"予期しないAPIの状態","ui.app.configSecurity1":"セキュリティ警告!!! 保護していない設定ディレクトリを検出","ui.app.configSecurity2":"Contao Managerは設定ファイルが公開してアクセスできる状態を検出しました。ディレクトリを安全な状態にするまで、すべての操作は動作しません、そうしないとインストールに含まれている極秘データを攻撃者がアクセスできる可能性があるためです。\\n\\nこれを修正するには\\"contao-manager\\"のディレクトリへのアクセスを禁止してください。この方法を学ぶには、ウェブサーバーのマニュアルを参照するかホスティング提供者に連絡してください。","ui.account.welcome":"ようこそ","ui.account.intro1":"Contao Managerにようこそ。Contao ManagerはContaoオープンソースCMSのインストールと管理を行う多才なツールです。Contao Managerを初めて利用する場合は{readTheManualToGetStarted}","ui.account.introGetStarted":"最初に{readTheManual} ","ui.account.introManual":"マニュアルを読んでください","ui.account.intro2":"何か問題があった場合は、{ourGithubIssues} を確認して、まだ報告されていない新しいどの様な問題は自由に新しいIssueを作成してください。","ui.account.introIssues":"GitHubのIssue","ui.account.headline":"ユーザーアカウント","ui.account.description":"インストールしたContaoを管理するには新しいアカウントを作成してください。このアカウントはContaoのバックエンドやフロントエンドとはまったく関係ないことに注意してください。","ui.account.username":"ユーザー名","ui.account.password":"パスワード","ui.account.passwordPlaceholder":"最小で8文字","ui.account.passwordLength":"少なくとも8文字を入力してください。","ui.account.loginInvalid":"アカウントの作成でエラーとなりました。異なるユーザー名で試してください。","ui.account.submit":"アカウントを作成","ui.account.usePassword":"ログインにパスワードを使用","ui.account.usePasskey":"パスキーをログインに使用","ui.account.totpHeadline":"2ファクター認証","ui.account.totpDescription":"2ファクター認証を有効にしてセキュリティレベルを高めてください。ユーザー名とパスワードに加えて、1Password、Authy、Google Authenticator、LastPass Authenticatorや他のTOTP(Time-based One-Time Password)アプリの確認コードの入力が必要となります。","ui.account.totpSetup":"すぐに設定","ui.account.totpSkip":"後で設定","ui.account.login":"申し出を拒否","ui.account.contribute1":"ContaoとContao Managerは非営利のContao Associationが支援しています。","ui.account.contribute2":"{donate}でオープンソースに貢献することをご検討ください。","ui.account.contributeDonate":"寄付をする","ui.login.headline":"サインイン","ui.login.description":"インストールを管理するにはログインします。","ui.login.username":"ユーザー名","ui.login.password":"パスワード","ui.login.totpHeadline":"2ファクター認証","ui.login.totpDescription":"確認コードを入力してログイン処理を完了してください。","ui.login.totp":"確認コード","ui.login.forgotPassword":"パスワードを忘れましたか?","ui.login.button":"サインイン","ui.login.passkey":"パスキーでサインイン","ui.login.cancel":"取り止め","ui.login.locked":"Contao Managerはロック状態のためアクセスを拒否しました。ロックを解除するには、Contaoのルートディレクトリにあるファイル: {lockFile}を削除してください。","ui.logout.headline":"セッションタイムアウト","ui.logout.warning":"25分以上アクセスがありません。セキュリティ上の理由から、セッションを間もなく終了します。","ui.logout.expired":"30分以上アクセスがなかったため自動的にセッションを終了しました。","ui.logout.renew":"ログインを維持","ui.logout.logout":"ログアウト","ui.logout.login":"ログイン画面に戻る","ui.oauth.error":"不正なOAuthの試みです。リクエストのパラメーターを確認してください。","ui.oauth.https":"平文で認証トークンが転送されることを防ぐため、リダイレクトのURIは安全なプロトコル(https:)を*使用*しなければなりません。","ui.oauth.headline":"リモート認証","ui.oauth.description":"以下のアプリケーションやサービスが、このContao Managerへのリモートアクセスを要求しています。","ui.oauth.domain":"アクセスを許可する前に、このURLのことを知っていて所有者を信頼できることを確認してください!","ui.oauth.outOfScope":"残念ですが、このアクセスを許可するのに十分な権限がありません。","ui.oauth.allow":"アクセスを許可","ui.oauth.deny":"アクセスを拒否","ui.oauth.switchUser":"ユーザーを切り替え","ui.scope.admin":"ユーザー管理を含んだ管理者アクセス","ui.scope.install":"新しいパッケージのインストールとContaoの構成の変更","ui.scope.update":"パッケージの更新と保守の作業の実行","ui.scope.read":"パッケージと構成の読み取り","ui.boot.headline":"システム検査","ui.boot.description":"しばらくお待ちください、サーバーを解析中です...","ui.boot.issue1":"インストール上の問題を検出","ui.boot.issue2":"Contao Managerを使用できるようにする前に修正しなければならない問題があります。","ui.boot.run":"Contao Managerを開始","ui.boot.safeMode":"セーフモードで開始","ui.recovery.headline":"システム回復","ui.recovery.description":"Contao ManagerはContaoと思われるファイルを検出しましたが、コマンド行のインターフェイスは期待した様に動作しませんでした。","ui.recovery.console":"コンソール出力","ui.recovery.repairOptions":"インストールしたContaoを修正する方法を選択してください。","ui.recovery.repairHeadline":"自動修復","ui.recovery.repairDescription":"アプリケーションキャッシュの再構築とComposerパッケージを再インストールすることで、自動的にインストールの修復を試みます。","ui.recovery.repairWarning":"この処理でベンダーのファイルに行った変更は取り消されるかもしれません!","ui.recovery.repairFailed":"自動修復できませんでした。セーフモードで手作業でインストールを修復してみてください。","ui.recovery.repairButton":"システム修復を実行","ui.recovery.safeModeHeadline":"セーフモード","ui.recovery.safeModeDescription":"Contao Managerをセーフモードで開始するとパッケージの管理と特定の保守のタスクを実行できます。しかし、インストールしたContaoの動作に依存した機能は利用できません。","ui.recovery.safeModeButton":"セーフモードで開始","ui.server.pending":"待機中...","ui.server.running":"解析中…","ui.server.error":"サーバーからの予期しない応答のため検査に失敗しました。","ui.server.details":"詳細","ui.server.prerequisite":"前提条件を満たせていないため検査を取り止めました。","ui.server.selfUpdate.title":"Contao Managerを更新","ui.server.selfUpdate.update":"新しいContao Managerのバージョン {latest} を利用できます。","ui.server.selfUpdate.manualUpdate":"新しいContao Managerバージョン{latest}を利用できます。使用しているサーバーは自動的な更新をサポートしていません、新しいバージョンを {download} からダウンロードしてください。","ui.server.selfUpdate.latest":"最新のバージョン: {current}を使用しています。","ui.server.selfUpdate.dev":"開発版は自動的な更新をサポートしていません。","ui.server.selfUpdate.unsupported":"新しいバージョンを利用できますが、使用しているPHPのバージョンをサポートしていません。","ui.server.selfUpdate.button":"自己更新を実行","ui.server.selfUpdate.continue":"続ける","ui.server.config.title":"サーバーの構成","ui.server.config.setup":"構成","ui.server.config.change":"変更","ui.server.config.save":"保存","ui.server.config.cancel":"取り止め","ui.server.config.customOption":"その他…","ui.server.config.description":"バックグラウンドのタスクを正しく実行するため、Contao ManagerはPHPのコマンド行の実行ファイルがある場所と、ウェブのプロセスから切り離してコマンドを実行する方法を知る必要があります。","ui.server.config.formTitle":"サーバーの構成","ui.server.config.formText":"PHPの実行ファイルのパスを入力してください。Webのプロセスと同じバージョンのPHPであることを忘れずに確認してください。","ui.server.config.cloudTitle":"Composerリゾルバークラウド","ui.server.config.cloudText":"Composerリゾルバークラウドによって、サーバーが十分なローカルのメモリを提供しない場合でもComposerの依存関係のインストールが可能になります。パッケージの情報がContao Associationが運用するクラウドに送信されることに注意してください。","ui.server.config.cloud":"Composerリゾルバークラウドを使用","ui.server.config.cli":"PHPの実行ファイル","ui.server.config.stateErrorCli":"有効なPHPの実行ファイルをサーバー上に見つけられませんでした。","ui.server.config.stateErrorCloud":"Composerリゾルバークラウドをサポートしていません。","ui.server.config.stateSuccess":"PHPの実行ファイルは{php_cli}です。","ui.server.php_web.title":"PHPのWebプロセス","ui.server.php_web.below7":"PHPのバージョン {version} を検出しました。可能な限りPHP 7に切り替えてください!","ui.server.php_web.success":"PHPのバージョン {version} を検出しました、既知の問題はありませんでした。","ui.server.php_cli.title":"PHPコマンド行インターフェイス","ui.server.php_cli.success":"PHPのバージョン {version} を検出しました、既知の問題はありませんでした。","ui.server.composer.title":"Composer環境","ui.server.composer.success":"既知の問題はありませんでした。","ui.server.composer.install":"Composerの依存関係はインストールしていません。","ui.server.composer.button":"インストール","ui.server.contao.title":"Contaoのインストール","ui.server.contao.setup":"セットアップ","ui.server.contao.check":"データベースを検査","ui.server.contao.empty":"インストールしているContaoは見つかりませんでした。","ui.server.contao.old":"Contaoのバージョン{version}はContao Managerと互換性がありません。インストールしているContaoを手作業で更新してください。","ui.server.contao.found":"Contao {version} (APIバージョン {api})を検出しました。","ui.server.contao.connectionError":"データベースサーバーに接続できません。","ui.server.contao.connectionProblem":"データベースの問題が見つかりました。","ui.server.contao.missingUser":"管理者のアカウントがありません。","ui.setup.continue":"続ける","ui.setup.manager":"Contao Managerを開始","ui.setup.cancel":"取り止め","ui.setup.welcome":"ようこそ","ui.setup.welcome1":"このウィザードはContaoオープンソースCMSを設定するのに必要な段階を案内します。","ui.setup.welcome2":"もし質問がありましたらドキュメント、フォーラム、Slackのチャンネル、さらに多くの情報を{support}のページから探してください。","ui.setup.support":"コミュニティサポート","ui.setup.start":"始める","ui.setup.complete":"おめでとうございます!","ui.setup.complete1":"Contao {version}をうまくインストールしました。","ui.setup.complete2":"設定の処理を終えるには、インストールツールを開いて、データベース接続を構成し、バックエンドのユーザーを作成してください。","ui.setup.complete3":"Contaoのバックエンドでウェブサイトを作成できるようになりました。追加の機能拡張が必要な場合は、Contao Managerを続けてください。","ui.setup.installTool":"インストールツールを開く","ui.setup.login":"Contaoにログイン","ui.setup.funding":"フリーソフトウェアの「フリー」は「言論の自由」の自由であって、「無料のビール」の「無料」ではありません。Contaoのようなオープンソースのプロジェクトは一人の個人や1つの会社では集められない資金を必要とします。\\nContaoでウェブサイトを構築したり、構築したウェブサイトを販売される場合は、ビジネスが依存する製品に金銭的に貢献されることを期待しています。","ui.setup.fundingLink":"さらに学ぶ","ui.setup.document-root.headline":"Webサーバーの設定","ui.setup.document-root.warning":"Contao ManagerからContaoをインストールするには、Webサーバーのドキュメントルートを修正しなければなりません。","ui.setup.document-root.description1":"Contaoは公開するファイルに別のフォルダーを使用し、その親のフォルダーにアプリケーションのファイルをインストールします。フォルダーの構造が正しくないか、またはフォルダーが空でない場合はContaoをインストールできません。","ui.setup.document-root.description2":"ドキュメントルートを構成する方法を知らない場合は、Contaoのドキュメントを読むかホスティングサービスの提供者に連絡してください。","ui.setup.document-root.documentation":"ドキュメントを読む","ui.setup.document-root.conflictsTitle":"インストール先のディレクトリが空ではありません","ui.setup.document-root.conflictsDirectory":"Contaoをインストールしようとしているルートのディレクトリが空ではありません、インストールの処理で{count}個のファイルを上書きするかもしれません。Contaoのために空のディレクトリ構造の作成を推奨しますが、以下のファイルを使用していないことが確かな場合は、これらを削除して再検査することもできます。","ui.setup.document-root.ignoreConflicts":"空でないディレクトリにContaoをインストールしようとしています。Web領域の既存のファイルを上書きする可能性を理解しています。","ui.setup.document-root.check":"再検査","ui.setup.document-root.create":"ディレクトリを作成","ui.setup.document-root.change":"ディレクトリを変更","ui.setup.document-root.formTitle":"ディレクトリ設定","ui.setup.document-root.formText1":"Contao Managerはサーバー上に新しいディレクトリ構成を自動的に作成できます。","ui.setup.document-root.formText2":"手作業で(例えば、ホスティングの管理パネルから)新しいドキュメントルートを構成する必要があります。","ui.setup.document-root.autoconfig":"サーバーの構成を変更しなければならないことを理解しました。ドキュメントルートを構成しないとContao Managerは壊れ、(アカウントの詳細とパスワードを含んだ)構成ファイルを剥き出しの状態にしてしまいます。","ui.setup.document-root.directory":"新しいディレクトリ","ui.setup.document-root.currentRoot":"現在のドキュメントルート","ui.setup.document-root.newRoot":"新しいドキュメントルート","ui.setup.document-root.finish":"ディレクトリの設定","ui.setup.document-root.publicDir":"{dir}を(Contao {version}の)公開ファイルの場所として使用","ui.setup.document-root.directoryInvalid":"有効なディレクトリの名前を入力してください。","ui.setup.document-root.directoryExists":"目的のディレクトリは既に存在します。異なる名前を入力してください。","ui.setup.document-root.confirmation":"Contao ManagerはContaoのインストールに必要なディレクトリを作成しました。次にウェブサーバーのドキュメントルートを構成しなければなりません。このページをそれまで再読み込みしないでください。","ui.setup.document-root.reload":"ページを再読み込み","ui.setup.document-root.success":"ウェブサーバーにディレクトリ構造を正しく設定できました!","ui.setup.document-root.installingProjectDir":"{dir}にアプリケーションのファイルをインストールします。","ui.setup.document-root.installingPublicDir":"{dir}に公開するファイルをインストールします。","ui.setup.document-root.installedProjectDir":"{dir}にアプリケーションのファイルをインストールしました。","ui.setup.document-root.installedPublicDir":"{dir}に公開するファイルをインストールしました。","ui.setup.create-project.headline":"Contaoのインストール","ui.setup.create-project.description":"Contaoの開発は{semver}の概念にしたがっていて、新しいマイナーバージョンを6か月毎にリリースします。現在サポートしているリリース:","ui.setup.create-project.semver":"セマンティックバージョニング","ui.setup.create-project.latestTitle":"最新","ui.setup.create-project.ltsTitle":"長期サポート版","ui.setup.create-project.latestQ1":"最新のバージョン、もっとも多くの機能を提供して{year}年2月までサポートします。","ui.setup.create-project.latestQ3":"最新のバージョン、もっとも多くの昨日を提供して{year}年8月までサポートします。","ui.setup.create-project.ltsText":"現在のLTSバージョン、安定性を重視する場合に選んでください。さらに{year}年2月までの長期サポートを提供します。","ui.setup.create-project.pltsText":"以前のLTSバージョン、さらに{year}年2月までの長期サポートを提供します。","ui.setup.create-project.requiresPHP":"少なくともPHP {version}が必要です、現在はPHP {current}です。","ui.setup.create-project.releaseplan":"詳細な情報は{contaoReleasePlan}を参照してください。","ui.setup.create-project.releaseplanLink":"Contaoのリリース計画","ui.setup.create-project.installed":"サーバーにContao {version}のインストールに成功しました。データベースの設定を続けるか、異なるバージョンをインストールするにはContao Managerを起動してください。","ui.setup.create-project.formTitle":"配布の選択","ui.setup.create-project.formText":"インストールするバージョンを選択してください。","ui.setup.create-project.version":"バージョン","ui.setup.create-project.demo":"Contaoのデモ版のWebサイトをインストール","ui.setup.create-project.demoDescription":"デモ版のWebサイトはContaoと、その基本的な特徴を知る助けとなります。テーマはさらに{store}で入手できます。","ui.setup.create-project.coreOnly":"最小のインストール(コアだけ)","ui.setup.create-project.noUpdate":"インストールを省く(専門家だけ!)","ui.setup.create-project.theme":"Contaoのテーマ","ui.setup.create-project.themeInstall":"Contaoのテーマをインストールするには、検索入力を使用するか、Contao Managerからのインストールをサポートしたテーマのファイル(.ctoまたは.zip)をアップロードしてください。","ui.setup.create-project.themeBuy":"必ず公式の{store}にアクセスしてください。","ui.setup.create-project.themeStore":"Contaoのテーマのストア","ui.setup.create-project.themeUpload":"テーマのファイル(.cto/.zip)をアップロード","ui.setup.create-project.themeInvalid":"アップロードしたファイルはContaoのテーマではないか、Contao Managerをサポートしていません。","ui.setup.create-project.themeWarning":"このテーマがサーバーと互換性があるかどうか、COntao Managerは判断できません。何か疑問がある場合はテーマのベンダーに相談してください。","ui.setup.create-project.themeTitle":"テーマの詳細を調査","ui.setup.create-project.themeDetails":"このテーマは以下の依存関係とファイルもインストールします。","ui.setup.create-project.themeRequire":"{count} 依存関係 | {count} 依存関係","ui.setup.create-project.themeFiles":"{count} ファイル | {count} ファイル","ui.setup.create-project.theme.or":"または公開テーマを検索","ui.setup.create-project.theme.search":"テーマを検索","ui.setup.create-project.theme.more":"さらにテーマ","ui.setup.create-project.theme.empty":"{query}に一致するテーマがありません。","ui.setup.create-project.theme.uploaded":"テーマのファイルのアップロードに成功しました。","ui.setup.create-project.theme.packageName":"パッケージ名","ui.setup.create-project.theme.version":"バージョン","ui.setup.create-project.theme.authors":"作成者","ui.setup.create-project.install":"インストール","ui.setup.create-project.cancel":"取り止め","ui.setup.database-connection.headline":"データベース接続","ui.setup.database-connection.description":"Contaoはページ、コンテント、ユーザー、他の関係のあるデータを保管するためにMySQLデータベース(またはMariaDBの様な互換性のある分岐)を必要とします。接続のパラメーターは、Contaoをインストールしたプロジェクトのルートにある{env}ファイルに保存します。","ui.setup.database-connection.formTitle":"接続パラメーター","ui.setup.database-connection.formText":"データベースのURLを入力するか、ユーザー名、パスワード、サーバー、データベースの欄を別々に入力してください。","ui.setup.database-connection.url":"データベースのURL","ui.setup.database-connection.validUrl":"データベースのURLが正しくないか、サーバーへの接続に失敗しました。","ui.setup.database-connection.or":"または","ui.setup.database-connection.user":"ユーザー名","ui.setup.database-connection.password":"パスワード","ui.setup.database-connection.server":"サーバー(:ポート)","ui.setup.database-connection.database":"データベース名","ui.setup.database-connection.connected":"{server}のデータベース{database}に接続しました。","ui.setup.database-connection.error":"データベースの接続のエラーです。","ui.setup.database-connection.problem":"Contaoはデータベースサーバーの問題を検出しました。","ui.setup.database-connection.schemaTitle":"データベーススキーマ","ui.setup.database-connection.migration":"未解決の移行が1件あります。 | 未解決の移行が{count}件あります。","ui.setup.database-connection.schema":"未解決のスキーマの更新が1件あります。 | 未解決のスキーマの更新が{count}件あります。","ui.setup.database-connection.noChanges":"データベースのスキーマは最新です。","ui.setup.database-connection.check":"データベースを検査","ui.setup.database-connection.skip":"飛ばす","ui.setup.database-connection.save":"保存","ui.setup.database-connection.change":"認証情報を変更","ui.setup.database-connection.restoreTitle":"データベースをインポート","ui.setup.database-connection.restoreText":"先ほどインストールしたテーマはデータベースのバックアップを含んでいます。データベースを復元してテーマのデータを取り込むか、空のContaoのインストールから始める場合はこの段階を飛ばしてください。 | 先ほどインストールしたテーマは複数のデータベースのバックアップを含んでいます。バックアップのファイルを選択してテーマのデータをインポートするか、空のContaoのインストールから始める場合はこの段階を飛ばしてください。","ui.setup.database-connection.backup":"インポート前に現在のデータベースをバックアップ","ui.setup.database-connection.backupWarning":"データベースのすべてのデータを上書きします。データベースが空でない場合は最初にバックアップを作成してください。","ui.setup.database-connection.restore":"テーマのデータベースをインポート","ui.setup.database-connection.restoreOption":"{date} ({size})からバックアップ","ui.setup.database-connection.restored":"テーマのデータベースのインポートに成功しました。データベースのスキーマの検証に進んでください。","ui.setup.backend-user.success":"データベースにContaoのバックエンドの管理者のアカウントがあります。さらにユーザーを追加するにはContaoのバックエンドを使用してください。","ui.setup.backend-user.error":"ユーザーのリストを取り出せません。詳細はコンソールの出力を確認してください。","ui.setup.backend-user.headline":"バックエンドのアカウント","ui.setup.backend-user.description":"ウェブサイトを管理するには、少なくともContaoのバックエンドの管理者のアカウントが1つ必要です。このアカウントはContao Managerと無関係なことに注意してください。","ui.setup.backend-user.formTitle":"アカウントを作成","ui.setup.backend-user.formText":"新しいバックエンドのアカウントの詳細を入力してください。","ui.setup.backend-user.username":"ユーザー名","ui.setup.backend-user.name":"名前","ui.setup.backend-user.email":"電子メールアドレス","ui.setup.backend-user.emailInvalid":"有効な電子メールアドレスを入力してください。","ui.setup.backend-user.password":"パスワード","ui.setup.backend-user.passwordPlaceholder":"最小で8文字","ui.setup.backend-user.passwordLength":"少なくとも8文字を入力してください。","ui.setup.backend-user.create":"アカウントを追加","ui.task.headline":"バックグランドのタスク","ui.task.loading":"詳細を読み込み中...","ui.task.created":"詳細を読み込み中...","ui.task.active":"Contao Managerがバックグラウンドでタスクの処理を実行を開始するまで、しばらくお待ちください。","ui.task.complete":"すべての処理を正常に完了しました。詳細はコンソールの出力を確認してください。","ui.task.aborting":"バックグラウンドの処理を取り消すまで、しばらくお待ちください。","ui.task.stopped":"バックグラウンドの処理の一部を取り消しました。コンソールの出力を確認してください。","ui.task.error":"バックグラウンドの処理が予期せず停止しました。コンソールの出力を確認してください。","ui.task.failed":"Contao Managerはバックグラウンドのタスクを開始できませんでした!","ui.task.failedDescription1":"バックグラウンドで処理を実行しようとするときに何か問題がありました。","ui.task.failedDescription2":"これが再度起きる場合は、サーバーはサポートされていないかもしれません。","ui.task.reportProblem":"問題を報告","ui.task.sponsor":"{sponsor}が後援のComposer Cloud","ui.task.buttonAudit":"データベースを更新","ui.task.buttonClose":"閉じる","ui.task.buttonConfirm":"確認して閉じる","ui.task.buttonCancel":"取り止め","ui.task.confirmCancel":"このタスクを本当に取り止めて良いですか? 取り止めるとContaoのインストールを壊れた状態のままにするかもしれません。","ui.task.autoclose":"正常に終了したときにタスクの詳細を閉じる","ui.console.toggle":"コンソールの出力を表示・非表示","ui.console.showLog":"完全なコンソールのログを表示","ui.console.copyLog":"ログをクリップボードにコピー","ui.migrate.headline":"データベースの更新","ui.migrate.migrationsOnly":"(移行だけ)","ui.migrate.schemaOnly":"(スキーマだけ)","ui.migrate.loading":"しばらくお待ちください、データベースを検査中です...","ui.migrate.empty":"未解決な移行やスキーマの更新はありません。データベースは最新です。","ui.migrate.emptyMigrations":"未解決な移行はありません。スキーマの更新も忘れずにしてください。","ui.migrate.emptySchema":"未解決なスキーマの更新はありません。移行の確認も忘れずにしてください。","ui.migrate.pending":"データベースが最新ではありません。以下のコンソール出力を再確認して変更を実行してください。","ui.migrate.previousChanges":"以前のデータベース移行を確認できませんでした。\\n以下のコンソール出力を再確認して、次の変更の確認に進んでください。","ui.migrate.previousComplete":"以前のデータベース移行を確認できませんでしたので、以下のコンソール出力を再確認してください。\\nこれ以上の未解決な変更はありません。","ui.migrate.appliedChanges":"データベースの更新を適用しました。\\n以下のコンソール出力を再確認して、次の変更の確認に進んでください。","ui.migrate.appliedComplete":"データベースの更新を適用しました。\\n未確認の移行やスキーマの更新はありません。データベースは最新の状態です。","ui.migrate.problem":"Contaoはデータベースサーバーの問題を検出しました。\\n下のコンソール出力を再確認して修正しなければならない事項を調査してください!","ui.migrate.warning":"Contaoはデータベースサーバーの誤った設定を検出しました。\\n一時的に警告は無視できますが、最適な性能とデータの一貫性のためには修正しなければなりません。","ui.migrate.error":"変更を適用できませんでした。データベースは変更されているかもしれません、再確認して再実行してください。","ui.migrate.execute":"実行","ui.migrate.close":"閉じる","ui.migrate.confirm":"確認して閉じる","ui.migrate.cancel":"取り止め","ui.migrate.continue":"続ける","ui.migrate.setup":"セットアップ","ui.migrate.skip":"飛ばす","ui.migrate.retry":"再検査","ui.migrate.retryAll":"すべて検査","ui.migrate.withDeletes":"DROPの処理を含む、すべてのデータベースの変更を実行します。","ui.migrate.migrationTitle":"データベースの移行","ui.migrate.schemaTitle":"スキーマの更新","ui.migrate.problemTitle":"データベースの問題","ui.migrate.warningTitle":"データベースの警告","ui.migrate.addTable":"テーブルを追加","ui.migrate.dropTable":"テーブルを削除","ui.migrate.addField":"項目{table}.{field}を追加","ui.migrate.changeField":"項目{table}.{field}を変更","ui.migrate.dropField":"項目{table}.{field}を削除","ui.migrate.createIndex":"{table}にインデックス\\"{name}\\"を作成","ui.migrate.dropIndex":"{table}のインデックス\\"{name}\\"を削除","ui.widget.mandatory":"この欄の入力は必須です。","ui.widget.blankOption":"選択してください…","ui.widget.showPassword":"パスワードを表示","ui.widget.hidePassword":"パスワードを非表示","ui.error.title":"\\"{method} {url}\\"というHTTPの要求に失敗しました。","ui.error.server500":"予期しないエラーがサーバーで発生したようです。Webサーバー(Apache/Nginx)のログファイルと、Contao Managerの\\"contao-manager/logs\\"へのログを確認してください。","ui.error.response":"サーバーは{status}という応答コードを返しました。","ui.error.moreLink":"詳細な情報","ui.error.support":"Contaoサポート","ui.error.permission":"この機能を使用する権限がありません。","ui.footer.help":"ヘルプ","ui.footer.reportProblem":"問題を報告","ui.navigation.discover":"発見","ui.navigation.packages":"パッケージ","ui.navigation.tools":"ツール","ui.navigation.installTool":"インストールツール","ui.navigation.backend":"Contaoのバックエンド","ui.navigation.debug":"Contaoのデバッグモード","ui.navigation.logViewer":"ログ表示","ui.navigation.phpinfo":"PHPの情報","ui.navigation.phpinfoLoading":"PHPの情報を読み込み中...","ui.navigation.maintenance":"保守","ui.navigation.rebuildCache":"キャッシュを再作成","ui.navigation.users":"アカウント","ui.navigation.systemCheck":"システム検査","ui.navigation.advanced":"詳細","ui.navigation.logout":"ログアウト","ui.maintenance.database.title":"データベースの移行とバックアップ","ui.maintenance.database.description":"データベースの移行はデータとテーブルのスキーマの一貫性を確保します。","ui.maintenance.database.migrations":"未解決のデータベース移行が1件 | 未解決のデータベース移行が{count}件","ui.maintenance.database.schemaUpdates":"未解決のスキーマの更新が1件 | 未解決のスキーマの更新が{count}件","ui.maintenance.database.error":"データベースの問題が見つかりました。","ui.maintenance.database.warning":"データベースの警告が見つかりました。","ui.maintenance.database.button":"データベースを検査","ui.maintenance.database.migrationOnly":"移行だけを検査","ui.maintenance.database.schemaOnly":"スキーマだけを検査","ui.maintenance.database.installTool":"インストールツールを開く","ui.maintenance.database.createBackup":"バックアップを作成","ui.maintenance.database.backupUnsupported":"このContaoのバージョンではデータベースのバックアップをサポートしていません。","ui.maintenance.database.backupList":"データベースのバックアップが1個あって、{date}に作成されています。 | データベースのバックアップが{count}個あって、最新のものは{date}に作成されています。","ui.maintenance.database.backupEmpty":"現在データベースのバックアップはありません。","ui.maintenance.rebuildCache.title":"アプリケーションキャッシュ","ui.maintenance.rebuildCache.description":"構成ファイルのいずれかを修正した後はアプリケーションキャッシュの再構築が必要です。","ui.maintenance.rebuildCache.rebuildProd":"実稼働用のキャッシュを再構築","ui.maintenance.rebuildCache.rebuildDev":"開発用のキャッシュを再構築","ui.maintenance.rebuildCache.clearProd":"実稼働用のキャッシュを消去","ui.maintenance.rebuildCache.clearDev":"開発用のキャッシュを消去","ui.maintenance.installTool.title":"Contaoインストールツール","ui.maintenance.installTool.description":"連続して3回誤ったパスワードを入力すると、Contaoのインストールツールは自動的にロック状態となります。","ui.maintenance.installTool.unlock":"インストールツールのロックを解除","ui.maintenance.installTool.lock":"インストールツールをロック","ui.maintenance.dumpAutoload.title":"Composerクラスローダー","ui.maintenance.dumpAutoload.description":"ComposerのオートローダーがPHPのクラスの読み込み担当します。rootのcomposer.jsonに独自のネームスペースを追加した後は、オートローダーを書き出さなければなりません。","ui.maintenance.dumpAutoload.button":"オートローダーを書き出し","ui.maintenance.composerInstall.title":"Composerの依存関係","ui.maintenance.composerInstall.description":"Composerの依存関係はアプリケーションのルートの{vendor}フォルダーに配置されています。{composerLock}ファイルを操作や手動でアップロードした後は依存関係の再インストールが必要な場合があります。","ui.maintenance.composerInstall.button":"インストーラーを実行","ui.maintenance.composerInstall.update":"Composerで更新を実行","ui.maintenance.composerCache.title":"Composerキャッシュ","ui.maintenance.composerCache.description":"Composerは性能向上のためにダウンロードしたパッケージをキャッシュします。壊れたファイルのような問題がある場合は、Composerキャッシュを削除して強制的に新しいダウンロードを行ってみてください。","ui.maintenance.composerCache.button":"キャッシュを消去","ui.maintenance.maintenanceMode.title":"保守モード","ui.maintenance.maintenanceMode.description":"Contaoを保守モードにするとウェブサイトでは\\"503 Service Unavailable\\"のテンプレートを表示します。","ui.maintenance.maintenanceMode.enable":"有効","ui.maintenance.maintenanceMode.disable":"無効","ui.maintenance.debugMode.title":"デバッグモード","ui.maintenance.debugMode.description":"{appDevPhp}のエントリーポイントにユーザーとパスワードを設定してデバッグモードを有効にします。","ui.maintenance.debugMode.descriptionJwt":"現在のドメインにデバッグ用のクッキーを設定してデバッグモードを有効にします。","ui.maintenance.debugMode.activate":"有効化","ui.maintenance.debugMode.deactivate":"無効化","ui.maintenance.debugMode.credentials":"認証情報","ui.maintenance.debugMode.user":"デバッグモードのユーザー名を入力してください。","ui.maintenance.debugMode.password":"デバッグモードのパスワードを入力してください。","ui.maintenance.opcodeCache.title":"Opcodeキャッシュ","ui.maintenance.opcodeCache.description":"Opcodeは高速な実行のためにPHPのファイルをウェブプロセス常にキャッシュします。変更後にファイルの変化を認識していないといった、特定の状況では削除しなければなりません。","ui.maintenance.opcodeCache.button":"キャッシュを切り詰め","ui.maintenance.safeMode":"セーフモードでは利用不可","ui.maintenance.unsupported":"このContaoのバージョンでは非サポート","ui.packages.updateButton":"パッケージを更新","ui.packages.searchButton":"パッケージを検索","ui.packages.searchPlaceholder":"パッケージを検索中…","ui.packages.uploadOverlay":"アップロードするファイルをドラッグアンドドロップ","ui.packages.uploadButton":"パッケージをアップロード","ui.packages.uploadMessage":"未確認の1個のアップロードがあります。 | 未確認の{count}個のアップロードがあります。","ui.packages.uploadApply":"アップロードを実行","ui.packages.uploadReset":"アップロードを削除","ui.packages.uploadIncomplete":"このファイルは完全にアップロードできていません。一旦削除削除してもう一度アップロードしてください。","ui.packages.uploadDuplicate":"このファイルを複数回アップロードした様です。重複しているファイルを削除してください。","ui.packages.uploadInstalled":"このファイルを既にインストールしています。重複しているファイルを削除してください。","ui.packages.uploadUnsupported":"インストールしたContaoはアップロードをサポートしていません。PHPのzip拡張のインストールと依存関係の更新を確認してください。","ui.packages.changesMessage":"未確認の1個の変更があります。 | 未確認の{count}個の変更があります。","ui.packages.changesDryrun":"変更を試行","ui.packages.changesApply":"変更を適用","ui.packages.changesApplyAll":"すべてのパッケージを更新","ui.packages.changesDryrunAll":"すべてのパッケージの変更を試行","ui.packages.changesReset":"変更をリセット","ui.packages.changesReview":"変更を見直し","ui.packagelist.loading":"読み込み中...","ui.packagelist.uploads":"アップロード","ui.packagelist.added":"新しいパッケージ","ui.packagelist.installed":"インストール済みのパッケージ","ui.package.hintRevert":"変更を取り消す","ui.package.hintNoupdate":"更新しない","ui.package.hintConstraint":"この変更を適用すると、このパッケージを{constraint}の制約によりインストールします。","ui.package.hintConstraintBest":"変更を適用すると、このパッケージの利用できる一番良いバージョンをインストールします。","ui.package.hintConstraintChange":"変更を適用すると、このパッケージへの制約は\\"{from}\\"から\\"{to}\\"に変更します。","ui.package.hintConstraintUpdate":"変更を適用すると、このパッケージを更新します。","ui.package.hintAdded":"変更を適用すると、このパッケージをインストールします。","ui.package.hintRemoved":"変更を適用すると、このパッケージを削除します。","ui.package.requiredTitle":"手作業で追加済み","ui.package.requiredText":"このパッケージはcomposer.jsonで必要としていますが、インストールされていません。","ui.package.removedTitle":"手作業で削除済み","ui.package.removedText":"このパッケージはcomposer.jsonから削除されています。","ui.package.installed":"インストール済み:","ui.package.version":"バージョン{version}","ui.package.additionalDownloads":"{count}個のダウンロード | {count}個のダウンロード","ui.package.additionalStars":"{count}のスター | {count}のスター","ui.package.editConstraint":"編集","ui.package.uploadConstraint":"この定数はアップロードしたパッケージで定義されています。","ui.package.updateButton":"更新","ui.package.removeButton":"削除","ui.package.installButton":"パッケージを追加","ui.package.installButtonShort":"追加","ui.package.detailsButton":"詳細","ui.package.latestConstraint":"最新のバージョン","ui.package.update":"更新を利用可能","ui.package.updateLatest":"最新のバージョン","ui.package.updateAvailable":"バージョン{version}を利用可能","ui.package.updateUnknown":"不明なバージョン","ui.package.updateConstraint":"バージョンの制約外に利用できる新しいバージョンがあります。","ui.package.incompatible":"{package}はContao {constraint}では動作しません。","ui.cloudStatus.headline":"Composerリゾルバークラウド","ui.cloudStatus.version":"バージョン{version}","ui.cloudStatus.waitingTime":"待ち時間","ui.cloudStatus.jobs":"現在のジョブ","ui.cloudStatus.workers":"ワーカー","ui.cloudStatus.approx":"{minutes}分","ui.cloudStatus.none":"なし","ui.cloudStatus.short":"ca. {minutes}分","ui.cloudStatus.long":"ca. {minutes}分{seconds}秒","ui.cloudStatus.error":"Composerリゾルバークラウドの状態を取得できません。保守または技術的な問題のため停止しているかもしれません。","ui.cloudStatus.button":"クラウドの状態","ui.cloudStatus.refresh":"クラウドの状態を更新","ui.log-viewer.loading":"読み込み中...","ui.log-viewer.empty":"サーバーにログファイルはありません。","ui.log-viewer.reload":"際読み込み","ui.log-viewer.file":"ログファイル","ui.log-viewer.channel":"チャネル","ui.log-viewer.channelTitle":"このメッセージを記録する先のチャネルです。","ui.log-viewer.level":"レベル","ui.log-viewer.levelTitle":"ログメッセージの深刻さです。","ui.log-viewer.timeHeader":"時刻","ui.log-viewer.messageHeader":"メッセージ","ui.log-viewer.showContext":"コンテキストを表示","ui.log-viewer.hideContext":"コンテキストを非表示","ui.log-viewer.showExtra":"追加を表示","ui.log-viewer.hideExtra":"追加を非表示","ui.log-viewer.more":" さらに読み込む...","ui.log-viewer.download":"ダウンロード","ui.log-viewer.downloadTitle":"\\"{file}\\"をダウンロード","ui.log-viewer.prodEnvironment":"実運用環境","ui.log-viewer.devEnvironment":"開発環境(デバッグモード)","ui.user-manager.loading":"ユーザーを読み込み中...","ui.user-manager.changePassword":"パスワードを変更","ui.user-manager.setupTotp":"2ファクター認証を設定","ui.user-manager.disableTotp":"2ファクター認証を無効","ui.user-manager.invite":"ユーザーを招待","ui.user-manager.delete":"削除","ui.user-manager.deleteConfirm":"ほんとうにユーザー: \\"{username}\\"を削除しますか?","ui.user-manager.deleted":"ユーザー: {username}を削除しました。","ui.user-manager.passwordHeadline":"パスワードを変更","ui.user-manager.passwordText":"パスワードを変更するには、現在のパスワードと新しいパスワードをそれぞれの欄に入力してください。","ui.user-manager.currentPassword":"現在のパスワード","ui.user-manager.newPassword":"新しいパスワード","ui.user-manager.passwordPlaceholder":"最小で8文字","ui.user-manager.submitPassword":"送信","ui.user-manager.passwordChanged":"パスワードを変更しました。","ui.user-manager.passwordError":"このパスワードは間違っています。","ui.user-manager.inviteHeadline":"ユーザーを招待","ui.user-manager.inviteText":"Contao Managerに複数のログイン情報が必要な場合、ここで招待のリンクを作成できます。このリンクを誰か、または他の機器で使用して、指定した権限の新しいアカウントを作成してください。","ui.user-manager.inviteSuccess1":"新しい招待のリンクを作成しました。以下のURLを使用して、このContao Managerの新しいユーザーを作成できます。この招待は(今から1週間後の){expires}に期限が切れます。","ui.user-manager.inviteSuccess2":"リンクをクリップボードにコピーしてください。一度だけ動作し、このダイアログを閉じた後に再び見ることはできません。","ui.user-manager.createInvitation":"招待のリンクを作成","ui.user-manager.clipboard":"クリップボードにコピー","ui.user-manager.permissions":"権限について学ぶ","ui.user-manager.cancel":"取り止め","ui.user-manager.close":"閉じる","ui.user-manager.you":"あなた","ui.totp.headline":"2ファクター認証","ui.totp.setupQr":"2FA/TOTPアプリでQRコードを読み取ってください。","ui.totp.setupCode":"QRコードを読み取れない場合は、このキーを代わりに入力してください: ","ui.totp.codeLabel":"確認コード","ui.totp.codeDescription":"2FA/TOTPアプリが生成した確認コードを入力してください。","ui.totp.disableText":"2ファクター認証を無効にするには確認コードを入力してください。","ui.totp.invalid":"確認コードが無効です。","ui.totp.enable":"有効","ui.totp.disable":"無効","ui.totp.cancel":"取り止め","ui.totp.enabled":"2ファクター認証を有効にしました。","ui.totp.disabled":"2ファクター認証を無効にしました。","ui.totp.setup":"2ファクター認証を設定","ui.totp.skip":"2ファクター認証を飛ばす"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[477],{6477:function(e){e.exports=JSON.parse('{"ui.app.httpsHeadline":"!! Unsichere Verbindung !!","ui.app.httpsDescription":"Ohne HTTPS werden deine vertraulichen Daten unverschlüsselt übertragen.","ui.app.httpsLink":"Weitere Informationen","ui.app.httpsHref":"https://https.cio.gov/everything/","ui.app.safeModeHeadline":"!! Abgesicherter Modus !!","ui.app.safeModeDescription":"Einige Funktionen des Contao Managers sind nicht verfügbar.","ui.app.safeModeExit":"Beenden","ui.app.limitedHeadline":"Remote-Anmeldung","ui.app.limitedDescription":"Du hast eingeschränkte Berechtigungen wegen automatischer Anmeldung.","ui.app.limitedLogout":"Neu anmelden","ui.app.totpHeadline":"Sicherheitshinweis","ui.app.totpDescription":"Konfiguriere jetzt die Zwei-Faktor-Anmeldung, um dein Konto sicherer zu machen.","ui.app.totpSetup":"Einrichtung","ui.app.loading":"Contao Manager wird geladen …","ui.app.apiError":"Unerwarteter API-Status","ui.app.configSecurity1":"SICHERHEITSWARNUNG !!! Das Konfigurationsverzeichnis ist ungeschützt","ui.app.configSecurity2":"Der Contao Manager hat erkannt, dass seine Konfigurationsdateien öffentlich erreichbar sind. Du musst diese Dateien schützen, bevor der Manager verwendet werden kann, da ein Angreifer sonst auf sensible Daten zugreifen könnte.\\n\\nUm dieses Problem zu beheben, schütze das Verzeichnis \\"contao-manager\\" auf deinem Server. Bei Fragen lies das Handbuch deines Webservers oder wende dich an deinen Hosting-Anbieter.","ui.account.welcome":"Willkommen","ui.account.intro1":"Willkommen zum Contao Manager, einem universellen Werkzeug, um das Contao Open Source CMS zu installieren, zu konfigurieren und zu warten. Wenn du den Manager zum ersten Mal einsetzt, {readTheManualToGetStarted}.","ui.account.introGetStarted":"{readTheManual} bevor du beginnst","ui.account.introManual":"lies die Dokumentation","ui.account.intro2":"Sollten Probleme auftreten, dann prüfe {ourGithubIssues}. Falls für dein Anliegen noch kein Ticket existiert, kannst du gern ein Neues erstellen.","ui.account.introIssues":"die Tickets auf GitHub","ui.account.headline":"Benutzerkonto","ui.account.description":"Erstelle ein Benutzerkonto, um deine Installation zu verwalten. Beachte, dass dieses Konto in keinem Zusammenhang mit dem Contao Backend oder Frontend steht.","ui.account.username":"Benutzername","ui.account.password":"Passwort","ui.account.passwordPlaceholder":"min. 8 Zeichen","ui.account.passwordLength":"Bitte gib mindestens 8 Zeichen ein.","ui.account.loginInvalid":"Beim erstellen des Konto ist ein Fehler aufgetreten. Bitte versuche einen anderen Benutzernamen.","ui.account.submit":"Benutzerkonto erstellen","ui.account.usePassword":"Mit Passwort anmelden","ui.account.usePasskey":"Mit Passkey anmelden","ui.account.totpHeadline":"Zwei-Faktor Anmeldung","ui.account.totpDescription":"Bitte aktivieren die Zwei-Faktor-Anmeldung, welche dein Konto sicherer macht. Zusätzlich zu deinem Benutzernamen und Passwort musst du einen Sicherheitscode eingeben, welcher von einer Zwei-Faktor-App wie 1Password, Authy, Google Authenticator, Microsoft Authenticator, LassPass Authenticator oder einer beliebigen anderen TOTP-App erzeugt wird.","ui.account.totpSetup":"Jetzt einrichten","ui.account.totpSkip":"Später einrichten","ui.account.login":"Einladung ablehnen","ui.account.contribute1":"Contao und der Contao Manager werden durch die Contao Association gefördert.","ui.account.contribute2":"{donate} und leiste deinen Beitrag zu Open Source!","ui.account.contributeDonate":"Mach eine Spende","ui.login.headline":"Anmelden","ui.login.description":"Melde dich an, um deine Installation zu verwalten.","ui.login.username":"Benutzername","ui.login.password":"Passwort","ui.login.totpHeadline":"Zwei-Faktor Anmeldung","ui.login.totpDescription":"Bitte gibt den Sicherheitscode ein, umd die Anmeldung abzuschliessen.","ui.login.totp":"Sicherheitscode","ui.login.forgotPassword":"Passwort vergessen?","ui.login.button":"Anmelden","ui.login.passkey":"Mit Passkey anmelden","ui.login.cancel":"Abbrechen","ui.login.locked":"Der Zugriff wurde verweigert, da der Contao Manager gesperrt ist. Zum Entsperren lösche die Datei {lockFile} in deinem Contao Hauptverzeichnis.","ui.logout.headline":"Session-Timeout","ui.logout.warning":"Du warst mehr als 25 Minuten inaktiv. Aus Sicherheitsgründen wird deine Sitzung in Kürze beendet.","ui.logout.expired":"Deine Sitzung wurde automatisch beendet, da du mehr als 30 Minuten inaktiv warst.","ui.logout.renew":"Angemeldet bleiben","ui.logout.logout":"Abmelden","ui.logout.login":"Zurück zum Login","ui.oauth.error":"Ungültiger OAuth-Versuch. Bitte überprüfe die Request-Parameter.","ui.oauth.https":"Die Rückleitungs-URL MUSS eine sichere Verbindung (https:) nutzen, um die Übertragung der Anmeldedaten im Klartext zu verhindern.","ui.oauth.headline":"Remote-Anmeldung","ui.oauth.description":"Die folgende Anwendung oder der folgende Dienst fordert den Fernzugriff auf deine Contao Manager-Instanz an.","ui.oauth.domain":"Bevor du diesen Zugriff erlaubst, stelle sicher, dass du die URL kennst und ihr vertraust!","ui.oauth.outOfScope":"Du hast leider nicht genügend Berechtigungen um diesen Zugriff zu gewähren.","ui.oauth.allow":"Zugriff erlauben","ui.oauth.deny":"Zugriff verweigern","ui.oauth.switchUser":"Benutzer wechseln","ui.scope.admin":"Admin-Zugriff inkl. Benutzerverwaltung","ui.scope.install":"Pakete installieren und Contao-Konfiguration ändern","ui.scope.update":"Pakete aktualisieren und Wartungsaufgaben ausführen","ui.scope.read":"Pakete und Konfiguration sehen","ui.boot.headline":"Systemprüfung","ui.boot.description":"Bitte warten, dein Server wird überprüft …","ui.boot.issue1":"Installationsprobleme erkannt","ui.boot.issue2":"Du musst die Installationsprobleme beheben, bevor der Contao Manager verwendet werden kann.","ui.boot.run":"Contao Manager starten","ui.boot.safeMode":"Abgesicherten Modus starten","ui.recovery.headline":"Systemwiederherstellung","ui.recovery.description":"Es wurden Dateien erkannt, die nach einer Contao-Installation aussehen, aber die Kommandozeile scheint nicht korrekt zu funktionieren.","ui.recovery.console":"Konsolenausgabe","ui.recovery.repairOptions":"Wähle eine Option, um das System zu reparieren.","ui.recovery.repairHeadline":"Automatische Reparatur","ui.recovery.repairDescription":"Versucht eine automatische Systemreparatur, indem der Cache neu aufgebaut und die Composer-Pakete neu installiert werden.","ui.recovery.repairWarning":"Manuelle Änderungen an den vendor-Dateien können dabei verloren gehen!","ui.recovery.repairFailed":"Die automatische Reparatur ist fehlgeschlagen. Versuche den abgesicherten Modus, um die Installation von Hand zu reparieren.","ui.recovery.repairButton":"Reparatur ausführen","ui.recovery.safeModeHeadline":"Abgesicherter Modus","ui.recovery.safeModeDescription":"Der abgesicherte Modus erlaubt die Paketverwaltung und gewisse Wartungsaufgaben, aber Funktionen, welche ein funktionierendes Contao benötigen, sind nicht verfügbar.","ui.recovery.safeModeButton":"Abgesicherten Modus starten","ui.server.pending":"Warten …","ui.server.running":"Analysiere …","ui.server.error":"Die Prüfung ist aufgrund einer unerwarteten Server-Antwort fehlgeschlagen.","ui.server.details":"Details","ui.server.prerequisite":"Prüfung aufgrund fehlender Abhängigkeiten abgebrochen.","ui.server.selfUpdate.title":"Updates für den Contao Manager","ui.server.selfUpdate.update":"Die neue Version {latest} des Contao Managers ist verfügbar.","ui.server.selfUpdate.manualUpdate":"Eine neue Version {latest} des Contao Manager ist verfügbar. Dein Server unterstützt keine automatischen Updates, bitte lade die neue Version von {download} herunter.","ui.server.selfUpdate.latest":"Du verwendest die aktuelle Version {current}.","ui.server.selfUpdate.dev":"Entwicklungs-Versionen können nicht automatisch aktualisiert werden.","ui.server.selfUpdate.unsupported":"Eine neue Version ist verfügbar, aber diese funktioniert nicht mit deiner PHP-Version.","ui.server.selfUpdate.button":"Aktualisieren","ui.server.selfUpdate.continue":"Weiter","ui.server.config.title":"Serverkonfiguration","ui.server.config.setup":"Konfigurieren","ui.server.config.change":"Ändern","ui.server.config.save":"Speichern","ui.server.config.cancel":"Abbrechen","ui.server.config.customOption":"Andere …","ui.server.config.description":"Der Contao Manager benötigt den Pfad zum PHP-Binary und weitere Server-Informationen, um Hintergrund-Prozesse korrekt auszuführen.","ui.server.config.formTitle":"Serverkonfiguration","ui.server.config.formText":"Bitte gib den Pfad zu deinem PHP-Binary ein. Das Binary muss dieselbe PHP-Version sein wie der Webprozess.","ui.server.config.cloudTitle":"Composer Resolver Cloud","ui.server.config.cloudText":"Die Composer Resolver Cloud erlaubt die Installation von Composer-Abhängigkeiten, selbst wenn der lokale Server nicht über genug Arbeitsspeicher verfügt. Beachte, dass deine Paketinformationen an einen Cloud-Dienst der Contao Association übermittelt werden.","ui.server.config.cloud":"Die Composer Resolver Cloud verwenden","ui.server.config.cli":"PHP-Binary","ui.server.config.stateErrorCli":"Es wurde kein valides PHP-Programm auf dem Server gefunden.","ui.server.config.stateErrorCloud":"Die Composer Resolver Cloud wird nicht unterstützt.","ui.server.config.stateSuccess":"PHP-Binary in {php_cli}.","ui.server.php_web.title":"PHP-Webprozess","ui.server.php_web.below7":"PHP Version {version} gefunden. Bitte wechsle baldmöglichst auf PHP 7!","ui.server.php_web.success":"PHP Version {version}, keine bekannten Probleme gefunden.","ui.server.php_cli.title":"PHP Kommandozeilen-Programm","ui.server.php_cli.success":"PHP Version {version}, keine bekannten Probleme gefunden.","ui.server.composer.title":"Composer-Umgebung","ui.server.composer.success":"Keine bekannten Probleme gefunden.","ui.server.composer.install":"Composer-Abhängigkeiten sind nicht installiert.","ui.server.composer.button":"Installieren","ui.server.contao.title":"Contao-Installation","ui.server.contao.setup":"Einrichtung","ui.server.contao.check":"Datenbank prüfen","ui.server.contao.empty":"Es wurde keine Contao-Installation gefunden.","ui.server.contao.old":"Contao {version} ist nicht kompatibel mit dem Contao Manager; bitte aktualisiere deine Installation manuell.","ui.server.contao.found":"Contao {version} (API-Version {api}) gefunden.","ui.server.contao.connectionError":"Verbindung zum Datenbank-Server fehlgeschlagen.","ui.server.contao.connectionProblem":"Datenbank-Problem gefunden.","ui.server.contao.missingUser":"Administratorkonto nicht gefunden.","ui.setup.continue":"Weiter","ui.setup.manager":"Contao Manager starten","ui.setup.cancel":"Abbrechen","ui.setup.welcome":"Willkommen","ui.setup.welcome1":"Dieser Assistent führt dich durch die Installation und Einrichtung deines Contao Open Source CMS.","ui.setup.welcome2":"Solltest du Fragen haben, findest du die Dokumentation, das Forum, den Slack Kanal und weiteres auf der {support}-Seite.","ui.setup.support":"Contao-Support","ui.setup.start":"Los geht\'s","ui.setup.complete":"Geschafft!","ui.setup.complete1":"Contao {version} wurde erfolgreich installiert.","ui.setup.complete2":"Um die Installation fertig zu stellen, öffne bitte das Install-Tool um die Datenbank zu verbinden und ein Backend-Konto hinzuzufügen.","ui.setup.complete3":"Du kannst nun deine Webseite im Contao Backend einrichten. Willst du Erweiterungen installieren, fahre mit dem Contao Manager fort.","ui.setup.installTool":"Install-Tool öffnen","ui.setup.login":"Contao Login","ui.setup.funding":"Ohne seine Community wäre Contao nicht das, was es heute ist. Wenn du professionell Webseiten mit Contao erstellst, sind wir auf deine Unterstützung angewiesen. Mit einer Investition in das Projekt sicherst du die Entwicklung für die Zukunft, damit dein Unternehmen weiterhin von Contao profitieren kann.","ui.setup.fundingLink":"Weitere Informationen","ui.setup.document-root.headline":"Webserver-Einrichtung","ui.setup.document-root.warning":"Um Contao über den Contao Manager zu installieren, muss das Wurzelverzeichnis des Webservers angepasst werden.","ui.setup.document-root.description1":"Contao verwendet einen Unterordner für öffentliche Dateien, die Systemdaten werden im übergeordneten Ordner installiert. Contao kann nicht installiert werden, wenn die Struktur nicht stimmt oder die Ordner nicht leer sind.","ui.setup.document-root.description2":"Falls du nicht weisst, wie dein Wurzelverzeichnis konfiguriert werden kann, lies die Contao Dokumentation oder kontaktiere deinen Hosting-Anbieter.","ui.setup.document-root.documentation":"Dokumentation lesen","ui.setup.document-root.conflictsTitle":"Installationsverzeichnis nicht leer","ui.setup.document-root.conflictsDirectory":"Das Wurzelverzeichnis deiner zukünftigen Contao-Installation ist nicht leer, es wurden {count} Datei(en) gefunden, die bei der Installation überschrieben werden könnten. Es wird empfohlen Contao in ein leeres Verzeichnis zu installieren, aber du kannst auch die Dateien löschen und erneut prüfen lassen, wenn du sicher bist, dass diese nicht benötigt werden.","ui.setup.document-root.ignoreConflicts":"Ich will Contao in ein nicht-leeres Verzeichnis installieren. Ich verstehe, dass dadurch bestehende Dateien auf meinem Server möglicherweise überschrieben werden.","ui.setup.document-root.check":"Erneut prüfen","ui.setup.document-root.create":"Verzeichnisse erstellen","ui.setup.document-root.change":"Verzeichnisse ändern","ui.setup.document-root.formTitle":"Verzeichnisstruktur einrichten","ui.setup.document-root.formText1":"Der Contao Manager kann automatisch eine neue Verzeichnisstruktur auf dem Server einrichten.","ui.setup.document-root.formText2":"Du musst das Wurzelverzeichnis danach manuell umkonfigurieren (z. B. über die Hosting-Administration).","ui.setup.document-root.autoconfig":"Ich habe verstanden, dass meine Server-Konfiguration geändert werden muss. Wenn ich dies nicht tue, funktioniert der Contao Manager nicht mehr und meine Konfigurationsdateien (inklusive Benutzer & Passwörter) werden öffentlich erreichbar!","ui.setup.document-root.directory":"Neuer Ordner","ui.setup.document-root.currentRoot":"Aktuelles Wurzelverzeichnis","ui.setup.document-root.newRoot":"Neues Wurzelverzeichnis","ui.setup.document-root.finish":"Ordner erstellen","ui.setup.document-root.publicDir":"{dir} für öffentliche Dateien nutzen (Contao {version})","ui.setup.document-root.directoryInvalid":"Bitte gib einen gültigen Ordnernamen ein.","ui.setup.document-root.directoryExists":"Das Zielverzeichnis ist bereits vorhanden. Bitte gibt einen anderen Namen ein.","ui.setup.document-root.confirmation":"Der Contao Manager hat die benötigten Verzeichnisse erfolgreich angelegt. Nun musst du dein Wurzelverzeichnis anpassen. Lade die Seite nicht neu, bis dies erledigt ist.","ui.setup.document-root.reload":"Neu laden","ui.setup.document-root.success":"Die Verzeichnisstruktur auf deinem Server ist korrekt eingerichtet!","ui.setup.document-root.installingProjectDir":"Systemdateien werden nach {dir} installiert.","ui.setup.document-root.installingPublicDir":"Öffentliche Dateien werden nach {dir} installiert.","ui.setup.document-root.installedProjectDir":"Systemdateien sind in {dir} installiert.","ui.setup.document-root.installedPublicDir":"Öffentliche Dateien sind in {dir} installiert.","ui.setup.create-project.headline":"Contao-Installation","ui.setup.create-project.description":"Die Contao-Entwicklung folgt dem Prinzip von {semver}, eine neue Minor-Version wird alle sechs Monate veröffentlicht. Die aktuell unterstützten Versionen sind:","ui.setup.create-project.semver":"Semantic Versioning","ui.setup.create-project.latestTitle":"Neuste","ui.setup.create-project.ltsTitle":"Langzeit-Support","ui.setup.create-project.latestQ1":"Unsere neuste Version mit den meisten Funktionen, wird bis Februar {year} unterstützt.","ui.setup.create-project.latestQ3":"Unsere neuste Version mit den meisten Funktionen, wird bis August {year} unterstützt.","ui.setup.create-project.ltsText":"Unsere aktuelle LTS-Version mit Fokus auf Stabilität. Bietet einen verlängerten Supportzeitraum bis Februar {year}.","ui.setup.create-project.pltsText":"Die vorherige LTS-Version, hat einen verlängerten Supportzeitraum bis Februar {year}","ui.setup.create-project.requiresPHP":"Benötigt mindestens PHP {version}, du hast PHP {current}.","ui.setup.create-project.releaseplan":"Weitere Details findest du im {contaoReleasePlan}.","ui.setup.create-project.releaseplanLink":"Contao Release-Plan","ui.setup.create-project.installed":"Contao {version} wurde erfolgreich auf dem Server installiert. Fahre weiter, um die Datenbank einzurichten, oder gehe zum Contao Manager um eine andere Version zu installieren.","ui.setup.create-project.formTitle":"Wähle eine Distribution","ui.setup.create-project.formText":"Bitte wähle die zu installierende Version.","ui.setup.create-project.version":"Version","ui.setup.create-project.demo":"Beispiel-Webseite installieren","ui.setup.create-project.demoDescription":"Die Beispiel-Webseite von Contao hilft dir dabei, dich mit dem System und seinen Hauptfunktionen vertraut zu machen. Weitere Themes findest du im {store}.","ui.setup.create-project.coreOnly":"Minimale Installation (nur Core)","ui.setup.create-project.noUpdate":"Installation überspringen (Expertenmodus!)","ui.setup.create-project.theme":"Theme für Contao","ui.setup.create-project.themeInstall":"Um ein Theme für Contao zu installieren, benutze die Sucheingabe oder lade eine Theme-Datei (.cto/.zip) hoch, die den Contao Manager unterstützt.","ui.setup.create-project.themeBuy":"Besuche auch den {store}.","ui.setup.create-project.themeStore":"Contao Themes-Store","ui.setup.create-project.themeUpload":"Theme-Datei (.cto/.zip) hochladen","ui.setup.create-project.themeInvalid":"Die hochgeladene Datei ist kein Theme für Contao oder unterstützt die Installation im Contao Manager nicht.","ui.setup.create-project.themeWarning":"Der Contao Manager kann nicht beurteilen, ob dieses Theme mit deinem Server kompatibel ist. Wende dich bei Fragen bitte direkt an den Theme-Hersteller.","ui.setup.create-project.themeTitle":"Theme-Details überprüfen","ui.setup.create-project.themeDetails":"Die nachfolgenden Abhängigkeiten und Dateien werden mit diesem Theme installiert.","ui.setup.create-project.themeRequire":"{count} Abhängigkeit | {count} Abhängigkeiten","ui.setup.create-project.themeFiles":"{count} Datei | {count} Dateien","ui.setup.create-project.theme.or":"oder suche öffentliche Themes","ui.setup.create-project.theme.search":"Themes durchsuchen","ui.setup.create-project.theme.more":"Weitere Themes","ui.setup.create-project.theme.empty":"Keine Theme für {query} gefunden","ui.setup.create-project.theme.uploaded":"Die Theme-Datei wurde erfolgreich hochgeladen.","ui.setup.create-project.theme.packageName":"Paketname","ui.setup.create-project.theme.version":"Version","ui.setup.create-project.theme.authors":"Autor(en)","ui.setup.create-project.install":"Installieren","ui.setup.create-project.cancel":"Abbrechen","ui.setup.database-connection.headline":"Datenbank-Verbindung","ui.setup.database-connection.description":"Contao benötigt eine MySQL Datenbank (oder ein kompatibler Fork wie MariaDB), um Seiten, Inhalte und andere Daten zu speichern. Die Verbindungsdaten werden in der Datei {env} im Systemverzeichnis von Contao gespeichert werden.","ui.setup.database-connection.formTitle":"Verbindungs-Parameter","ui.setup.database-connection.formText":"Gib eine Datenbank-URL ein, oder fülle die Felder für Benutzername, Passwort, Server und Datenbank separat aus.","ui.setup.database-connection.url":"Datenbank-URL","ui.setup.database-connection.validUrl":"Datenbank-URL ungültig oder Verbindung zum Server fehlgeschlagen.","ui.setup.database-connection.or":"oder","ui.setup.database-connection.user":"Benutzername","ui.setup.database-connection.password":"Passwort","ui.setup.database-connection.server":"Server (:Port)","ui.setup.database-connection.database":"Datenbankname","ui.setup.database-connection.connected":"Erfolgreich verbunden mit Datenbank {database} auf {server}.","ui.setup.database-connection.error":"Fehler beim Verbinden mit der Datenbank.","ui.setup.database-connection.problem":"Contao hat ein Problem mit dem Datenbank-Server gefunden.","ui.setup.database-connection.schemaTitle":"Datenbank-Schema","ui.setup.database-connection.migration":"Es gibt eine ausstehende Migration. | Es gibt {count} ausstehende Migrationen.","ui.setup.database-connection.schema":"Es gibt eine ausstehende Schema-Änderung. | Es gibt {count} ausstehende Schema-Änderungen.","ui.setup.database-connection.noChanges":"Dein Datenbank-Schema ist aktuell.","ui.setup.database-connection.check":"Datenbank prüfen","ui.setup.database-connection.skip":"Überspringen","ui.setup.database-connection.save":"Speichern","ui.setup.database-connection.change":"Zugangsdaten ändern","ui.setup.database-connection.restoreTitle":"Datenbank-Import","ui.setup.database-connection.restoreText":"Das soeben installierte Theme enthält ein Datenbank-Backup. Du kannst diese Theme-Daten in die Datenbank importieren oder diesen Schritt überspringen und mit einem leeren Contao beginnen. | Das soeben installierte Theme enthält mehrere Datenbank-Backups. Wähle eine Backup-Datei für den Import oder überspringe diesen Schritt, um mit einem leeren Contao zu beginnen.","ui.setup.database-connection.backup":"Datenbank vor dem Import sichern","ui.setup.database-connection.backupWarning":"Alle Daten in der Datenbank werden beim Import überschrieben! Erstelle zuerst ein Backup, falls die Datenbank nicht leer ist.","ui.setup.database-connection.restore":"Theme importieren","ui.setup.database-connection.restoreOption":"Backup vom {date} ({size})","ui.setup.database-connection.restored":"Die Theme-Datenbank wurde erfolgreich importiert. Fahre fort, um das Datenbank-Schema zu überprüfen.","ui.setup.backend-user.success":"Es ist bereits ein Benutzerkonto in der Datenbank vorhanden. Weitere Konten können über das Backend hinzugefügt werden.","ui.setup.backend-user.error":"Die Benutzerliste konnte nicht gelesen werden. Weitere Details findest du in der Konsolen-Ausgabe.","ui.setup.backend-user.headline":"Backend-Konto","ui.setup.backend-user.description":"Um deine Webseite zu verwalten, benötigst du mindestens ein Administratorkonto für das Contao Backend. Beachte, dass dieses Konto nicht mit dem Contao Manager zusammenhängt.","ui.setup.backend-user.formTitle":"Benutzerkonto erstellen","ui.setup.backend-user.formText":"Bitte gib die Details für das neue Backend-Konto ein.","ui.setup.backend-user.username":"Benutzername","ui.setup.backend-user.name":"Name","ui.setup.backend-user.email":"E-Mail-Adresse","ui.setup.backend-user.emailInvalid":"Bitte gib eine gültige E-Mail-Adresse ein","ui.setup.backend-user.password":"Passwort","ui.setup.backend-user.passwordPlaceholder":"min. 8 Zeichen","ui.setup.backend-user.passwordLength":"Bitte gib mindestens 8 Zeichen ein.","ui.setup.backend-user.create":"Konto hinzufügen","ui.task.headline":"Hintergrund-Prozess","ui.task.loading":"Lade Details …","ui.task.created":"Lade Details …","ui.task.active":"Bitte warte, während der Contao Manager die nötigen Operationen im Hintergrund ausführt.","ui.task.complete":"Alle Operationen erfolgreich abgeschlossen. Weitere Details findest du in der Konsolen-Ausgabe.","ui.task.aborting":"Bitte warte, während der Hintergrund-Prozess abgebrochen wird.","ui.task.stopped":"Einige Operationen wurden abgebrochen. Bitte prüfe die Konsolen-Ausgabe.","ui.task.error":"Ein Hintergrund-Prozess wurde unerwartet beendet. Bitte prüfe die Konsolen-Ausgabe.","ui.task.failed":"Der Contao Manager konnte den Hintergrund-Prozess nicht starten.","ui.task.failedDescription1":"Die Ausführung der Aufgabe ist fehlgeschlagen.","ui.task.failedDescription2":"Sollte dies wiederholt geschehen, wird dein Server möglicherweise nicht unterstützt.","ui.task.reportProblem":"Probleme melden","ui.task.sponsor":"Composer Cloud gesponsert von {sponsor}","ui.task.buttonAudit":"Datenbank aktualisieren","ui.task.buttonClose":"Schließen","ui.task.buttonConfirm":"Bestätigen & Schließen","ui.task.buttonCancel":"Abbrechen","ui.task.confirmCancel":"Möchtest du diesen Prozess wirklich abbrechen? Deine Contao-Installation könnte in einem defekten Zustand zurückbleiben!","ui.task.autoclose":"Fenster bei Erfolg schließen","ui.console.toggle":"Konsolenausgabe anzeigen/verstecken","ui.console.showLog":"Vollständige Konsole anzeigen","ui.console.copyLog":"Konsole in Zwischenablage kopieren","ui.migrate.headline":"Datenbank-Änderungen","ui.migrate.migrationsOnly":"(nur Migrationen)","ui.migrate.schemaOnly":"(nur Schema)","ui.migrate.loading":"Bitte warten, die Datenbank wird überprüft …","ui.migrate.empty":"Keine ausstehenden Migrationen oder Schema-Änderungen gefunden. Deine Datenbank ist auf dem aktuellsten Stand.","ui.migrate.emptyMigrations":"Keine ausstehenden Migrationen gefunden. Bitte prüfe auch die Schema-Änderungen.","ui.migrate.emptySchema":"Keine ausstehenden Schema-Änderungen gefunden. Bitte prüfe auch die Migrationen.","ui.migrate.pending":"Die Datenbank ist nicht aktuell. Bitte prüfe die untenstehende Konsolenausgabe und führe die Änderungen aus.","ui.migrate.previousChanges":"Eine vorherige Datenbankmigration wurde nicht bestätigt.\\nBitte prüfen die untenstehende Konsolenausgabe und klicke weiter, um die nächsten Änderungen zu sehen.","ui.migrate.previousComplete":"Eine vorherige Datenbankmigration wurde nicht bestätigt, bitte prüfe die untenstehende Konsolenausgabe.\\nEs gibt keine weiteren ausstehenden Änderungen.","ui.migrate.appliedChanges":"Die Datenbankänderungen wurden übernommen.\\nBitte prüfe die untenstehende Konsolenausgabe, dann klicke weiter, um die nächsten Änderungen zu sehen.","ui.migrate.appliedComplete":"Die Datenbankänderungen wurden übernommen.\\nEs gibt keine weiteren Migrationen oder Schema-Änderungen. Deine Datenbank ist auf dem aktuellen Stand.","ui.migrate.problem":"Contao hat ein Problem mit dem Datenbank-Server gefunden.\\nBitte prüfe die Konsolen-Ausgabe unten, um zu sehen was angepasst werden muss. | Contao hat Probleme mit dem Datenbank-Server gefunden.\\nBitte prüfe die Konsolen-Ausgabe unten, um zu sehen was angepasst werden muss.","ui.migrate.warning":"Contao hat eine Fehlkonfiguration des Datenbank-Servers gefunden.\\nDie unten stehenden Warnungen sollten für optimalen Betrieb und Datensicherheit behoben werden.","ui.migrate.error":"Die Änderungen konnten nicht angewendet werden. Möglicherweise wurde die Datenbank geändert, bitte prüfe nochmals und versuche es erneut.","ui.migrate.execute":"Ausführen","ui.migrate.close":"Schließen","ui.migrate.confirm":"Bestätigen & Schließen","ui.migrate.cancel":"Abbrechen","ui.migrate.continue":"Weiter","ui.migrate.setup":"Einrichtung","ui.migrate.skip":"Überspringen","ui.migrate.retry":"Erneut prüfen","ui.migrate.retryAll":"Alles überprüfen","ui.migrate.withDeletes":"Alle Änderungen inklusive Löschungen anwenden.","ui.migrate.migrationTitle":"Datenbank-Migrationen","ui.migrate.schemaTitle":"Schema-Änderungen","ui.migrate.problemTitle":"Datenbank-Probleme","ui.migrate.warningTitle":"Datenbank-Warnungen","ui.migrate.addTable":"Tabelle {table} hinzufügen","ui.migrate.dropTable":"Tabelle {table} löschen","ui.migrate.addField":"Feld {table}.{field} hinzufügen","ui.migrate.changeField":"Feld {table}.{field} ändern","ui.migrate.dropField":"Feld {table}.{field} löschen","ui.migrate.createIndex":"Index \\"{name}\\" zu {table} hinzufügen","ui.migrate.dropIndex":"Index \\"{name}\\" aus {table} löschen","ui.widget.mandatory":"Dieses Feld darf nicht leer sein.","ui.widget.blankOption":"Bitte wählen …","ui.widget.showPassword":"Passwort anzeigen","ui.widget.hidePassword":"Passwort ausblenden","ui.error.title":"HTTP-Anfrage für \\"{method} {url}\\" fehlgeschlagen.","ui.error.server500":"Es scheint ein unbekannter Fehler aufgetreten zu sein. Prüfe die Log-Dateien deines Webservers (Apache/Nginx) und des Contao Managers im Ordner \\"contao-manager/logs\\".","ui.error.response":"Der Server hat eine Antwort mit Status-Code {status} gesendet.","ui.error.moreLink":"Weitere Informationen","ui.error.support":"Contao Support","ui.error.permission":"Du hast keine Berechtigung für diese Funktion.","ui.footer.help":"Hilfe","ui.footer.reportProblem":"Probleme melden","ui.navigation.discover":"Entdecken","ui.navigation.packages":"Pakete","ui.navigation.tools":"Tools","ui.navigation.installTool":"Installtool","ui.navigation.backend":"Contao-Backend","ui.navigation.debug":"Contao-Debug-Modus","ui.navigation.logViewer":"System-Log","ui.navigation.phpinfo":"PHP-Informationen","ui.navigation.phpinfoLoading":"Lade PHP-Informationen…","ui.navigation.maintenance":"Systemwartung","ui.navigation.rebuildCache":"Cache erneuern","ui.navigation.users":"Konten","ui.navigation.systemCheck":"Systemprüfung","ui.navigation.advanced":"Fortgeschritten","ui.navigation.logout":"Abmelden","ui.maintenance.database.title":"Datenbank-Migrationen und -Backups","ui.maintenance.database.description":"Datenbankmigrationen stellen konsistente Daten und Tabellenschemas sicher.","ui.maintenance.database.migrations":"Eine ausstehende Datenbank-Migration | {count} ausstehende Datenbank-Migrationen","ui.maintenance.database.schemaUpdates":"Eine ausstehende Schema-Änderung | {count} ausstehende Schema-Änderungen","ui.maintenance.database.error":"Datenbank-Problem gefunden.","ui.maintenance.database.warning":"Datenbank-Warnung gefunden.","ui.maintenance.database.button":"Datenbank prüfen","ui.maintenance.database.migrationOnly":"Nur Migrationen prüfen","ui.maintenance.database.schemaOnly":"Nur Schema prüfen","ui.maintenance.database.installTool":"Install-Tool öffnen","ui.maintenance.database.createBackup":"Backup erstellen","ui.maintenance.database.backupUnsupported":"Datenbank-Backups werden von deiner Contao-Version nicht unterstützt.","ui.maintenance.database.backupList":"Du hast ein Datenbank-Backup, erstellt am {date}. | Du hast {count} Datenbank-Backups, das neuste wurde am {date} erstellt.","ui.maintenance.database.backupEmpty":"Du hast noch keine Datenbank-Backups.","ui.maintenance.rebuildCache.title":"Anwendungs-Cache","ui.maintenance.rebuildCache.description":"Nach dem Ändern einer der Konfigurationsdateien muss der Anwendungs-Cache neu aufgebaut werden.","ui.maintenance.rebuildCache.rebuildProd":"Prod.-Cache erneuern","ui.maintenance.rebuildCache.rebuildDev":"Dev.-Cache erneuern","ui.maintenance.rebuildCache.clearProd":"Prod.-Cache leeren","ui.maintenance.rebuildCache.clearDev":"Dev.-Cache leeren","ui.maintenance.installTool.title":"Contao-Installtool","ui.maintenance.installTool.description":"Das Contao-Installtool wird automatisch gesperrt, wenn das Passwort drei Mal falsch eingegeben wird.","ui.maintenance.installTool.unlock":"Installtool entsperren","ui.maintenance.installTool.lock":"Installtool sperren","ui.maintenance.dumpAutoload.title":"Composer Class Loader","ui.maintenance.dumpAutoload.description":"Der Composer-Autoloader ist für das Laden der PHP-Klassen verantwortlich. Der Autoloader muss nach dem Hinzufügen von eigenen Namespaces in die composer.json neu geschrieben werden.","ui.maintenance.dumpAutoload.button":"Datei aktualisieren","ui.maintenance.composerInstall.title":"Composer-Abhängigkeiten","ui.maintenance.composerInstall.description":"Composer-Abhängigkeiten befinden sich im Ordner {vendor} im Hauptverzeichnis deiner Anwendung. Eine Neuinstallation der Abhängigkeiten kann nach der Bearbeitung oder dem manuellen Hochladen der Datei {composerLock} notwendig sein.","ui.maintenance.composerInstall.button":"Installer ausführen","ui.maintenance.composerInstall.update":"Composer Update ausführen","ui.maintenance.composerCache.title":"Composer-Cache","ui.maintenance.composerCache.description":"Composer speichert heruntergeladene Pakete im Cache, um die Performance zu verbessern. Wenn Du z. B. Probleme mit korrupten Dateien hast, kannst du den Composer-Cache leeren, um einen neuen Download zu erzwingen.","ui.maintenance.composerCache.button":"Cache leeren","ui.maintenance.maintenanceMode.title":"Wartungsmodus","ui.maintenance.maintenanceMode.description":"Im Wartungsmodus zeigt Contao das \\"503 Dienst nicht verfügbar\\"-Template anstelle der Webseite an.","ui.maintenance.maintenanceMode.enable":"Aktivieren","ui.maintenance.maintenanceMode.disable":"Deaktivieren","ui.maintenance.debugMode.title":"Debug-Modus","ui.maintenance.debugMode.description":"Aktiviere den Debug-Modus, indem du einen Benutzer und ein Passwort für den Einstiegspunkt {appDevPhp} festlegen.","ui.maintenance.debugMode.descriptionJwt":"Aktiviert den Debug-Modus, indem für die aktuelle Domain ein entsprechendes Cookie gesetzt wird.","ui.maintenance.debugMode.activate":"Aktivieren","ui.maintenance.debugMode.deactivate":"Deaktivieren","ui.maintenance.debugMode.credentials":"Anmeldedaten","ui.maintenance.debugMode.user":"Bitte gib einen Benutzernamen für den Debug-Modus ein.","ui.maintenance.debugMode.password":"Bitte gib ein Passwort für den Debug-Modus ein.","ui.maintenance.opcodeCache.title":"Opcode-Cache","ui.maintenance.opcodeCache.description":"Der Opcode-Cache speichert PHP-Dateien im Webprozess für eine schnellere Ausführung. Er muss unter Umständen gelöscht werden, wenn Dateien nach dem Ändern nicht erkannt werden.","ui.maintenance.opcodeCache.button":"Cache leeren","ui.maintenance.safeMode":"Deaktiviert im abgesicherten Modus","ui.maintenance.unsupported":"Von deiner Contao-Version nicht unterstützt","ui.packages.updateButton":"Pakete aktualisieren","ui.packages.searchButton":"Pakete suchen","ui.packages.searchPlaceholder":"Pakete suchen …","ui.packages.uploadOverlay":"Lege Dateien hier ab, um sie hochzuladen","ui.packages.uploadButton":"Pakete hochladen","ui.packages.uploadMessage":"Du hast einen unbestätigten Upload. | Du hast {count} unbestätigte Uploads.","ui.packages.uploadApply":"Uploads bestätigen","ui.packages.uploadReset":"Uploads löschen","ui.packages.uploadIncomplete":"Diese Datei wurde nicht vollständig hochgeladen. Bitte entferne sie und versuchen es noch einmal.","ui.packages.uploadDuplicate":"Diese Datei scheint mehrfach hochgeladen worden zu sein. Bitte entferne die Duplikate.","ui.packages.uploadInstalled":"Diese Datei ist bereits installiert. Bitte entferne die Duplikate.","ui.packages.uploadUnsupported":"Uploads werden in deiner Installation nicht unterstützt. Stelle sicher, dass die PHP ZIP-Erweiterung installiert ist und aktualisiere die Abhängigkeiten.","ui.packages.changesMessage":"Du hast eine unbestätigte Änderung. | Du hast {count} unbestätigte Änderungen.","ui.packages.changesDryrun":"Testlauf","ui.packages.changesApply":"Änderungen anwenden","ui.packages.changesApplyAll":"Alle Pakete aktualisieren","ui.packages.changesDryrunAll":"Testlauf mit allen Paketen","ui.packages.changesReset":"Änderungen verwerfen","ui.packages.changesReview":"Änderungen prüfen","ui.packagelist.loading":"Laden …","ui.packagelist.uploads":"Uploads","ui.packagelist.added":"Neue Pakete","ui.packagelist.installed":"Installierte Pakete","ui.package.hintRevert":"Änderung verwerfen","ui.package.hintNoupdate":"Nicht aktualisieren","ui.package.hintConstraint":"Dieses Paket wird mit der Versionsbedingung {constraint} installiert, wenn du die Änderungen anwendest.","ui.package.hintConstraintBest":"Dieses Paket wird in der besten verfügbaren Version installiert, wenn du die Änderungen anwendest.","ui.package.hintConstraintChange":"Die Versionsbedingung dieses Pakets wird von \\"{from}\\" in \\"{to}\\" geändert, wenn du die Änderungen anwendest.","ui.package.hintConstraintUpdate":"Dieses Paket wird aktualisiert, wenn du die Änderungen anwendest.","ui.package.hintAdded":"Dieses Paket wird installiert, wenn du die Änderungen anwendest.","ui.package.hintRemoved":"Dieses Paket wird entfernt, wenn du die Änderungen anwendest.","ui.package.requiredTitle":"manuell hinzugefügt","ui.package.requiredText":"Dieses Paket wurde in der composer.json hinzugefügt, ist aber nicht installiert.","ui.package.removedTitle":"manuell entfernt","ui.package.removedText":"Dieses Paket wurde aus der composer.json entfernt.","ui.package.installed":"Aktuell installiert:","ui.package.version":"Version {version}","ui.package.additionalDownloads":"{count} Download | {count} Downloads","ui.package.additionalStars":"{count} Stern | {count} Sterne","ui.package.editConstraint":"Bearbeiten","ui.package.uploadConstraint":"Diese Versionsbedingung wird von dem hochgeladenen Paket definiert.","ui.package.updateButton":"Aktualisieren","ui.package.removeButton":"Entfernen","ui.package.installButton":"Paket hinzufügen","ui.package.installButtonShort":"Hinzufügen","ui.package.detailsButton":"Details","ui.package.latestConstraint":"neuste Version","ui.package.update":"Update verfügbar","ui.package.updateLatest":"neuste Version","ui.package.updateAvailable":"{version} verfügbar","ui.package.updateUnknown":"unbekannte Version","ui.package.updateConstraint":"Es ist eine neuere Version ausserhalb der Versionsbedingung verfügbar.","ui.package.incompatible":"{package} funktioniert nicht mit Contao {constraint}.","ui.cloudStatus.headline":"Composer Resolver Cloud","ui.cloudStatus.version":"Version {version}","ui.cloudStatus.waitingTime":"Wartezeit","ui.cloudStatus.jobs":"Aktive Aufgaben","ui.cloudStatus.workers":"Server","ui.cloudStatus.approx":"{minutes} min","ui.cloudStatus.none":"keine","ui.cloudStatus.short":"ca. {minutes} min","ui.cloudStatus.long":"ca. {minutes} min {seconds} sek","ui.cloudStatus.error":"Status der Composer Resolver Cloud konnte nicht abgerufen werden. Möglicherweise gibt es ein Wartungsfenster oder Systemprobleme.","ui.cloudStatus.button":"Cloud-Status","ui.cloudStatus.refresh":"Cloud-Status aktualisieren","ui.log-viewer.loading":"Laden …","ui.log-viewer.empty":"Auf dem Server sind keine Logdateien vorhanden.","ui.log-viewer.reload":"Neu laden","ui.log-viewer.file":"Logdatei","ui.log-viewer.channel":"Kanal","ui.log-viewer.channelTitle":"Kanal in welcher die Nachricht geschrieben wurde.","ui.log-viewer.level":"Stufe","ui.log-viewer.levelTitle":"Wichtigkeit der Log-Nachricht.","ui.log-viewer.timeHeader":"Uhrzeit","ui.log-viewer.messageHeader":"Nachricht","ui.log-viewer.showContext":"Kontext anzeigen","ui.log-viewer.hideContext":"Kontext ausblenden","ui.log-viewer.showExtra":"Extras anzeigen","ui.log-viewer.hideExtra":"Extras ausblenden","ui.log-viewer.more":"Mehr laden …","ui.log-viewer.download":"Herunterladen","ui.log-viewer.downloadTitle":"Datei \\"{file}\\" herunterladen","ui.log-viewer.prodEnvironment":"Produktivumgebung","ui.log-viewer.devEnvironment":"Entwicklungsumgebung (Debug Modus)","ui.user-manager.loading":"Lade Benutzer:innen …","ui.user-manager.changePassword":"Passwort ändern","ui.user-manager.setupTotp":"Zwei-Faktor konfigurieren","ui.user-manager.disableTotp":"Zwei-Faktor deaktivieren","ui.user-manager.invite":"Benutzer:in einladen","ui.user-manager.delete":"Löschen","ui.user-manager.deleteConfirm":"Möchtest du das Konto von \\"{username}\\" wirklich löschen?","ui.user-manager.deleted":"Das Konto für {username} wurde gelöscht.","ui.user-manager.passwordHeadline":"Passwort ändern","ui.user-manager.passwordText":"Um dein Passwort zu ändern, gibt dein bestehendes und ein neues Passwort in den entsprechenden Feldern ein.","ui.user-manager.currentPassword":"Aktuelles Passwort","ui.user-manager.newPassword":"Neues Passwort","ui.user-manager.passwordPlaceholder":"min. 8 Zeichen","ui.user-manager.submitPassword":"Absenden","ui.user-manager.passwordChanged":"Dein Passwort wurde erfolgreich geändert.","ui.user-manager.passwordError":"Dieses Passwort stimmt nicht.","ui.user-manager.inviteHeadline":"Benutzer:in einladen","ui.user-manager.inviteText":"Falls du mehrere Logins zum Contao Manager benötigst, kannst du hier einen Einladungs-Link erstellen. Teile diesen Link mit jemandem oder benutze ihn auf einem anderen Gerät, um ein neues Konto mit den entsprechenden Berechtigungen zu erstellen.","ui.user-manager.inviteSuccess1":"Ein Einladungs-Link wurde erstellt. Mit der untenstehenden URL kann ein neues Konto für diesen Contao Manager erstellt werden. Die Einladung läuft ab am {expires} (eine Woche ab jetzt).","ui.user-manager.inviteSuccess2":"Kopiere den Link in deine Zwischenablage. Er funktioniert nur einmal, und du kannst ihn nach dem Schliessen dieses Fensterns nicht mehr sehen.","ui.user-manager.createInvitation":"Einladungs-Link erstellen","ui.user-manager.clipboard":"In Zwischenablage kopieren","ui.user-manager.permissions":"Mehr über Berechtigungen","ui.user-manager.cancel":"Abbrechen","ui.user-manager.close":"Schließen","ui.user-manager.you":"Du","ui.totp.headline":"Zwei-Faktor Anmeldung","ui.totp.setupQr":"Scanne den QR-Code mit deiner 2FA/TOTP-Applikation.","ui.totp.setupCode":"Falls du den QR-Code nicht scannen kannst, gibt folgenden Schlüssel ein:","ui.totp.codeLabel":"Sicherheitscode","ui.totp.codeDescription":"Bitte gibt den Sicherheitscode ein, welcher von deiner 2FA/TOTP-Applikation generiert wurde.","ui.totp.disableText":"Gib den Sicherheitscode ein, um die Zwei-Faktor-Anmeldung zu deaktivieren.","ui.totp.invalid":"Der Sicherheitscode ist ungültig.","ui.totp.enable":"Aktivieren","ui.totp.disable":"Deaktivieren","ui.totp.cancel":"Abbrechen","ui.totp.enabled":"Die Zwei-Faktor-Anmeldung wurde erfolgreich aktiviert.","ui.totp.disabled":"Die Zwei-Faktor-Anmeldung wurde erfolgreich deaktiviert.","ui.totp.setup":"Zwei-Faktor-Anmeldung konfigurieren","ui.totp.skip":"Two-Factor-Anmeldung überspringen"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[557],{1557:function(a){a.exports=JSON.parse('{"ui.app.title":"Расширения Contao","ui.app.loading":"Загрузка списка расширений...","ui.app.language":"Переключить язык Contao Manager","ui.app.colorDark":"Темный режим","ui.app.colorDarkTitle":"Переключить цветовую схему на темную","ui.app.colorLight":"Светлый режим","ui.app.colorLightTitle":"Переключить цветовую схему на светлую","ui.discover.advertisement":"Реклама в списке расширений","ui.discover.loading":"Загрузка...","ui.discover.offline":"Не удалось получить результаты.","ui.discover.offlineExplain":"Проверьте подключение к сети Интернет и отключите блокировку JavaScript в своем браузере.","ui.discover.offlineButton":"Попробовать еще раз","ui.discover.searchPlaceholder":"Поиск в {count} расширениях...","ui.discover.empty":"Нет результатов для {query}","ui.discover.more":"Другие результаты","ui.discover.sortBy":"Сортировать по","ui.discover.sortReleased":"Выпуск","ui.discover.sortReleasedTitle":"Сортировать результаты по дате выпуска","ui.discover.sortLatest":"Обновлено","ui.discover.sortLatestTitle":"Сортировать результаты по последнему обновлению","ui.discover.sortDownloads":"Загрузки","ui.discover.sortDownloadsTitle":"Сортировать результаты по количеству загрузок","ui.discover.sortFavers":"Рейтинг","ui.discover.sortFaversTitle":"Сортировать результаты по рейтингу","ui.discover.detailsButton":"Сведения","ui.discover.latestPackages":"Последние и обновленные расширения","ui.discover.faversPackages":"Расширения с высоким рейтингом","ui.discover.downloadsPackages":"Самые загружаемые расширения","ui.package.homepage":"Веб-сайт проекта","ui.package.private":"Частный пакет","ui.package.privateTitle":"Частные пакеты доступны только у поставщика (наприм., в виде загрузки ZIP-файла). Посетите веб-сайт для получения дополнительной информации.","ui.package.abandoned":"Заброшенный","ui.package.abandonedText":"Этот пакет отмечен как заброшенный и больше не поддерживается.","ui.package.abandonedReplace":"Этот пакет имеет статус заброшенного и больше не поддерживается. Автор предлагает вместо него использовать пакет {replacement}.","ui.package.contaoVersion":"Доступно для Contao","ui.package-details.previous":"Детали предыдущего расширения","ui.package-details.close":"Закрыть детали расширения","ui.package-details.loading":"Загрузка...","ui.package-details.tabDescription":"Описание","ui.package-details.tabRequire":"Требования","ui.package-details.tabFeatures":"Особенности","ui.package-details.tabSuggest":"Предложения","ui.package-details.tabConflict":"Конфликты","ui.package-details.tabDependents":"Зависимые","ui.package-details.linkRequires":"требует","ui.package-details.linkReplaces":"заменяет","ui.package-details.linkProvides":"обеспечивает","ui.package-details.linkConflicts":"конфликты","ui.package-details.funding":"Финансировать дальнейшее развитие!","ui.package-details.contaoVersions":"Поддерживаемые версии Contao","ui.package-details.latest":"Последняя версия","ui.package-details.released":"выпуск от","ui.package-details.license":"Лицензия(и)","ui.package-details.authors":"из","ui.package-details.more":"Еще","ui.package-details.packagist":"Сведения о пакете","ui.package-details.metadata":"Редактировать метаданные","ui.package-details.support_docs":"Документация","ui.package-details.support_wiki":"Вики","ui.package-details.support_forum":"Форум поддержки","ui.package-details.support_issues":"Проблемы / Отчет об ошибках","ui.package-details.support_source":"Исходный код","ui.package-details.support_irc":"IRC / Чат","ui.package-details.support_email":"E-Mail поддержки","ui.package-details.support_rss":"RSS-канал"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[140],{1140:function(e){e.exports=JSON.parse('{"ui.app.title":"Contao Extensions","ui.app.loading":"Loading Extension List …","ui.discover.advertisement":"Advertisement in the extension list","ui.discover.loading":"O kargañ ...","ui.discover.offline":"N\'eo ket gouest da adtapout disoc\'hoù.","ui.discover.offlineExplain":"Check your internet connection and disable JavaScript blockers in your browser.","ui.discover.offlineButton":"Try again","ui.discover.searchPlaceholder":"Search in {count} extensions …","ui.discover.empty":"No results for {query}","ui.discover.more":"More Results","ui.discover.sortBy":"Sort by","ui.discover.sortLatest":"Updated","ui.discover.sortLatestTitle":"Sort search results by last updated","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Sort search results by number of downloads","ui.discover.sortFavers":"Rating","ui.discover.sortFaversTitle":"Sort search results by rating","ui.discover.detailsButton":"Munudoù","ui.discover.latestPackages":"Latest and updated extensions","ui.discover.faversPackages":"Top rated extensions","ui.discover.downloadsPackages":"Most downloaded extensions","ui.package.homepage":"Lec\'hienn ar raktres","ui.package.private":"Private Package","ui.package.privateTitle":"Private packages are only available from the vendor (e.g. as a ZIP download). Please visit the website for more information.","ui.package.abandoned":"dilezet","ui.package.abandonedText":"This package is abandoned and no longer maintained.","ui.package.abandonedReplace":"This package is abandoned and no longer maintained. The author suggests using the {replacement} package instead.","ui.package-details.previous":"Previous Extension Details","ui.package-details.close":"Close Extension Details","ui.package-details.loading":"O kargañ ...","ui.package-details.tabDescription":"Description","ui.package-details.tabRequire":"Requirements","ui.package-details.tabFeatures":"Features","ui.package-details.tabSuggest":"Suggestions","ui.package-details.tabConflict":"Conflicts","ui.package-details.tabDependents":"Dependents","ui.package-details.linkRequires":"requires","ui.package-details.linkReplaces":"replaces","ui.package-details.linkProvides":"provides","ui.package-details.linkConflicts":"conflicts","ui.package-details.funding":"Fund package maintenance!","ui.package-details.latest":"Latest version","ui.package-details.released":"released on","ui.package-details.license":"License(s)","ui.package-details.authors":"from","ui.package-details.more":"Muioc\'h","ui.package-details.packagist":"Munudoù ar pakaj","ui.package-details.metadata":"Edit Metadata","ui.package-details.support_docs":"Titouroù","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Forom skoazell","ui.package-details.support_issues":"Kudennoù/Danevell beugoù","ui.package-details.support_source":"Kod mamenn","ui.package-details.support_irc":"IRC/Flapva","ui.package-details.support_email":"Skoazell dre Bostel","ui.package-details.support_rss":"Froud RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[496,531],{763:function(e,t,s){s.r(t),s.d(t,{default:function(){return ki}});var i=s(641),a=s(33),o=s(3382),n=s(6894);const r={key:0,class:"view-setup__steps"},l=["onClick","disabled"],u=["src"],c={key:1,class:"view-setup__main"},d={class:"view-setup__headline"},p={class:"view-setup__description"},h={class:"view-setup__description"},m={href:"/contao/install",class:"widget-button widget-button--primary view-setup__continue"},_={class:"view-setup__description"},v={href:"/contao",class:"widget-button widget-button--primary view-setup__continue"},k={class:"view-setup__funding"},b={class:"view-setup__funding-link widget-button widget-button--small widget-button--funding widget-button--link",href:"https://to.contao.org/donate",target:"_blank"},g={key:3,class:"view-setup__main"},f={class:"view-setup__headline"},y={class:"view-setup__description"},w={href:"https://to.contao.org/support",target:"_blank"};function L(e,t,s,L,$,C){const E=(0,i.g2)("i18n-t"),X=(0,i.g2)("boxed-layout");return(0,i.uX)(),(0,i.Wv)(X,{wide:!0,slotClass:"view-setup"},{default:(0,i.k6)((()=>[C.currentStep>0?((0,i.uX)(),(0,i.CE)("section",r,[(0,i.Lk)("ul",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(C.steps,((e,t)=>((0,i.uX)(),(0,i.CE)("li",{class:(0,a.C4)({active:C.currentStep>t}),key:e.name},[(0,i.Lk)("button",{onClick:e=>C.currentStep=t+1,disabled:C.currentStep<=t+1},[(0,i.Lk)("img",{src:e.icon,width:"24",height:"24",alt:""},null,8,u)],8,l)],2)))),128)),(0,i.Lk)("li",{class:(0,a.C4)({active:C.currentStep>C.steps.length})},t[4]||(t[4]=[(0,i.Lk)("button",{disabled:""},[(0,i.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24px",viewBox:"0 0 24 24",width:"24px"},[(0,i.Lk)("path",{d:"M0 0h24v24H0z",fill:"none"}),(0,i.Lk)("path",{d:"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"})])],-1)]),2)])])):(0,i.Q3)("",!0),C.currentStep>C.steps.length?((0,i.uX)(),(0,i.CE)("main",c,[t[6]||(t[6]=(0,i.Lk)("span",{class:"view-setup__party"},"🎉",-1)),(0,i.Lk)("h1",d,(0,a.v_)(e.$t("ui.setup.complete")),1),(0,i.Lk)("p",p,(0,a.v_)(e.$t("ui.setup.complete1",{version:e.contaoVersion})),1),e.databaseSupported&&e.userSupported?((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.Lk)("p",_,(0,a.v_)(e.$t("ui.setup.complete3")),1),(0,i.Lk)("button",{class:"widget-button view-setup__continue",onClick:t[1]||(t[1]=function(){return C.launch&&C.launch(...arguments)})},(0,a.v_)(e.$t("ui.setup.manager")),1),(0,i.Lk)("a",v,(0,a.v_)(e.$t("ui.setup.login")),1)],64)):((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.Lk)("p",h,(0,a.v_)(e.$t("ui.setup.complete2")),1),(0,i.Lk)("button",{class:"widget-button widget-button--inline",onClick:t[0]||(t[0]=function(){return C.launch&&C.launch(...arguments)})},(0,a.v_)(e.$t("ui.setup.manager")),1),(0,i.Lk)("a",m,(0,a.v_)(e.$t("ui.setup.installTool")),1)],64)),(0,i.Lk)("div",k,[t[5]||(t[5]=(0,i.Lk)("figure",null,[(0,i.Lk)("img",{src:o,width:"80",height:"80",alt:""})],-1)),(0,i.Lk)("div",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.$t("ui.setup.funding").split("\n"),((e,t)=>((0,i.uX)(),(0,i.CE)("p",{key:t},(0,a.v_)(e),1)))),128)),(0,i.Lk)("p",null,[(0,i.Lk)("a",b,(0,a.v_)(e.$t("ui.setup.fundingLink")),1)])])])])):C.currentStep>0?((0,i.uX)(),(0,i.Wv)((0,i.$y)(C.steps[C.currentStep-1].component),{key:2,onContinue:t[2]||(t[2]=e=>C.currentStep+=1)},null,32)):((0,i.uX)(),(0,i.CE)("main",g,[t[7]||(t[7]=(0,i.Lk)("img",{src:n,width:"100",height:"100",alt:"Contao Logo",class:"view-setup__icon"},null,-1)),(0,i.Lk)("h1",f,(0,a.v_)(e.$t("ui.setup.welcome")),1),(0,i.Lk)("p",y,(0,a.v_)(e.$t("ui.setup.welcome1")),1),(0,i.bF)(E,{tag:"p",class:"view-setup__description",keypath:"ui.setup.welcome2"},{support:(0,i.k6)((()=>[(0,i.Lk)("a",w,(0,a.v_)(e.$t("ui.setup.support")),1)])),_:1}),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary view-setup__start",onClick:t[3]||(t[3]=e=>C.currentStep=1)},(0,a.v_)(e.$t("ui.setup.start")),1)]))])),_:1})}s(4114);var $=s(707),C=s(6278),E=s(5404),X=s(3751),F=s.p+"img/document-root.0e6dd2e4.svg",j=s.p+"img/button-update.ad79c617.svg";const A={class:"setup__header"},V={class:"setup__headline"},U={key:0,class:"setup__warning"},x={class:"setup__description"},D={class:"setup__description"},S=["href"],P={class:"setup__form setup__form--center",key:"updated"},W={class:"setup__fields"},T={class:"setup__fielddesc"},I={class:"setup__directories"},q={key:0},R={key:1},M={key:2},B={key:3},O={key:4},H={key:5},Q={key:6},K={class:"setup__actions setup__actions--center"},J={class:"setup__form",key:"conflicts"},N={class:"setup__fields"},z={class:"setup__fieldtitle"},Z={class:"setup__fielddesc"},Y={key:0},G={class:"setup__actions setup__actions--center"},ee=["disabled"],te={class:"setup__form",key:"setup"},se={class:"setup__fields"},ie={class:"setup__fieldtitle"},ae={class:"setup__fielddesc"},oe={class:"setup__directories"},ne={key:0},re={key:1},le={key:2},ue={key:3},ce={key:4},de={key:5},pe={key:6},he={class:"setup__actions setup__actions--center"},me=["disabled"],_e={class:"setup__form",key:"confirmation"},ve={class:"setup__fields setup__fields--center"},ke={class:"setup__fielddesc"},be={class:"setup__actions setup__actions--center"};function ge(e,t,s,o,n,r){const l=(0,i.g2)("loading-button"),u=(0,i.g2)("check-box"),c=(0,i.g2)("text-field"),d=(0,i.g2)("radio-button"),p=(0,i.g2)("i18n-t");return(0,i.uX)(),(0,i.CE)("section",null,[(0,i.Lk)("header",A,[t[10]||(t[10]=(0,i.Lk)("img",{src:F,width:"80",height:"80",alt:"",class:"setup__icon"},null,-1)),(0,i.Lk)("h1",V,(0,a.v_)(e.$t("ui.setup.document-root.headline")),1),r.needsFix?((0,i.uX)(),(0,i.CE)("p",U,(0,a.v_)(e.$t("ui.setup.document-root.warning")),1)):(0,i.Q3)("",!0),(0,i.Lk)("p",x,(0,a.v_)(e.$t("ui.setup.document-root.description1")),1),(0,i.Lk)("p",D,(0,a.v_)(e.$t("ui.setup.document-root.description2")),1),(0,i.Lk)("a",{class:"widget-button widget-button--inline widget-button--info widget-button--link",href:`https://to.contao.org/docs/webroot?lang=${e.$i18n.locale}`,target:"_blank"},(0,a.v_)(e.$t("ui.setup.document-root.documentation")),9,S)]),null!==e.projectDir?((0,i.uX)(),(0,i.Wv)(X.eB,{key:0,name:e.forceInstall?"none":"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)((()=>[r.needsFix||e.wantsFix?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[e.directoryUpdated?((0,i.uX)(),(0,i.CE)("main",P,[(0,i.Lk)("div",W,[t[13]||(t[13]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",T,(0,a.v_)(e.$t("ui.setup.document-root.confirmation")),1),(0,i.Lk)("dl",I,[(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.currentRoot")),1),e.isWeb?((0,i.uX)(),(0,i.CE)("dd",q,(0,a.v_)(e.projectDir)+"/web",1)):e.isPublic?((0,i.uX)(),(0,i.CE)("dd",R,(0,a.v_)(e.projectDir)+"/public",1)):((0,i.uX)(),(0,i.CE)("dd",M,(0,a.v_)(e.projectDir),1)),(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.newRoot")),1),!e.isEmpty||e.wantsFix&&e.directory||!r.canUsePublicDir||!e.usePublicDir?!e.isEmpty||e.wantsFix&&e.directory?r.canUsePublicDir&&e.usePublicDir?((0,i.uX)(),(0,i.CE)("dd",H,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,"/"+(0,a.v_)(e.directory)+"/public",1)])):((0,i.uX)(),(0,i.CE)("dd",Q,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,"/"+(0,a.v_)(e.directory)+"/web",1)])):((0,i.uX)(),(0,i.CE)("dd",O,[(0,i.eW)((0,a.v_)(e.projectDir),1),t[12]||(t[12]=(0,i.Lk)("span",null,"/web",-1))])):((0,i.uX)(),(0,i.CE)("dd",B,[(0,i.eW)((0,a.v_)(e.projectDir),1),t[11]||(t[11]=(0,i.Lk)("span",null,"/public",-1))]))])]),(0,i.Lk)("div",K,[(0,i.bF)(l,{inline:"",loading:e.processing,color:"primary",icon:"update",onClick:r.reload},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.reload")),1)])),_:1},8,["loading","onClick"])])])):e.conflicts.length?((0,i.uX)(),(0,i.CE)("main",J,[(0,i.Lk)("div",N,[(0,i.Lk)("h2",z,(0,a.v_)(e.$t("ui.setup.document-root.conflictsTitle")),1),(0,i.Lk)("p",Z,(0,a.v_)(e.$t("ui.setup.document-root.conflictsDirectory",{count:e.conflicts.length})),1),(0,i.Lk)("ul",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.conflicts.slice(0,5),(e=>((0,i.uX)(),(0,i.CE)("li",{key:e},(0,a.v_)(e),1)))),128)),e.conflicts.length>5?((0,i.uX)(),(0,i.CE)("li",Y,"...")):(0,i.Q3)("",!0)]),e.isPublic||e.isWeb?((0,i.uX)(),(0,i.Wv)(u,{key:0,name:"ignoreConflicts",label:e.$t("ui.setup.document-root.ignoreConflicts"),disabled:e.processing,modelValue:e.forceInstall,"onUpdate:modelValue":t[0]||(t[0]=t=>e.forceInstall=t)},null,8,["label","disabled","modelValue"])):(0,i.Q3)("",!0)]),(0,i.Lk)("div",G,[e.forceInstall?((0,i.uX)(),(0,i.CE)("button",{key:0,class:"widget-button widget-button--alert widget-button--run",onClick:t[1]||(t[1]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.server.contao.setup")),1)):((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.bF)(l,{inline:"",icon:"update",loading:e.processing,onClick:t[2]||(t[2]=e=>r.init(!1))},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.check")),1)])),_:1},8,["loading"]),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary widget-button--gear",disabled:e.processing,onClick:t[3]||(t[3]=t=>e.conflicts=[])},(0,a.v_)(e.$t("ui.setup.document-root.create")),9,ee)],64))])])):((0,i.uX)(),(0,i.CE)("main",te,[t[14]||(t[14]=(0,i.Lk)("img",{src:j,class:"invisible",alt:""},null,-1)),(0,i.Lk)("div",se,[(0,i.Lk)("h2",ie,(0,a.v_)(e.$t("ui.setup.document-root.formTitle")),1),(0,i.Lk)("p",ae,[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.formText1"))+" ",1),(0,i.Lk)("u",null,(0,a.v_)(e.$t("ui.setup.document-root.formText2")),1)]),!e.isEmpty||e.wantsFix?((0,i.uX)(),(0,i.Wv)(c,{key:0,ref:"directory",name:"directory",label:e.$t("ui.setup.document-root.directory"),error:r.directoryError,required:!e.isEmpty,pattern:"^[^/]+$",validate:"",modelValue:e.directory,"onUpdate:modelValue":t[4]||(t[4]=t=>e.directory=t)},null,8,["label","error","required","modelValue"])):(0,i.Q3)("",!0),r.canUsePublicDir?((0,i.uX)(),(0,i.Wv)(d,{key:1,name:"usePublicDir",options:r.publicDirOptions,"allow-html":"",modelValue:e.usePublicDir,"onUpdate:modelValue":t[5]||(t[5]=t=>e.usePublicDir=t)},null,8,["options","modelValue"])):(0,i.Q3)("",!0),(0,i.Lk)("dl",oe,[(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.currentRoot")),1),e.isWeb?((0,i.uX)(),(0,i.CE)("dd",ne,(0,a.v_)(e.projectDir)+(0,a.v_)(e.directorySeparator)+"web",1)):e.isPublic?((0,i.uX)(),(0,i.CE)("dd",re,(0,a.v_)(e.projectDir)+(0,a.v_)(e.directorySeparator)+"public",1)):((0,i.uX)(),(0,i.CE)("dd",le,(0,a.v_)(e.projectDir),1)),(0,i.Lk)("dt",null,(0,a.v_)(e.$t("ui.setup.document-root.newRoot")),1),!e.isEmpty||e.wantsFix&&e.directory||!r.canUsePublicDir||!e.usePublicDir?!e.isEmpty||e.wantsFix&&e.directory?r.canUsePublicDir&&e.usePublicDir?((0,i.uX)(),(0,i.CE)("dd",de,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+(0,a.v_)(e.directory)+(0,a.v_)(e.directorySeparator)+"public",1)])):((0,i.uX)(),(0,i.CE)("dd",pe,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+(0,a.v_)(e.directory)+(0,a.v_)(e.directorySeparator)+"web",1)])):((0,i.uX)(),(0,i.CE)("dd",ce,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+"web",1)])):((0,i.uX)(),(0,i.CE)("dd",ue,[(0,i.eW)((0,a.v_)(e.projectDir),1),(0,i.Lk)("span",null,(0,a.v_)(e.directorySeparator)+"public",1)]))]),(0,i.bF)(u,{name:"autoconfig",label:e.$t("ui.setup.document-root.autoconfig"),disabled:e.processing,modelValue:e.autoconfig,"onUpdate:modelValue":t[6]||(t[6]=t=>e.autoconfig=t)},null,8,["label","disabled","modelValue"])]),(0,i.Lk)("div",he,[(0,i.bF)(l,{color:"primary",icon:"run",loading:e.processing,disabled:!e.autoconfig||!!r.directoryError||e.wantsFix&&!e.directory&&(e.isPublic&&e.usePublicDir||e.isWeb&&!e.usePublicDir),onClick:r.setupDocroot},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.document-root.finish")),1)])),_:1},8,["loading","disabled","onClick"]),e.wantsFix?((0,i.uX)(),(0,i.CE)("button",{key:0,type:"button",class:"widget-button",disabled:e.processing,onClick:t[7]||(t[7]=function(){return r.init&&r.init(...arguments)})},(0,a.v_)(e.$t("ui.setup.cancel")),9,me)):(0,i.Q3)("",!0)])]))],64)):((0,i.uX)(),(0,i.CE)("main",_e,[(0,i.Lk)("div",ve,[t[15]||(t[15]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",ke,(0,a.v_)(e.$t("ui.setup.document-root.success")),1),(0,i.bF)(p,{tag:"p",class:"setup__fielddesc",keypath:`ui.setup.document-root.${e.contaoVersion?"installed":"installing"}ProjectDir`},{dir:(0,i.k6)((()=>[(0,i.Lk)("code",null,(0,a.v_)(e.projectDir),1)])),_:1},8,["keypath"]),(0,i.bF)(p,{tag:"p",class:"setup__fielddesc",keypath:`ui.setup.document-root.${e.contaoVersion?"installed":"installing"}PublicDir`},{dir:(0,i.k6)((()=>[(0,i.Lk)("code",null,(0,a.v_)(r.publicDir),1)])),_:1},8,["keypath"])]),(0,i.Lk)("div",be,[e.contaoVersion?(0,i.Q3)("",!0):((0,i.uX)(),(0,i.CE)("button",{key:0,class:"widget-button widget-button--inline widget-button--gear",onClick:t[8]||(t[8]=t=>e.wantsFix=!0)},(0,a.v_)(e.$t("ui.setup.document-root.change")),1)),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary",onClick:t[9]||(t[9]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1)])]))])),_:1},8,["name"])):(0,i.Q3)("",!0)])}var fe=s(683);const ye={key:0},we=["id","name","disabled","required","checked","onClick"],Le=["for","innerHTML"],$e=["for"];function Ce(e,t,s,o,n,r){return(0,i.uX)(),(0,i.CE)("fieldset",{class:(0,a.C4)(["widget widget-radio-button",{"widget--required":s.required}])},[s.label||e.$slots.label?((0,i.uX)(),(0,i.CE)("legend",ye,[(0,i.RG)(e.$slots,"label",{},(()=>[(0,i.eW)((0,a.v_)(s.label),1)]))])):(0,i.Q3)("",!0),((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(s.options,((e,t)=>((0,i.uX)(),(0,i.CE)("div",{key:t},[(0,i.Lk)("input",{ref_for:!0,ref:"input",type:"radio",id:`ctrl_${s.name}_${e.value}`,name:s.name,disabled:e.disabled,required:s.required,checked:s.modelValue===e.value,onClick:t=>r.input(e.value)},null,8,we),s.allowHtml?((0,i.uX)(),(0,i.CE)("label",{key:0,for:`ctrl_${s.name}_${e.value}`,innerHTML:e.label},null,8,Le)):((0,i.uX)(),(0,i.CE)("label",{key:1,for:`ctrl_${s.name}_${e.value}`},(0,a.v_)(e.label),9,$e))])))),128))],2)}var Ee={emits:["input","update:modelValue"],props:{name:{type:String,required:!0},options:{type:Array,required:!0},label:String,modelValue:{required:!0},disabled:Boolean,required:Boolean,allowHtml:{type:Boolean,default:!1}},methods:{input(e){this.$emit("input"),this.$emit("update:modelValue",e)}}},Xe=s(6262);const Fe=(0,Xe.A)(Ee,[["render",Ce]]);var je=Fe,Ae=s(3018),Ve=s(6966),Ue={components:{TextField:fe.A,RadioButton:je,CheckBox:Ae.A,LoadingButton:Ve.A},data:()=>({processing:!1,usePublicDir:!1,wantsFix:!1,conflicts:[],isEmpty:!0,isWeb:!0,isPublic:!1,projectDir:null,autoconfig:!1,forceInstall:!1,directory:"",directoryExists:!1,directoryUpdated:!1,directorySeparator:"/"}),computed:{...(0,C.aH)("server/php-web",["phpVersionId"]),...(0,C.aH)("server/contao",["contaoVersion"]),needsFix:e=>!e.isEmpty||!e.isWeb&&(!e.isPublic||!e.canUsePublicDir),publicDirOptions:e=>[{label:e.$t("ui.setup.document-root.publicDir",{dir:"web",version:"4.9+"}),value:!1},{label:e.$t("ui.setup.document-root.publicDir",{dir:"public",version:"4.13+"}),value:!0}],canUsePublicDir:e=>e.phpVersionId>=70400,publicDir:e=>e.isWeb?`${e.projectDir}${e.directorySeparator}web`:`${e.projectDir}${e.directorySeparator}public`,directoryError(){return this.directoryExists?this.$t("ui.setup.document-root.directoryExists"):this.directory&&!this.directory.match(/^[^/]+$/)?this.$t("ui.setup.document-root.directoryInvalid"):this.wantsFix||this.isEmpty||this.directory?"":this.$t("ui.setup.document-root.directoryInvalid")}},methods:{reload(){this.processing=!0,window.location.reload()},async setupDocroot(){this.processing=!0;const e=await this.$store.dispatch("server/contao/documentRoot",{directory:!this.isEmpty||this.wantsFix?this.directory:null,usePublicDir:this.canUsePublicDir&&this.usePublicDir});if(403===e.status)return this.directoryExists=!0,this.processing=!1,void this.$refs.directory.focus();this.processing=!1,this.directoryUpdated=!0,this.$store.commit("auth/resetCountdown")},async init(){let e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.processing=!0;const t=await this.$store.dispatch("server/contao/get",e);this.projectDir=t.data.project_dir,this.conflicts=t.data.conflicts,this.isEmpty=0===t.data.conflicts.length,this.isWeb="web"===t.data.public_dir,this.isPublic="public"===t.data.public_dir,this.usePublicDir="public"===t.data.public_dir,this.wantsFix=!1,this.directory=this.isEmpty?"":location.hostname,this.directorySeparator=t.data.directory_separator,this.processing=!1}},watch:{directory(){this.directoryExists=!1}},async mounted(){this.init()}};const xe=(0,Xe.A)(Ue,[["render",ge]]);var De=xe,Se=(s(8111),s(1701),s.p+"img/create-project.b22522ee.svg"),Pe=s(7591);const We={class:"setup__header"},Te=["src","alt"],Ie={key:1,src:Se,width:"80",height:"80",alt:"",class:"setup__icon"},qe={class:"setup__headline"},Re={class:"setup__description"},Me={class:"setup__version"},Be={class:"setup__version"},Oe={key:2,class:"setup__version"},He={key:3,class:"setup__version"},Qe={key:4,class:"setup__version"},Ke=["href"],Je={class:"setup__form"},Ne={key:0,class:"setup__fields"},ze={class:"setup__fieldtitle"},Ze={class:"setup__fielddesc"},Ye={class:"setup__tabs"},Ge={class:"setup__tab-controls"},et={key:0,class:"setup__tab"},tt={class:"setup__requires"},st={key:1,class:"setup__tab setup__tab--files"},it={class:"setup__fielddesc setup__fielddesc--warning"},at={class:"setup__actions"},ot=["disabled"],nt={class:"setup__header"},rt={class:"setup__headline"},lt={href:"https://semver.org",target:"_blank",rel:"noreferrer noopener"},ut={class:"setup__versions"},ct={class:"setup__version--warning"},dt=["href"],pt={key:0,class:"setup__form"},ht={class:"setup__fields setup__fields--center"},mt={class:"setup__fielddesc"},_t={class:"setup__actions setup__actions--center"},vt={key:1,class:"setup__form"},kt={class:"setup__fields"},bt={class:"setup__fieldtitle"},gt={class:"setup__fielddesc setup__fielddesc--version"},ft={key:0,class:"setup__theme"},yt={href:"https://themes.contao.org",target:"_blank"},wt={class:"package-uploads__overlay"},Lt={href:"https://themes.contao.org",target:"_blank"},$t={class:"setup__fields"},Ct={class:"setup__or"},Et=["disabled"],Xt=["disabled"],Ft={key:2,class:"setup__themes"},jt={key:1,class:"setup__theme-search setup__theme-search--offline"},At={key:2,class:"setup__theme-search setup__theme-search--empty"},Vt={class:"setup__themes-results"},Ut={class:"setup__themes-more"};function xt(e,t,s,o,n,r){const l=(0,i.g2)("file-upload"),u=(0,i.g2)("file-tree"),c=(0,i.g2)("loading-button"),d=(0,i.g2)("i18n-t"),p=(0,i.g2)("radio-button"),h=(0,i.g2)("check-box"),m=(0,i.g2)("search-input"),_=(0,i.g2)("button-group"),v=(0,i.g2)("loading-spinner"),k=(0,i.g2)("discover-package");return(0,i.uX)(),(0,i.CE)("div",null,[(0,i.bF)(l,{name:"package",ref:"uploader","post-action":"api/packages/uploads",multiple:!0,drop:!0,"drop-directory":!1,"chunk-enabled":!0,chunk:{action:"api/packages/uploads"},onInputFile:r.uploadTheme,onInputFilter:r.filterTheme},null,8,["onInputFile","onInputFilter"]),e.theme?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.Lk)("header",We,[e.themeImage?((0,i.uX)(),(0,i.CE)("img",{key:0,class:"setup__theme-image",src:e.themeImage,alt:e.theme.composerJson.name},null,8,Te)):((0,i.uX)(),(0,i.CE)("img",Ie)),(0,i.Lk)("h1",qe,(0,a.v_)(e.$t("ui.setup.create-project.headline")),1),(0,i.Lk)("p",Re,(0,a.v_)(e.$t("ui.setup.create-project.theme.uploaded")),1),(0,i.Lk)("div",Me,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.packageName"))+":",1),(0,i.eW)(" "+(0,a.v_)(e.theme.composerJson.name),1)]),(0,i.Lk)("div",Be,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.version"))+":",1),(0,i.eW)(" "+(0,a.v_)(e.theme.composerJson.version),1)]),e.theme.composerJson.authors||e.theme.authors?((0,i.uX)(),(0,i.CE)("div",Oe,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.authors"))+":",1),e.theme.composerJson.authors?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.eW)((0,a.v_)(e.theme.composerJson.authors.map((e=>e.name)).join(", ")),1)],64)):((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.eW)((0,a.v_)(e.theme.authors),1)],64))])):(0,i.Q3)("",!0),e.theme.composerJson.license?((0,i.uX)(),(0,i.CE)("div",He,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.package-details.license"))+":",1),(0,i.eW)(" "+(0,a.v_)(Array.isArray(e.theme.composerJson.license)?e.theme.composerJson.license.join(", "):e.theme.composerJson.license),1)])):(0,i.Q3)("",!0),e.theme.composerJson.homepage?((0,i.uX)(),(0,i.CE)("div",Qe,[(0,i.Lk)("strong",null,(0,a.v_)(e.$t("ui.package.homepage"))+": ",1),(0,i.Lk)("a",{href:e.theme.composerJson.homepage,target:"_blank"},(0,a.v_)(e.theme.composerJson.homepage),9,Ke)])):(0,i.Q3)("",!0),(0,i.Lk)("button",{class:"widget-button widget-button--info widget-button--details",onClick:t[0]||(t[0]=function(){return r.themeDetails&&r.themeDetails(...arguments)})},(0,a.v_)(e.$t("ui.package.detailsButton")),1)]),(0,i.Lk)("main",Je,[e.theme.files?((0,i.uX)(),(0,i.CE)("div",Ne,[(0,i.Lk)("h2",ze,(0,a.v_)(e.$t("ui.setup.create-project.themeTitle")),1),(0,i.Lk)("p",Ze,(0,a.v_)(e.$t("ui.setup.create-project.themeDetails")),1),(0,i.Lk)("div",Ye,[(0,i.Lk)("div",Ge,[(0,i.Lk)("button",{class:(0,a.C4)(["setup__tab-control",{"setup__tab-control--active":"require"===e.view}]),onClick:t[1]||(t[1]=t=>e.view="require")},(0,a.v_)(e.$tc("ui.setup.create-project.themeRequire",Object.keys(e.theme.composerJson.require).length)),3),(0,i.Lk)("button",{class:(0,a.C4)(["setup__tab-control",{"setup__tab-control--active":"files"===e.view}]),onClick:t[2]||(t[2]=t=>e.view="files")},(0,a.v_)(e.$tc("ui.setup.create-project.themeFiles",e.theme.files.length)),3)]),"require"===e.view?((0,i.uX)(),(0,i.CE)("div",et,[(0,i.Lk)("table",tt,[(0,i.Lk)("tbody",null,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.theme.composerJson.require,((e,t)=>((0,i.uX)(),(0,i.CE)("tr",{key:t},[(0,i.Lk)("td",null,(0,a.v_)(t)+":",1),(0,i.Lk)("td",null,(0,a.v_)(e),1)])))),128))])])])):(0,i.Q3)("",!0),"files"===e.view?((0,i.uX)(),(0,i.CE)("div",st,[(0,i.bF)(u,{files:r.themeFiles},null,8,["files"])])):(0,i.Q3)("",!0)]),(0,i.Lk)("p",it,(0,a.v_)(e.$t("ui.setup.create-project.themeWarning")),1)])):(0,i.Q3)("",!0),(0,i.Lk)("div",at,[(0,i.bF)(c,{color:"primary",icon:"run",loading:e.processing,onClick:r.installTheme},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.create-project.install")),1)])),_:1},8,["loading","onClick"]),(0,i.Lk)("button",{class:"widget-button",onClick:t[3]||(t[3]=function(){return r.cancelTheme&&r.cancelTheme(...arguments)}),disabled:e.processing},(0,a.v_)(e.$t("ui.setup.create-project.cancel")),9,ot)])])],64)):((0,i.uX)(),(0,i.CE)(i.FK,{key:1},[(0,i.Lk)("header",nt,[t[14]||(t[14]=(0,i.Lk)("img",{src:Se,width:"80",height:"80",alt:"",class:"setup__icon"},null,-1)),(0,i.Lk)("h1",rt,(0,a.v_)(e.$t("ui.setup.create-project.headline")),1),(0,i.bF)(d,{tag:"p",keypath:"ui.setup.create-project.description",class:"setup__description"},{semver:(0,i.k6)((()=>[(0,i.Lk)("a",lt,(0,a.v_)(e.$t("ui.setup.create-project.semver")),1)])),_:1}),(0,i.Lk)("ul",ut,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(r.versions,(e=>((0,i.uX)(),(0,i.CE)(i.FK,null,[e.description?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[e.disabled?((0,i.uX)(),(0,i.CE)("li",{class:"setup__version",key:e.value},[(0,i.Lk)("strong",null,(0,a.v_)(e.label),1),t[13]||(t[13]=(0,i.Lk)("br",null,null,-1)),(0,i.Lk)("span",ct,(0,a.v_)(e.problem),1)])):((0,i.uX)(),(0,i.CE)("li",{class:"setup__version",key:e.value},[(0,i.Lk)("strong",null,(0,a.v_)(e.label),1),t[12]||(t[12]=(0,i.Lk)("br",null,null,-1)),(0,i.eW)(" "+(0,a.v_)(e.description),1)]))],64)):(0,i.Q3)("",!0)],64)))),256))]),(0,i.bF)(d,{tag:"p",keypath:"ui.setup.create-project.releaseplan",class:"setup__releaseplan"},{contaoReleasePlan:(0,i.k6)((()=>[(0,i.Lk)("a",{href:`https://to.contao.org/release-plan?lang=${e.$i18n.locale}`,target:"_blank",rel:"noreferrer noopener"},(0,a.v_)(e.$t("ui.setup.create-project.releaseplanLink")),9,dt)])),_:1})]),e.contaoVersion?((0,i.uX)(),(0,i.CE)("main",pt,[(0,i.Lk)("div",ht,[t[15]||(t[15]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",mt,(0,a.v_)(e.$t("ui.setup.create-project.installed",{version:e.contaoVersion})),1)]),(0,i.Lk)("div",_t,[(0,i.Lk)("button",{class:"widget-button widget-button--inline",onClick:t[4]||(t[4]=function(){return r.launch&&r.launch(...arguments)})},(0,a.v_)(e.$t("ui.setup.manager")),1),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary",onClick:t[5]||(t[5]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1)])])):((0,i.uX)(),(0,i.CE)("main",vt,[(0,i.Lk)("div",kt,[(0,i.Lk)("h2",bt,(0,a.v_)(e.$t("ui.setup.create-project.formTitle")),1),(0,i.Lk)("p",gt,(0,a.v_)(e.$t("ui.setup.create-project.formText")),1),(0,i.bF)(p,{name:"version",options:r.versions,disabled:e.processing,modelValue:e.version,"onUpdate:modelValue":t[6]||(t[6]=t=>e.version=t)},null,8,["options","disabled","modelValue"]),"theme"===e.version?((0,i.uX)(),(0,i.CE)("div",ft,[(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.setup.create-project.themeInstall")),1),(0,i.bF)(d,{keypath:"ui.setup.create-project.themeBuy",tag:"p"},{store:(0,i.k6)((()=>[(0,i.Lk)("a",yt,(0,a.v_)(e.$t("ui.setup.create-project.themeStore")),1)])),_:1}),(0,i.bo)((0,i.Lk)("div",wt,[(0,i.Lk)("div",null,[t[16]||(t[16]=(0,i.Lk)("img",{src:Pe,alt:"",width:"128",height:"128"},null,-1)),(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.packages.uploadOverlay")),1)])],512),[[X.aG,e.$refs.uploader&&e.$refs.uploader.dropActive]])])):((0,i.uX)(),(0,i.Wv)(h,{key:1,name:"demo",label:e.$t("ui.setup.create-project.demo"),disabled:e.processing,modelValue:e.demo,"onUpdate:modelValue":t[7]||(t[7]=t=>e.demo=t)},{description:(0,i.k6)((()=>[(0,i.bF)(d,{tag:"p",keypath:"ui.setup.create-project.demoDescription"},{store:(0,i.k6)((()=>[(0,i.Lk)("a",Lt,(0,a.v_)(e.$t("ui.setup.create-project.themeStore")),1)])),_:1})])),_:1},8,["label","disabled","modelValue"]))]),(0,i.Lk)("div",$t,["theme"===e.version?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.bF)(c,{color:"primary",icon:"upload",loading:e.processing,onClick:r.openFileSelector},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.create-project.themeUpload")),1)])),_:1},8,["loading","onClick"]),(0,i.Lk)("div",Ct,[(0,i.Lk)("span",null,(0,a.v_)(e.$t("ui.setup.create-project.theme.or")),1)]),(0,i.bF)(m,{placeholder:e.$t("ui.setup.create-project.theme.search"),disabled:e.processing},null,8,["placeholder","disabled"])],64)):((0,i.uX)(),(0,i.Wv)(_,{key:1,color:"primary",icon:"run",disabled:!e.version,loading:e.processing,onClick:t[10]||(t[10]=()=>r.install()),label:e.$t("ui.setup.create-project.install")},{default:(0,i.k6)((()=>[e.demo?(0,i.Q3)("",!0):((0,i.uX)(),(0,i.CE)("button",{key:0,class:"widget-button",disabled:!e.version||e.processing,onClick:t[8]||(t[8]=function(){return r.installCoreOnly&&r.installCoreOnly(...arguments)})},(0,a.v_)(e.$t("ui.setup.create-project.coreOnly")),9,Et)),(0,i.Lk)("button",{class:"widget-button",disabled:!e.version||e.processing,onClick:t[9]||(t[9]=function(){return r.installNoUpdate&&r.installNoUpdate(...arguments)})},(0,a.v_)(e.$t("ui.setup.create-project.noUpdate")),9,Xt)])),_:1},8,["disabled","loading","label"]))])])),t[17]||(t[17]=(0,i.Lk)("div",{class:"clearfix"},null,-1)),e.searching||e.results||e.offline?((0,i.uX)(),(0,i.CE)("div",Ft,[e.searching&&!e.results?((0,i.uX)(),(0,i.Wv)(v,{key:0,class:"setup__theme-search setup__theme-search--loader"},{default:(0,i.k6)((()=>[(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.discover.loading")),1)])),_:1})):e.offline?((0,i.uX)(),(0,i.CE)("div",jt,[(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.discover.offline")),1),(0,i.Lk)("p",null,(0,a.v_)(e.$t("ui.discover.offlineExplain")),1),(0,i.Lk)("button",{class:"widget-button widget-button--inline widget-button--update",onClick:t[11]||(t[11]=function(){return r.searchThemes&&r.searchThemes(...arguments)})},(0,a.v_)(e.$t("ui.discover.offlineButton")),1)])):e.isSearching&&e.results&&!Object.keys(e.results).length?((0,i.uX)(),(0,i.CE)("div",At,[(0,i.bF)(d,{tag:"p",keypath:"ui.setup.create-project.theme.empty"},{query:(0,i.k6)((()=>[(0,i.Lk)("i",null,(0,a.v_)(e.query),1)])),_:1})])):e.isSearching&&e.results?((0,i.uX)(),(0,i.CE)(i.FK,{key:3},[(0,i.Lk)("div",Vt,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(e.results,(e=>((0,i.uX)(),(0,i.Wv)(k,{class:"setup__themes-item",data:e,key:e.name},null,8,["data"])))),128))]),(0,i.Lk)("div",Ut,[e.hasMore?((0,i.uX)(),(0,i.Wv)(c,{key:0,inline:"",icon:"search",loading:e.searching,onClick:e.loadMore},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.create-project.theme.more")),1)])),_:1},8,["loading","onClick"])):(0,i.Q3)("",!0)])],64)):(0,i.Q3)("",!0)])):(0,i.Q3)("",!0)],64))])}s(2489),s(116),s(7588),s(4603),s(7566),s(8721);var Dt=s(4686),St=s.n(Dt),Pt=s(1881),Wt=s(8568),Tt=s.n(Wt);const It=["href"],qt=["href"],Rt={key:3};function Mt(e,t,s,o,n,r){const l=(0,i.g2)("package-constraint"),u=(0,i.g2)("package-details");return(0,i.uX)(),(0,i.Wv)(u,null,{"package-actions":(0,i.k6)((()=>[!e.isTheme||r.data.uploaded||r.isPrivate?r.data.homepage||e.metadata.homepage?((0,i.uX)(),(0,i.CE)("a",{key:1,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:r.data.homepage||e.metadata.homepage},(0,a.v_)(e.$t("ui.package.homepage")),9,It)):r.isPrivate?((0,i.uX)(),(0,i.CE)("div",Rt)):((0,i.uX)(),(0,i.CE)("a",{key:2,class:"widget-button widget-button--primary widget-button--link",target:"_blank",href:`https://packagist.org/packages/${r.data.name}`},(0,a.v_)(e.$t("ui.package-details.packagist")),9,qt)):((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[(0,i.Lk)("button",{class:"widget-button widget-button--primary widget-button--run",onClick:t[0]||(t[0]=function(){return r.install&&r.install(...arguments)})},(0,a.v_)(e.$t("ui.setup.create-project.install")),1),(0,i.bF)(l,{class:"theme-details__constraint",emit:!0,data:r.data,modelValue:e.version,"onUpdate:modelValue":t[1]||(t[1]=t=>e.version=t)},null,8,["data","modelValue"])],64))])),_:1})}var Bt=s(9500),Ot=s(3629),Ht=s(416),Qt=s(8200),Kt={mixins:[Ht.A,Qt.A],components:{PackageConstraint:Ot.A,PackageDetails:Bt["default"]},data:()=>({version:""}),computed:{...(0,C.aH)("packages",{allInstalled:"installed"}),...(0,C.aH)("packages/details",["current"]),data:e=>e.allInstalled[e.current]||{name:e.current},isPrivate:e=>e.metadata&&!!e.metadata.private},methods:{install(){this.$store.commit("contao/installTheme",{package:this.data.name,version:this.version})}}};const Jt=(0,Xe.A)(Kt,[["render",Mt]]);var Nt=Jt,zt=s(2361),Zt=s(4999),Yt=s(6077);const Gt={class:"file-tree"},es=["onClick"],ts={key:1,class:"file-tree__file"};function ss(e,t,s,o,n,r){const l=(0,i.g2)("file-tree",!0);return(0,i.uX)(),(0,i.CE)("ul",Gt,[((0,i.uX)(!0),(0,i.CE)(i.FK,null,(0,i.pI)(s.files,((e,t)=>((0,i.uX)(),(0,i.CE)(i.FK,{key:t},[e.children.length?((0,i.uX)(),(0,i.CE)("li",{key:0,class:(0,a.C4)("file-tree__folder"+(r.isOpen(e)?" file-tree__folder--open":""))},[(0,i.Lk)("button",{onClick:t=>r.toggle(e)},(0,a.v_)(r.name(e)),9,es),r.isOpen(e)?((0,i.uX)(),(0,i.Wv)(l,{key:0,files:e.children},null,8,["files"])):(0,i.Q3)("",!0)],2)):((0,i.uX)(),(0,i.CE)("li",ts,[(0,i.Lk)("span",null,(0,a.v_)(r.name(e)),1)]))],64)))),128))])}var is={name:"FileTree",props:{files:{type:Array,required:!0}},data:()=>({open:[]}),computed:{name:()=>e=>e.name?e.name:e.path.substring(e.path.lastIndexOf("/")+1),isOpen:e=>t=>e.open.includes(t)},methods:{toggle(e){this.open.includes(e)?this.open=this.open.filter((t=>t!==e)):this.open.push(e)}}};const as=(0,Xe.A)(is,[["render",ss]]);var os=as,ns=s(2880),rs={mixins:[Pt.A],components:{ButtonGroup:ns.A,FileTree:os,DiscoverPackage:Yt.A,LoadingSpinner:Zt.A,SearchInput:zt.A,FileUpload:Tt(),RadioButton:je,CheckBox:Ae.A,LoadingButton:Ve.A},data:()=>({processing:!1,isWeb:!0,version:"5.5",demo:!1,view:"require",theme:null,themeImage:null,searching:!1,results:null,hasMore:!1,offline:!1}),computed:{...(0,C.aH)("tasks",{taskStatus:"status"}),...(0,C.aH)("server/php-web",["phpVersionId","phpVersion"]),...(0,C.aH)("server/contao",["contaoVersion"]),...(0,C.aH)("contao",{themeName:"package",themeVersion:"version"}),themeFiles:e=>St()(e.theme.files,{directoriesFirst:!0}).children,versions(){const e=[];return e.push({value:"5.5",label:`Contao 5.5 (${this.$t("ui.setup.create-project.latestTitle")})`,disabled:this.phpVersionId<80200,description:this.$t("ui.setup.create-project.latestQ3",{year:"2025"}),problem:this.$t("ui.setup.create-project.requiresPHP",{version:"8.2.0",current:this.phpVersion})}),e.push({value:"5.3",label:`Contao 5.3 (${this.$t("ui.setup.create-project.ltsTitle")})`,disabled:this.phpVersionId<80100,description:this.$t("ui.setup.create-project.ltsText",{year:"2027"}),problem:this.$t("ui.setup.create-project.requiresPHP",{version:"8.1.0",current:this.phpVersion})}),e.push({value:"4.13",label:`Contao 4.13 (${this.$t("ui.setup.create-project.ltsTitle")})`,disabled:this.phpVersionId<70400,description:this.$t("ui.setup.create-project.pltsText",{year:"2025"}),problem:this.$t("ui.setup.create-project.requiresPHP",{version:"7.4.0",current:this.phpVersion})}),e.push({value:"theme",label:this.$t("ui.setup.create-project.theme")}),e}},watch:{version(){this.stopSearch(),this.searching=!1,this.results=null,this.hasMore=!1},sorting(){this.searchThemes()},query(){this.results=null,this.query?this.searchThemes():(this.searching=!1,this.hasMore=!1)},pages(){this.searchThemes()},themeName(){this.closePopup(),this.install({package:this.themeName,version:this.themeVersion})}},methods:{...(0,C.PY)("packages/details",{closePopup:"clearCurrent"}),async searchThemes(){this.searching=!0,this.offline=!1;try{const e={facetFilters:["type:contao-theme"],hitsPerPage:10*this.pages};this.query?e.query=this.query:this.sorting&&(e.sorting=this.sorting);const t=await this.$store.dispatch("algolia/findPackages",e);if(this.hasMore=t.nbPages>1,0===t.nbHits)return void(this.results={});const s={};t.hits.forEach((e=>{s[e.name]=e})),this.results=s}catch(e){this.offline=!0}this.searching=!1},async install(e){let t,s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;this.processing=!0,t=e||(this.theme?{upload:this.theme.upload.id}:this.demo?{package:"contao/contao-demo",version:this.version,"no-update":"no-update"===s?"1":"0"}:{version:this.version,"core-only":"core-only"===s?"1":"0","no-update":"no-update"===s?"1":"0"}),await this.$store.dispatch("contao/install",t),"complete"===this.taskStatus&&(this.$store.commit("tasks/setDeleting",!0),"no-update"===s?(this.$store.commit("setSafeMode",!0),this.$store.commit("setView",$.A.READY)):(this.isWeb="web"===(await this.$store.dispatch("server/contao/get",!1)).data.public_dir,await Promise.all([this.$store.dispatch("contao/install-tool/fetch",!1),this.$store.dispatch("server/database/get",!1),this.$store.dispatch("contao/backup/fetch",!1)]),this.$store.commit("contao/backup/setRestore",!0),this.$store.commit("setup",3)),this.$store.dispatch("tasks/deleteCurrent"))},installNoUpdate(){this.install(null,"no-update")},installCoreOnly(){this.install(null,"core-only")},launch(){this.$store.commit("setView",$.A.READY)},openFileSelector(){this.$refs.uploader&&this.$refs.uploader.$el.querySelector("input").click()},async filterTheme(e,t,s){if(e&&!t&&!/(\.cto|\.zip)$/i.test(e.name))return console&&console.debug(`${e.name} is not a .zip or .cto`),alert(this.$t("ui.setup.create-project.themeInvalid")),s()},async uploadTheme(e,t){if(e){if(this.processing=!0,this.$refs.uploader.uploaded&&e&&t&&!e.active&&t.active)return this.theme.upload=e.response.data,void(e.success&&this.install());e.url=URL.createObjectURL(e.file);try{const t=new File([e.file],e.name,{type:e.type}),a=(await s.e(710).then(s.t.bind(s,1710,23))).default,o=await a.loadAsync(t),n=o.filter((e=>!["composer.json","theme.xml"].includes(e)&&!e.startsWith("__MACOSX/")&&!e.includes(".DS_Store")&&!e.endsWith("/"))).map((e=>e.name));let r=n[0].substring(0,n[0].indexOf("/")+1);n.find((e=>e.substr(0,r.length)!==r))&&(r="");const l=JSON.parse(await o.file(`${r}composer.json`).async("string")),u=await o.file(`${r}theme.xml`).async("string"),c=new DOMParser,d=c.parseFromString(u,"application/xml");if(this.theme={tstamp:d.querySelector('table[name="tl_theme"] field[name="tstamp"]')?.innerHTML,name:d.querySelector('table[name="tl_theme"] field[name="name"]')?.innerHTML,author:d.querySelector('table[name="tl_theme"] field[name="author"]')?.innerHTML,screenshot:d.querySelector('table[name="tl_theme"] field[name="screenshot"]')?.innerHTML,composerJson:l,files:n},this.theme.screenshot&&"NULL"!==this.theme.screenshot)try{const e=await o.file(`${r}${this.theme.screenshot}`);this.themeImage=e?URL.createObjectURL(await e.async("blob")):null}catch(i){}}catch(i){console&&console.debug(i),alert(this.$t("ui.setup.create-project.themeInvalid")),this.cancelTheme()}this.processing=!1}},cancelTheme(){this.theme=null,this.$refs.uploader.clear()},themeDetails(){this.$store.commit("packages/setInstalled",{local:{[this.theme.composerJson.name]:Object.assign({},this.theme.composerJson,{uploaded:!0})}}),this.$store.commit("packages/details/setCurrent",this.theme.composerJson.name)},installTheme(){this.$refs.uploader.active||(this.processing=!0,this.$refs.uploader.active=!0)}},async mounted(){await this.$router.isReady(),Object.keys(this.$route.query).length&&this.$router.replace({query:null}),await this.$store.dispatch("packages/details/init",{vue:this,component:Nt}),this.$store.commit("packages/setInstalled",{}),this.isWeb="web"===(await this.$store.dispatch("server/contao/get")).data.public_dir,this.version=this.versions.find((e=>!e.disabled)).value}};const ls=(0,Xe.A)(rs,[["render",xt]]);var us=ls,cs=s(9472);const ds={class:"setup__header"},ps={class:"setup__headline"},hs={class:"setup__form",key:"setup"},ms={class:"setup__fields"},_s={class:"setup__fieldtitle"},vs={class:"setup__fielddesc"},ks={key:0,class:"setup__warning"},bs={class:"setup__or"},gs={class:"setup__actions"},fs=["disabled"],ys={class:"setup__form",key:"confirmation"},ws={class:"setup__fields"},Ls={class:"setup__fieldtitle"},$s={key:"migrate"},Cs={class:"setup__fields"},Es={class:"setup__fieldtitle"},Xs={key:0,class:"setup__fielddesc setup__warning"},Fs={key:1,class:"setup__fielddesc"},js={class:"setup__actions setup__actions--center"},As={key:"restored"},Vs={class:"setup__fields"},Us={class:"setup__fieldtitle"},xs={class:"setup__fielddesc"},Ds={class:"setup__actions setup__actions--center"},Ss={key:"backup"},Ps={class:"setup__fields"},Ws={class:"setup__fieldtitle"},Ts={class:"setup__fielddesc"},Is={class:"setup__fielddesc setup__warning"},qs={class:"setup__actions"},Rs=["disabled"];function Ms(e,t,s,o,n,r){const l=(0,i.g2)("i18n-t"),u=(0,i.g2)("text-field"),c=(0,i.g2)("loading-button"),d=(0,i.g2)("radio-button");return(0,i.uX)(),(0,i.CE)("section",null,[(0,i.Lk)("header",ds,[t[17]||(t[17]=(0,i.Lk)("img",{src:cs,width:"80",height:"80",class:"setup__icon",alt:""},null,-1)),(0,i.Lk)("h1",ps,(0,a.v_)(e.$t("ui.setup.database-connection.headline")),1),(0,i.bF)(l,{tag:"p",keypath:"ui.setup.database-connection.description",class:"setup__description"},{env:(0,i.k6)((()=>t[16]||(t[16]=[(0,i.Lk)("code",null,".env.local",-1)]))),_:1})]),e.currentState?((0,i.uX)(),(0,i.Wv)(X.eB,{key:0,name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)((()=>["error"===e.currentState||"edit"===e.currentState?((0,i.uX)(),(0,i.CE)("main",hs,[(0,i.Lk)("form",{onSubmit:t[7]||(t[7]=(0,X.D$)((function(){return r.save&&r.save(...arguments)}),["prevent"]))},[(0,i.Lk)("div",ms,[(0,i.Lk)("h2",_s,(0,a.v_)(e.$t("ui.setup.database-connection.formTitle")),1),(0,i.Lk)("p",vs,(0,a.v_)(e.$t("ui.setup.database-connection.formText")),1),"edit"!==e.currentState&&""!==e.currentUrl?((0,i.uX)(),(0,i.CE)("p",ks,(0,a.v_)(e.$t("ui.setup.database-connection.error")),1)):(0,i.Q3)("",!0),(0,i.bF)(u,{ref:"url",name:"url",type:"url",label:e.$t("ui.setup.database-connection.url"),placeholder:"mysql://user:password@server:port/database",required:"",pattern:e.urlPattern,validate:"",disabled:e.processing,modelValue:e.url,"onUpdate:modelValue":t[0]||(t[0]=t=>e.url=t),onKeyup:t[1]||(t[1]=t=>e.validUrl=!0),onBlur:r.parseUrl,error:e.validUrl?void 0:e.$t("ui.setup.database-connection.validUrl")},null,8,["label","pattern","disabled","modelValue","onBlur","error"]),(0,i.Lk)("div",bs,[(0,i.Lk)("span",null,(0,a.v_)(e.$t("ui.setup.database-connection.or")),1)]),(0,i.bF)(u,{name:"user",label:e.$t("ui.setup.database-connection.user"),disabled:e.processing,modelValue:e.user,"onUpdate:modelValue":t[2]||(t[2]=t=>e.user=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{name:"password",type:"password",label:e.$t("ui.setup.database-connection.password"),disabled:e.processing,modelValue:e.password,"onUpdate:modelValue":t[3]||(t[3]=t=>e.password=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{name:"server",label:e.$t("ui.setup.database-connection.server"),disabled:e.processing,required:"",modelValue:e.server,"onUpdate:modelValue":t[4]||(t[4]=t=>e.server=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{name:"database",label:e.$t("ui.setup.database-connection.database"),disabled:e.processing,required:"",modelValue:e.database,"onUpdate:modelValue":t[5]||(t[5]=t=>e.database=t)},null,8,["label","disabled","modelValue"])]),(0,i.Lk)("div",gs,[(0,i.bF)(c,{submit:"",color:"primary",icon:"save",loading:e.processing,disabled:!e.valid},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.database-connection.save")),1)])),_:1},8,["loading","disabled"]),"edit"===e.currentState?((0,i.uX)(),(0,i.CE)("button",{key:0,type:"button",class:"widget-button",disabled:e.processing,onClick:t[6]||(t[6]=function(){return r.load&&r.load(...arguments)})},(0,a.v_)(e.$t("ui.setup.cancel")),9,fs)):(0,i.Q3)("",!0)])],32)])):((0,i.uX)(),(0,i.CE)("main",ys,[(0,i.Lk)("div",ws,[(0,i.Lk)("h2",Ls,(0,a.v_)(e.$t("ui.setup.database-connection.formTitle")),1),e.url?((0,i.uX)(),(0,i.Wv)(l,{key:0,tag:"p",keypath:"ui.setup.database-connection.connected",class:"setup__fielddesc"},{database:(0,i.k6)((()=>[(0,i.Lk)("i",null,(0,a.v_)(e.database),1)])),server:(0,i.k6)((()=>[(0,i.Lk)("i",null,(0,a.v_)(e.server),1)])),_:1})):(0,i.Q3)("",!0),(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--edit widget-button--small",onClick:t[8]||(t[8]=t=>e.currentState="edit")},(0,a.v_)(e.$t("ui.setup.database-connection.change")),1)]),(0,i.bF)(X.eB,{name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)((()=>[!e.hasDatabaseError&&e.backupRestore&&e.hasBackups?e.backupRestored?((0,i.uX)(),(0,i.CE)("div",As,[(0,i.Lk)("div",Vs,[(0,i.Lk)("h2",Us,(0,a.v_)(e.$t("ui.setup.database-connection.restoreTitle")),1),t[18]||(t[18]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",xs,(0,a.v_)(e.$t("ui.setup.database-connection.restored")),1)]),(0,i.Lk)("div",Ds,[(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--primary",onClick:t[12]||(t[12]=t=>e.$store.commit("contao/backup/setRestore",!1))},(0,a.v_)(e.$t("ui.setup.continue")),1)])])):((0,i.uX)(),(0,i.CE)("div",Ss,[(0,i.Lk)("div",Ps,[(0,i.Lk)("h2",Ws,(0,a.v_)(e.$t("ui.setup.database-connection.restoreTitle")),1),(0,i.Lk)("p",Ts,(0,a.v_)(e.$tc("ui.setup.database-connection.restoreText",e.files.length)),1),e.files.length>1?((0,i.uX)(),(0,i.Wv)(d,{key:0,required:"","allow-html":"",options:r.fileOptions,name:"selection",modelValue:e.selection,"onUpdate:modelValue":t[13]||(t[13]=t=>e.selection=t)},null,8,["options","modelValue"])):(0,i.Q3)("",!0),(0,i.Lk)("p",Is,(0,a.v_)(e.$t("ui.setup.database-connection.backupWarning")),1)]),(0,i.Lk)("div",qs,[(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline",onClick:t[14]||(t[14]=t=>e.$store.commit("contao/backup/setRestore",!1))},(0,a.v_)(e.$t("ui.setup.database-connection.skip")),1),(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline widget-button--primary",disabled:e.files.length>1&&!e.selection,onClick:t[15]||(t[15]=function(){return r.restore&&r.restore(...arguments)})},(0,a.v_)(e.$t("ui.setup.database-connection.restore")),9,Rs)])])):((0,i.uX)(),(0,i.CE)("div",$s,[(0,i.Lk)("div",Cs,[(0,i.Lk)("h2",Es,(0,a.v_)(e.$t("ui.setup.database-connection.schemaTitle")),1),e.status&&e.status.total>0?((0,i.uX)(),(0,i.CE)("p",Xs,(0,a.v_)(e.$tc(`ui.setup.database-connection.${e.currentState}`,e.status.total)),1)):((0,i.uX)(),(0,i.CE)("p",Fs,(0,a.v_)(e.$t("ui.setup.database-connection.noChanges")),1))]),(0,i.Lk)("div",js,[e.status&&e.status.total>0?((0,i.uX)(),(0,i.CE)(i.FK,{key:0},[e.hasDatabaseError?(0,i.Q3)("",!0):((0,i.uX)(),(0,i.CE)("button",{key:0,type:"button",class:"widget-button widget-button--inline",onClick:t[9]||(t[9]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.database-connection.skip")),1)),(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline widget-button--primary",onClick:t[10]||(t[10]=function(){return r.checkMigrations&&r.checkMigrations(...arguments)})},(0,a.v_)(e.$t("ui.setup.database-connection.check")),1)],64)):((0,i.uX)(),(0,i.CE)("button",{key:1,type:"button",class:"widget-button widget-button--primary",onClick:t[11]||(t[11]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1))])]))])),_:1})]))])),_:1})):(0,i.Q3)("",!0)])}var Bs=s(4210),Os=s(4960),Hs={components:{RadioButton:je,TextField:fe.A,LoadingButton:Ve.A},data:()=>({processing:!1,validUrl:!0,valid:!1,validating:!1,currentState:null,url:"",user:"",password:"",server:"localhost",database:"",backup:!0,selection:null}),computed:{...(0,C.aH)("tasks",{taskStatus:"status"}),...(0,C.aH)("contao/backup",{backupRestored:"restored",backupRestore:"restore"}),...(0,C.aH)("server/database",{currentUrl:"url",urlPattern:"pattern",status:"status"}),...(0,C.aH)("contao/backup",["files"]),...(0,C.L8)("server/database",{hasDatabaseError:"hasError"}),...(0,C.L8)("contao/backup",["hasBackups"]),fileOptions(){return this.files.map((e=>({value:e.name,label:this.$t("ui.setup.database-connection.restoreOption",{date:(0,Bs.A)(e.createdAt),size:(0,Os.A)(e.size)})})))}},methods:{datimFormat(e){return(0,Bs.A)(e,"short","long")},checkMigrations(){this.$store.commit("checkMigrations")},parseUrl(){if(!this.validateUrl())return;this.validating=!0;const e=new RegExp(this.urlPattern,"i").exec(this.url);this.user=e[3]?decodeURIComponent(e[3]):"",this.password=e[5]?decodeURIComponent(e[5]):"",this.server=decodeURIComponent(e[6]),this.database=decodeURIComponent(e[8]),":3306"===this.server.substring(this.server.length-5)?this.server=this.server.substring(0,this.server.length-5):this.server.includes(":")||(this.server=`${this.server}:3306`),this.valid=this.validateUrl(),this.validating=!1},updateUrl(){if(this.validating)return;if(this.valid=!1,!this.server)return;const e=this.server.split(":",2),t=`${encodeURIComponent(e[0])}:${e[1]||"3306"}`;let s="mysql://";this.user&&(s+=encodeURIComponent(this.user),this.password&&(s+=":"+encodeURIComponent(this.password)),s+="@"),s+=t,this.database&&(s+="/"+encodeURIComponent(this.database)),this.url=s,this.valid=this.validateUrl()},validateUrl(){return this.validUrl=!0,this.valid=!1,""!==this.url&&(this.validUrl=new RegExp(this.urlPattern,"i").test(this.url),this.validUrl)},async load(){this.url=(await this.$store.dispatch("server/database/get")).data.url,this.currentState=this.status?.type,this.parseUrl(),"error"===this.currentState&&(this.validUrl=!1,this.valid=!1)},async save(){this.processing=!0;const e=await this.$store.dispatch("server/database/set",this.url);if("error"===e.data.status.type)return this.processing=!1,this.validUrl=!1,void(this.valid=!1);await this.$store.dispatch("server/adminUser/get",!1),this.processing=!1},async restore(){await this.$store.dispatch("tasks/execute",{name:"contao/backup-restore",config:{file:this.files.length>1?this.selection:this.files[0].name,backup:!1}}),"complete"===this.taskStatus&&(this.$store.commit("contao/backup/setRestored"),await this.$store.dispatch("tasks/deleteCurrent"))}},watch:{user(){this.updateUrl()},password(){this.updateUrl()},server(){this.updateUrl()},database(){this.updateUrl()},status(){this.currentState=this.status?.type}},mounted(){this.load(),this.selection=null,this.backup=!0}};const Qs=(0,Xe.A)(Hs,[["render",Ms]]);var Ks=Qs,Js=s.p+"img/user.129e863d.svg";const Ns={class:"setup__header"},zs={class:"setup__headline"},Zs={class:"setup__description"},Ys={key:0,class:"setup__form"},Gs={class:"setup__fields"},ei={class:"setup__warning"},ti={class:"setup__form setup__form--center",key:"confirmation"},si={class:"setup__fields"},ii={class:"setup__fielddesc"},ai={class:"setup__actions setup__actions--center"},oi={class:"setup__form",key:"setup"},ni={class:"setup__fields"},ri={class:"setup__fieldtitle"},li={class:"setup__fielddesc"},ui={class:"setup__actions setup__actions--center"};function ci(e,t,s,o,n,r){const l=(0,i.g2)("console-output"),u=(0,i.g2)("text-field"),c=(0,i.g2)("loading-button");return(0,i.uX)(),(0,i.CE)("section",null,[(0,i.Lk)("header",Ns,[t[8]||(t[8]=(0,i.Lk)("img",{src:Js,width:"80",height:"80",class:"setup__icon",alt:""},null,-1)),(0,i.Lk)("h1",zs,(0,a.v_)(e.$t("ui.setup.backend-user.headline")),1),(0,i.Lk)("p",Zs,(0,a.v_)(e.$t("ui.setup.backend-user.description")),1)]),null===e.hasUser?((0,i.uX)(),(0,i.CE)("main",Ys,[(0,i.Lk)("div",Gs,[(0,i.Lk)("p",ei,(0,a.v_)(e.$t("ui.setup.backend-user.error")),1),502===e.response.status?((0,i.uX)(),(0,i.Wv)(l,{key:0,class:"view-recovery__console",title:e.$t("ui.recovery.console"),operations:[{status:"error",summary:"vendor/bin/contao-console contao:user:list",console:e.response.data.detail}],"console-output":e.response.data.detail,"show-console":"","force-console":""},null,8,["title","operations","console-output"])):(0,i.Q3)("",!0)])])):((0,i.uX)(),(0,i.Wv)(X.eB,{key:1,name:"animate-flip",type:"transition",mode:"out-in"},{default:(0,i.k6)((()=>[e.hasUser?((0,i.uX)(),(0,i.CE)("main",ti,[(0,i.Lk)("div",si,[t[9]||(t[9]=(0,i.Lk)("svg",{class:"setup__check",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,i.Lk)("path",{d:"M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z"})],-1)),(0,i.Lk)("p",ii,(0,a.v_)(e.$t("ui.setup.backend-user.success")),1)]),(0,i.Lk)("div",ai,[(0,i.Lk)("button",{type:"button",class:"widget-button widget-button--inline widget-button--primary",onClick:t[0]||(t[0]=t=>e.$emit("continue"))},(0,a.v_)(e.$t("ui.setup.continue")),1)])])):((0,i.uX)(),(0,i.CE)("main",oi,[(0,i.Lk)("form",{onSubmit:t[7]||(t[7]=(0,X.D$)((function(){return r.save&&r.save(...arguments)}),["prevent"]))},[(0,i.Lk)("div",ni,[(0,i.Lk)("h2",ri,(0,a.v_)(e.$t("ui.setup.backend-user.formTitle")),1),(0,i.Lk)("p",li,(0,a.v_)(e.$t("ui.setup.backend-user.formText")),1),(0,i.bF)(u,{ref:"username",name:"username",label:e.$t("ui.setup.backend-user.username"),disabled:e.processing,required:"",validate:"",modelValue:e.username,"onUpdate:modelValue":t[1]||(t[1]=t=>e.username=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{ref:"name",name:"name",label:e.$t("ui.setup.backend-user.name"),disabled:e.processing,required:"",validate:"",modelValue:e.name,"onUpdate:modelValue":t[2]||(t[2]=t=>e.name=t)},null,8,["label","disabled","modelValue"]),(0,i.bF)(u,{ref:"email",name:"email",type:"email",label:e.$t("ui.setup.backend-user.email"),disabled:e.processing,required:"",validate:"",error:e.errors.email,onFocus:t[3]||(t[3]=t=>e.errors.email=""),onBlur:r.validateEmail,modelValue:e.email,"onUpdate:modelValue":t[4]||(t[4]=t=>e.email=t)},null,8,["label","disabled","error","onBlur","modelValue"]),(0,i.bF)(u,{ref:"password",name:"password",type:"password",label:e.$t("ui.setup.backend-user.password"),placeholder:e.$t("ui.setup.backend-user.passwordPlaceholder"),disabled:e.processing,required:"",minlength:"8",validate:"",error:e.errors.password,onFocus:t[5]||(t[5]=t=>e.errors.password=""),onBlur:r.validatePassword,modelValue:e.password,"onUpdate:modelValue":t[6]||(t[6]=t=>e.password=t)},null,8,["label","placeholder","disabled","error","onBlur","modelValue"])]),(0,i.Lk)("div",ui,[(0,i.bF)(c,{submit:"",color:"primary",loading:e.processing,disabled:!e.valid},{default:(0,i.k6)((()=>[(0,i.eW)((0,a.v_)(e.$t("ui.setup.backend-user.create")),1)])),_:1},8,["loading","disabled"])])],32)]))])),_:1}))])}var di=s(6774),pi={components:{TextField:fe.A,LoadingButton:Ve.A,ConsoleOutput:di.A},data:()=>({processing:!1,valid:!1,username:"",name:"",email:"",password:"",errors:{email:"",password:""}}),computed:{...(0,C.aH)("server/adminUser",{hasUser:"hasUser",response:"cache"})},methods:{validate(){this.valid=this.$refs.username.checkValidity()&&this.$refs.name.checkValidity()&&this.$refs.email.checkValidity()&&this.$refs.password.checkValidity()},validateEmail(){this.errors.email=null,""!==this.email&&(this.$refs.email.checkValidity()||(this.errors.email=this.$t("ui.setup.backend-user.emailInvalid")))},validatePassword(){this.errors.password=null,""!==this.password&&this.password.length<8&&(this.errors.password=this.$t("ui.setup.backend-user.passwordLength"))},async save(){this.processing=!0,await this.$store.dispatch("server/adminUser/set",{username:this.username,name:this.name,email:this.email,password:this.password}),this.processing=!1,this.$store.commit("setup",5)}},watch:{username(){this.validate()},name(){this.validate()},email(){this.validate()},password(){this.validate()}}};const hi=(0,Xe.A)(pi,[["render",ci]]);var mi=hi,_i={components:{BoxedLayout:E.A,DocumentRoot:De,CreateProject:us,DatabaseConnection:Ks,BackendUser:mi},computed:{...(0,C.aH)(["setupStep"]),...(0,C.aH)("server/contao",["contaoVersion"]),...(0,C.aH)("server/database",{databaseSupported:"supported"}),...(0,C.aH)("server/adminUser",{userSupported:"supported"}),currentStep:{get(){return this.setupStep},set(e){this.$store.commit("setup",e)}},steps(){const e=[];return e.push({name:"document-root",icon:F,component:De}),e.push({name:"create-project",icon:Se,component:us}),this.databaseSupported&&e.push({name:"database-connection",icon:cs,component:Ks}),this.userSupported&&e.push({name:"backend-user",icon:Js,component:mi}),e}},methods:{launch(){this.$store.commit("setView",$.A.READY)}},mounted(){this.$store.dispatch("server/adminUser/get"),this.$store.dispatch("contao/backup/fetch")}};const vi=(0,Xe.A)(_i,[["render",L]]);var ki=vi},4686:function(e,t){var s=this&&this.__extends||function(){var e=function(t,s){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s])},e(t,s)};return function(t,s){if("function"!==typeof s&&null!==s)throw new TypeError("Class extends value "+String(s)+" is not a constructor or null");function i(){this.constructor=t}e(t,s),t.prototype=null===s?Object.create(s):(i.prototype=s.prototype,new i)}}();Object.defineProperty(t,"__esModule",{value:!0}),t.treeifyPaths=t.Node=t.PathTree=void 0;var i=function(){function e(e){void 0===e&&(e=""),this.path=e,this.name="",this.children=[]}return e}();t.PathTree=i;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return s(t,e),t}(i);function o(e,t,s){void 0===s&&(s={});var a={};t.forEach((function(t){var s=t[0],o=t[1],n=r(s).split("/"),l=n[0];if(!a[l]){var u="".concat(e.path,"/").concat(n[0]);a[l]={paths:[],obj:new i(r(u))}}if(1==n.length)a[l].obj.name=l,a[l].obj.ctx=o;else{n.shift();var c=n.join("/");a[l].paths.push([c,o]),a[l].obj.ctx=o}}));var n=Object.keys(a);return s.caseInsensitive?n.sort((function(e,t){return e.toLocaleLowerCase().localeCompare(t.toLocaleLowerCase())})):n.sort(),n.forEach((function(t){var i=a[t].obj;o(i,a[t].paths,s),(i.name||i.path||i.children.length)&&e.children.push(i)})),s.directoriesFirst?e.children.sort((function(e,t){return e.children.length&&!t.children.length?-1:t.children.length&&!e.children.length?1:0})):s.directoriesLast&&e.children.sort((function(e,t){return e.children.length&&!t.children.length?1:t.children.length&&!e.children.length?-1:0})),e}function n(e,t){void 0===e&&(e=[]),void 0===t&&(t={});var s=l(e)?e.map((function(e){return[e,void 0]})):e;return o(new i,s,t)}t.Node=a,t.treeifyPaths=n,t["default"]=n;var r=function(e){return e.replace(/^\/*/,"").replace(/\/*$/,"")},l=function(e){return"string"===typeof e[0]}},9472:function(e,t,s){e.exports=s.p+"img/database.7f0a8c49.svg"}}]);(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[710],{1710:function(e,t,r){ /*! JSZip v3.10.1 - A JavaScript class for generating and reading zip files (c) 2009-2016 Stuart Knightley Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown. JSZip uses the library pako released under the MIT license : https://github.com/nodeca/pako/blob/main/LICENSE */ !function(t){e.exports=t()}((function(){return function e(t,r,n){function i(a,o){if(!r[a]){if(!t[a]){var h=void 0;if(!o&&h)return require(a,!0);if(s)return s(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=r[a]={exports:{}};t[a][0].call(l.exports,(function(e){var r=t[a][1][e];return i(r||e)}),l,l.exports,e,t,r,n)}return r[a].exports}for(var s=void 0,a=0;a>2,o=(3&t)<<4|r>>4,h=1>6:64,u=2>4,r=(15&a)<<4|(o=s.indexOf(e.charAt(u++)))>>2,n=(3&o)<<6|(h=s.indexOf(e.charAt(u++))),c[l++]=t,64!==o&&(c[l++]=r),64!==h&&(c[l++]=n);return c}},{"./support":30,"./utils":32}],2:[function(e,t,r){"use strict";var n=e("./external"),i=e("./stream/DataWorker"),s=e("./stream/Crc32Probe"),a=e("./stream/DataLengthProbe");function o(e,t,r,n,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=r,this.compression=n,this.compressedContent=i}o.prototype={getContentWorker:function(){var e=new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")),t=this;return e.on("end",(function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")})),e},getCompressedWorker:function(){return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(e,t,r){return e.pipe(new s).pipe(new a("uncompressedSize")).pipe(t.compressWorker(r)).pipe(new a("compressedSize")).withStreamInfo("compression",t)},t.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,r){"use strict";var n=e("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(){return new n("STORE compression")},uncompressWorker:function(){return new n("STORE decompression")}},r.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,r){"use strict";var n=e("./utils"),i=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t){return void 0!==e&&e.length?"string"!==n.getTypeOf(e)?function(e,t,r,n){var s=i,a=n+r;e^=-1;for(var o=n;o>>8^s[255&(e^t[o])];return~e}(0|t,e,e.length,0):function(e,t,r,n){var s=i,a=n+r;e^=-1;for(var o=n;o>>8^s[255&(e^t.charCodeAt(o))];return~e}(0|t,e,e.length,0):0}},{"./utils":32}],5:[function(e,t,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(e,t,r){"use strict";var n=null;n="undefined"!=typeof Promise?Promise:e("lie"),t.exports={Promise:n}},{lie:37}],7:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,i=e("pako"),s=e("./utils"),a=e("./stream/GenericWorker"),o=n?"uint8array":"array";function h(e,t){a.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}r.magic="\b\0",s.inherits(h,a),h.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,e.data),!1)},h.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var e=this;this._pako.onData=function(t){e.push({data:t,meta:e.meta})}},r.compressWorker=function(e){return new h("Deflate",e)},r.uncompressWorker=function(){return new h("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,t,r){"use strict";function n(e,t){var r,n="";for(r=0;r>>=8;return n}function i(e,t,r,i,a,l){var f,c,d=e.file,p=e.compression,m=l!==o.utf8encode,_=s.transformTo("string",l(d.name)),g=s.transformTo("string",o.utf8encode(d.name)),b=d.comment,v=s.transformTo("string",l(b)),y=s.transformTo("string",o.utf8encode(b)),w=g.length!==d.name.length,k=y.length!==b.length,x="",S="",z="",C=d.dir,E=d.date,A={crc32:0,compressedSize:0,uncompressedSize:0};t&&!r||(A.crc32=e.crc32,A.compressedSize=e.compressedSize,A.uncompressedSize=e.uncompressedSize);var I=0;t&&(I|=8),m||!w&&!k||(I|=2048);var O=0,B=0;C&&(O|=16),"UNIX"===a?(B=798,O|=function(e,t){var r=e;return e||(r=t?16893:33204),(65535&r)<<16}(d.unixPermissions,C)):(B=20,O|=function(e){return 63&(e||0)}(d.dosPermissions)),f=E.getUTCHours(),f<<=6,f|=E.getUTCMinutes(),f<<=5,f|=E.getUTCSeconds()/2,c=E.getUTCFullYear()-1980,c<<=4,c|=E.getUTCMonth()+1,c<<=5,c|=E.getUTCDate(),w&&(S=n(1,1)+n(h(_),4)+g,x+="up"+n(S.length,2)+S),k&&(z=n(1,1)+n(h(v),4)+y,x+="uc"+n(z.length,2)+z);var R="";return R+="\n\0",R+=n(I,2),R+=p.magic,R+=n(f,2),R+=n(c,2),R+=n(A.crc32,4),R+=n(A.compressedSize,4),R+=n(A.uncompressedSize,4),R+=n(_.length,2),R+=n(x.length,2),{fileRecord:u.LOCAL_FILE_HEADER+R+_+x,dirRecord:u.CENTRAL_FILE_HEADER+n(B,2)+R+n(v.length,2)+"\0\0\0\0"+n(O,4)+n(i,4)+_+x+v}}var s=e("../utils"),a=e("../stream/GenericWorker"),o=e("../utf8"),h=e("../crc32"),u=e("../signature");function l(e,t,r,n){a.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=t,this.zipPlatform=r,this.encodeFileName=n,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}s.inherits(l,a),l.prototype.push=function(e){var t=e.meta.percent||0,r=this.entriesCount,n=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,a.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:r?(t+100*(r-n-1))/r:100}}))},l.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var t=this.streamFiles&&!e.file.dir;if(t){var r=i(e,t,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},l.prototype.closedSource=function(e){this.accumulate=!1;var t=this.streamFiles&&!e.file.dir,r=i(e,t,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(r.dirRecord),t)this.push({data:function(e){return u.DATA_DESCRIPTOR+n(e.crc32,4)+n(e.compressedSize,4)+n(e.uncompressedSize,4)}(e),meta:{percent:100}});else for(this.push({data:r.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},l.prototype.flush=function(){for(var e=this.bytesWritten,t=0;t=this.index;t--)r=(r<<8)+this.byteAt(t);return this.index+=e,r},readString:function(e){return n.transformTo("string",this.readData(e))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},t.exports=i},{"../utils":32}],19:[function(e,t,r){"use strict";var n=e("./Uint8ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},i.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},i.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],21:[function(e,t,r){"use strict";var n=e("./ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return new Uint8Array(0);var t=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./ArrayReader":17}],22:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../support"),s=e("./ArrayReader"),a=e("./StringReader"),o=e("./NodeBufferReader"),h=e("./Uint8ArrayReader");t.exports=function(e){var t=n.getTypeOf(e);return n.checkSupport(t),"string"!==t||i.uint8array?"nodebuffer"===t?new o(e):i.uint8array?new h(n.transformTo("uint8array",e)):new s(n.transformTo("array",e)):new a(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,t,r){"use strict";r.LOCAL_FILE_HEADER="PK",r.CENTRAL_FILE_HEADER="PK",r.CENTRAL_DIRECTORY_END="PK",r.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",r.ZIP64_CENTRAL_DIRECTORY_END="PK",r.DATA_DESCRIPTOR="PK\b"},{}],24:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../utils");function s(e){n.call(this,"ConvertWorker to "+e),this.destType=e}i.inherits(s,n),s.prototype.processChunk=function(e){this.push({data:i.transformTo(this.destType,e.data),meta:e.meta})},t.exports=s},{"../utils":32,"./GenericWorker":28}],25:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../crc32");function s(){n.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}e("../utils").inherits(s,n),s.prototype.processChunk=function(e){this.streamInfo.crc32=i(e.data,this.streamInfo.crc32||0),this.push(e)},t.exports=s},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataLengthProbe for "+e),this.propName=e,this.withStreamInfo(e,0)}n.inherits(s,i),s.prototype.processChunk=function(e){if(e){var t=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=t+e.data.length}i.prototype.processChunk.call(this,e)},t.exports=s},{"../utils":32,"./GenericWorker":28}],27:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataWorker");var t=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,e.then((function(e){t.dataIsReady=!0,t.data=e,t.max=e&&e.length||0,t.type=n.getTypeOf(e),t.isPaused||t._tickAndRepeat()}),(function(e){t.error(e)}))}n.inherits(s,i),s.prototype.cleanUp=function(){i.prototype.cleanUp.call(this),this.data=null},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,n.delay(this._tickAndRepeat,[],this)),!0)},s.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(n.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},s.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,t=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":e=this.data.substring(this.index,t);break;case"uint8array":e=this.data.subarray(this.index,t);break;case"array":case"nodebuffer":e=this.data.slice(this.index,t)}return this.index=t,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},t.exports=s},{"../utils":32,"./GenericWorker":28}],28:[function(e,t,r){"use strict";function n(e){this.name=e||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}n.prototype={push:function(e){this.emit("data",e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(e){this.emit("error",e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit("error",e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,t){return this._listeners[e].push(t),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,t){if(this._listeners[e])for(var r=0;r "+e:e}},t.exports=n},{}],29:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./ConvertWorker"),s=e("./GenericWorker"),a=e("../base64"),o=e("../support"),h=e("../external"),u=null;if(o.nodestream)try{u=e("../nodejs/NodejsStreamOutputAdapter")}catch(e){}function l(e,t){return new h.Promise((function(r,i){var s=[],o=e._internalType,h=e._outputType,u=e._mimeType;e.on("data",(function(e,r){s.push(e),t&&t(r)})).on("error",(function(e){s=[],i(e)})).on("end",(function(){try{var e=function(e,t,r){switch(e){case"blob":return n.newBlob(n.transformTo("arraybuffer",t),r);case"base64":return a.encode(t);default:return n.transformTo(e,t)}}(h,function(e,t){var r,n=0,i=null,s=0;for(r=0;r>>6:(r<65536?t[a++]=224|r>>>12:(t[a++]=240|r>>>18,t[a++]=128|r>>>12&63),t[a++]=128|r>>>6&63),t[a++]=128|63&r);return t}(e)},r.utf8decode=function(e){return i.nodebuffer?n.transformTo("nodebuffer",e).toString("utf-8"):function(e){var t,r,i,s,a=e.length,h=new Array(2*a);for(t=r=0;t>10&1023,h[r++]=56320|1023&i)}return h.length!==r&&(h.subarray?h=h.subarray(0,r):h.length=r),n.applyFromCharCode(h)}(e=n.transformTo(i.uint8array?"uint8array":"array",e))},n.inherits(u,a),u.prototype.processChunk=function(e){var t=n.transformTo(i.uint8array?"uint8array":"array",e.data);if(this.leftOver&&this.leftOver.length){if(i.uint8array){var s=t;(t=new Uint8Array(s.length+this.leftOver.length)).set(this.leftOver,0),t.set(s,this.leftOver.length)}else t=this.leftOver.concat(t);this.leftOver=null}var a=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0||0===r?t:r+o[e[r]]>t?r:t}(t),h=t;a!==t.length&&(i.uint8array?(h=t.subarray(0,a),this.leftOver=t.subarray(a,t.length)):(h=t.slice(0,a),this.leftOver=t.slice(a,t.length))),this.push({data:r.utf8decode(h),meta:e.meta})},u.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:r.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},r.Utf8DecodeWorker=u,n.inherits(l,a),l.prototype.processChunk=function(e){this.push({data:r.utf8encode(e.data),meta:e.meta})},r.Utf8EncodeWorker=l},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,t,r){"use strict";var n=e("./support"),i=e("./base64"),s=e("./nodejsUtils"),a=e("./external");function o(e){return e}function h(e,t){for(var r=0;r>8;this.dir=!!(16&this.externalFileAttributes),0==e&&(this.dosPermissions=63&this.externalFileAttributes),3==e&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var e=n(this.extraFields[1].value);this.uncompressedSize===i.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===i.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===i.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===i.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(e){var t,r,n,i=e.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});e.index+4>>6:(r<65536?t[a++]=224|r>>>12:(t[a++]=240|r>>>18,t[a++]=128|r>>>12&63),t[a++]=128|r>>>6&63),t[a++]=128|63&r);return t},r.buf2binstring=function(e){return h(e,e.length)},r.binstring2buf=function(e){for(var t=new n.Buf8(e.length),r=0,i=t.length;r>10&1023,u[n++]=56320|1023&i)}return h(u,n)},r.utf8border=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0||0===r?t:r+a[e[r]]>t?r:t}},{"./common":41}],43:[function(e,t,r){"use strict";t.exports=function(e,t,r,n){for(var i=65535&e,s=e>>>16&65535,a=0;0!==r;){for(r-=a=2e3>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t,r,i){var s=n,a=i+r;e^=-1;for(var o=i;o>>8^s[255&(e^t[o])];return~e}},{}],46:[function(e,t,r){"use strict";var n,i=e("../utils/common"),s=e("./trees"),a=e("./adler32"),o=e("./crc32"),h=e("./messages"),u=0,l=4,f=0,c=-2,d=-1,p=4,m=2,_=8,g=9,b=286,v=30,y=19,w=2*b+1,k=15,x=3,S=258,z=S+x+1,C=42,E=113,A=1,I=2,O=3,B=4;function R(e,t){return e.msg=h[t],t}function T(e){return(e<<1)-(4e.avail_out&&(r=e.avail_out),0!==r&&(i.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function N(e,t){s._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,F(e.strm)}function U(e,t){e.pending_buf[e.pending++]=t}function P(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function L(e,t){var r,n,i=e.max_chain_length,s=e.strstart,a=e.prev_length,o=e.nice_match,h=e.strstart>e.w_size-z?e.strstart-(e.w_size-z):0,u=e.window,l=e.w_mask,f=e.prev,c=e.strstart+S,d=u[s+a-1],p=u[s+a];e.prev_length>=e.good_match&&(i>>=2),o>e.lookahead&&(o=e.lookahead);do{if(u[(r=t)+a]===p&&u[r+a-1]===d&&u[r]===u[s]&&u[++r]===u[s+1]){s+=2,r++;do{}while(u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&sh&&0!=--i);return a<=e.lookahead?a:e.lookahead}function j(e){var t,r,n,s,h,u,l,f,c,d,p=e.w_size;do{if(s=e.window_size-e.lookahead-e.strstart,e.strstart>=p+(p-z)){for(i.arraySet(e.window,e.window,p,p,0),e.match_start-=p,e.strstart-=p,e.block_start-=p,t=r=e.hash_size;n=e.head[--t],e.head[t]=p<=n?n-p:0,--r;);for(t=r=p;n=e.prev[--t],e.prev[t]=p<=n?n-p:0,--r;);s+=p}if(0===e.strm.avail_in)break;if(u=e.strm,l=e.window,f=e.strstart+e.lookahead,c=s,d=void 0,d=u.avail_in,c=x)for(h=e.strstart-e.insert,e.ins_h=e.window[h],e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x)if(n=s._tr_tally(e,e.strstart-e.match_start,e.match_length-x),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=x){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x&&e.match_length<=e.prev_length){for(i=e.strstart+e.lookahead-x,n=s._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-x),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=i&&(e.ins_h=(e.ins_h<e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(j(e),0===e.lookahead&&t===u)return A;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,N(e,!1),0===e.strm.avail_out))return A;if(e.strstart-e.block_start>=e.w_size-z&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===l?(N(e,!0),0===e.strm.avail_out?O:B):(e.strstart>e.block_start&&(N(e,!1),e.strm.avail_out),A)})),new M(4,4,8,4,Z),new M(4,5,16,8,Z),new M(4,6,32,32,Z),new M(4,4,16,16,W),new M(8,16,32,32,W),new M(8,16,128,128,W),new M(8,32,128,256,W),new M(32,128,258,1024,W),new M(32,258,258,4096,W)],r.deflateInit=function(e,t){return Y(e,t,_,15,8,0)},r.deflateInit2=Y,r.deflateReset=K,r.deflateResetKeep=G,r.deflateSetHeader=function(e,t){return e&&e.state?2!==e.state.wrap?c:(e.state.gzhead=t,f):c},r.deflate=function(e,t){var r,i,a,h;if(!e||!e.state||5>8&255),U(i,i.gzhead.time>>16&255),U(i,i.gzhead.time>>24&255),U(i,9===i.level?2:2<=i.strategy||i.level<2?4:0),U(i,255&i.gzhead.os),i.gzhead.extra&&i.gzhead.extra.length&&(U(i,255&i.gzhead.extra.length),U(i,i.gzhead.extra.length>>8&255)),i.gzhead.hcrc&&(e.adler=o(e.adler,i.pending_buf,i.pending,0)),i.gzindex=0,i.status=69):(U(i,0),U(i,0),U(i,0),U(i,0),U(i,0),U(i,9===i.level?2:2<=i.strategy||i.level<2?4:0),U(i,3),i.status=E);else{var d=_+(i.w_bits-8<<4)<<8;d|=(2<=i.strategy||i.level<2?0:i.level<6?1:6===i.level?2:3)<<6,0!==i.strstart&&(d|=32),d+=31-d%31,i.status=E,P(i,d),0!==i.strstart&&(P(i,e.adler>>>16),P(i,65535&e.adler)),e.adler=1}if(69===i.status)if(i.gzhead.extra){for(a=i.pending;i.gzindex<(65535&i.gzhead.extra.length)&&(i.pending!==i.pending_buf_size||(i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),F(e),a=i.pending,i.pending!==i.pending_buf_size));)U(i,255&i.gzhead.extra[i.gzindex]),i.gzindex++;i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),i.gzindex===i.gzhead.extra.length&&(i.gzindex=0,i.status=73)}else i.status=73;if(73===i.status)if(i.gzhead.name){a=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),F(e),a=i.pending,i.pending===i.pending_buf_size)){h=1;break}h=i.gzindexa&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),0===h&&(i.gzindex=0,i.status=91)}else i.status=91;if(91===i.status)if(i.gzhead.comment){a=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>a&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),F(e),a=i.pending,i.pending===i.pending_buf_size)){h=1;break}h=i.gzindexa&&(e.adler=o(e.adler,i.pending_buf,i.pending-a,a)),0===h&&(i.status=103)}else i.status=103;if(103===i.status&&(i.gzhead.hcrc?(i.pending+2>i.pending_buf_size&&F(e),i.pending+2<=i.pending_buf_size&&(U(i,255&e.adler),U(i,e.adler>>8&255),e.adler=0,i.status=E)):i.status=E),0!==i.pending){if(F(e),0===e.avail_out)return i.last_flush=-1,f}else if(0===e.avail_in&&T(t)<=T(r)&&t!==l)return R(e,-5);if(666===i.status&&0!==e.avail_in)return R(e,-5);if(0!==e.avail_in||0!==i.lookahead||t!==u&&666!==i.status){var p=2===i.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(j(e),0===e.lookahead)){if(t===u)return A;break}if(e.match_length=0,r=s._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===l?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(i,t):3===i.strategy?function(e,t){for(var r,n,i,a,o=e.window;;){if(e.lookahead<=S){if(j(e),e.lookahead<=S&&t===u)return A;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=x&&0e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=x?(r=s._tr_tally(e,1,e.match_length-x),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=s._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===l?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(i,t):n[i.level].func(i,t);if(p!==O&&p!==B||(i.status=666),p===A||p===O)return 0===e.avail_out&&(i.last_flush=-1),f;if(p===I&&(1===t?s._tr_align(i):5!==t&&(s._tr_stored_block(i,0,0,!1),3===t&&(D(i.head),0===i.lookahead&&(i.strstart=0,i.block_start=0,i.insert=0))),F(e),0===e.avail_out))return i.last_flush=-1,f}return t!==l?f:i.wrap<=0?1:(2===i.wrap?(U(i,255&e.adler),U(i,e.adler>>8&255),U(i,e.adler>>16&255),U(i,e.adler>>24&255),U(i,255&e.total_in),U(i,e.total_in>>8&255),U(i,e.total_in>>16&255),U(i,e.total_in>>24&255)):(P(i,e.adler>>>16),P(i,65535&e.adler)),F(e),0=r.w_size&&(0===o&&(D(r.head),r.strstart=0,r.block_start=0,r.insert=0),d=new i.Buf8(r.w_size),i.arraySet(d,t,p-r.w_size,r.w_size,0),t=d,p=r.w_size),h=e.avail_in,u=e.next_in,l=e.input,e.avail_in=p,e.next_in=0,e.input=t,j(r);r.lookahead>=x;){for(n=r.strstart,s=r.lookahead-(x-1);r.ins_h=(r.ins_h<>>=y=v>>>24,p-=y,0===(y=v>>>16&255))C[s++]=65535&v;else{if(!(16&y)){if(0==(64&y)){v=m[(65535&v)+(d&(1<>>=y,p-=y),p<15&&(d+=z[n++]<>>=y=v>>>24,p-=y,!(16&(y=v>>>16&255))){if(0==(64&y)){v=_[(65535&v)+(d&(1<>>=y,p-=y,(y=s-a)>3,d&=(1<<(p-=w<<3))-1,e.next_in=n,e.next_out=s,e.avail_in=n>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function _(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new n.Buf16(320),this.work=new n.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function g(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=c,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new n.Buf32(d),t.distcode=t.distdyn=new n.Buf32(p),t.sane=1,t.back=-1,l):f}function b(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,g(e)):f}function v(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15=a.wsize?(n.arraySet(a.window,t,r-a.wsize,a.wsize,0),a.wnext=0,a.whave=a.wsize):(i<(s=a.wsize-a.wnext)&&(s=i),n.arraySet(a.window,t,r-i,s,a.wnext),(i-=s)?(n.arraySet(a.window,t,r-i,i,0),a.wnext=i,a.whave=a.wsize):(a.wnext+=s,a.wnext===a.wsize&&(a.wnext=0),a.whave>>8&255,r.check=s(r.check,j,2,0),w=y=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&y)<<8)+(y>>8))%31){e.msg="incorrect header check",r.mode=30;break}if(8!=(15&y)){e.msg="unknown compression method",r.mode=30;break}if(w-=4,F=8+(15&(y>>>=4)),0===r.wbits)r.wbits=F;else if(F>r.wbits){e.msg="invalid window size",r.mode=30;break}r.dmax=1<>8&1),512&r.flags&&(j[0]=255&y,j[1]=y>>>8&255,r.check=s(r.check,j,2,0)),w=y=0,r.mode=3;case 3:for(;w<32;){if(0===b)break e;b--,y+=d[_++]<>>8&255,j[2]=y>>>16&255,j[3]=y>>>24&255,r.check=s(r.check,j,4,0)),w=y=0,r.mode=4;case 4:for(;w<16;){if(0===b)break e;b--,y+=d[_++]<>8),512&r.flags&&(j[0]=255&y,j[1]=y>>>8&255,r.check=s(r.check,j,2,0)),w=y=0,r.mode=5;case 5:if(1024&r.flags){for(;w<16;){if(0===b)break e;b--,y+=d[_++]<>>8&255,r.check=s(r.check,j,2,0)),w=y=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(b<(C=r.length)&&(C=b),C&&(r.head&&(F=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),n.arraySet(r.head.extra,d,_,C,F)),512&r.flags&&(r.check=s(r.check,d,C,_)),b-=C,_+=C,r.length-=C),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===b)break e;for(C=0;F=d[_+C++],r.head&&F&&r.length<65536&&(r.head.name+=String.fromCharCode(F)),F&&C>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=12;break;case 10:for(;w<32;){if(0===b)break e;b--,y+=d[_++]<>>=7&w,w-=7&w,r.mode=27;break}for(;w<3;){if(0===b)break e;b--,y+=d[_++]<>>=1)){case 0:r.mode=14;break;case 1:if(S(r),r.mode=20,6!==t)break;y>>>=2,w-=2;break e;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=30}y>>>=2,w-=2;break;case 14:for(y>>>=7&w,w-=7&w;w<32;){if(0===b)break e;b--,y+=d[_++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&y,w=y=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(C=r.length){if(b>>=5,w-=5,r.ndist=1+(31&y),y>>>=5,w-=5,r.ncode=4+(15&y),y>>>=4,w-=4,286>>=3,w-=3}for(;r.have<19;)r.lens[Z[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,U={bits:r.lenbits},N=o(0,r.lens,0,19,r.lencode,0,r.work,U),r.lenbits=U.bits,N){e.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have>>16&255,B=65535&L,!((I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<>>=I,w-=I,r.lens[r.have++]=B;else{if(16===B){for(P=I+2;w>>=I,w-=I,0===r.have){e.msg="invalid bit length repeat",r.mode=30;break}F=r.lens[r.have-1],C=3+(3&y),y>>>=2,w-=2}else if(17===B){for(P=I+3;w>>=I)),y>>>=3,w-=3}else{for(P=I+7;w>>=I)),y>>>=7,w-=7}if(r.have+C>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=30;break}for(;C--;)r.lens[r.have++]=F}}if(30===r.mode)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,U={bits:r.lenbits},N=o(h,r.lens,0,r.nlen,r.lencode,0,r.work,U),r.lenbits=U.bits,N){e.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,U={bits:r.distbits},N=o(u,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,U),r.distbits=U.bits,N){e.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(6<=b&&258<=v){e.next_out=g,e.avail_out=v,e.next_in=_,e.avail_in=b,r.hold=y,r.bits=w,a(e,x),g=e.next_out,p=e.output,v=e.avail_out,_=e.next_in,d=e.input,b=e.avail_in,y=r.hold,w=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;O=(L=r.lencode[y&(1<>>16&255,B=65535&L,!((I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<>R)])>>>16&255,B=65535&L,!(R+(I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<>>=R,w-=R,r.back+=R}if(y>>>=I,w-=I,r.back+=I,r.length=B,0===O){r.mode=26;break}if(32&O){r.back=-1,r.mode=12;break}if(64&O){e.msg="invalid literal/length code",r.mode=30;break}r.extra=15&O,r.mode=22;case 22:if(r.extra){for(P=r.extra;w>>=r.extra,w-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;O=(L=r.distcode[y&(1<>>16&255,B=65535&L,!((I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<>R)])>>>16&255,B=65535&L,!(R+(I=L>>>24)<=w);){if(0===b)break e;b--,y+=d[_++]<>>=R,w-=R,r.back+=R}if(y>>>=I,w-=I,r.back+=I,64&O){e.msg="invalid distance code",r.mode=30;break}r.offset=B,r.extra=15&O,r.mode=24;case 24:if(r.extra){for(P=r.extra;w>>=r.extra,w-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===v)break e;if(C=x-v,r.offset>C){if((C=r.offset-C)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=30;break}E=C>r.wnext?(C-=r.wnext,r.wsize-C):r.wnext-C,C>r.length&&(C=r.length),A=r.window}else A=p,E=g-r.offset,C=r.length;for(vb?(y=U[P+f[S]],T[D+f[S]]):(y=96,0),d=1<>I)+(p-=d)]=v<<24|y<<16|w,0!==p;);for(d=1<>=1;if(0!==d?(R&=d-1,R+=d):R=0,S++,0==--F[x]){if(x===C)break;x=t[r+f[S]]}if(E>>7)]}function U(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function P(e,t,r){e.bi_valid>m-r?(e.bi_buf|=t<>m-e.bi_valid,e.bi_valid+=r-m):(e.bi_buf|=t<>>=1,r<<=1,0<--t;);return r>>>1}function Z(e,t,r){var n,i,s=new Array(p+1),a=0;for(n=1;n<=p;n++)s[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var o=e[2*i+1];0!==o&&(e[2*i]=j(s[o]++,o))}}function W(e){var t;for(t=0;t>1;1<=r;r--)G(e,s,r);for(i=h;r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],G(e,s,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,s[2*i]=s[2*r]+s[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,s[2*r+1]=s[2*n+1]=i,e.heap[1]=i++,G(e,s,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,s,a,o,h=t.dyn_tree,u=t.max_code,l=t.stat_desc.static_tree,f=t.stat_desc.has_stree,c=t.stat_desc.extra_bits,m=t.stat_desc.extra_base,_=t.stat_desc.max_length,g=0;for(s=0;s<=p;s++)e.bl_count[s]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r>=7;n>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return i;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return s;for(t=32;t>>3,(o=e.static_len+3+7>>>3)<=a&&(a=o)):a=o=r+5,r+4<=a&&-1!==t?J(e,t,r,n):4===e.strategy||o===a?(P(e,2+(n?1:0),3),K(e,z,C)):(P(e,4+(n?1:0),3),function(e,t,r,n){var i;for(P(e,t-257,5),P(e,r-1,5),P(e,n-4,4),i=0;i>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(A[r]+u+1)]++,e.dyn_dtree[2*N(t)]++),e.last_lit===e.lit_bufsize-1},r._tr_align=function(e){P(e,2,3),L(e,g,z),function(e){16===e.bi_valid?(U(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},{"../utils/common":41}],53:[function(e,t,r){"use strict";t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,t,n){(function(e){!function(e,t){"use strict";if(!e.setImmediate){var r,n,i,s,a=1,o={},h=!1,u=e.document,l=Object.getPrototypeOf&&Object.getPrototypeOf(e);l=l&&l.setTimeout?l:e,r="[object process]"==={}.toString.call(e.process)?function(e){process.nextTick((function(){c(e)}))}:function(){if(e.postMessage&&!e.importScripts){var t=!0,r=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=r,t}}()?(s="setImmediate$"+Math.random()+"$",e.addEventListener?e.addEventListener("message",d,!1):e.attachEvent("onmessage",d),function(t){e.postMessage(s+t,"*")}):e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){c(e.data)},function(e){i.port2.postMessage(e)}):u&&"onreadystatechange"in u.createElement("script")?(n=u.documentElement,function(e){var t=u.createElement("script");t.onreadystatechange=function(){c(e),t.onreadystatechange=null,n.removeChild(t),t=null},n.appendChild(t)}):function(e){setTimeout(c,0,e)},l.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n[(0,o.Lk)("header",s,[r[1]||(r[1]=(0,o.Lk)("img",{src:a,width:"80",height:"80",alt:"",class:"view-recovery__icon"},null,-1)),(0,o.Lk)("h1",n,(0,i.v_)(e.$t("ui.recovery.headline")),1)]),(0,o.Lk)("main",c,[(0,o.Lk)("p",l,(0,i.v_)(e.$t("ui.recovery.description")),1),console?((0,o.uX)(),(0,o.Wv)(w,{key:0,class:"view-recovery__console",title:e.$t("ui.recovery.console"),operations:[{status:"error",summary:"vendor/bin/contao-console list",console:this.error}],"console-output":e.error,"show-console":"","force-console":""},null,8,["title","operations","console-output"])):(0,o.Q3)("",!0),(0,o.Lk)("p",d,(0,i.v_)(e.$t("ui.recovery.repairOptions")),1),(0,o.Lk)("div",u,[(0,o.Lk)("h3",null,(0,i.v_)(e.$t("ui.recovery.repairHeadline")),1),(0,o.Lk)("p",null,(0,i.v_)(e.$t("ui.recovery.repairDescription")),1),(0,o.Lk)("p",null,[(0,o.Lk)("strong",null,(0,i.v_)(e.$t("ui.recovery.repairWarning")),1)]),e.repairFailed?((0,o.uX)(),(0,o.CE)("p",v,(0,i.v_)(e.$t("ui.recovery.repairFailed")),1)):(0,o.Q3)("",!0),(0,o.bF)(f,{inline:"",color:"alert",icon:"run",disabled:e.repairFailed,loading:e.repairStarted&&!e.repairFailed,onClick:y.runRepair},{default:(0,o.k6)((()=>[(0,o.eW)((0,i.v_)(e.$t("ui.recovery.repairButton")),1)])),_:1},8,["disabled","loading","onClick"])]),(0,o.Lk)("div",p,[(0,o.Lk)("h3",null,(0,i.v_)(e.$t("ui.recovery.safeModeHeadline")),1),(0,o.Lk)("p",null,(0,i.v_)(e.$t("ui.recovery.safeModeDescription")),1),(0,o.Lk)("button",{class:"widget-button widget-button--inline widget-button--primary",disabled:e.repairStarted&&!e.repairFailed,onClick:r[0]||(r[0]=function(){return y.runSafeMode&&y.runSafeMode(...arguments)})},(0,i.v_)(e.$t("ui.recovery.safeModeButton")),9,h)])])])),_:1})}var k=t(6278),y=t(707),w=t(5404),f=t(6966),m=t(6774),g={components:{BoxedLayout:w.A,LoadingButton:f.A,ConsoleOutput:m.A},data:()=>({repairStarted:!1,repairFailed:!1,error:""}),computed:{...(0,k.aH)("tasks",{taskStatus:"status"})},methods:{async runRepair(){let e;this.repairStarted=!0;const r=[{name:"contao/rebuild-cache"},{name:"composer/install"},{name:"composer/install",config:{"remove-vendor":!0}}];while(void 0!==(e=r.shift()))try{return await this.$store.dispatch("tasks/execute",e),await this.$store.dispatch("tasks/deleteCurrent"),void window.location.reload(!0)}catch(t){if("failed"===this.taskStatus){await this.$store.dispatch("tasks/deleteCurrent");break}await this.$store.dispatch("tasks/deleteCurrent")}this.repairFailed=!0},runSafeMode(){this.$store.commit("setSafeMode",!0),this.$store.commit("setView",y.A.READY)}},async mounted(){const e=await this.$store.dispatch("server/contao/get");502===e.status&&e.data.error&&(this.error=e.data.error)}},$=t(6262);const L=(0,$.A)(g,[["render",_]]);var b=L}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[769],{4769:function(i){i.exports=JSON.parse('{"ui.app.title":"Estensioni Contao","ui.app.loading":"Caricamento lista estensioni...","ui.app.language":"Switch language for the Contao Manager","ui.app.colorDark":"Dark Mode","ui.app.colorDarkTitle":"Switch color scheme to dark","ui.app.colorLight":"Light Mode","ui.app.colorLightTitle":"Switch color scheme to light","ui.discover.advertisement":"Pubblicità nell\'elenco delle estensioni","ui.discover.loading":"Caricamento in corso ...","ui.discover.offline":"Non è stato possibile ottenere alcun risultato.","ui.discover.offlineExplain":"Controlla la tua connessione internet e disabilita i blocchi JavaScript nel tuo browser.","ui.discover.offlineButton":"Riprova","ui.discover.searchPlaceholder":"Cerca in {conti} estensioni ...","ui.discover.empty":"Nessun risultato per {query}","ui.discover.more":"Ulteriori risultati","ui.discover.sortBy":"Ordina per","ui.discover.sortReleased":"Rilasciato","ui.discover.sortReleasedTitle":"Ordina i risultati per data di rilascio","ui.discover.sortLatest":"Aggiornamento eseguito","ui.discover.sortLatestTitle":"Ordina i risultati per ultimo aggiornamento","ui.discover.sortDownloads":"Downloads","ui.discover.sortDownloadsTitle":"Ordina i risultati per numero di download","ui.discover.sortFavers":"Valutazione","ui.discover.sortFaversTitle":"Ordina i risultati per valutazione","ui.discover.detailsButton":"Dettagli","ui.discover.latestPackages":"Estensioni più recenti e aggiornate","ui.discover.faversPackages":"Estensioni più votate","ui.discover.downloadsPackages":"Estensioni più scaricate","ui.package.homepage":"Sito web del progetto","ui.package.private":"Pacchetto privato","ui.package.privateTitle":"I pacchetti privati sono disponibili solo attraverso il fornitore (ad es. Come download ZIP). Per ulteriori informazioni, visitare il sito Web.","ui.package.abandoned":"dismesso","ui.package.abandonedText":"Questo pacchetto è abbandonato e non è più mantenuto.","ui.package.abandonedReplace":"Questo pacchetto è abbandonato e non è più mantenuto. L\'autore suggerisce di usare il pacchetto {sostituzione}.","ui.package.contaoVersion":"Available for Contao","ui.package-details.previous":"Dettagli estensione precedente","ui.package-details.close":"Chiudi dettagli estensione","ui.package-details.loading":"Caricamento in corso ...","ui.package-details.tabDescription":"Descrizione","ui.package-details.tabRequire":"Requisiti","ui.package-details.tabFeatures":"Caratteristiche","ui.package-details.tabSuggest":"Suggerimenti","ui.package-details.tabConflict":"Conflitti","ui.package-details.tabDependents":"Dipendenti","ui.package-details.linkRequires":"richiede","ui.package-details.linkReplaces":"sostituisce","ui.package-details.linkProvides":"fornisce","ui.package-details.linkConflicts":"Conflitti","ui.package-details.funding":"Manutenzione del pacchetto!","ui.package-details.contaoVersions":"Supported Contao version(s)","ui.package-details.latest":"Ultima versione","ui.package-details.released":"rilasciato il","ui.package-details.license":"Licenza","ui.package-details.authors":"da","ui.package-details.more":"Altro","ui.package-details.packagist":"Dettagli del pacchetto","ui.package-details.metadata":"Modifica metadati","ui.package-details.support_docs":"Documentazione","ui.package-details.support_wiki":"Wiki","ui.package-details.support_forum":"Forum di supporto","ui.package-details.support_issues":"Problemi / Bug Report","ui.package-details.support_source":"Source Code","ui.package-details.support_irc":"IRC / Chat","ui.package-details.support_email":"E-Mail di supporto","ui.package-details.support_rss":"Feed RSS"}')}}]);"use strict";(self["webpackChunkcontao_manager"]=self["webpackChunkcontao_manager"]||[]).push([[212],{300:function(t,e,o){o.r(e),o.d(e,{default:function(){return wt}});var s=o(641),i=o(33),r=o.p+"img/boot.92149bf5.svg";const a={class:"view-boot__header"},n={class:"view-boot__headline"},c={class:"view-boot__description"},u={key:0,class:"view-boot__checks"},h={key:0,class:"view-boot__summary view-boot__summary--error"},l={class:"view-boot__issue"},d={class:"view-boot__issue"},p={key:1,class:"view-boot__summary"},b={key:2,class:"view-boot__summary"},v=["disabled"],g={key:1,class:"view-boot__loading"};function m(t,e,o,m,f,w){const k=(0,s.g2)("boot-php-web"),_=(0,s.g2)("boot-config"),$=(0,s.g2)("boot-php-cli"),S=(0,s.g2)("boot-self-update"),y=(0,s.g2)("boot-composer"),C=(0,s.g2)("boot-contao"),A=(0,s.g2)("loading-spinner"),L=(0,s.g2)("boxed-layout");return(0,s.uX)(),(0,s.Wv)(L,{wide:!0,slotClass:"view-boot"},{default:(0,s.k6)((()=>[(0,s.Lk)("header",a,[e[9]||(e[9]=(0,s.Lk)("img",{src:r,width:"80",height:"80",alt:"",class:"view-boot__icon"},null,-1)),(0,s.Lk)("h1",n,(0,i.v_)(t.$t("ui.boot.headline")),1),(0,s.Lk)("p",c,(0,i.v_)(t.$t("ui.boot.description")),1)]),t.tasksInitialized?((0,s.uX)(),(0,s.CE)("main",u,[(0,s.Lk)("div",null,[(0,s.bF)(k,{ready:w.canShow("PhpWeb"),onResult:e[0]||(e[0]=function(){for(var t=arguments.length,e=new Array(t),o=0;o[t.problem&&t.problem.type?((0,s.uX)(),(0,s.CE)("a",{key:0,href:t.problem.type,target:"_blank"},(0,i.v_)(t.$t("ui.server.details")),9,y)):(0,s.Q3)("",!0)])),_:1},8,["progress","title","description","detail"])}var A={props:{ready:!1,current:!1},data:()=>({booted:!1,bootState:"loading",bootDescription:""}),watch:{ready(t){t&&(this.booted=!0,this.boot())}},created(){this.bootDescription=this.$t("ui.server.pending"),this.ready&&(this.booted=!0,this.boot())}};const L={class:"boot-check"},D={key:1,class:"boot-check__icon boot-check__icon--success"},x={key:2,class:"boot-check__icon boot-check__icon--info"},E={key:3,class:"boot-check__icon boot-check__icon--warning"},X={key:4,class:"boot-check__icon boot-check__icon--error"},U={class:"boot-check__label"},O={class:"boot-check__title"},M={class:"boot-check__description"},P={key:0,class:"boot-check__detail"},j={class:"boot-check__action"};function z(t,e,o,r,a,n){const c=(0,s.g2)("loading-spinner");return(0,s.uX)(),(0,s.CE)("div",L,["loading"===o.progress?((0,s.uX)(),(0,s.Wv)(c,{key:0,class:"boot-check__icon"})):"success"===o.progress?((0,s.uX)(),(0,s.CE)("div",D,e[0]||(e[0]=[(0,s.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("circle",{cx:"12",cy:"12",r:"8",fill:"#fff"}),(0,s.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"})],-1)]))):"info"===o.progress||"action"===o.progress?((0,s.uX)(),(0,s.CE)("div",x,e[1]||(e[1]=[(0,s.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("circle",{cx:"12",cy:"12",r:"8",fill:"#fff"}),(0,s.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"})],-1)]))):"warning"===o.progress?((0,s.uX)(),(0,s.CE)("div",E,e[2]||(e[2]=[(0,s.Lk)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},[(0,s.Lk)("path",{d:"M5 19h15L12 5",fill:"#fff"}),(0,s.Lk)("path",{d:"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"})],-1)]))):((0,s.uX)(),(0,s.CE)("div",X,e[3]||(e[3]=[(0,s.Lk)("svg",{height:"24",viewBox:"0 0 24 24",width:"24",xmlns:"http://www.w3.org/2000/svg"},[(0,s.Lk)("circle",{cx:"12",cy:"12",r:"8",fill:"#fff"}),(0,s.Lk)("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})],-1)]))),(0,s.Lk)("div",U,[(0,s.Lk)("h2",O,(0,i.v_)(o.title),1),(0,s.Lk)("p",M,[(0,s.RG)(t.$slots,"description",{},(()=>[(0,s.eW)((0,i.v_)(o.description),1)]))]),o.detail?((0,s.uX)(),(0,s.CE)("p",P,(0,i.v_)(o.detail),1)):(0,s.Q3)("",!0)]),(0,s.Lk)("div",j,[(0,s.RG)(t.$slots,"default")])])}var B={components:{LoadingSpinner:S.A},props:{title:String,description:String,detail:String,progress:{type:String,required:!0,validator:t=>-1!==["ready","loading","success","info","warning","error","action"].indexOf(t)}}},G=o(6262);const W=(0,G.A)(B,[["render",z]]);var I=W,Q={mixins:[A],components:{BootCheck:I},data:()=>({problem:{}}),methods:{async boot(){this.bootDescription=this.$t("ui.server.running");const t=await this.$store.dispatch("server/php-web/get");200===t.status?t.data.problem?(this.problem=t.data.problem,this.bootState="error",this.bootDescription=t.data.problem.title):t.data.version_id<7e4?(this.bootState="info",this.bootDescription=this.$t("ui.server.php_web.below7",t.data)):(this.bootState="success",this.bootDescription=this.$t("ui.server.php_web.success",t.data)):(this.bootState="error",this.bootDescription=this.$t("ui.server.error")),this.$emit("result",this.bootState)}}};const R=(0,G.A)(Q,[["render",C]]);var T=R;const V=["disabled"],N=["disabled"];function F(t,e,o,r,a,n){const c=(0,s.g2)("boot-check");return(0,s.uX)(),(0,s.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.config.title"),description:t.bootDescription},{default:(0,s.k6)((()=>["error"===t.bootState||"action"===t.bootState?((0,s.uX)(),(0,s.CE)("button",{key:0,class:"widget-button widget-button--alert",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[0]||(e[0]=function(){return n.showConfiguration&&n.showConfiguration(...arguments)})},(0,i.v_)(t.$t("ui.server.config.setup")),9,V)):"loading"!==t.bootState?((0,s.uX)(),(0,s.CE)("button",{key:1,class:"widget-button widget-button--edit",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[1]||(e[1]=function(){return n.showConfiguration&&n.showConfiguration(...arguments)})},(0,i.v_)(t.$t("ui.server.config.change")),9,N)):(0,s.Q3)("",!0)])),_:1},8,["progress","title","description"])}var H={mixins:[A],components:{BootCheck:I},computed:{...(0,f.L8)("auth",["isGranted"]),scopes:()=>w.A},methods:{async boot(){this.bootDescription=this.$t("ui.server.running"),this.$store.dispatch("server/config/get").then((t=>{this.php_cli=t.php_cli,this.cloud=t.cloud.enabled,this.cloudIssues=t.cloud.issues,t.php_cli?t.cloud.enabled&&t.cloud.issues.length>0?(this.bootState="error",this.bootDescription=this.$t("ui.server.config.stateErrorCloud")):(this.bootState="success",this.bootDescription=this.$t("ui.server.config.stateSuccess",{php_cli:t.php_cli})):(this.bootState="error",this.bootDescription=this.$t("ui.server.config.stateErrorCli"))})).catch((()=>{this.bootState="error",this.bootDescription=this.$t("ui.server.error")})).then((()=>{this.$emit("result",this.bootState)}))},showConfiguration(){this.$store.commit("setView",k.A.CONFIG)}}};const q=(0,G.A)(H,[["render",F]]);var Y=q;const J=["href"];function K(t,e,o,r,a,n){const c=(0,s.g2)("boot-check");return(0,s.uX)(),(0,s.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.php_cli.title"),description:t.bootDescription,detail:t.problem&&t.problem.detail},{default:(0,s.k6)((()=>[t.problem&&t.problem.type?((0,s.uX)(),(0,s.CE)("a",{key:0,href:t.problem.type,target:"_blank"},(0,i.v_)(t.$t("ui.server.details")),9,J)):(0,s.Q3)("",!0)])),_:1},8,["progress","title","description","detail"])}var Z={mixins:[A],components:{BootCheck:I},data:()=>({problem:{}}),methods:{boot(){this.bootDescription=this.$t("ui.server.running"),this.$store.dispatch("server/php-cli/get").then((t=>{t.problem?(this.problem=t.problem,this.bootState="error",this.bootDescription=t.problem.title):(this.bootState="success",this.bootDescription=this.$t("ui.server.php_cli.success",{version:t.version}))})).catch((t=>{503===t.status?(this.bootState="error",this.bootDescription=this.$t("ui.server.prerequisite")):(this.bootState="error",this.bootDescription=this.$t("ui.server.error"))})).then((()=>{this.$emit("result",this.bootState)}))}}};const tt=(0,G.A)(Z,[["render",K]]);var et=tt;function ot(t,e,o,r,a,n){const c=(0,s.g2)("i18n-t"),u=(0,s.g2)("boot-check");return(0,s.uX)(),(0,s.Wv)(u,{progress:t.bootState,title:t.$t("ui.server.selfUpdate.title"),description:t.bootDescription},(0,s.eX)({default:(0,s.k6)((()=>[t.isSupported||"action"!==t.bootState?t.hasUpdate?((0,s.uX)(),(0,s.CE)("button",{key:1,class:"widget-button widget-button--alert",onClick:e[1]||(e[1]=function(){return n.update&&n.update(...arguments)})},(0,i.v_)(t.$t("ui.server.selfUpdate.button")),1)):(0,s.Q3)("",!0):((0,s.uX)(),(0,s.CE)("button",{key:0,class:"widget-button widget-button--warning",onClick:e[0]||(e[0]=function(){return n.next&&n.next(...arguments)})},(0,i.v_)(t.$t("ui.server.selfUpdate.continue")),1))])),_:2},[t.latestDownload?{name:"description",fn:(0,s.k6)((()=>[(0,s.bF)(c,{keypath:"ui.server.selfUpdate.manualUpdate"},{latest:(0,s.k6)((()=>[(0,s.eW)((0,i.v_)(t.latestDownload),1)])),download:(0,s.k6)((()=>e[2]||(e[2]=[(0,s.Lk)("a",{href:"https://to.contao.org/download?lang=${this.$i18n.locale}",target:"_blank",rel:"noreferrer noopener"},"https://to.contao.org/download",-1)]))),_:1})])),key:"0"}:void 0]),1032,["progress","title","description"])}var st={mixins:[A],components:{BootCheck:I},data:()=>({hasUpdate:!1,isSupported:!0,latestDownload:null}),methods:{async boot(){let t;this.bootDescription=this.$t("ui.server.running");try{t=await this.$store.dispatch("server/self-update/get")}catch(o){return void this.emitState("error",this.$t("ui.server.error"))}const e={current:t.current_version,latest:t.latest_version};if(null!==t.latest_version)if(t.error){if("dev"===t.channel)return void this.emitState("warning",t.error);try{const o=await this.$store.dispatch("server/self-update/latest");o===t.current_version?this.emitState("success",this.$t("ui.server.selfUpdate.latest",e)):(this.latestDownload=o,this.emitState("error",this.$t("ui.server.selfUpdate.manualUpdate",{latest:o,download:`https://to.contao.org/download`})))}catch(o){this.emitState("warning",t.error)}}else if(t.current_version!==t.latest_version){if(!t.supported)return this.isSupported=!1,void this.emitState("action",this.$t("ui.server.selfUpdate.unsupported",e));if("dev"===t.channel)return this.hasUpdate=!0,void this.emitState("warning",this.$t("ui.server.selfUpdate.update",e));this.hasUpdate=!0,this.emitState("error",this.$t("ui.server.selfUpdate.update",e))}else this.emitState("success",this.$t("ui.server.selfUpdate.latest",e));else this.emitState("info",this.$t("ui.server.selfUpdate.dev"))},async update(){try{await this.$store.dispatch("tasks/execute",{name:"manager/self-update",ignoreErrors:!0})}catch(t){}setTimeout((()=>{window.location.reload(!0)}),3e3)},next(){this.bootState="info",this.$emit("result",this.bootState)},emitState(t,e){this.bootState=t,this.bootDescription=e,this.$emit("result",t)}}};const it=(0,G.A)(st,[["render",ot]]);var rt=it;function at(t,e,o,r,a,n){const c=(0,s.g2)("boot-check");return(0,s.uX)(),(0,s.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.composer.title"),description:t.bootDescription},{default:(0,s.k6)((()=>["action"===t.bootState?((0,s.uX)(),(0,s.CE)("button",{key:0,onClick:e[0]||(e[0]=function(){return n.install&&n.install(...arguments)}),class:"widget-button widget-button--primary widget-button--run"},(0,i.v_)(t.$t("ui.server.composer.button")),1)):(0,s.Q3)("",!0)])),_:1},8,["progress","title","description"])}var nt={mixins:[A],components:{BootCheck:I},computed:{...(0,f.aH)("tasks",{taskStatus:"status"})},methods:{async boot(){this.bootState="loading",this.bootDescription=this.$t("ui.server.running");try{const t=await this.$store.dispatch("server/composer/get");t.json.found&&!t.json.valid?(this.bootState="error",this.bootDescription=t.json.error):t.json.found&&!t.vendor.found?(this.bootState="action",this.bootDescription=this.$t("ui.server.composer.install"),this.$store.commit("setSafeMode",!0)):(this.bootState="success",this.bootDescription=this.$t("ui.server.composer.success"));const e=await this.$store.dispatch("config/composer/get");e&&0!==e.length||await this.$store.dispatch("config/composer/writeDefaults")}catch(t){503===t.status?(this.bootState="error",this.bootDescription=this.$t("ui.server.prerequisite")):(this.bootState="error",this.bootDescription=this.$t("ui.server.error"))}this.$emit("result",this.bootState)},async install(){await this.$store.dispatch("tasks/execute",{name:"composer/install"}),"complete"===this.taskStatus&&await this.$store.dispatch("tasks/deleteCurrent")}}};const ct=(0,G.A)(nt,[["render",at]]);var ut=ct;const ht=["disabled"],lt=["disabled"],dt=["disabled"];function pt(t,e,o,r,a,n){const c=(0,s.g2)("boot-check");return(0,s.uX)(),(0,s.Wv)(c,{progress:t.bootState,title:t.$t("ui.server.contao.title"),description:t.bootDescription},{default:(0,s.k6)((()=>["action"===t.bootState?((0,s.uX)(),(0,s.CE)("button",{key:0,class:"widget-button widget-button--primary widget-button--run",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[0]||(e[0]=function(){return n.setup&&n.setup(...arguments)})},(0,i.v_)(t.$t("ui.server.contao."+(t.databaseProblem&&!t.databaseAccessProblem?"check":"setup"))),9,ht)):(0,s.Q3)("",!0),"warning"===t.bootState?((0,s.uX)(),(0,s.CE)("button",{key:1,class:"widget-button widget-button--alert",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[1]||(e[1]=function(){return n.setup&&n.setup(...arguments)})},(0,i.v_)(t.$t("ui.server.contao."+(t.databaseProblem&&!t.databaseAccessProblem?"check":"setup"))),9,lt)):(0,s.Q3)("",!0),"success"===t.bootState&&t.databaseSupported?((0,s.uX)(),(0,s.CE)("button",{key:2,class:"widget-button",disabled:!t.isGranted(n.scopes.INSTALL),onClick:e[2]||(e[2]=function(){return n.setup&&n.setup(...arguments)})},(0,i.v_)(t.$t("ui.server.contao.setup")),9,dt)):(0,s.Q3)("",!0)])),_:1},8,["progress","title","description"])}var bt={mixins:[A],components:{BootCheck:I},data:()=>({processing:!1}),computed:{...(0,f.aH)("server/database",{databaseSupported:"supported",databaseStatus:"status"}),...(0,f.aH)("server/adminUser",{userSupported:"supported",hasUser:"hasUser"}),...(0,f.L8)("auth",["isGranted"]),...(0,f.L8)("server/database",{databaseProblem:"hasError",databaseAccessProblem:"accessProblem"}),scopes:()=>w.A},methods:{async boot(){this.bootState="loading",this.bootDescription=this.$t("ui.server.running");const t=await this.$store.dispatch("server/contao/get",!1),e=t.data;let o=this.bootState,s=this.bootDescription;if(200===t.status?e.version?e.supported?(o="success",s=this.$t("ui.server.contao.found",{version:e.version,api:e.api.version})):(o="error",s=this.$t("ui.server.contao.old",e)):(o="action",s=this.$t("ui.server.contao.empty")):503===t.status?(o="error",s=this.$t("ui.server.prerequisite")):502===t.status?(window.localStorage.removeItem("contao_manager_booted"),this.$store.commit("setView",k.A.RECOVERY)):(o="error",s=this.$t("ui.server.error")),"success"===o&&this.isGranted(w.A.UPDATE)&&(await Promise.all([this.$store.dispatch("contao/install-tool/fetch",!1),this.$store.dispatch("server/database/get",!1)]),this.databaseSupported&&(this.databaseAccessProblem?(o="warning",s+=` ${this.$t("ui.server.contao.connectionError")}`):this.databaseProblem?(o="warning",s+=` ${this.$t("ui.server.contao.connectionProblem")}`):this.isGranted(w.A.INSTALL)&&(await this.$store.dispatch("server/adminUser/get",!1),this.userSupported&&!this.hasUser&&(o="warning",s+=` ${this.$t("ui.server.contao.missingUser")}`)))),"warning"===o)this.$store.commit("setSafeMode",!0);else if("action"===o){const t=await this.$store.dispatch("server/composer/get");t.json.found&&t.json.valid&&this.$store.commit("setSafeMode",!0)}this.bootState=o,this.bootDescription=s,this.$emit("result",this.bootState)},async setup(){this.$store.commit("setSafeMode",!1);const t=await this.$store.dispatch("server/composer/get");t.json.found?this.databaseAccessProblem?this.$store.commit("setup",3):this.databaseProblem?this.$store.commit("setView",k.A.MIGRATION):this.hasUser?this.$store.commit("setup",0):this.$store.commit("setup",null===this.hasUser?3:4):this.$store.commit("setup",0)}}};const vt=(0,G.A)(bt,[["render",pt]]);var gt=vt,mt={components:{BoxedLayout:$.A,LoadingSpinner:S.A,BootPhpWeb:T,BootConfig:Y,BootPhpCli:et,BootSelfUpdate:rt,BootComposer:ut,BootContao:gt},data:()=>({status:{}}),computed:{...(0,f.aH)(["safeMode"]),...(0,f.aH)("tasks",{tasksInitialized:"initialized"}),...(0,f.L8)("auth",["isGranted"]),scopes:()=>w.A,isOAuth:t=>t.$route.name===_.A.oauth.name,hasError:t=>-1!==Object.values(t.status).indexOf("error"),autoContinue:t=>"1"===window.localStorage.getItem("contao_manager_booted")&&-1===Object.values(t.status).indexOf("error")&&-1===Object.values(t.status).indexOf("action")&&-1===Object.values(t.status).indexOf("warning")||t.isOAuth,canContinue:t=>-1===Object.values(t.status).indexOf(null)&&-1===Object.values(t.status).indexOf("error")&&-1===Object.values(t.status).indexOf("action"),shouldContinue:t=>-1===Object.values(t.status).indexOf(null)&&-1===Object.values(t.status).indexOf("error")&&-1===Object.values(t.status).indexOf("action")&&-1===Object.values(t.status).indexOf("warning")},methods:{runSafeMode(){this.$store.commit("setSafeMode",!0),this.$store.commit("setView",k.A.READY)},finish(){window.localStorage.setItem("contao_manager_booted","1"),this.$store.commit("setSafeMode",!1),this.$store.commit("setView",k.A.READY)},result(t,e){this.status[t]=e},canShow(t){const e=Object.keys(this.status);for(let o=0;oPNG  IHDR(-SgAMA a cHRMz&u0`:pQ<PLTE}||}z|||||}wv||||||{|{y|{~{y|{{{{{}}|||z{||{}|||z|}|8mpA;tRNS/. PR (OGW&{Ux-0Mh͠,s+&ObKGD}?||||||{W|||||{ }|||||R|||||$$|||||v |||||{6{8||||}{||||{r|v {v||||}|||}||z0|||||U||||}b|||}h|e||||{:|||| |||||v t ||||{6|{||||||||||z0|||||w}||||c|||||||}h|g||||||||}5|||||||||v {8||||||||||||||||||z0||||||||f|||||||||||}hm|||||||||||||||||||}fm|||||||||||||||||||%||||||||}5|||||||||{8||||}||||c|||||||{W|g|||||{|||||||||||%|||||w{:|||| |||||t ||||{6U||||}f|||{W|e||||}|||| |||%|||||{||||{z|{v|||||||||{6{8||||{|||||z|||||{W|||||{||||||R{|||||}5}7||||||{|||||{vq {p|||||}t {||||||}b{_||||||{t f|||||||||{_}5zxxz{6{_|||||||||{U|||||||||||||||||||||||Rx|||||||||||||||||||||||||||||||||||}{{6|s||||||||{r}5????????????( @  y({>{>y( |%||||||||||$y}||||||||||||}{8||||||{|{]{]|}}|||||}5}V||||}\m}^|||||T}9|||{q {|||{6y|||{p{t||||||||||||!|||m}z0|||{|||}Z}|}h{]|||}|||}||}||||||}||||z0|||}/|||{}|||||{]|}||}-zI||}`}|||||||v }b|||HzI|||a}|||||||t }b|||Hz0||{z}|||||}f{|||z.|||}|||||%||||||}|||t f||||||}Z}|{W{]|||}|!|||m{z|%|||{||||||||y|||{p{t|||}9|||{q {|||{6}V||||}\m}^|||||T{8||||||{|{]{]|}}|||||}5y}||||||||||||}|%||||||||||$ y({>{>y( ??????(  z,|s{{|s}+ |||||||| v |||P|R|| ||{|{y(|{O{M}h|R|y&|{|{U|||{x{{{U|||z0{|{{{U||}}-|||{|{U|{|{xy(|{O~G{W|R|y&||{|{v |||P|R|| |||||||}w}/|||}z.{99{?PNG  IHDR DgAMA a cHRMz&u0`:pQ<PLTEy{||||||y}||}{|||{{|}||}}||}m}|||}{q{{y|{{|||||{{}}{|||tf|||||z|}zz|}|}|v}||}||}}||||kb\tRNS (>%$8|]}5V\^T9 6pt!zZW Ω0f.IabH` /{-h5bKGD]0 pHYsctIME J}$IDAT8˭gS@C X @PŎc];Iqӻ>s(d*L|LmjGݙBF'BQA!H ʣ;CmO Az<,\U>`9T^ɳZT#-Li*j) tGnuN9!)9&kiBprj'E89\%\u wp4;1'3ܤҢP@}A^Ք ؅__{%Xc|M.Q_G#%tEXtdate:create2019-08-13T09:12:01+02:00=M%tEXtdate:modify2019-08-13T09:12:01+02:00LtEXtSoftwarewww.inkscape.org<WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`PNG  IHDR(-SgAMA a cHRMz&u0`:pQ<PLTEQAPAOANCP@PAPAPAPAPAQBUDQAQAP@QAPAPAMDRBOAPAO>QAM@QBMAPBQAQBOBPAPBP@PBOAQAQAPBPAQ@P@Q@PAS@PAQCPAN;PAPBU@QAQ@OBP@PA>˝i;tRNS/.PRЬ-Oe+|bxaypnm{`_(& ,tsn܌bKGDÞ/.GoP4 V|%tEXtdate:create2019-08-13T08:08:59+02:00Mxo%tEXtdate:modify2019-08-13T08:08:59+02:00<%"tEXtSoftwarewww.inkscape.org<WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`00 %6  % h6(0` $BP6BOtAPۨBPAPAPAPAPAQAPۨ@PsCR5@RAP܉AQAPAPAPAPAPAPAPAPAPAPAPAPAPBQۈBLGUAO۔APAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAOܑAQ?APAPAPAPAPAPڒ@QXAPAPAPAPAQBR@P APAPAPAPAP@OTIIAPAPAPAPAP@N$@N$APAPAPAPAP;N APەAPAPAPAPBP6@R8AOAPAPAPBPܐ@RAPAPAPAPAQrAPvAPAPAPAO=RBQۈAPAPAPAP@@3fAP۬@P\@P\BQ۫3fUUAPAPAPAPAQۅUUAPAPAPAPAQb@@AP۬APAP@P\@P\APAPBQ۫@@BQeAPAPAPAP BO:APAPAPAPMM APۥAPAPAPAP@Q[@Q[APAPAPAPAOۤFF APAPAPAPBP6@Q{APAPAPAPۥ@QXAPAPAPAPAPAOZAOZAPAPAPAPAP@OWAP۩APAPAP@Ow@QڮAPAPAP@PcAPVAPAPAPAPAPBPYBPYAPAPAPAPAPBQU@OgAPAPAPBQ۫AQAPAPAPCR5@OTAPAPAPAPAPAPAPAPAPAPAPS@R8APAPAPBPAPAPAPAP@MAQRAPAPAPAPAPAPAPAPBOQFQAPAPAPAPAPAPAPAP3f@PPAPAPAPAPAPAP@PPIIAPAPAPAPAPAPAPAPUUAPSAPAPAPAPAPAPAPSIIAPAPAPAPAPAPAPAP@M@P\APAPAPAPAPAPAPAP@P\FQAPAPAPAPAQAPAPAPCR5@Q[APAPAPAPAPAPAPAPAPAP@Q[@R8APAPAPBP@QڮAPAPAP@PcAOZAPAPAPAPAP@OW@QXAPAPAPAPAPAOZ@OgAPAPAPBQ۫@Q{APAPAPAPۥBPYAPAPAPAPAPBQUAPVAPAPAPAPAPBPYAP۩APAPAP@OwBO:APAPAPAPMM BPۣAPAPAPAPAPS@OTAPAPAPAPAPۢFF APAPAPAPBP6UUAPAPAPAPAPfUUAPۥAPAPBOQAQRAPAPAOۤUUBQeAPAPAPAP BQۈAPAPAPAPMM UUAP۝@PP@PPAP۝UUUUAPAPAPAPAQۅ>OAPAPAPAPAOzAPvAPAPAPAPBLAP۝APAPAPAPBP6@R8AOAPAPAPAPڙBLAPAPAPAPAP@U=RAPAPAPAPAPCNAOZAPAPAPAPAP>ODMAQAPAPAPAPAPVAQۡAPAPAPAPAPCR5AO7AOAPAPAPAPAP۝IIAP۽APAPAPAPAPAPv9U @@BPpAPAPAPAPAP@PۺUU@U @PۺAPAPAPAPAPAPAQb@`@`@Q_BPAPAPAPAPAPAO۷@U UUAPڙAPAPAPAPAPAPAPAPۢ@Q_CR5CNBN>@S(@U >S%AOہAPAPAPAPAPAPAPAPBPۀ@N$@MAPڒAPAPAPAPAPAPAPAPAPAPAPAPBPܐCQ@R8APAPAPAPAPBQ۫BP|BP]BP]AP}AP۬APAPAPAPAPAO7@OWAPAPAPAP@P\UUIIAO^APAPAPAOAPVCQ9APAPAP@Oܗ@`9U BQۛAPAPAOAO7=UAOAPAPBPpBOtAPAPAPCQAPۍAPAPAPڠAPۢAPAPAP܉>M!APAPAPIICNCN@`APAPAPBRBPۀAPAPAOZAOJAPAO^@Q_APBPIBP]APAPAP}APAPAP3f@RAOAPAPAQbAQbAPAPAP@RIIAPAPAP@MAPAPAPܦ@OdAPAPAPBQeAPfAPAPAP@OdAP۩APAPGU@P0APAPAOzBOaAPAPAPAPAPAP@P`BP|APAPCN.BPIAPAP@P`BP]APAPAPAPBP]AQbAPAP@QHBPIAPAPBOaBOaAPAPAPAPBOaAQbAPAP@QHAQ/APAP@Q{BPiAPAPAPAPAPAPBPiAP}APAP>O-@MAPAPAPܦBQhAPAPAPBQeAPfAPAPAPBQhAP۩APAPGUAPAPAP3f@RAOAPAPAQbAQbAPAPAO@RIIAPAPAPBPۀAPAPAOZAOJAPAO^@Q_APBPIBP]APAPAP}>M!APAPAPIICNCN@`APAPAPBRAPۖAPAPAQێAPڒAPAPAPڒ=UAOAPAPBPpBOtAPAPAPCQCQ9APAPAP@Oܗ@`9U BQۛAPAPAOAO7@OWAPAPAPAP@P\UUIIAO^APAPAPAOAPV@R8APAPAPAPAPBQ۫BP|BP]BP]AP}AP۬APAPAPAPAPAO7@MAPڒAPAPAPAPAPAPAPAPAPAPAPAPBPܐCQ>S%AOہAPAPAPAPAPAPAPAPBPۀ@N$@U @S(BN>BN>@S(@U ??????(  @Q,BOtBPܟBPܟ@PsAM+;N AQۡAPAPAPܻAPܻAPAPBPܟ@U ;N APAQ@PPAQRAPBP@U APۢAPDMBRAOAQ۞@S(APAQO@MBQeBQe@MAQRAPCQ&@Q{AO@P`APBQxBQxAP@Q_APBQxBPܟ@P۶AQnAPAPBPmAP۸AQ۞BPܟ@P۶BPpAPAPBPpAO۷AQ۞BP|AQAQbAPBQxBQxAPBOaAPAPy>O-APAQO@MBQeBQe@MAQRAPAM+AP۬APDMBRAOAPۨ@PAQAQ@PPAQRAPAPDU@PAPܭAPAPAPܻAPܻAPAPBQ۫DUAQ/AP܂AOۤAOۤAP܂CN.ݻyyݻ?PNG  IHDR DgAMA a cHRMz&u0`:pQ<PLTEU@S@NBS>OAPAPAPAPBN@M@PAPAPBQCR@PAPAQBPBPBPAPAPAPAOAO@PAPAP@UUIIOAPAOAPAQCO@`@U9QBU=OAPBOBPAQAM>PAPANCRBOAOAPAQ@PBPAPAf3R@PAQAPAPAQBQBPAPAUGQAQ@PBO>OBQ@P@PAP@OANCO@PAPAPAPAPAPAXtRNS (>%ˀ$8|]}7W\^V9 pt!ZJ_Ibͦhef/{i-aH`0z.dbKGDY pHYsctIME  AϺa0IDAT8˭R1P#zX b+ؾsrg㸓7϶l %Ţ=}%?>{LЖp?2c)JO(89Og ;3 ʿXKˊceւ!UN.9`׳]U̒ qwA)RQ}'JU H0lI*QuKĕ ƣBged˰E40T S,)"e3X6mz?va+_Zڏ_PCZ%tEXtdate:create2019-08-13T08:09:00+02:00O%tEXtdate:modify2019-08-13T08:09:00+02:00tEXtSoftwarewww.inkscape.org<WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`PNG  IHDR(-SgAMA a cHRMz&u0`:pQ<PLTE1L1K2K1K2N0P1K1K1K1K1K1K3D1J1K0M2K1K1L5O3M1K1J3J1K1I3M/M1J1K1L0L0J3J0K$I1K+U1K1K2K1M1K2K0J1K'N2K1K0K1J3M1J/J1L1K2L1J.K0K1K1Kw@tRNS/.PRЬ-N*<+|y7 ?0 {x(&Ρ,ts[bKGDAlN pHYs ǠtIME }_IDATm0 D(Bbq_.`qUB^&ssN&ȭBQJꕷaVk__ FSiIKOG6uPǖ320/j vE1yF'[;>'.Xj"4=]7/',{ %tEXtdate:create2019-08-13T08:05:08+02:00V%tEXtdate:modify2019-08-13T08:05:08+02:00'LYBtEXtSoftwarewww.inkscape.org<WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`00 %6  % h6(0` $L/6K1sJ1K1K1K1K1K1J1J1K1sM05I.J0K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1L/K-K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1P0J2VK1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1J1S33K0K1K1K1K1K1K1K1L1L1^M05N,UUUUN,L/6K0_K0K1K1K1K1K1K1K1K233U+ J2K1K1K1K1K1K1K1c@@@@L2aK1K1K1K1K1K1K1F. 33K1K1K1K1K1K1L1U+ @@L2K1K1K1K1K1K2@@K1K1K1K1K1L1K2=J1>K1K1K1K1K1L1L2WK1K1K1K1K2M3J1K1K1K1K1K1J1SI7K1K1K1K1K1I3#N2$K1K1K1K1K1N' L0K1K1K1K1M05I28K1K1K1K1J2L/K1K1K1K1J2qK1K1L2vK1K1K1K1G3L1K1K1K1L2@@K1K1K1K1U+K1K1K1K1K2UUK1K1K1K1K1bK1K1K1K1K1K1L0eK1K1K1J1 K0:K1K1K1K1M3 K1K1K1K1K1K1K1K1F. K1K1K1K1L/6K2{K1K1K1L1K1K1K1K1K1K1K1K1K1K1K0K1K1K1K1wK0K1K1K1K1cK1K1K1K1K1K1K1K1K1K1K1K1J2gK1K1K1K1K1K1K1K1M05K1K1K1K1K1K1K23K23K1K1K1K1K1K1I28K1K1K1K1K1K1K1K1M3K1K1K1K1K1K1K23J14K1K1K1K1K1K1F.K1K1K1K1K1K1K1K133K1K1K1K1K1K1J14J14K1K1K1K1K1K1I$K1K1K1K1K1K1K1K1U+K1K1K1K1K1M1?M1?K1K1K1K1K1L2I$K1K1K1K1K1K1K1K1M3K1~K1K1M05M05K1K1K1K1K1K1F.K1K1K1K1K1K1K1K1M05L0yL/6M05K1K1K1K1K1K1I28K1K1K1K1K0K1K1K1K1cM05K1K1K1K1K1K1J2gK1K1K1K1K2{K1K1K1L1L/6K1K1K1K1K1K1K0K1K1K1K1wK0:K1K1K1K1M3 L/6K1K1K1K1L0yF. K1K1K1K1L/6UUK1K1K1K1K1bL/6K1K1K1}K1iK1K1K1J1 L1K1K1K1L2@@J37L0yF. K1K1K1K1K2O5K1K1K1K1J2qJ1|K1K1K1K1L/K1K1K1K1K1K.,I28K1K1K1K1K1I1K1K1K1K1K1N,O5K1K1K1K1K1Q6L2WK1K1K1K1K1F.O5K2K1K1K1K1J1SK1K1K1K1K1L2K2)M05K1K1K1K1K1L133K1K1K1K1K1K1K1mUU@@L0oK1K1K1K1K1K2@@U+ J2K1K1K1K1K1K1J1]@@@@L1^K1K1K1K1K1K1K1F. 33K0K1K1K1K1K1K1K1L1L1^M05N,K-K-N,L/6K0_K0K1K1K1K1K1K1K1K233J2VK1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1J1SK-K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1P0I.J0K1K1K1K1K1K1K1K1K1K1K1K1K1K1L1L/L/6K1sJ1K1K1K1K1K1J1J1K1sM05????????>?????( @ U+ M3(J1>J1>M3(U+ L0%K1K1K1K1K1K1K1K1J1L2N2$Q6K1K1K1K1K1K1K1K1K1K1K1K1K1K0G+I28K1K1K1K1K1K1J1|J1]J1]K1}K1K0K1K1K1K1L/6J2VK1K1K1K1L0[U+U+J1]K1K1K1K1K0UL19K1K1K1K1@@@@K2K1K1K1L/6I1K1K1K1L0oL1rK1K1K1Q6K1K1K1K1L1K1K1J0M.!K1K1K0U+K-K1J1>@@K1K1K1J1L2K1K1J1YK-K1K1K1J1>K2\K1K1K1}L2K1K1U+F. K1K1K1K1K1K23@@K1K1K1M3K1K1K1K-K1K1K1K1K1K1K1J1>K0K1K1G+L1/K1K1K2{F. K1K1K1K1M3K1K1K1K1K23K1}K1K1J3-I1IK1K1J0`K-K1K1K1K1J5K0K1K1K1J1>K1bK1K1J2HI1IK1K1L2aK-L2K1K1H0 UUK1K1K1K1K23K1bK1K1J2HL1/K1K1K2{I7K2G3K0K1K1K1J1>K1}K1K1J3-M3K1K1K1K2K1K1K1J1>K0K1K1G+K1K1K133K2K1K1K1I$K1K1K1L2K1K1J1YL1L1N' K2\K1K1K1}M.!K1K1K0U+U+ @@K1K1K1J1K1K1K1J1L1K1K1K1I1K1K1K1L0oL1rK1K1K1Q6L19K1K1K1K1@@@@K2K1K1K1L/6J2VK1K1K1K1L0[U+U+J1]K1K1K1K1K0UI28K1K1K1K1K1K1J1|J1]J1]K1}K1K0K1K1K1K1L/6Q6K1K1K1K1K1K1K1K1K1K1K1K1K1K0G+L0%K1K1K1K1K1K1K1K1J1L2N2$U+ M3(J1>J1>M3(U+ ???珇??(  K.,K0tK2K2K1sM/+N' J1K1K1K1K1K1K1K2U+ N' K1K1M0PK2RK1L2U+ L1K1O5M3K1J0M3(K1K1NM1?J1P0K2RK1J/&K2{K1M1?K1K1K0D3K1J1xK2L1M1?K1K2J00K1K1N' K1J0J0L1J37K0I$I1*K1K1U+ K1K1J1|K1I1*K1L1K1L0yJ3-K1K1NI1*M3%ʀ$8|]}6V[U9or!Y \/{-Ia 3bH` 1bKGDb+< pHYsctIME  M;IDAT8˭V@'DAD%X{ EN&GٽΙ%_MZZm_L::+J[UBo{¼# uhs=cD8$LE~&Y#D$2u]|qiVիX[q.q6l9zyyE&EiÏpNTA`uy\XpS/8W<ׁ׆/\iPxHAdɬ mF}.ހFށ?wď\Ə=~~zOq(Xv'B%tEXtdate:create2019-08-13T08:05:09+02:00fJ%tEXtdate:modify2019-08-13T08:05:09+02:00;RtEXtSoftwarewww.inkscape.org<WzTXtRaw profile type iptcx qV((OIR# .c #K D4d#T ˀHJ.tB5IENDB`handle($request); $response->send(); $kernel->terminate($request, $response); } catch (\Throwable $throwable) { ApiProblemResponse::createFromException($throwable, 'prod' !== 'prod')->send(); } PNG  IHDRa pHYs{RkGIDATxc`|fK _G~hRfXa1~ O4CY *OO~Ss[#>< apg]<%~vH ֧a) qa :ı x2?wU`@ " ul"j,|xDP&_8 B# 'jjhcCg. 1%p^+#PmFNpxv_6d'&{aac:7+B i!u,>:NWVRfJȊ$IENDB`PNG  IHDR66뼾 pHYs{RkIDATxwUՙ/  1j,q1&j2Klfq̲Rd9zGQE&U@@UO/{>D"J[w=gK%B!B!B!B!B!B!B!B!B!B!B!BHq'2g]g~VeXT7*[%!Zr|^,ѲQ\ܢSأ}~@%^_݊KJg%ʕzsv{]{Zuu]w{Y͇#I 2vv[l63QX/1<)y.;8nzdVZMbv?'$5wmD3BHm2j=GHY6iw>"Όq4;.9{NT֕ڠۥ-tRV<T$ݱ|lRyp$o{цR4;>"u;AG'//52w{($GGHu}Nk6O,=52޵SV9)PisNt!t=]l$-KнDHpG5Mwt)¯/Ҵ ߛ!BG%zMo_kӪ ;b*&!',* v)I675:wG !'\91Gbkى#q_) ޔ*Eq}&ʼݮk9P:orjY?SR/B[)㝫mBHVi>˝pߗ{}!LU=*?),)-^k5k x/=l?$ڞ/`qX8F!ǷR.WQMjKi{|ݽv Dµ[;Fm~)wOD}53}@vxl؆x]B$pxq̕ >!$ oh4_bkz6;!;|7El\AHyjs|k/6uzRE^o5;UF;EיJUl6b$і%əhh'6Y>7Q[ed54!{L;~tM !RJF;dovBHiu.‹M}CBC?\H#Pݿ Ra=]BBAKbqt1%ύp1NlґBCb*ؒŸFHk˩0b !( ˩bSI!zBpA^ltH淒^%' ồdjrbzM`r-6Y_8{7p(ѿvղѱվi~tG-9dn/+e7]"r; qICSb݃s%OUՓG? [?{} sGӓ_spObVZ-΀*wbs!6Ä~r?rG6tݒ"{axNlqoKvi;tܠo'H~-7r#6gy@ In[·7Q^+36|_Elބ?a4ajɎ7vdqzɃ%t?FlѦEzT#;TחN!%QPM- "V7V:ɺ*%b5G,W/PYp+h@GfxmY.1ɤG7S9b*$N()r-uυؒIYPK#rFkA)ҟZ:C,æ^Fm[.6uRz]bz20_s{HwT}Uօײ0bStkn->= D\ezy;Z1"tSdP,EH%KІv3)F<q}"bmj xc0(pRvVXm?o /j. 0t9.Њd4ŶgZ  #*L ~2 1FT.u]ޤ'0&WN@@+9]03@@+xaDb[υ7È ӏߛn7È 6)zGRT77Zau9F,6wO}0%؜7={0dY.F{@;}Kts00Ylr.[›abS/[]55ts00]lі%hhua^lʉhhaa؂Ex00Ylfhh*AF,6w}hh?9AF,6.Mn_0`YC{@;K 0d:Rz=)N7 cƵl`w"IF,prIF,6VG{&aaؼvo7  ڡ[abڞ~DA-QF*6+IFaa53n0%؂f{x00Yl6-B{@;e0d{= o$&}hhx310Ulv+5F*6QYWnßL #cd#F,6zk#ba؜!w5%j\ 0TYmE;@Kٝ 0TĻע=j3FkH׵ =%QM+65>[FFeCjwtiVf}@{S+6oa_gNe!T (ck{eqŦv ofX? ,KWlj1OlӉ6opƀTחv5{w2X4h(7BĖf*A>DJՙgKh{by{*`~dܡLqcl$A뾘V [lql'S4?ڿjGƝ>!ڱ?a$iJc2ڲ$u77.De;%VRw'I[ \ljG-qG>jI}4Ql^lޔTCኞl9ğӭbS2$} o'|2'~_W;/Z\KVjqBa?1#?MŦv%Om}Ѧos!6ɗ 3NN71,&㝫[zy/z,$6zM \t7PD ٝKmQowkBߔ2\3CJO^hܑ!6v3z\}8TBOZm΁X3HJ^bS"&^c-;mYZmr)67-1O&%EJt)"X7d48n;ڞ+cwDZM|<%݈{#HӺKlb]6!x{}=҈nA}v`3ތ(H~bx9$1z$rX8%Z QMWOK,ڝ<юX2uĖle\84}qݿ\#_qE$jM/Cniw"=ҲQN${JrF`ı WO,YIC ,#{{> >^z/=,_H_d>%g+j)6Y/Š-YV]+r C_C%"wr ˥j6;`VJ޸M&xz!Ljz)CulI [[pkɯPlGmϿ䕼bS W!8IKiL !MK‹M%&n>3>Ĩ&WBr{".ZMT7MB;;ZM8C-!kv nD!q7ڈMş`K)3іuBu> ZMş\RB&\3_m\T)Ub$جgXlEטjiVl ΄;~?PlIU}B2'Z?7W1:j/$7[W }i*_s^I>;D_HV F9nWF_HV:}'ƅ#y3;-+YB2[gUWBŷr>X/>_rYLdm}h7Q>"}ڿ(A߾}1Yw3O'$%USr>ꄧK ˥;uOUWB%"v,0Z"y}AYjqwA!% s;;\(bեY>r"%^|.ۤJ`~*![Jv/IY_>$Ey6VF=T*`Ɉy_m5R[}X}8vdKm 1XlvKspq?fI)/-Zyg">7b?H:o?˭ O/ =nBIIwOspk;*[ځyYJƷ9ބ?ab?HY1ImfDjOB>]򐩪' %=7NkN @Yr]@ɹ9fxIJ٨TscSl ᲊ;.%F,z*5jKq*B(շy?,CGu )=qu\Vα4~xkv ~qU֑~ ƔD{6厸w3=}8J)e!B!B!B!B!B!B!B!B!B!B!B!BHisEx}dIENDB`PNG  IHDRǵ pHYs{Rk IDATxyUe8ieum2o6? V`eY2ou/, * "((,ȸ鹯gdp眽wg߯^f?ZcY!Ԕ惃YܿN{w|d7uVvP>R{->qﱉ?4ۥ?&{,ޤo.\u^07|eQqg4#}%pׯg]:+oY9ߛ2S6'TIgF(E.M;NU-?+JEt_I"roKW\U;\ФoK|3}Ng]4.Ա?ܱg .r">3NjC75ЛH-ƜTJ$ݵQ9)>;:5oށmsVIZ^1z; m$yIex 7emvL]k't+9v?wwv}[zԻIU `?Jw/tpAybP*XxZ3or9!0(l]![N?~bs􋬩QyZKӭCFIEO,UzF y)a/WCy=3 u$Y5v ozTJڏ | 3SRv􋪕Sy ,&}S|3\>3-/:ޡݛ# $u_S] Y[ϼÍۡ*t@d?9ԥύRYެ^&bjax  ׊! :=Py˛_LG@ѿL< bޖ;+_HGtR#=7@s.q3-wۥ_H{uzVKgrD&d`A3$WhT@Prr;~!џs@NI{s?V{\,Bڪ;Qq-H*;z,^4 }%v/^?~J귉-;Q+#zFeb@7dY"> 6,%_…c%yYRt`g#QzWߕm/>ӺB@8tn'4;'!P*3;[|90Ik"0drew=P~Q-OD:'`( ;s؏z?&0tFew?L|Q1|dt>p{$>(IGʻs%!\_|QE<@< x:'%#Z2N~[.$V')@IU| ۾+P|@|(+JN CtqNjR@adsi  Wr~p.E-PRU#T@ fZ_PuQ5Gw?*{eTbJ^{A9'C|8_V*MDg~XoczoW2WáC:RwrzI|@]^C)I^]]wnrz)A/h%`{H6=9WB-ˤ&$ݹS Lg *6Mw9\,)-H^^* ug?NSGJh0gϸpG~Fz]īfgwHf6uRt:Ef7gϤ-Po3]7GpY$]/9c +0tZ-P7Jo`6[B^ޤjM~F@7Z*^~ @ x֌(ۤjHE/TcS'̽KBl]x֊\(k 5"Z<2g^:yQ?Hϗ3~QLj.SIgIq>J_L+ZdE>$J6?'(ϕ{nj.ZO )kAkgV>S%|.Zs|x@M2Z6UzU E{)!ʟm=V| mlHpgH4GdKOBWp`OP/^v 4uRU:^eăi9oYT06q鵱Kh @?L!ݵ;~L@?(oYq՘t x7CD+l/I퟈R3GBex2[SzA+D*`f].DD+x= *@V){_#=ߠADD˼_"=ߠ= FD*wi A0"eV8=P*MT?ÈYMwmoPaDD˼N.FD+p H(FD+ϤT"MkY:]zAx?+HD*ב TҁDDˬв'P$"ZMR@"e^4K7D*ۡDDˬ&}SzAO%"Zf3Uoٕ%"ZfIv %"Z!y *TQzAY]zA8O*"Zf7<U="eV8}ޢTJ7GD"ZF*Zt *T!,nDi'JP%-`ɮ,ux&`7ujuo yAtz[0=2rA @ N!P`A5}-nz O5}~x7x^}-nR ŠCpx^Q-$޸Wvr4 D7K>_m|\*wnIx^_ʙq?]O#h,ϔGJP%ur=Y_EU P:n½#,IP%{ntJ,gIP-m'lUe~儰 `̮C>Xa SѲKU=>ZOT.`KTIjo ]n'ɖ.wik,c}uzI:6.}ϱ ݖA6tlX.1ܺ[z g;fJgtlvv |_Kw)tdl@  V~ I0y uRI, |h8@ ]5/Thl=^Q` -t]ּp>W<3Xn@ 轙+}.&tl'I`:-h8gp9B 7L`z"htKu[ Exxfu(ko݋X@ ( X``s DKoۺߑ^h#` 6uVC:"^u[B-=Z0UsW5ş}! @#Mݤs̼L: oZgC5^=W:Im [ބ/A>Iwm䠘8<;nIa @EŃ%VxŌq @/m$~?ԷB~ Jw'ij{/8@+SPZFJ` V?(B@`)"qO՜vH]3P0"LųSfݡ'bI6 y%88F*␃'*Ll}}(;\G:CF@2CxcА\SVl]92U B`0 `ﶶA`Rq(P%Y ˆ1Y{ 9şm*ݱFzY װ|U?m 9$l@lwH/)7,#F@vX|{1xecS zj^eĨkK!Ԁh,`毥AdlcsbZ.o9$y*z&9p]L!M3U$)gsLCb\h>`I\."=_~ L҃όe HbOHW9l,E=ިRzCH=ZƜqS_:…Ud%s[gc9 @?x~Vnl~Jūfgkz`U?eY=us^A%*=KUSZ-]h}aZCW"= KY0&OTs}`_ ,{~wB|^o>lh8%w["PUIDATJgJFpG[B?;gDG> =lCMjoQNg//' 0߈: `?NLcmv2Z0~^~$>(V֕?3x&>(*tG|CfcH &ts{ga`0]'n@iI^{Ae@;ԇs7羚ϱ6;- ɋ!^1xnA-3DWUvIP΀wϯ6.^/$O<@P|n[1g~!y3^3_:SP^ɦ'&Z)Bry[hIg rL\Vy.T^ay7/&oszӭmGa7$rgCTut DKϨ?WJdiܡ'm~Ays&O>|9O1~i `C_P^  @y<?E|.u7N.{x1{N_XuzI;Kr?QRX3S _X^&|E:w LDYQ>Ǩdֿ ;`#i&槲['PG qRGS_?9WUُ?P.Ror_|uTw臔w]a#G/4OU*wO@)H a:h]RX{/}'X`ґ̾B|Bi/86uRҹ:>vޘ Zբ'>#h\'Os3YQ>kT=^WX9׼g? `8I6-QNË?&(:YaKu3}˥!y5{tV;+;?GF{/KG_y>RU^{\K#eoUKa v;DkHg:x[=~~ǩpɍkR{ 4v;E\>^Cb$w+wisv;D3/RJh՛s3%/?oP B']z~ww槆)3q2y$OmǟY4TCeB G)wIuO]/VJF?7߱_tF|j3C>oo5TA@l{<9?'&}g`^Ei#U蝛`b쩶IENDB`PNG  IHDRe %ӹ pHYs{Rk IDATx{uAYY4SV^rF2 /55ڤ45499!D.@** qppk"Г@pYk7]}/{*,'eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eDQ @eeF\O+Ww_Q5jE=~Ri 4JԽf35N˻'/X]O<7FQ]]Vh霸W?lfܟRg1`T5alx{_tHbWseFJEN\Xt7=~/k6[=epʨP'ez5'=0?Yl?{RY ,{fs5LގdpɥelXz_p^X܏Okf0c|[[R2f+ԃɟ'xuj ץnŠ]~׬IkG~{Y2Q ~>msەp̸pYvJ>>34Qf+ˏ*Ձ/mecg9sj{tz]׬[{_aL2 8T$i;Sg:snܹtU׬/՟t(SqIi;8R_fT!_5x#^S]TDQtO?Z[>hA/5y+/3:i1QfpK ٥Է>hו5} 6VJӣotN+b27<Է_4.C͌2ÛF<[S7:` _a>EѰHVn[3/.iOf'o_6RzF29o57dnr .Tʣ(Sɯ֤ srU;YytOz=p|EMjĿ֐ޱן6lYCYylw]5Qfp屓7՚;wN_Ϩ.$/mfѵm &3e }mj2椥<`i :ͬ<;f3/\ZÂ̆:`ɍΡ/[Yylv((ӿ`7ΚO>Rfh }fV3מ<Qao5j[b۾Q}6֖_ze=dlY7~y TXxDVfښ]֯OgY(F &Yc?{:}` ~@Z[sK}ue;(gſ9֜NRƣ8}`j`Z[wOG=p{XcݰW)ᢼ`{{p3kmo,eGA|maY72nbQ{q3km92xo`YN.H4n+/ߓYk >!e:.[s+ʸ}60z[{JÛ7ʌTkw֌~ @ ?ͪ)[חR)ԃ0E[3^{maNnGs>O7uDP|WmՉ sLǽ5~nfo6ԛo(վ;Xk }yO&w/~5nf-|:uKeFui &+ <ѽJ{߿YytK?4Qfp_5c Vm5 /j{x3kMJGō2CZG_Qx-%hEͬzgQQ6R\z;~?ofGMeFR;(u>2>#hAtUZu7cqL16k2~Ÿ@c-SlZEK/wkv-]"hz9Z}>Jwm[鞲w9ުJż@_7H뻯ۺ(3zɛĿ .R\ƣ=~Jm]}oi).?B_}Yf2}zQf}Tkwz{פKgtוwY׿pӋ2K>?h-|L_WKyfM_З2=(>7m󷅏R_w;}goo<(Sqi`mzR?i-#^&0kzgE.~6^~r\n19sK(3jZ,x<>60kɣsi1o,/x B~F0kzgɣL@"}/qy91K?+5q(eT?AJuKis5]W2ݳTkv?3h껮z(39ړ)^qtlE6ce__?8_OCԽfU=me:yslݰW)Q< Csğ!̪m}e2Tk?8-aظex:Fw^Q;ş%̪;[F+eg`+ .>4w`ڍG{aVDHG;0#>ħjm1 <]o1fpޔy̚Q]:G&Lcb&cRzFƬ2ȉ?N . %TE.EDE5(5^zyQ,gf2-=!BB2e3)d =63}s19{sz^p2Ye*saѳZ$IҘ־t!(SQ>RQDiI$IZbs $I$i.=xUlA>e*s͡ѳY$IREj!(S~mI$IU4קo ߅ B2R[_[$I4u;*||9THCg$I*Vqȇw"ȇLE%I$I^0e*UXw_ $ITZ?A>De*}^ѳW$IRQ2նCps>R={%I$iI Gqp[sS̕$IM}/DeF#1z.J$IҜ_b01;eFH󻟉$I4#  2bVX@<$I9yd0Q>G:o~$I 9ʌoLEs}$IZg|%|7d2#}~O$IB+jڒWgQfv{GJV$IZMhQfu?:zI$IPT4֥ڲׅiQf^ܓ$I}%qb[Nw$I4\T%pR>RQD;I$IڗA^G!ս9'I$IYj;%|o|@2CqoF8I$Iڗ}#|w|@2C{eM$IvݻeHQf4Hh$I}.;p2{.k$I4:Ĵ8(3DNH$I}}r"{.g$I4RgRm7sQfH4&zI$IH>QNyeDsL$IF.Ֆ6||e$Ij7?||e@Ӣ$I$tET[p VgR*zK$IF9A>2:=$I$i,*j|+<ȧQ&PmmG-I$IZ9|׃|e;z^I$IXU?  G _R+W$I4v5T48i(zNI$IX{五ϟA 2m5*It*?㷧CW'LSwT*K4Uߏ`be4O$IRA{Esѩ}u?w258C{Sm׷ڲז/ HeK=~*5&5s#f19 $Ix'M'94%~S¥S/C$UI0eHC9xꮩԘ_~wL▤jUԟLů A2s1uNƻv=uwfj;=l܂R㰏εM:$ik-|&~\|} $e|S?J?oOm֩ $IX[<8́ˣ$OJuT1SϾlKX6ȟQfv}[Jn$ R;iI͓vRRQ{"O$ĺyefY$zݒZ9v|s? :R?2*Tȟ(3n|Mؑ$ͤn+un8&5pspg_Ơ{?W`Y2y'$ikIs}V /zIhV4N̬qV$mbDl`,"5Ol*y$O$&55Y2[WWV{tuS\Z4&1_Ysk8̎Ol$ ߏ+/%ve:6IIh8Ÿp_FIsSkT[gc/WF$M]+Ÿp/=_$Iǘu_g`:RX- ID>A2GYй"I?Zg}-۽,@#$I(SOflji%;ڲ׆?4TFHW;R>^3eJT]> S/P/V0S?&߽o!Ij;Jr)QEѳDƿn;/K|yz]:7\ $G̟%4u0zȮ[sS$N~4@V92e}!1"Ic[̣yg=̆ڒWlIZ{3reJҹ"IWQL}b'Dym_ZIRLSw'{1s)ÂS!4VMQ?a5&<'IqGßd(SFI:7jۿ!|CoI6JֽJq)ACg$EEs}jm:-)Iիי:?HU(3[d萤wT]sHO[I4wV, d(3mg$vnj)_YLa<`IÊL74zÙ:=3$id+jO>a5ݩ_$M(|U { IR\jY#/釢u%i+kSkłOV 2|y!I#YꃧsFMm׷ޓwD Ki=SJ=ޝ=Ye8 sa#DFN35O R%i$++uVZ)5?9k橨==S$id?a ԶC=tM$ {7Z[j|Smp wDIzkn 㤶թ{ߥޒ4ͧSKR{y_nӐOLڗ=w$i$sa-{m܆{4u[}S?=0Q(ӏRQ$IC_6̶E/Oݻ/vY΍8rCF%I&|س'f8^xԽuyjXGnjۿ>~qC¥ѳJZc-}M=tuiW4ק]+RRj;%|B>e{%IYQχiaƧ2Iz[s?D-L8XmZ:$I/扟PuޘzO|/z"HrEzߖ:5ӳȷ{i||9PE8Iz?ϧ6zBH3{%S/8> a23Rjע$ A3AoVJf4NYYl|8uGǢ$ OE #y'$I|KzsMt |9@G$ M5|.:k#CҐU<9o~j rGNIW>\u@U+̟>Qfj-zJPԹ#h{׊"i8h/2~iCeygǫ$׽o u~W>|g M4un:>zJRhGK`{T*OEI}TkRRkł!mdqd ;1P_{"icy *pɒWY uFOIU=00QM201qTZg|%|`<-=0@Gi|$UG``Ԗ*=jh{א.156vxc> GM)ѳ\B^_"/m9xmCW{ QfS_C>=%iΛ|ym׷``n4#{`>u>$5OT})_y3GM=OIZc?>YuPF=05߷@6e6{_5^ v/EIiWq~"v|S(ƑxUw0eVSSo_$5TK&8ʼ/IEc]Ef^7 15}!:yqy}9r F(i⩻^%py_~HҬW<ԯ)D\`HmR9xԽuyjXGnj^01;e^D纣G45y >MӌWӊԽԾpijTGsQEk~FIҬ6Y ֹ=4:8ɟ G cя,I:T 6O\^=vK\{xjT)_ee(c41&I;g-0mE/{`}Y|8l@k4kgRm7Z`L.R|:u$W1qԵg Q2нkENf֊sQ~zy @M2/4^*4+T[Y ~O׍g"5uV+NT?Sg c2/P4kNRF_oD3P/xl(+IX^ c+R豦O5?G$Gh3)IRυX`|4xXӋmރR}SO{ ry}E?F%iV%/*|{IMyԹȩ_Q)e6ȦQ/m=hKlSxԽ:o"5T[?d}sy?k׼5=6ƞg$^+0lz=F^'ܔ:xא{l4eg%iuS}wW`5i7rO?Q8h/zyG9(KRunNlarh{S8rTG{ G=~[3[J~g+P ]ޚR+OUo=0\ڗ쒚~"v}[Yq TJL{ëSgՁ{fQ9~%.I<^!?4(GL$ӏזl>[qh{/1k @6ve^G_J TyS>9Ru۩S<*z%i9<{Ҫ TWM57#R/=q Us"HR)>|to;5 {`"kse&?q$Vk*@}ϟt(3E8sIT[ 0s7(3Y_0Hֹ _&Rh>]{`!u>$5Ol )_y?(38/ 45 |&{! @&ƓO^4&|0|muj=0t'T%29\$ivy !?8Uz L8ʤ|Tb7)I*z2%/|[`bxT(Sg(I*c`d#Gޥ$i|d#G֙KI5d<Q}ѻ$ VjK_>OlF*yN:%IսY d3VL$ T @6c>,2^7zy Qǻw)ITl>Ol*}i|ES4PN@֗JeZ)zjY d}Qr}J/R K2[Nާ$Zyl>K/>\RIRu:/|Y*})?SIRߵ/X>Go=,,^7zkY ~U(S-$ TmR [e2~%z+jQ He28z~9 dQ ;$]( Gˢw*I @6e:SIR9 dQ{;$WKWQ He257GUW{g( G.z~z U(;$]{sHQީ$Z9|*yiJq( G?SIRyoU(C<4EUWov RT(p"z9 2T(SM;$]m>G;JUsJQLmw*I^'Q +E2GAZ%I}UԞ@Ve~"z=yG T(s⧣*Iëg(rG/DUW. @VeZ^%I}ս dQfłJ{ dQ}{$Ucg(zG{DUWk @Ve:ޫ$W>C4;\wT^%I}5~3JSL擢*IP +M2wWIR_/9|YiwJjg(rGރ*IKg(zG57GUWP +M2{*I֊3JS*Iy3JS3DUW g(zGJ} dQD^%I}վpY T(S*zj_c T(\WIR_/5|Yiwi=WIR_/F T(ڵJ}^3JSLWIR_u?|Yiw鶣*IεP +M2n^%I}չ dQ(*I-'P +M2ETw;Ί@*K2 6ީ$\?GTjenSIR*~,:lJsHeQff;$];(RO_EUW3P +M2V^%Ig(zGVVIRM~\RT(S4FTwe @VeǢw*Iڮo @Ve~(zsJQ{w*IAۄQ +E2'ީ$G|,|Y)wyJyܟQ +E2SIR5O\RT(5;$]@Ve"zk_kRT(ӽJsasJQGTw[Q +E2SIRu4|Y)*wt|N%I}{9 dQãw*I"_>G;ʴ'zuR>^,U(sN+$ Tmkg) rG֊$ T}wR X2gs>%I87g) rG)ާ$iY,U(s_ES4PS>Kl`;4}J}Y dQ氏DS4PUR X2~=zrr,U({)IR X2D>%IUKl`;,~e:%IW[y dQfR궣)I^ @6Je}JjrxGR H%2oާ$i'Y dQˣ)Iֹ>Kl Oo<4]J~௅S [52mKI5y d}QDR4p5|Y*y]J}>_%2-w)ImS G,g)Iޣ7R [u2OOI@V٣Lˣ)IWS Ke2[Nޥ$i7|Y_*{:0zkm<T(Ӿ`q.%I:R٣"#I^)G1KIun:>|Y_*{i]J5R٣L?KIuR٣Lmѻ$Rmg*Xe2RKIy d3VL]Jy')X2ޥ$iZg=|ٌU(ӽuy.%I׹y d3VLꃣw)IS Je,ޥ$i @6c>4O]JIg*H2# zR d3RL}EQTJ>>SlF*}m=JJ 3fGI]ޥ$iڗ}#|ٌT({]J{ifG]+w)Is<Q]JN-g*M[2 FRTJ"|ٴU(<(I* @6m?46zRj3ȦGGIR)/+|ٴU(S{$R{gT e&v-z=yg<isRER4xnn>SlZe&ԽkE*%IT=3ȦQf"KkGIR)5 d(3y{$<@6-2Yj=JJs3ȦQf"K~=zR=|mLiqRmޣ$ڵTyq4"#IPm׷U mszGIR)5XLMryN3(I*֙_ @I2i_o%IԹ d(YGIR)u4|@I2ig{$RQ2|&9<(I*o @Q2ϩ-{]%I8s6Qyƺ=JJy߇T (G=r]%I^gLry'EQTJ; @Q2Ӿx=JJX@Lryw?GIR9E-:|ًryGQTZ?>WE9We6s;$V?@}21i%4./\>We69c;$VsȾQf#j#z*>We6fKRjע(I*H@( ^$(|GM\wd%IZ dSe6uοEPTZ@6QfS_#ޡ$]>Wl&v}[%IU4Nye6iT4GQTZ?[(3 WFPTZ(|ttVCIRiΛ@(3ӿCIRiun<.|̴Hn%I{ d2QM;$WE[V5JJ*T]QfzwCIRi5*T]QfzڗCIRi'|@5eyw(I*+*T]Qfzz%Iծ|f sWTk$V}V+QfFPTZ*|@^a23нJJ}ns sw(I*U+Qfi%IU4֥| U(3CIRv{glefbT4GPTZc,~D59P;$VesrUGPTZ>W (Gj;$V W JJ[g+(3S_Rыޡ$Gn?[`ze{JJbA\eйJJ{w*(ӇUqXw_\eJJg+(Ӈڮoޟ$}$|@^12?/;$V0Q-2}}A%Iչ y8};$V*(ӧ CIRyE-:|@^!2}s+$ZWLlRCIRiNrlp@+w(I*εU+Qfޡ$z\>W G4Ol%I|Vp@}DPTjs-z@^2e)u;$VVG!z\u@\"eY}D%I{ yE8 uWw(I*N# W̠_C>BIRy_leT[uJECIRi5 y8ʔ;$@6'eJйJJs p)Aޡ$/*|@>e"~W(I*>[ s2CIRiN s)Iۢw(I*oUǜLI:CIRi%|@>eJ:㟢w(I*H1GF %IoVǘLIj_RCIRi s)QoM;$VUǘL:CIRik 1GNJJg+cQD-zRk r)v/Kێޡ$Z+VO2%=r]%Iս r)YCw(I*"_>W S2%k-|%IV1(Sޟ$Ԛ1(S[mEPTZv01~efAkw(I*]Uǐ,:0z*gds͓?CIRxwl|8̂~?IR5Tl|8̆[iDPTZ{V/2;$V*cQf7zjק~ 0z@>FefI󤿍^$/|@>FefI}FOTj~&|@>Fef˂Rj;$VgՁ&Ƈ,|1$K GY^g%Im|V1(3'M %IV?Wg+cQfzO$I:g+cQf6I*w(I*oV2{׊JJحs1(3mCIRyE-}Ml| 8?^$Nl| 8̲N??IR pw(I*Uǀ|b%IUk*cQfz%IV(3_oV$I_VG-~eJn%I^gl|9̑ޣ7FPTZ 8G9ҹJʫNg+#Qf4O\ %IV?g+#QfIJuWg+#Qf,,VCIRiun<.~rC{/ޡ$UGj_k%IVg+#Qf5d$IVGIJ}(3NJgޡ$\>W Q2s{Jʫ]Kg+#QfΛBIR r/?IR>|@>eXmkR*JJs(;$V*#Q&@gw(I*H_>[ 12ZC %I8(~DOTj g+#Q&-S4w(I*Ό01Ze2z*kd3(}^;$Z}ϟG *zRk q R$Zg+#Q&y=CIRi^?[`bt8qV%IWVGLW(I*!G/FOTj>[ 2j;H$Iֽ p V'z*~8|@>"eun86zR p :$Z?G(zRk_{l|8D[zJJw&=:z궧ѳ!(3:WBIR5 s͓6zRk!(3{\$Iֽ s_JJhm&̐}~%I6Sѳ!(3$?IR5O\l|9 w$IY seHJJ[g+CQfto>)zRkg!(3DZ[$I־!(3DN$I{pUl|H9 ڒWTw(I*^'2|@>eLo+$OFVȇ̐\sh$I:o~l|9 )?IRu8+|@>eL}_ޟ$Ԋ/,|@>de-Rjעw(I*>01\ePK'I*֩_ G!ԾlIJsg+CQf5IJXw_l|8 nޟ$j5|@>DeT??IRM`l|8 mEOTj+G!:o~$I{xula(3~$IWWȇ̐-}MJEBIR5 pboޟ$/  G!YIJ{y!(3Z~1zrk)_y||8 >IR{||8 [ԮGOTjӿ?_`"̐ݿ2zRx\l|8 ='I*g+CQf5EOTzod|<̐IJτWȃ9ʌ"_?IRu;2|@Qfto;-zR+?<\?${~oy:uol$I,ejP缙'k~G$If)SZ} `ڧ|*|J$IY`25()ePV>_%I,0KT[}0TVI$) R&V}0tno $IRLM|o}_WI$) R&5}w=4|J$IYP2ui)uOCU>zg|$Id)S{.~|$IRL^{еO*If6K=2O]?O@25}OMO IDATwU$I/_mj9irz*zM>3?_D25*큗MQ=|J$i۽,xoOυYԬ2[;$wyk|$I<['?t'SSbN;KL]i*IMR {ڿ뒔z^0xU$iWi| iLGd)S_RY`K3V$i31|aM;-ejXnMA $ISsn3UIﺣFY԰# /|J$MBoKU׻[D25󕿉>/CW5|J$խ Sˈ,ejXswGW)|J$>0E?M}cK}XI}u+ya*,LM+< ]}$IR7^?u4M 7R;U `ko$I#oKyLӬx,ejWLLo$IcHN)#* K30>>c%Izǐn?7n RMg нb*I);>P^<לRUn73"K׿`uWIg>0#U>@q@25ss0.?>c%Ids2[Lks0SG$Iӓ+GY{]D$i2˷œC: whl=؈RDѼ}ufQ$I5oϻ񏗀,ej^og`${3|J׎~Iæ񏡀,ej^+}tF>c%IRM31/_X^;1Lk0o-|Jjou7ʍETa؊^,"Kt0.{q$IǐNLd)3\}|FuoXI4M=XL@ `u/>|J>0:-~rT\6]}vF^EYI-*5'o{QX}`;e /w&U?$aiEd`d)i~o9-D}g$I3>K?_>B#Q<+IҴo:O~ i|LRfBjG`d>g%I詯]*ޔRYD?33̤%)c0/e$i>>cC5ug$"K x`u1 džXIj}sx^egcRf]o92_0Lh Rfjt9+IR}`d;7.KIjf 0?g%I}`gz3̄_sFY^+e˶ $ |Kvǐ`O<~.#:D%i9+IB31~@̄:g `d_)|J,Jߑ'~"u/#\>x'?YLXv/u&VqUsV/*)~#|Xe_>g%IYR_|#`Sό01 ?YL`>O#>sV4}|u4s>O#[}D$MQw/L7~ʃҿ9Ȕs$i~z_sflRfYcg `d+~JъM3>V2 OYLhω>S#9oq$U%?}`:O[&]L RfB^+ Lq>k%I#j LϞ,e&bݭ `dz>g%IC}`RQ@2\âȔ|\$->0C@">3 `{\$=wv/}`6>TTχϬ,e&^>W#9_g$-̙8jbO@t7s, KInfT>[#ӿY+Iس׎~Zj}'g[@2^h{׆ZI4~&L菆Ϻ,e&KHMUfo7#}F{nVa$[>Hn T:g}>z4l^;|nFe)3}F?>o%*ucXde6|nFe)3%}Fsg$UUGeMV-|nFe)3%n86Tg$UM'FeMVM܌RfJ|oh)VP2&ya܌RfJjs `fol=o% ^=6Y[ͨ,e%DY[I@{G2&]{X܌Rf~nYxʖn>o%)mFdMֽdU܌Rf^,\G1tB Rfj0r+Y-ѣ`Nڧ|*|vFe)3E۽,}F|, UswFb9i̔U<:\s_UEa9i;-e7>o#׽hy+IQX1|vFe)3eOxybMVc`N^>;]}Ƣ;g$EԽd ~}Vn7\χ[Iw1#` YLa>w#׿V" ɦc-KsG;+˔C3W] fYfgT2SXswE;|g$ɢ/&|r܌Rf[T>{#7E 0'+ YLiΊ>{W)_m̕qѓ`N:/ YLis5E4},zI>;#Z7Eg$Y=vuggd2-S`~wz]ܕ1Խb 0'ͽ>;#w^}b+iz93zɴdz9i>s%i=r6]E32K)uoFAwSë$%/\E]sql2S굣!XI;G-F̂w_}Ƣ3WFY먏DZ9xB̢gt׽hs0eۆ]IUe,8K)u!tsWFUꃢ,tٙg)3+^Rы>cѿ+Iҁiٙg)T{EYL.o 4) 0'C>;,e}Ʀs$ م3@43 RFuEE):|JҰk 07e[,z~[(U0-#|J0ѣ`N YѠg`l:/ 4z7=Z3@2Խ|3 06R6(|JҰ*VhggV,e4}FIj+ICi) 0' YhP_ 0-W>{%ixoH>? d)W`)[+I sG*U K=U%Xh앤ֻq 0g.o YSOs 0VN ЊGSwSdU K=Ur 0^Nw|Mjj|U$K=ٯ&*|J|k;c`w>?d)ջ 0V>{%iu/\=Fl3z~fRFO}ei'$ͧw.s9Ϭ"Yi;璁ӽdU9)u#`ZG~ ]\,e􌊇n>cUn|(eK4ZjRnYn)>c:WRsW􋞡YE3jc 0v[N 4=:x3P2zFv/Kߍ>URr,I-S=9Wgd)gm+bM/_IڔZfЬBYY^<]nMf`Iz=2}ghV,e uo`Iz2{=C e)go)u 0v<;19U(K=go-_o \OI 0/eU,K=g>}fBt,IUc$~3|fRFYs>!Jْ$=Wa7DIy><~.V2zf2{8h9,I?PFGyOs4X2zz7}nBoj w`Z} |fRFwLHno ÒT3r`Uo4^k:W"#s4`2zǾ}~¾1_9,I.s4`2zzW}~tNlG6={tq > LȷCѳXt:䷢!?giV,e;>>aZN,49$z,Hs_ Y&U%MWsk0:/ YE&׿ gs`c |fRF\>oy,iJ,}'z,XRF\swGep>>%MG#~7z,XyU8Kdk4@r})[eL4ujX_ Yќ]wd>SXdzKJE/z,Xe35p2S?}oOْdI[ѣ`(ZG~(|fRFs*)E>3YdoTsCU8K͹⾫5@bm-#i$u\gjV,e4m}*}ŸdI֒S `(z7?WW;K͹ց}*xۃ ,irj'ѣ `h:K\*ޒ3wOx\4180IZ?|fRFwIoqoICu䇣Gewxul*U}*>%ռEq04gg)yv S|,H(uG֬Yh>9sYR%sߕc `ڧ}&~.~2w >Q6M ͒WߏaCτ׬Yh5sP),f-<=l=fFw6S[糤>ѓ `k YMт><TJoYR=W4O<=sج&YhAP-eZ7|>K~݋vX#:7glV,e_R}*DhI-_y~7e˷ YMтya>%UGG)(2|f5RF s=@唏ߝ/ ђg?09(K-?}*{3ZRZe*Vx?kkRP=E/5-:u_=F*_mjR=>@%u74;R굢Y,K !}*}iI8/zTgmV,e4nc3Y-))E#>mV,e4|#s]LSR=F,SgnV,e4f<1>%R;E+>~._2ZkG*7>^>%ι=zƢ/ܬYhYPik ՒSsK߉;c:s7a2j>= *uG絤|T9zGKv/뗥ZM<|]Wn>%wLnV,e4 ׿, ْ_F^}j^ 9g|0uZ/|f5RFC k)|nKNIcwEORl4Kbѣ|WmI l澅Jύ뛥FR]g@mn>e׽lQ>g)=ѳV:g~.|vK_SWpV,e4frý>:W緤9:C) |9g)ֻrQPK ᒞYëhv d)< 㒾ۤ]DJsyqh[TfG z*uGg-: z*TF,~6/2ykUv6> Tl_sF8bmydd):wg@*Osi*[Կ1P)ϋ'#K[xٯw.MM}<TNlBX>"znL[>ӥi( xcP9eє-"|NgREP5+>ץI._m*}*i?Gl>\=?&BnMW%~KXsw{9@eYMP2ߠw`bݕyLb>>xϧ=z^g``8N/.MBS?Rы>ֿyMX2_K6OƇD)7>벥dW'}2~n/,e4ֺ+zLRsR# PE/;:|vgZ_%N~1|KuϻRG6w> RFmf@7O~/~Ko7`uNl&0KFUSR%[u]sp)Lœ^s_){vw'F|*X{solBQHۢ >V)_Mh2 i[bݚG7g4},G@0|g*:zL!hF]SӢhٞMp2 C IDATs?FR{)[ys4f6|u?}&GKN'7K5{g95{ /4I570\5gl³Qh5gFT>zgj+BwxU^& _? لg)'|}&W^?Ov2m֩l==nZЍN6k`n:)|gS]{XN&l=*ojIc0|gSk[멹O?7H+mw0Fe)RFl FMKV|K#4p~s޵?dS*QsP>qjMWnoOv:Ÿ)RF;+4xܔ0Ϣٔe)Jջ9O<:_-&9Dmf ͧ_ @ŵOӕ*UߊCCz|97?:_i9 |'\?4ƞ̢ݾ~'V>V|ykgƽһrl Qꜿ$zPekc[UjԻzG=)/KU|[|`}v{{smRU7D?Xbݭ-3KUmgG%,RsR]\>/Rӽ#`t|L6YʨGSS_Oْßw,,JͽSϩ) k|?,,eT͖n|]x` `},e+^4;nлj|G?dS*[=cV0}|?M÷%`^2ISy/?eS*[sϟOD*Mgo*o禺vNe`z^4,eTw_=^;sQꜿ4G]*݊~9uwñ>3tN)e)*>s wSh:g}jޔ-:+0/fٿ;๔>*8>KUe[/s[>Rew$s^;ß԰Qk~?x! XXw~fo}9: u/>u]7S?ڧrg}5[s>Jaxgv2;өs?]_|r냏JELScjQsDhk<5YʨP{evpk<5Yʨ-yѓ`:/S^2M WD/Sïx*Kզ|JG1Z]spuORFis ~253tj<-K ~Nyk)Te+^~ Ƴf)Z֔^|Eۇ_Yʨn:)zTWo vS9Qmkk#W~ݦ_Zʨ_=4MRF}u[}D/ݲrC:25kJ/j_#2ruj_S6@%4456)KMD+{~}&g)(탻L! >ScԻ25攥&aZG}$L9e)s`N̢k25攥&Q= ƮuïԘ5&EX{S<+Kfq=>S3`lf/죯ԘW2n FEuI5|D9 ѳ`ZZRFYS|4z>LsïXP2غ,#:WïXP2_cs`kRcYh^CL}~ƂDTv6FLx|CRF_]g&p?~Pė `RchYh*^gX?:G__1,e4ޒR=Cs_[1,e45?zK)[MuCRFSS[Swg)OT5CRFSUꃢg)koJْïz2w˸ P##?~-H囘k(5F|ץ1zvW&PoZcq6?T'Y Lq~F%jǃD#U?Tf6KŽWDk`לT'qv~c#Uoހ `C9jTٯDwFbkh/ïoԨTݯ8xl47X}E6 ;K̢5*UF󨏆0RU3ǖ~]Fc6*[E*=jW4JUxcѹ`E#U!@8ǖwQjtWHUwӉ3Dw5*Ykz4zw]IUoR' @=OL5u,jT˞iPR]xB*wñ*jTe/NzR{ ?Tߘcr})*j&O-e' ޘ beZ/EZ9>s)3+m?Tf6K1 ^KR]kϾig?T_݈T@u{D_QoRKR~}LjDSs &Q6g)[˶:6rC~>ƨ`w~c煛:ho|>}~-:CZS*˹-ew_Kuwq|ZƤs__QzW𼏯g]{O/յ| WSd 5jYS淔xb/ չ1u \TG_WQۺ\ʤHn?KHuwQC~jFM~=F?=ްe>(\+v>ڧk 5j]UX{ޥLR?Huu F_CQۦ͇}uGBR]}0*fʖ8AZ׻M~̽Rfpo>j݊bݚ>ERn|(T;RfSLw_E῜T|JB'Q(zuЯ_3Qf]顷IKY? J5sP猿VP z6y)S<~_ʶ{y/)պR|P]wTuRW)F8悗2:_)#ս~fpx`x_;z_2̬i IuoXKf?ICK|M@˷I.CthKTSߋCI5wC;02O5-*o?g$-efu۩y`R[U*vGM/ĿW[e=NiAj\~A}_kZ֗GXRfL퍩yo:o6]S6Yyջ|W]:@3^jdG&Xgo:^._RbtKYnj?Tۖ(`&W~eqkxպ^L{R{w>oIX?T_GQ*p_w#?c}~)]GK #KuIeg㸎+F|45qK6O WTcm)3)[Cp7)[Rc]*GRKus̸,TSZNktշ֡|-ؗ2E:6."AU3RB-TFK?\l֩/|\K?xcʿ3 RZu**@/9SUZz*ݚ"t)3i_H(GK.oMe6uN_oHLU7|%եR}t`l:YKH3>SUf)3P{)pR jO-E;V,T>zGj-ehoLs%m\u?T}d`fo[5ZT)A%2S<`ji㲭a6od`bu{-᯻U햽xpSTz)=ņS/زRK* U}-d|嶩sTn|0Q-2S6%lVk*nQz֖nZG4o9=~7Y2O)Ի:>$}_noKƇO(,Hӏ~} d:ཀྵ{kz.eOK+M̓ߗ6:Rj)u һ Uo'wIKWl\WZAʶ{EHuGR*G;d%?CR4{wץsylW?Ȥ1DBdk_;os? 0}WԙwORe?|kp|j85I{ɪ/LW5RRSﶳS SߪzGZLRB,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,eX`)R @K2,e׎0 s< O @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@xgCn .IDAT @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@Ѩ<} rIENDB`PNG  IHDR<P pHYs{Rk IDATxyewY{+AdDEZmDmm\glEQWP[ට$Uy 3!!3 IHH  !sRkJw<_\{_{:g_W ҿxu9kJk6oߧ)mťѷJ{KߏMnɶ3Q_V3?;1g龥{(կlso3P=x]iw%iK핥?)+o~`&X31-gVf[WTuWK{ƿ3IMK-ïUhT0=Jkg?dY-ٶ ;.xZսW/w.;ݗD?j0U,{%{o~5>n>=$#ϋX{3Uo}#YS]zg}??|Մyetѷ fyAi-{n4V>ZwociYw6<8?Ln VBZ];4PJ5~`,iUo}Q{ꁯEߖaJgׇIuOxw)~ce̪* g=^{/}_-k(U/ ?"k`f 3ZsgiC-*HcQkiRdRя# 3Z{wiaR9jIn:o&E>Mꮋ~q̔Hi!RIZ2 ſIu>ReK_[ 'Eߕw7)gj8@c, ~QI[TW}WL*OA;\+iX0'7|XT}KLAt8)~LS[`*խK{ׄI#~Uя#l1 @JksD?DߒSz^C{Y{*U ӫP9`ˌn: "G S{{‡B{JoI1`w<)GD?Y0|2|TR)N- 0[Nw=)ۗۢFxF,:UgmizY0:ԝ5ѷ$lvK "' @N>*zѷ#L[ګ_'E6G6 SetUxP-ۮT\};,}WֲƿJAm\ކG6 ӣoFߍ OſJ_f`j 8(|S| j/^?&`: :Cb;`᪆_'e`zX0_#|Slc9g`SoxpТ =T~ `X0%ÞFw^XZ G"G6 <$|S\=_;/c=ڻXJoC#ߓ UUi!OA/*#D߅|.8}Qh?R,HmxÝZM~~-SJgo&\7G?~=YZ? o?ꑯ/w&k?xZUmx<+|ѷhx ҤG i/7| {ѷ'=Rd^9 iuNW\nIi*d@J{KknNlv+ѷPM|JiB;xJ4aNlnQ~-4wKiBuzK#O:^0?ѷ Ki"-޺TG9xR3sHc~hH[_:h{47 =qL}^_[U^7Ҹя<) @y!N㯽z 1\_;45Q'e@:(|^w\8u~w;qR6x @i!N?FfL@zW,Sg՚;5x @RJknQ9- {ѷ25 TFw_>i|wٱkXwEq5tG T>iL-*No>?N*~ ,HMcX@ޫJkɶRNxwO`@*ݓ>Ra@ysXHT:G-|xSWȠ?*5Y5' o `s[m_Hz^wU{6' ?>}KUj)' / LZJ]ERdTWߛ*5Q{(x @Ri->|xS_H^s?b TZK ޴ ;.V` .;U; Q' M[^uU:B; M[Vgו>6`T|m.+=,T7mA)=EBLEgg YJg]o?),H%zp3{/RoXͥ9f@F= ڻofo,H%zp7YQ K?+mNdd@*у6Ie1/)uM,H%zpf ԝ5ѷ 3w߆J YJMotөѷ 3>6΢yM,H%zpӦ;/ofOJ YJMӟF*,#+},T7}F7}@TZZK,=]dd@*уIEX`_Z,=]dd@*уf?0~%}Xz,T7=uN=XFw^PZs߉',H%zpӓ;ϣo  /, @2 MO2̮z? @zbc黳 # @RF7}[+ߏ,H%zpw;o O~ҷg@F=ۇzݽѷ|-g+Kߞ YJlâoxROVY Dnz'~IUZZK,m,H%zp z[VĿ;K$e@*у .56o(/,T^g72GI-Y Dn Gth-,T\?`U\ZZsߧp # @Rj;z}?<#c/Z 7 @2 m6|ꑯ֒m߫0 # @Rb~jZY Dn ѝF# ߯ # @RZ4# .\ YJචZ]@sߵ # @RR/.qk> YJPjRWץsτskd@F=-Q،nB;Ndd@*уBshe#~-[ # @2 m!4Ʈ5([ YJ6u?1LLwk # @Rf۔ᛢ?bJknwqtdd@*у,??^gGf; @2 mVkx~7<U|}aDkv # @Rf?Z;5Y DnX{&0cwgk6 # @RfE?V5Y DnV{K?V;[˷Ge@F=Z+H Ge@F=R=_[ʨ@Jkvꚭ,TYjx'?ꚭ,TYg,Tmɶ^Nu5(^S YJ6NVwkz # @Rܦk?:Z;N,H%zpƺGFJY3_vm:%^ә YJ6nB0 ^sG22t?_KԿ)UGt +J{7,_}iK{*\Gf?_•exetzR+06,Tis?2Rox >XGgm{AꗗaN~o|iExr-PJg?5}Y Dnc?2Opn%{9[w; _PR5X=|s*+ ?5}Y DnT{W2DdխJߋU/-pOVu7\x Ni|I٭,H%zp_3H^8oٙjw:|iyY,H%zp˟W޺ [}翯j2tpѪR=z[G ByoFkj # @Rܦi e箳YsϗezÃџ2@~&kz # @Rܦ꾯DTU 8tygi-{n9<-ަt2ڧK?~>[籦" @2 m3DoO]_=~wy)k%&{,Tihxաԝ5eJ_۪ٚt?Z:Vǟ,TWP Y~^B~.% ?k2RQ0V2U,TO1U+W={ .ݧa7v}*dd@*у[l*۾Pzǿo~6.q7~_cw@Erg@F=esE<X][,=^~jFnU # @R27`(su;LQMΡP{.Q?vZf@F=e J?MV`i-. UPsJPzqY DnY &NxߔepTTy # @RܲV=x}Gwމ^Zs[Y7FߪX7ʙ YJ??>'5}uR{U] ye3T # @R5U}3ck?Uڻ2td2r LY~*]dd@*у[5#գQo?5[u?+^wo Io.Egre@F=ekxա @)n響ilw}qrFI6#sS # @RRY< g^?5-*?TJ5L,H%zpTߍ8-,,koG6ʗʓ YJ8jtA-ڻT^(<9 ?+' @2 -K/eЎ8]9U9(> 9:xRR YJIQ LOw4 ,xRݣ~#T,T,qvG, +?w_R 0Q9 # @R2^r1) ?M{䯗.Oհw{E,T >wTZ:g9uRox aT\V[z'Yic٨,T n\iNz&|m D2?{/焟ʗ YJ]{K?`Vu響wҖ5z' 1o'9)uw{8\f@F=E 4+#=r'K@{J}}^hdd@*у[h.u1K瀟?q.1QWן{4,TȺ̘K{WoҸk~y5-N-s?VGZi!L,H%zpl=/?0CZڻ(l&ewGP#m,H%zpo.Mwya&M^+A N 5U9#=Ydd@*у[T~<3+ˎUg,uwml-.<65 @2 -YoIZʰHO^|z響tygisCڒ,T{.W~IYǥU ^[WFw| .ZUztdd@* rX\?Hͥ3)[%e4(սWY:ۧ YJQwG_v`ʿ3k2)k+~La4oэ IDAT<ӂ,H%zphxї?9瘔۔m_~\aݵϒ퓞 YJQLQt|[&MCzFPFw]\Sz'?Yf@F=(Sj>äi&хwexAwJg([?4e@F=Mi\[%MckTG}osßMiڳ # @R&/90eF7f4ϛ~!{V J YJ6zÃї"ڻV'G?м~7(@dd@*у$ї&Ng4 w~AjX)ë)SzIqY Dn?G_n`NsK:a7цMR=z[~ӥֿ>)add@*у$rFS,iF?uE{I" # @R&mJ[})Pw}Q%h Œ+O,TI9E_j`u~,ih[#ig!Fz2?)% $mydd@*уۤK LeW҂9(gl\,;PK|{]x # @R&F_j ꑯֲ+i4pec*U_\Zvi)4,TIUox0Ru~GY%->T|-g>Iߕ YJ6:{.2 JZuxc)~@[{UR,TI;Ϣ/3X[Wڻ"jGWF7^/)cYڻ0? @2 m ./2?sJZ-ަT߼"(`Bbtŏ)Uګ^I,TI䇊So~NI V#& :et%/Nxw#,H%zp{K㻅=7)I??@v'ibY Dnn讋(IVetG{v$-,Tq?CїHs ?$}g~xOGG][FS_ZQ^D,Tq7K $4Iғ2CJ7̌'$黳 # @R]=їȦJg ?$=EK]o}#}uUn,ïYC3d_6! @2  W< n:5|u|[Q1s|oY,H%zpguInxgU֗]) <%,Tq?ߢ//L+&IV{J},ȯ>}]z퓴  # @Rƙ[~6Ig(H<ןPg~h^I& YJ6Ϊo@"Kkgh6PE$%,H%zp3']?$mv˭uYh7<\Iʘ YJ6:)ԝ5ggLKuepKξo}Y Dnw_F_Z Ky;-.J4g@F=@"T$i޾_;I,Tq5 їH3IR-ۮԏ]2|o$d@F=P3IR3m0հTP=<;IRPdd@*39 )IJk璤۪T}e2S|IR,Tq=mїHbpgfϊvχ)OISg@F=Y}Y$:l$F_?s˾ J?*_$i # @Rʃ/+@=5(L|}l;6{mK, @2 mm^/~I_+ބ{nNIRY Dn^{ge3IxjzYtZ響tE$I,H%zpk.E_V XҚ*L$IRY DncN `\oy$Id@F=5]wF_R '~9<$Ix # @Rܚ?E_R Xzo~I$i}) cA$I\dd@*у[SU\}) ;/ ?$I4,T9RA~I$irY DnMU@A$I\dd@*у[#-*F_J H?$I4,Tfc{AesH$I,He&=_}@Or9$Ie@F=5Q7E_F PgׇC$I\dd@*у[uz{ew1$I # @Rܚ?@.[C$I\dd@*у[OA$Ildd@*у[~I$iY DnM4x& $Id # @RܚhpŁї2Kg$I& YJDï} ~I$iY DnM43ї23H$I,H%zpk-gD_F I$M6 @2 F} +?$I4,T&,2A~I$iY DnMT=pme .\~I$iY DnMT=zke < $Id # @Rܚ^woe_~I$iY DnMTwD_F H ?$I4,T&*^eX$If@F=mq@9I$iY Dn[/!!I$M4 @2 V} @sH$I,H%zp3[G!I$M6s Y~(_$I& Y~+w@K!I$M6 @2 V4_Z~I$iY L/!hp.$I& Y~"?$I4,T~ї4tsH$I,He=^} @ë ?$I4,T-/!hx'!I$M6 @2 mK#ї4sH$I,H%zp:>F~I$iY Dn[Zg@煟C$5d # @Rܶ^?} @/ ?$I4,T~/!zk$I& Y~_} @;!I$M6 @2 V} @u[$I& YJfh~I$iT-nїZ]Y$Ie@F=mqK} `U/?$I4,T-nnQ%uH$I,H%zpkR /#s[!I$M. @2 ʰ}@ݣ~I$irY DnMTG_F P錄?$I4,T&;k/#!I$M. @2 D_F U$I& YJD;/#hx$I& YJDՃG_F !I$M. @2 {.@g@9$Ie@F=5/#zsH$I,H%zpkME_F P},$I # @Rܚhc/#g$I& YJDë@ꗇE$ILdd@*у[ .+2:H$I,H%zpkVD_F X_?$I4,T&g$I& YJD} 2g~0,$Id # @Rܚw/#l>$I4,T&~H$I,H%zpkQo@ѭ?$I4,T&1,$Id # @Rܚ/#?$I4,Tfbe$^Cy$Ig@F=5VUuH$Ic,H%zpk&RGfY$Ig@F=5Umї;g$IƟ YJTսWE_J "I$? @2 F})`ë?$I4,T^w|nBY$Ig@F=5/%zH$I,H%zpkD_J ڠ~I$iY DnM@]v ?$I4,TїH ?$I4,TK $=#I$7 @2 :)R >w$Iƛ Y "R .%<$Ix # @Rk6U 9:<$IX # @Rܚn+rFw^~I$iY DnMV=tc ?$I4,T& DZH$I,H%zpkuE_N ?~I$i|Y DnM6t $=w#I$/ @2 ~,r py$Ie@F=5YE_N G$I_dd@*у[u?[їH`t9$IƗ YJd}95G$I_dd@*35zi2FYg$IƓ YJhsJ/)@g?$I4,T}IGfy$Id@F=5讋/)@ ?$I4,T~K $0dH$I,H%zpkE/)#I$' @2 @%)<$Ix # @Rܚߏ@^im~&I$,TK $Ug$I,HeU/@5L$IRY Dn7U)~e7g$I,H%zpG;/+•$I,H%zpG.@O?$I|dd@*у8~ $P=tcy$I # @R/+hPZK ?$Ildd@*у8їH$I$5 YJ6GZe{g$I,He&=_}Y$~,L$IRY Dnci6TK $0g$I,H%zpWڻ/-@uU$I,H%zpW;}iҚ[~&I$,Tq5K $g$I,H%zpW/-D?$I\dd@*у۸їH?I$Ij. @2 m\uїHbx!g$I,Hef^}i$Fw]~&I$,T5U)NۏğI$Ij, @2 mU}y$ڻ8L$IR3Y DnltөїH{/I$Ij& @2 m .-IN3I$Id@F=i@K?$ILdd@*у8 $1g$I,He^}y$?$ILdd@*уX[TK dPץy$I8 @2 mU\}$:9L$IҖg@F=<\:Uc4f$&ڶIbbޘ6CNv+tt6csjB@bDJF AD&ADFbzass޵~?>GUs"7/1DoN3I$I۟ 9J [%|c3I$I۟ 9JN/1/$I$md@*ыb=_b ;g$I?@2r /`H$I/@2r mU_f ~-|&I$ir #@R^&ίF$0|&I$ir #@R^&#@ I$IھTI?#_f I$IھTI=@Vi, K$ITI'@"s3!z.I$is #@R^&R/5D?K$ITI5/5D$ImH%zqTkRI ;1|&I$is #@R^&`/5xӆ$ImH%zqTQȢ֪%I$m[d@*ыۤ/5H砷%I$m[d@*ыZRƣ/7D?$IM9 D/nl_n kg$I-@2r mn8% $1u}L$IҶ@FMyF$3I$Iۖ 9J6z/7H{ K$ITI_n Q K$IT|RF/9D̏%I$mud@*ыۤwmHbxgg$I>@2r m 9.K$1$IH%zqts5Kd1%I$m]d@*ыۤ~FɁD:>|.I$ir #@R^&]a2C IDATgN|_\$I@FM[_v {%I$mUd@*ы[D.In]>$Iu9 D/n 8"$Qu.%sI$I[ 9JQGفD{:|.I$is #@R^"/;H%I$myd@*S,~i)U:|.I$is #@R^ܢ#K$1g$I<@2r -эF$$I-H%zqj~EH%I$mYd@*ы[Tc K$=$I,@2r ]zUHl\$IҖ@F5T_~ '%I$mQd@*ы[d΋IT>$Ie9 D/n .^i$IgH%zqwҟGDG3|.I$s #@R^" _~ Y>$I9 D/n-n)~#^s\\$Iҳ@FE7G$1޴!|&I$s #@R^ܢ~яȢJ{%I$}Tg|8t$I 9J]߈~@"u K$I9 D/n)Ǫ~ @s8z.I$@Fez$1$I 9J□ 'G? V |.I$s #@R^2?wyc$IgH%zqP51N$IgH%zqP?D>$I9 D/n)YRG$1$IgH%zq/G? afwK$IzT, .dsI$IO 9J▥{sI$IO 9J▥~1Q /;4|.I$s #@R^4~+qI2~.I$is #@R^25d1%I$=5@2r -SD? !>$ITL8DvK$Izjd@*ы[:6q ::|.I$9 D/nYZޣяHb$I@FektW EUR\$Iғs #@R^ܲ5pG$=sI$IOH%zqV?~$@">>$ITluּ& [>$ITt,)U$Q=|G\$Iғr #@R^26$$IH%zq= H K$Iz"@2r -c[c_>$IDd@*ы[{:6 K$Iz"@2r -e3KJ~ IT$I 9J▵gE? '~<|.I$T [hDzǽ'|.I$TG$28$Is #@R^ܲE? ѭ$IH%zq\x$ޣ54|.I$H%zqhú$g$IT ֯~<@";%I$9 D/nяHd}$IT̵wE$I$@rr -{գwG?" a>$I=@2r -{O~D@">$I=@2r -{s5Ny\$ITu?[яHdxasI$is #@R^ܲ^R*1I*|.I$M{d@*ы[o)1YGEsI$is #@R^D?& >$I9@2r ŭO`c$I4@FաDF7>$I9@2r ŭ-n)^Z$I@Fե.~T@"Ox\$IT4я H? K$IӚ 9JVz'/Q .;|.I$Mkd@*ы[]yMyq\$IT4TŰWZ+?$I0@2r ŭNn>3qt~k\$IT:5$_$I49 D/nu{E?. dž%IiH%zqS}6>$I1@2r ŭn?%IiH%zq[k~d@"c~?|.I$M[d@*ы[sI$ir #@R^VG?2 -%IiH%zq]+_Ph؀$ޣ5,~6I$MQd@*ы[$ sI$ir #@R^҃H%IiH%zqc" 8<|.I$MSd@*ы[$2x]\$ITZ6TGEU#Tl$IT6u}$I4-9 D/numpяHL\$IT;/%IiH%zqk=~(TJkfIl$IT:W=rW|$I4@Fչ'E?> މ K$IӐ 9JV_$2d$I4 9 D/nu{;$I4@Fչ./.G?B ѠV |6I$5=@2r ŭ7^D$IT7G$?$IRs #@R^^DFօ%I@Fս΁o~@"UҚY>$I 9JVXʠD:>~6I$58@2r ŭ 01j$IT&4h$2$IT&G?F jsI$9 D/nM׫#L{ M$IMH%zqkJUkc$IT4 яHdp$IT?w6Q,|.I$55@2r ŭ)uzW2K{Ջg$IRs #@R^ܚR{RUяH{;g$IRs #@R^ܚoD?N _ =$I 9J֤W8DF7>$I 9J֤v~@"UҚ]>$I 9J֤:5qt$IԴTFy {яHg$IRr #@R^ܚK)c$IRr #@R^ܚ)HsI$i9 D/nMvG $&I&@F5ΚD?R >$I 9Jָf@cI$A9 D/nMltяHd|ϕsI$I9 D/nMl~ec2J{ח&I@F5ѿXd$IԔT&eTU$IԔTVm%n97|.I$5%@2r ŭ >6[|$IԄT_G $9g$IRr #@R^ܚZ_~@2/cl$IjBd@*ы[c[R $2g$IRr #@R^ܚˢ/HJ$-@d@*ы[\$ITT&[SI$9 D/nM5яHfa]l$I{d@*ы[YRяH=ZZ;'I@F5gF?b AoM$IuH%zqkz+1L̿M$IuH%zqkzݣ7Ɍn:=|6I$9@2r ŭ?яH>\Z$Ijn=~t?28ou};}@BMC[3L7&IԌګ^TJ۹ <7^{}YHTihxяHſ M$P:T)//?=_TihF7>$IR{t282Rm`f}]HTis/E?f $IO+}sэi1w@lH%zqV$IG׺d4} @R^ܦΚD?j oO$i [§~n_U:tzos #@R^ܦ%j?d_$I'}nK]yvts #@R^ܦgF?n ukg$Izs7N} itDž_}^$@*ы45X2qTM?!=$I=w~>pT]5: D/n?2|~O$5nBseXTi/S'Iϕ)YV^]xG} >  9J6mUo~@2NM$5s?oYH%zqWȁd?=$I\{ח<8 D/nV݇9P_ O$iss@FM[s̄'IB]V:T)/(e؋qͷ?H%zqV ,>@R^ܦ__?2|>I[{WucB| ,>@R^ܦQ~@B#w'IRS??T=v_o@r mZ_Xq%IW]tGjLzHTin| яH OP:nWy/;7^?,YU.`d@*ы47$4$I<{ǿ]nk 9J6Nyzg$)c6Ҭ@r m$59N3J4%l7@BMu3KK{$ɏ%IZ|n}9 D/ns_ xOܾA'xs !@R^ܦyF@Fai%Iږ$i}n3f}: D/nzN^utk$g$5A}LцulH%zqsJD@R/m^=WJexQe7v !@R^9Mѯ_ QTfw(}_Wzkw*הݗ2Es7ߟ  9J[ѯѰ7+sJj} ) /THT7=趯D @Rs=$)PK^y8JG$5ځ3J&ު>s*z$Cm .D@FA$U=|gEmvٓ>oWyepޮ  9J[`xe$?)IZU<f@r MOT=t{$?g$mK]_<}G*L߰@>鉆:In;/|FI}naZ_2Rm5z|_ψH%zqO`d5CWosVz'iXT7=Q_~zǽ'|NIޞ}VXof 9JR~%W?$M=v_SSְ9@>Ojm,sJRZc_s^yToysfs #@R^WD@b>$տ RR\9@zUYT7=~%Ά)Ij?=΀ kٳ9 D/nEv-e<~-w~5|NIy3K]ܯ ?  9J⦧6N5.@Tګ_=ɀI7HT7=%G@b;)IOE1`ª =  9J⦧;O_ 5LJ)Is/F1`ƛ6ϞH%zq,H=RZ+>$ճQ=ƀ uiYT7=}#ߊ~5ĺ9%N|_&lٳ9 D/nz~.^~XT>=€ ^yTYT7=}u;G@bU{Si>$կ# {ϞH%zq9Mѯ\S>$կ%G/`gsYT7=C;X$6xMTW= ٳ9 D/nzFzU|f*Ijty >{:@2r M˫_ AoUULX_ =  9Jgz [>$ըѣ >??8@2r MeťGѯxӆY%>h3@r M߽WG"@r}^>$գ!=Iƥ5,|,td@*ы{Y%{O&j?>"Ԯ IDAT{#@2r M߽ ɍ<|VIG/Lkgb@FY=^5UJRWn>+|,Fd@*ы7G&@r3w'E+`†W>{#@2r Mã_ m_ U7+28oٳ9 D/nzzѯ ]5._>$jmVOٳ9 D/nڂ?5;+IykzQ)U= ͜i$@*ы;_ -*Iy19 D/nڲWu5{pމO4d@*ы)5?JR_^=IJkv9 D/nڲ:k^50y%)gkOQU>{+@2r M[^=ѯ P5?>$k| ݗϞH%zqӖ7JR?Q?z<6H9 D/n uj`7KkfI̒?=>>+@2r M[^gG.@Mt%)O;E% @gr #@R^ܴ,)U{S+53KR=c~?|,Vd@*ы'E2@ TWZgn>3z,:!|,Vd@*ы~e~gU# {b@FiW?>$Phls !@R^ܴ.+Uhi|AܒZs=. ? 9J⦭oa]kD,I .;zם>3@2r M[_F6@Mn89|fImtDžѣ0`9 D/n:5b/>$ ѓ?3hs #@R^ܴ PѯP??$9䗣G{Իgb@Fixjޫg_i'gb@Fi9js/-Ioa]" 5,|-fd@*ыξ!jdp~sK҄]VC0 ?@FiYRG~}:Kkg9ѣ29 D/nW5;O疤`z K ZT7m{ѯP#[ [&c;}3hs #@R^ܴK?uRU5KZR99 D/nھƛ6DB@ .xܒu?qj99 D/nھ_; jj?PZ+>$-n~ӫz4T7m_Wi\ iYR5@ CH%zqv._Zx52%i/`zpDd@*ы]EF@t%iq:zzUDd@*ыGF@ /=(|vIZ1@Ρo CH%zq=ѯP7vi%ia|򧣧 J{ϢI@FiZRW _=Z@[Фr #@R^ܴ0n97UjzҚ!|~IZ-@ 'ϡI@FiaѯPC>$-L=R`/ EH%zq9ѯPC/_E{G XϢI@Fi]VCѯPCs?5>$m'z:l& 9J\zUk0IV{W2D ҃k9 D/nZƛn~:vK{W0I[_ $;ϣI@Fia\W W0I[R=t{3i9 D/nZغG3j"r #@R^ܴH-nzF^@[+癤'=D}tC@r M膓_/>$=CIUǾ?|6E@FiѯPw~LsJgϔ2DO )*@2r M#U0^y&9etiHfx)*@2r Mk_1Gf<)z N 9Jmpѯ{,e3MfݗG _ >r #@R^ܴu?ѯGLNU{Si, QQ9 D/nZXѯcc[\n/+Uo эN|t !@R^ܴ [ 13MWm$?#3*2@2r M_,j\:%|IPSVJUEIu}[H%zq?,ݗ&5-GIU H%zqdqQ4HsMjr+́FS9 D/nL>M2h?>ۤ&9M@b/Y 9JOGj@Ìnri, oRZ2޴!Hs/ϫT7M񦛢_7az&5G[UJkfiH%zqG4L{zU|P+׭ Wr #@R^4:-uhtDž5,|Iu-U{S3P:|feH%zqYZ~;?㤺|2oc&:k~&~n%H%zqd^Wht'ձE5Q=zwʒ 9J=Dr@CU^ڻ<|Iuwu^%@2r Mn J,jt9>P:A; >@Fi \k4=眔?\Gvd<*^>@FioѯdU5?gg.[^ ΋WT7,˫^Tʠ 6;>|I]VF7- P(@2r M1n89n7q.zIiYRW T7ϱD9 D/nw_=` nOI?z@ݍGYT7.ͻ0E5 F 0y1@2r Myv+LQt'-j3KOD ?#s-ad@*ыbѯ 0eޣs矴(,-6O϶9 D/nJk@G2Uԯ@iA[2o/A]?ے@F)цuѯ!0=3PZڻn h-kd@*ыV^sPڞ:T4Pg qYs #@R^_{2FrTR.|k˜ 9J?)UhPzY(mq3KJ)e<jp.qd@*ыr4]>g|~.躇=|eH%zqSV~OEepҚY?s-bZKkvY˜ 9J< >6u7sysQzү\RFo` /;$~%H%zqS}wm;/.^>+?/{d@*ыyl~%m| 5QS[oퟕp0EG? @2r M^zp+ $sǗ1>5]?etIѯ?0`fH%zqS=x*w/sR ofIݩTz`Ju~k,Ad@*ы5To~-簵W4~Vu2ѯ90Ūͷ}+ՠVp'LxzSnpXT7嫳5ѯ%wWࢽKkgjw_{hy?k 9J⦜uI />3UGfwM+ mouH%zqS 2~韻Oj2)kSd@*ыr奌ѯ'?xsu~kxZk zUSd@*ыJ:]Ox U?πFuH%zqSzǽ'6VJk gb~'P>7 9J-nZGlnhix^Lv2W`UJ{Ջghr #@R^ܔk_QV=t{Қ]>Wzu{Dj[mxhs #@R^ܔo~EkK:6e)N/GZ۬{gj s #@R^ܔ]E |mJ? PwQZ3Kgks #@R^ܔi,:n#V\{K _?غ@F&,Q >t|gi, zNin> Xxe{p !@R^TWLDe~ei;m?cCetWaFuH%zqS=W`qrn祽p#ݡt}u|ץTUSg?k 9J⦚4f cϙ~]UOOs[եCoD?=^= 9JzF _YTceͳTZ3KuXJgו)/+*CG?|gvs #@R^T>Hjo*O*tgb%{KyuI)V u'&@F^u|g+ P;#wэw~V~OLߒ9wŸetɥ|kG_᳽ 9 D/nY3K_[FnJ^qO N=7JgחXYRڻt=WJ.u;E,O-} lw@F~`~\ ,w/s]o222R/L|Sr #@R^T~b {ѯ.Ǡ]ګ_w@F :&^zPᛔ 9Jz=ѯ.CU> ;|r #@R^T]@zw@FO7-@2r M5n`+ iﻶfݽa9 D/nw ~ Iw&@FuyD EhGZ7:ULTgZG)^87&nҀbdD%AQh)H${陸U[ds=g9y5 t/JF?cNUq-<*|fȑ Y^4u[ ;Ú 9r +ыƚF?cK'Ú 9r +ыrw2d}s Gd%zqp\wjS{D/n^R Lus(@Js4~cL> 9#@i:yg`txS<>*9#@ic9XY|Tr Gd%zqXg sܲ)|ȑ Y^4[~0gW3|ȑ Y^45y_9}{r Gd%zqӐ6T|0y@ {r Gd%zqֺo7Us(@J!nѩ*G?qe# 9r +ыMcOWQ9M]T5vE?suoG5@r@V7 -~0?b=9#@i+='UͽOfGUE G9@r@V7F gD?u|:|ȑ Y^4ˎOUk<t[Xzs Gd%zqԾ3xV\-@@V7NŊ_N]~Гk[Gr Od%zqhtQ,|Or Gd%zqhU”:gR~$>O{ r +ыFF?{>>Gs Gd%zqUE)); 9MY{Oqg|D/n͊eIUsO|Y'Ȑ Y^408Es&@JѭX|LjOD_:.@JѮG0IT[tt@JoѼTi}O@J&n8-3}3 9r +ыT[pd*w)@Je7/Y9MWs{?Huȑ Y^ܤ}xc>Dž:tD/nϪ۳g܀ gIDATTUџ#=3 9r +ы:^I0> k9#@IOX:Q.RYXȐ Y^ܤ׾Zz U,{NIJmMz2_5vErwSm338£—7WWUꗾ)|+~QIJm×7iR J?X{sz~+L@VjO_ޤ?<RծS?`@RM:P_D6UW#|U5>W8I~omE& Ν\ͬSL@VW;|yV{Ê!Q~$K q5ᖥO &q +/C&b1ڳ5S`~wϷy~&5$duy˛tyuY\٩| &q +_ޤC6vX>1s`@UMZnP5D?);_)T5)OA+>jv*V`KUc—8i*X0`߸ |ո]O W)|RT0 ߛjϱVD?+/@?/qTk~O?A93f#F,/@ӾsK4l\ksfE&#@S}<_)VjtTsfƕ~Zp@dXur2'M֗> CUcW*zaٯ} ,5<|#Rџi^YU}ܾ9y9C/st_N@&:߾2|FUf _SYڊ/utko<+ bɳSi'@_8-|ݢSH"W*~6U;,UO0A9;RUFBi_Ϥ㼿O <|z}۹џ: E:|6!9֭+×;ݾ9`O|?Eշ'iF?58$@V;yKKKߔRٍ z:9|Uk/ 5%OgGB́SgO}wgU28˞SMë5s^kO —=@TT[xT̩V,96US@>4>vD'Z{ÊYV՞HY/ 5Z7/~n0- u _[T>vwgl);q[L_KU~q0- rT[r\'Z.?%fA /57u}sis`n??|fRDFP瞵sU' L%_Խo]@Iſ>SjZ4/UO>' oO J=V,;>U{)0MU#yI>?jn*?7U{F?9@Vwyˡs LMџpF쨹i}`}s`d(͠yxt[7q57n`V80~ |IfRGFGݩX|LqD?; f-2|YfR $X*zA~kS`80]ڙs p ]%5'T?`V904O'/RU=Sme75~Wl9T=PYPn3 p+>ѺPsSyg/RoYς'GwE?9@R7—J?)3)oIgA9/I C囩Rb ڳ53 _Nꗼ.UG?9;@ZwǃX%SſR }?Y;#QcR`N80=W/R/5`'0 便=ύZOOӊ~r0g ecOj|Oڷξ[/V>멿˟;0j)o_Jj?QSWykj09mK/_FT,Tn ;/N}l3SkSvq`4_O-Tb_6QHN ԿW8lHŪ×Ti:A#O`t۩?ԟ3:w_ mڒc×Vi*֟ k>ǩ-Z/)5ǣ_d~ܻ-5@Uu}E'025P٭Xr<@i;L/]_V:` L䭪Rneǧ RY~]5@8ɇS M _rrw?|N 4;W!7]R` 8!{O͛'/+|~lL2<}8|V̪҉ۯR~BK)|~V}ɩjBg?L9u-%@s^tZߟOk"Ֆ$K+ޞReĪGg3MS}ի&oWr#/ TUoƕqSmFux#{LOkXqb_\ZԹ듩eSJWCܽ%u6ߘZ_?#5T-Cp|3p u͛Ƣ?@V[T=~o*w>ѯҨ_\ܣR>:IENDB`PNG  IHDR6I pHYs{Rk IDATxwwY{w #RU@@)k;E ŋrX;C:$!l{LH'NzHBz=`^{f<~^ߙ>?֬(zto9/ޫN87Km+U?խ1t/s& KKֳwV^۾4|g"aK<*Ơ{ofϖi.ݛ(ӈhː&tf\stiRQsҽw0F`!}o[>4~^w|)VGX&,6dԶ{aFkf{嗢JXnjfyy_mGT,6s՗K} Zһ?Q^!-R}7GRYpómΕ^1ճJ3Ugicҹ 0(M`q^u͝^T,`ڧgivyeU_Q` lP+J pU%Uo-`ڪgi68M/>eh4ۿ&DJ?Hf?Vo3bo:v5KM`AQ_|G4T;AI,6'u֚R$EN{.~3j=Vl34T7+V/1J}q;V4&}ڃŸUa-`&p[,^ WDU=RGŸYw%!`Xl ai&{~Rwpch4l]7Yl OsVy7b@+[?HCiã?B@ MXmTo1 ՇܪgiVoZ:'#؄u?|h2mһT[?H#־s! & m˷5O+N~ɵNDs4JsJC?BYl ѹ`^\[i^sd[ Xz)&b~>o-]~+QV{%yHW)L&,3 pN zR%EЭټ>#L&,#/m~0AcsK^ W+Ɓ` H?0h̭yZ}{Hu=&&,;^js4VDO넏?+ICVե:`,6ah|] os~[<^4%iغWb}WieVRUo- ԷQs4L=XJb5ҥFu: &eGBYlB2o>5\>Rfғk`DL}JZ ?|&=Fd ɴNY ?'m[`fu=&yM[?'#bkR LmBsJ?,6!??9m0CKßߤJ0MHÇ6\"in8)Mk`Lmg}=uHu'YlBND}}_QotڃŸ紲+zG&$=mRz>'V#鴢؄,6!聯}E-қZ:,6!'MH&z筥o J"؄,6!聯igwn~K,ݫ?iEf 9YlB2_Fbr؄du R &d D|@oR~+,[ vbr؄d~t=:mτ?id 9YlB2:O+BKJmZYlBNL_tj7πZYlBNL_tZ?&d DZ?~VՇ? jg 9YlB2%Wb5}W3w&$=Wbk~V[Kmß |؄,6!聿j~_rЙl&d D_A!ZgD-,6!'MH&z௤Wr=!!M*Mb+~x&d D-J_jBkKmfόZVYlBNL_ uY2ɟ fbr؄drהmF,j<|؄,6!聿[Uz0%~Բbr؄druG_^o br؄dr JU{0`o&d DZ_ZF?K*&$=c/~iAKmfϔʝ&d Deך7D,A넿T,6!'MH&z/ڧsK UJ}?[*o&$=SmT_RƠsKbr؄dr󍽣_Nƥ(^YlBNL_.5v})N u/?9S9؄,6!聿\tJK {ß5/Mbˡ~ '?o*_&$=ӷzҿ jKϝJ&d DNDKn;/S؄,6!聟)ELA_T,6!'MH&zgs/SҿR[ YlBNLZ}WmE|LQs{ßC#MbY^qPK₩6 g 9YlB2?cϽ~7 @?j؄,6!聟U_6R[y3f;Mbj{/Z,T&d Dlu>"% X𭥶zgSn&$=3J/3uGŸO5YlBNLTc_.fDԦ6&d D,5|iTf&$=Ի R$YU&d D 5yk)UR0ZG| yU&d D n:%e`FV?j؄,6!?5z`Qܪbr؄d׽j]K{br؄d,W:/ 4{ϯ,6!'MH&zrDsß_5;YlBNL[?TG_iKϱ,6!'MH&zjdbr؄dLfR=zgK0UU[O.( v.J/iyௗ>o}':uG;nS_zןPzw|^;5dTϳ br؄d,:Ϣ_nt/?ׅc P;?LۤwTL&$=gR+HkK5ᅰPcD ӻkwb؄,6!?+n wn\ Ͻ&[w~y\[)ZXAq%؄,6!? 5vI4^{5R[~۽p'fC`{Obr؄d,ԹhXfGn/3wxi W9sR~YU;$t؄,6!ޖ(UX&zUVoiۿtOLOGun&$=kXJ ?~ii1Jm9M/MbzKd,|oZc7eo~.,3,~؄,6!Yc7E?QS:ػw~E= i}ƿ 4nԲ؄,6!? ~Mׄ_^]_Uz~~i:YlBNLkzyQiK1ͭ*>^"\C4M%MbQ5~/ 淿26K}g|&$=ik[}sJO-|*(_Lbr؄d~Hk^G̨ލ'.45zoW C,#I=f 9YlB2?} 4wTJߺ@B~iYlBNLw̘%_(~?)asJ眵TUH{Q&&d DiWt[̈@i{oݤ5}9?~wirYlBNLv*ȁѻREO=~j>_-M.MbӮsV/?~iy6,uqHzR$d؄,6!?ݧ{G#->}6yYH&$=Y+}@uǖ BZi|c=0ҿ:+M$MbӬw DJ5~O!OL'{JQw/AIbr؄doB+PUniwVv?Qj<\z7^:_ݺ4׽wxi=g 9YlB2Zzۥi։(G,quJkK}KoZbr؄d]w\QSԿRw&dVKJJ-}Zjk6[4YlBNLJk(Uk}QS2HOQ븿,?&HߋCwd 9YlB25}W1S2:ޑ}GT'-gι۔wB؄,6!?׹hR[~H Anﺸtߋ9}Ɯ&d D7T}u.l}# Y?:b~{Q}ʧJsڧ؄,6!?_#&]iVD`y/v/kEf 9YlB2O|u1ԚKS?J{1o=tۮ4ӏbr؄duҽw4zV}IG f[9\Wi祱O&_iYlBNLd$x 5i\wxi#[>#s* &d DI6W.Kmg1ҸkSj=|aQZj&$='Yו?~HyE`bwsn  ;iYlBNLdգwF/0FURw4ڧ:ݗ7.c?bjd 9YlB2R5v{m~HSinU^sdF^̅_)?3S+>Mbu'?}HӬճKk?zAUһLߋ)m Mb{G IuwQs)U ^Li,6!'MH&zOMJUNcп ʨ]?KϗqQ{t4 ebr؄d$j3 C^.N\g K!Mb>V` 'M}"DkX :bnL؄,6!?z7}n>m/CG'ҬOXGLڵ^L4,6!'MH&z՛>X%/OuG?̪~イt/ݷXiFߋ)g 9YlB25zsK:w4?!# ?tK~>|/4YlBNLw$KYm;Uj>į~/߇6&d Dq׽#Fmn GY?2)NsŔA&$=];7F)0Y~HY5dJkKCJO=+kޒ4,6!'MH&z6?XJUE)0wUjk~Hf^]]Pn8^SFme 9YlB25F\;DVzYs_$M7MbsFпCNe_{1%=E&$=_Si-գwFWbBuKc﷔f/MbcknUG'0޷HkR_oI9؄,6!?>(aUUitJ'rjL IDAT:?t%/]%br؄dj5Uեt<:һ'g"5؄,6!?:_#(!5CZNϚXb>pm^yHimvKbr؄dvnQCw,5O+o(+Ŕ4 YlBNLWUG u i9<7JR+/xWʏ@@؄,6!?;,!TYjk6;Z#ʲ<+[Z|4xCm~ޒTYlBNLGC~'!O{CZwdLוIS?HJ&d Dq> }wj%걻JcKϔV[?' %i)YlBNLGݫE#0_ 3̢|/1.]_^4,6!'MH&zWG#0w!ZGIG~ż:SҊbr؄d[y)v1R[oH+UwDžSW)k*S>U>=$) MbKכP+~gH+ƾTJUMlٻ>{MiR}%iV؄,6!聿ZGiJ}JwqKWGKֳJJP;h/I,6!'MH&z/̾ꊾ/Zs).Q:UZyiSbr؄dR^{t\ߋ3JR,6!'MH&z/WF!1NoBZCZWDH$؄,6!聿Ԫ#6wөw(AVJ&$=R}F0q~_H$M3MbKi{UWI؄,6!聿Z~$zv]!I4,6!'MH&z/W>>`#gK]!I4,6!'MH&z/7>>`#R]!I4,6!'MH&z/ݗDx<$Iv&$=Rx8En>-$Ibr؄dշ{A>$IYlBNL>?}tF4B$)"Mb:`p$IZYlBNLWG!UԷzv=!I&d DQEn#$I"؄,6!?Rk^JUE뎋'$I؄,6!?J]_}l": '$I"؄,6!?J}l"ZG}($Ibr؄d(c; I,6!'MH&zROF '$I"؄,6!?J梏 ؐ*[$IYlBNL΅>6`#$I؄,6!?J+>6`w_~GH$Eg 9YlB2z7}l?>$Ibr؄d(0؀ \g!I&d DQ?xC>3w$IRt&$=GiuGI,6!'MH&zܪRzc6y I,6!'MH&z[}E '$I؄,6!?l]_}d"_{B$):Mb-G, I,6!'MH&z[sEN/ '$I؄,6!?l̓~3ȀEn=!I&d Dak~ ؐ*՛$IYlBNLQ>2`Cڵ;B$i؄,6!?l?}dT~GH$B&$=}En#$If!Mb>Gl@IYbr؄d^}dXlJ$=&d Da뜿c`)ID&$=sGlŦ$IYlBNLD$IOd 9YlB2غW>2`߹1$I,6!'MH&z[ã MI'؄,6!?lk>2`,6%Ibr؄du=:Ȁ ؔ$Iz"Mbֽ#6bS$,6!'MH&z[ MI'؄,6!?lN>2`V!I4 YlBNLލ}dT~GH$B&$=DU;B$i؄,6!?lO>2`Cz;B$i؄,6!?l[Ό>2`5$IYlBNLޭgG'$I؄,6!?l[ϊ>2`_~OH$Eg 9YlB2z7}d".$Ibr؄dn<9ȀE4yk=!I&d Da]w\h~$IRt&$={͑G,y$IYlBNLU뢏 XD$IYlBNLEֱ '$I؄,6!?lK>2`?~OH$Eg 9YlB2:;ȀE{B$):Mbֹh#ѹh{B$):Mbֹ`# I,6!'MH&z[ XD3 I,6!'MH&z[G,$IRt&$=>2`cw$IYlBNL։}dbzR[~WH$Ef 9YlB2ZGYQw$IRd&$=y ؈g<$Ibr؄d5#6/$IYlBNL~}dF4׽'$Ibr؄d5zs:/ I,6!'MH&zw} I,6!'MH&z[}F v+$I"؄,6!?l}dFt88$Ibr؄dmRJUE޷WH$f 9YlB2c,$IRd&$=GzcQև$IYlBNLWD~WH$Ee 9YlB2z}lF4B$)*MbԽc6yo$IQYlBNLEG]!I&d DQꜿC9gB$)*Mb>3lD I,6!'MH&zR넏G[+$I؄,6!?J(؀?xC]!I&d DQjc6] +$I؄,6!?J&؀Է}~}!I&d DQcM$IRD&$=GjJ6y I,6!'MH&zZx8耍hw$IRD&$=Gm/.s6w$IRD&$=Gw۹GlD/$IYlBNL5GF;~WH$Ed 9YlB2:}tFT~WH$Ed 9YlB2gkoB$iYlBNL>:`~_H$M;Mb>`C~_H$M3MbK}g@/$I&d D:O@{$Ibr؄dRj~ w)$I4؄,6!聿껾:sS}!I4,6!'MH&z/[RUGlL]j73$I&d DV>B`]^~_H$M+MbKeG yo$Ibr؄dR]|hw$IҴ؄,6!聿:~.t.+$IV&$=ZOE!0ޭg$Ibr؄dRk{O~_H$M+MbKP}$Ibr؄dRo# Iid 9YlB2UD#0q~_H$M#Mb% sN$I4؄,6!?}z7G}!I4,6!'MH&z;D#0[ Iid 9YlB2ND13 IIg 9YlB25cw$IҤ؄,6!?{M1j'w$IҤ؄,6!?l^J}:lgH$M8Mb-G {Q$IҤ؄,6!?z7}_~_H$M:MbsG .՛$Ibr؄djwG h~E$Ibr؄djG w$I$؄,6!?껾:(OL!I4,6!'MH&z՛mE'0$Ibr؄d8?x}q}I}!I4,6!'MH&z 'E'0Nc᧬ IIe 9YlB2ukqj;C$iRYlBNLg:8!I4,6!'MH&z}: 3$I&&d DqV% wqw$IҤ؄,6!?G -$IҤ؄,6!?w^} Է~N!I4,6!'MH&zD)0ƾ~gH$M"Mb}?G)0 3$I&&d Dq<]G sw$I$؄,6!?껾:Hn;/ΐ$ID&$=&t j>Rjs I1g 9YlB2f;C$iYlBNLDݫ>V`@ߋ}gH$;Mb}c>_ Iqg 9YlB2@~;C$iYlBNLD2X&ΐ$Iw&$='J鶢D[jk7$IƘ&d DIտ-w$I8؄,6!?W>Z`@c>~gH$3Mbj/-9t.)ΐ$Ig&$='Us{P Iqf 9YlB2Rw}U~gH$3MbknUZ룏P}$Icbr؄d$uqjw$IҸ؄,6!?ɺ}ڧ&ΐ$IW&$='Y}W~gH$+Mby;P 3$Iƕ&d DIV J}$Ibr؄d+5;C$iYlBNLtO>b`@S>ΐ$IG&$='][E10$Ibr؄dk#Կ;C$iYlBNLtxJmg$IKbr؄dě[U 񅟏7$I&d DiԻc:w$IR؄,6!?:_#u/7ΐ$IZj&$=QE30ݗ$IKbr؄d4jcmښ Id 9YlB2*ݢ^'5zs!I,6!'MH&zOWG50ֱ 3$I&d DiսKG sw$IR؄,6!?_Ի;C$i)YlBNLV}6I!I4j&$=U}D50n 7$IFbr؄d43`!I4j&$=YP炝 IQ؄,6!?:_*n93ΐ$I5MbӬuF70pͭ 7$IFbr؄d4P IQ؄,6!?Vhj{C$i,6!'MH&zOmE90ιۆ$Id 9YlB2u.=ȁn9#ΐ$I%MbӮu̟G90? $IRf 9YlB25xCCh|' Ia؄,6!?6)Uk}j{C$i,6!'MH&zGA ?~gH$ &d D:_5؁n ΐ$I6MbPKmf$I0YlBNLkBc7$Id 9YlB2?Uj>}Ze!I4D&$=zv^;C$i,6!'MH&zG9Կ;C$i,6!'MH&zG:⏣TSjk~oH$ &d D껾:!4$IҠYlBNLBF?0ɟ7$Ibr؄d~dO>~`@+3$Ibr؄d~ds>~`@ 3$Ibr؄d~d0AUR$I YlBNL+B~oH$ &d D/0i~gH$ &d Dz7^sd!I4H&$=뜳eK zw$I YlBNL/0/ 7$I6&d D;4%'ΐ$IZ,MbROEڵR[Y!I,6!'MH&zJ}1M$I҆؄,6!?3ݢn+:$I؄,6!?K4Խ;C$iCYlBNL:r?p]!I,6!'MH&zRc<UU Ibr؄d,/0~oH$=U&$=gUj<j5oH$=E&$=g-gD$z7G!ITYlBNL:n]I{C$YlBNLCh|5$Iғ؄,6!?kշqK u̇ I'g 9YlB2#eԹx;C$YlBNLźsY!I,6!'MH&zb9eږ 7$I7MbX~Y!4{!IYlBNLɶ|f)nK h Ibr؄dֿPڣ Ibr؄d IDATֽtP;C${؄,6!?/ 0N/ 7$I+MbZc7E4ZQ!I_YlBNLVoZ/0;$I&d DYw۹/0$I&d DYsN/0Nl~oH$g 9YlB2> >o 7$I؄,6!?w~E }' I,6!'MH&zz{_"`@+~gH$g 9YlB2]BK o$IYlBNLgkK J}$I&$=gACh{o!Id 9YlB2֫oR~ s$I&d D >eԻ;C$br؄d~W2Jm I؄,6!聟I2Ch{C$,6!'MH&zg~!OL!IVv&$=SfR: P I؄,6!聟ETå6I!IVn&$=Թh Bc7$if 9YlB2?K>RChW$IZYlBNLR?RC^qp!IVn&$=4TD\oH&d DLn:5P I2؄,6!ޝ[V J`L:V;Ѥێt$Q߄vHӉIISU@1TY C!L%R2 ( S1sA1SY{^ysHG✳>~?ֳgys>#pREя ʏ IT,6!O ?@fssC$3Mȓ&d&ϩbRGPyߥsC$3Mȓ&d&ϭۣ0SNi!I&b2}VwGB $~YlB,6!3~nOR#f}ֿ IT,6!O ?N#fwisC$/Mȓ&d&ϮE[kG?6`4`!Ij&b2}Xyя IT,6!O ?:,~l,O!I&b2}X0 k>7$IR؄YlB,6!3~u9н!I&b2}ZF?:`ʇo $>YlB,6!3~mRUE?>`*{J$Ibd szB菇 IT,6!O ?纫VF?>`:>7$IR=؄8{ŷ'Mȓ&d&~kO $kwG'ML?.U(Y(*|nH4ߋL{nbd ǥяl.6|vH4Nߋ9H﫟,6!O \jG R;>;$IV.{1^L9qv~؄;$IHLߞ_{SM|{#Mȓ&d&mR8Y(<~vH4_)o^A؄؄{atJG씏bd ǭm?~,NT$[ }/Tlbd ǭι;G?R`>;$I}/ԯCR=qw#Mȓ&d&G~0T[3UC4R9ߋ9Ϫ?~؄;}d y؄D_X/F?V`ړirіC4Ŵ`QOb2}c+s0+C4/c"XlBf/lb&dsCv~AjCj{T>t?8ƪ'?s}d y؄D_ZD?Z`{/kfSS碽^;`MAsG'ML?u.\h*{CӿR~YBe?9Ð'ML?XyG${1~b>=A#7~؄rK쐤l P3G'ML?u?.sP,{usWʛODpH5g,6!O kя։ 4jm+%?H1W2&b2}sS_䧻je|/&#BYlB,6!3Xh++G'.|H|}/~>LWTvG1ޝ>bd ǽˢ10~;|~HҼ|/f ջK?YlB,6!3׹hG A眝$[/N5_wl֭0cN &b2}{c?9(<|~HҬs7I󽘌?W}d y؄D_^k10U%/ !=_Z:zw_R=9aW9'Mȓ&d&¯Cպ30?>?$iߋX􈄡\g,6!O n<)1s0}tCRͿzq!:. <&b2}ס_~TY=C${1#>؄C$P 6{11u/?bD罏,6!O .x}߆IqKO?{1a5W?O'ML_%/~n:%|H%f ?UhjO'ML_'~\t4h"ixu?.Uk6hk᳡,6!O NuW:#X믌}d y؄D_u}70GS,zHNS`_>bd Tc[70GwI #Ħ,6!O V-,Uя1~HxC?zR f y؄D_uwя_ !_=^gc^ѳ,6!O n^ȁ9*8|H|?=^g)&|6&b2}׭a~\UU*"|Hl%zһG᳡,6!O vnc#Z=G ,k f y؄D_u\}ecj$YãG ,K f y؄D_usяݶ #WS' ,sφ~؄؄>&b2}׹ {ŷ爤^ux(|0,6!O εO*I 6%^G ,>&b2}׹o~@3|H{壷F`L#bd k݂ͧ Iskі)1 @zw>K$ͬyG `=g~-|> *Mȓ&d&u~kQUUXy"؄4y"iõNT֧=93bPYlB,6!3~Z炥?J=O$m%ˣC7χAf y؄D_i>TON 6)_1GS ؄O$|SM1,6!O _Ϭ}# BUb٫ggֹpYt6>#&b2}5!H>{aLWD`_>#&b2}Y-_TV(6sbYlB,6!3_wQG;ĦsEsvF4yct'ML_E `'|Hu|1lH&l>'&b2}k^}4G)zQ"|N #Mȓ&d&׆+-xR_ +R[`tu:<|N #Mȓ&d&׆^v`ssEck?FOrF'ML :cN^>[:7?shY1,6!O _m__ԯFNu.zx/ bd >"U֤E[MlE쁍=?+&b2}ku.X}Dk"աϡwbXYlB,6!36^F`&EqCebXYlB,6!3E[.6-4{JJvGxc?>/&b2}c X3g4εZ^bd ܵOc ZU~>_lbT>v{xUjMȓ&d&sWc Aw"cqgϋaf y؄D_Y7F`Ъ255|HV? t-|^ 3Mȓ&d&\gQ{ E-c PkGg0؄*k>cq{1џj`2|f 3Mȓ&d& [TE`z7 ~HcPcץTv? Tόag y؄D_yO>.4#^ã? ?YlB,6!3f^E`Hz>ckz? i0|n ;Mȓ&d&+"Cv[\eri+t.'|vG'MLYpT5>6JrhbTyG&b2}kuo8!CTץbg4NT?=?#Mȓ&d&k}F`Ⱥ|'|H\/jU`'&b2}kKO0dS=oQsQ` &b2}kn\}t!+&M.,|HVTQ`ڧ|!|W'ML􅯹9w̃:@iF-<\樱v{,,6!O _ս#̣;|HYU*}^~P<,6!O _:GOVjkG\}E1)&b2}᫿ۦD#`^&w:|Hî{7`*4|w'ML~f1Y#g4Z'>c H&b2}Z'M1ObQTv?bt%|Dd y؄D_b_IE%`<3Hd}ߜџ.` IDAT#|Dd y؄D_L~}պ5X$ bz0@U4`&b2}k0G RwI\ecxWEZ>_؄V(SkGg:@=T#ir':Mȓ&d&+lRUF-`:I5kfsѧg+?#&b2}k8<7h.|>rvF44 YlB,6!3SG-`ĦsJ[[=UO>@.M.*|B'MLT_=XN U&6M3^{t,,6!O _ëw a;N*GŲWޝDk Xs埄ϣQbd 5Z'|*x#|T,{uR޵NlZk3lj5f y؄D_^.xSU<'|f)=CtrFDsiy؄D_nUGE1 U: ifMlZ8G/~>P'ML\#d{wSqRyG1U?J,6!O _CnZ`12R=yOjK#U/ΥTGAS&b2}ku~W1rSU{Airg[:s|8T#yϫbd 5f12U>t}j|1} ^;ד&b2}k~ZNIKݛuibU'Dek؄{/>)^{t|,6!O _[}0Ϊ2n:%5~G}S :j>jY7YlB,6!3淩?0zwG}$M.<|mwwgC55c&l>F9Mȓ&d&W25R=@ꜿ$5yc&6I>| DǻϿbd 5w=*b,̺E[aJupij؄zO+{wy}ڗRc7Q5u{!zG}8|F&b2}+桿}֫Zf~:q弴`OD+R]я`'Gf&b2}+MR9UߙW{':n9 {Aړf9K'ML􅯸 ;UGoMkN3Z7R6s[Y*j['~6u~8n^c KN*,~f&b2}+b^5=?ueb/qG755K_><;wz~*bz<=u'S:,JLLcMqӽל y؄D_{aG Dx鞼w')\}E*W_9oYw&b2}+Ɓ}qSg;ڣ]sbd O(N\;knYlB,6!3zQɝ_Κ['ML_G4آWsbd 5u~Sdw؄H0ӌ؄ Y ,6!O _#ނS!G}؄ Hχ_s'ML|*v.U,}*%M."r؄5WI{g y؄D_ʫb_ދ&wfȓ&d&W~u.;0G̓wC'ML*lR}t 'K%Mȓ&d&Wu./0e75yS{d]؄lDirubd w/LC hx;c؄o2?snubd 5&-"}H)Uk.wg y؄D_G}88Rj}O &b2}kqvޭbre 5^5͔2XSHŞ '&b2}kZ}j}Wt'MLXꔺ P+kc.uGMȌ _>Qq;oMlR G/5v8Uţi0Gɥ5w`UONmӊݶ>YlBf}~kL[Y*&Q3j0G_ߚnJU}R{Nb28ƻ`<}Wߗ?̑&dy§/~wҗ.>uY}<9؄̴=>󟣏:+]F`,6!3N U>/}W=@*v;m򁫢 0G7_Go d? F$d1bru 6P-i^}L>XlB}zT,}EZOEyL}/k? MP P}jG /e75|{{?b2ԹըMSy pQ MP9)%@- I\Yf 'MT[_T:|=6{6M3u磏 'MT/fT=qWYS&M3wG&d{/_>#{jyŒFOJŞ !P:*%=M3}W 0ً_Tۦj`4th]O0ut>XlB2{1Ay?jK}Sf_0@0:Wս:`}Œ0>,6aTճbR=џyѹ`iV}0`0&:+EAy{RPQ\yf_5a Yl¸uS[_T:. or;VS00Fw_&'6 iPM[E*,c0xfj_߷4Z|"Cb cyg_T{~։ *v&Uk>BXl˜)'Mn:s\w^}0D0:Wz׻@z&lnk4{k>:~N}y_Ȩ>5R굣>0Lf^e{2#bؠͧbׅبOBP9a;mg|% M`:>w4ˋ_t4u.7c{irbwmb}ֿrCGȌ&0#ek]jir_|4Ml7}1н4`mb_Nx,fJH^ҘSyE'Xck-,5ߡٞ>*@,6){{y_u;mcGr CUGIQkb"kꝫLߛ/Pߐ dj(4IjRן` &0XԽ:㫩8Һ /{ߑR}lSd^2:s{É\&85a U|*uo;#//NBj4gF)+?:mejX]uD\|vf{IꭹOb)&/:IENDB`PNG  IHDRF pHYs{Rk IDATxwibh1p4&@$DHǒĔWw,R-"%,eiW!]| 73}7wgw'I@ @ @ :szW ;_`m)Aʑ) #o(Պز{Glm/? );K}Lq@l8]ڂ&_WPxo_ Ƕ@-{2\2%Pz&H-j_dl@Wa(u ]"mnWɣWܗe5 YW 0AzWe7}MS )E]}s~_-z`BHZWcū}Z\X7$Q(h|I-vp*Z-T5#%׆?,; \:[CH[\}_&pN2f͌ZFI)t>D) `  :'! oSz\I`7X;. QO[ e#;eL +uw 0wN):G.c2+j]S#-17FG -p```_QY厰zn4R((u`mA2<֡enWd-PF}@fLJ(Lc!V16+[QQ/>;@!*8OkV`n QC[?k! ا Q?=,f\VhrO(Y$ݭroc e1=(ub}HHZeqf hDH ZRn:/EjMw /$b) mx'(RQN,I$/'$R8@f^".8X TOWsO,I,Fb \HY u@;DQoil=,jqݶ8Uc`> ɤ?ch(ȣ 8pkȃn~+6> p>R:Q"?+<6F_k l]XnlU*X0 eO$31jyBxK u }}Hk @p wQu'O T(:adN4x!}P:(z#<2iǽY- &U̚ O:ԡg^_OP|;wia@9:FU>wiX@W:z-yw 5D^W.% x9 :~1w/]w@) C~7ٗ5.GCp󠌺?|yBz?QWYx/lNhRb`e`rAQ<@zdȂȭRQ©?n BΑzXFR\R"J7< $v@O@o4rڒJjYa`c\ԙ=>칒VLI}es&sT,[HƜ>]4 V&ZR@GBqՅ!7_s#c(U_Υ\y\*z&QآGV+G +Ѵ'V"QVXGe0ڽ?&6-r ywÐHff2?omXWP!5V6DkS!=ư/"5Q=KPgl%vN Œ 6^G)ꪪs06@ @ @A嫟(]=IENDB`PNG  IHDR . pHYs{Rk IDATx1 0 ')(zF;:gF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 0 QQ(B(B F!`F!`1 0 QQ@B(B(bF!`F!0 }GIv.L`k`cql/s 8\ñ%͌(( BJPF9g HHwW8zzRwuUg_^{J]]U`Q(, BgQXE!0΢(, B`E!`QX8B(, qE!`QX, ‰3oՇƙߗ%IٜR6Vf|kf=|v t&ՏxjΡ३>NNEHL?ͫʖ/yu*5YlIYٟ !$M|z;G;SUoQܐ:w g.R/R{, l,!-zej|S^uZ5XS}T?M\PVE75ODL!iT_+Q FwQخǧ߶V?䝩x'El!i^j:4FnQ}Լ)[o"i3{O*󧢟2@?𤏅f=v][ҨEaRӉ55@*뢟6@t[qGg I[}z1`vj߰"\75KiƊfw/u;i 碰'#HR?2kS =$Ŕ/Ծ+/FC(l~Zz{xi[k%70ֆT?}3C!u>7 YvW'li[k)~᳈|(u- _SϦlq~|7$%Q^"/|+Ik7FcQ}ʔ-%APiÏS6GRm0kEaM)ԇ+>R7SjvJl>H \? 碰])[[(fC$w"zŚU)[OGeJecLCI \c'J?tk}klZO"Y$do&ilG}0;ˋ¢ Kӭu?Nx-xaL%6p. [W[?HLsi[$%EafUSʦo=_I \>>;W +M|7rSz H4|ΒT:}sftxI*u(]j*zޒT#n{VʗL?Rr󞟺߽x .`+׬J.Iij_w, [W. ISnvsWr +S6wKR_. f^ZӹoB%@. [/ GISyMe_9LRm`<uY5)(i*5`5lm}A<&60.ۻ?cT?䝩l= 0Tշ|.s@4aGMsQR1Tެ\PYҹLRm`j_|zՇ#mmfc7~J>>I D6⢰|'!mSswHݻΞ`8񳚤4u; mCfjZzo=I8Ꮷ(wÿxi[jS^U)MR-;b۶(,<{ g/me; IDAT#ޗR9*Pk_y`&^mQ֜/Z}_ O} 0'},|T ]۰(,/Zڪ00W)h(R\*Umݢ/Vڪl:8w)(J}­[6/_5.ٸCFNg:I޽¢2T+~` 25NNR-7(>te)mAoッSWO> $Bj_}͋;6WKS{gYUl᳞ڬ7Wś]~16Rsgy{lkJb>6ge+>>Iz݇|Qؾ/NT&rc)_['6/{Eaɪ)w%@et=+ jڟO(/NouDܑӺsڬEcO95gԽzT?WAIi*6JJ+|q'ÿ(TfOFމ%f8~΢h`]uy]@J?ȗ:~Nfѿ}-)k_Et:;|NT}^|x/HqT <35g4j.Tt*k?&jesڌU{to8&Qśs*!`G뽧|()D#y_]#<QRmF?qY bTݚU](:~ϑj}sWzOZŨyUV*/ w '%Z;QŨz_,œwFqlBL)ڗ-=k! bT:}0e+>>WJE{zײ}ŨZ5Ok i(׬J//%R/۵l¿U|7.N`>cJ{^ײ=_Ũ"1_}^,Qu{OZE_Q}TyЧ Kc_/ӵlN_FƑRэUϜjӪ{>ײyb4{-#,RϞjS΢PV-fP=)[SRmJYjVj Yо|TRmJYjS**f%G?|T, 51u2`Oޕ;ϤҶdQ} KϤj۔Ef?5OE7n BI/rl*YjF5kT<~s-gTIʢP3R#@/Ϩj[E^EC V>Jm1B|+R { W%նEZSP? Y%6E)z|=Jm2B%w`ϯj̢P}s) ,R_ a%&͢PӮqG_5 S6wYVRm, 5m:_YI(Դvr)SgZIdQ)%LUZIdQ)/z0-(|TaR[}0ʵl g\I^оda+ˢP۔WfyWR͢PVFL3]I5Bm}0`D5sTZښ=^ʵG;S6yU8BmUkE;| gQ-V_k)E}+Sk`)h|󞟊wDTD4V, /#콲-z fQMV?gR4*x>|.eQɛ}>tE@E5tl,U+BMZ}'Pae:{>KY(FK^ƚ;k_y@,eʢPչRS}d)HzN# S0w>+KYE(ԏc*5hY, 7 S6gYF`ښ'<|Ɩʢj-|Q*}/,i+?e?kKcEaj}@4\-e#Ea3\h |斲ȢBu=<kgn), +R}R*:g7]?=^>{KِgQXw}ni}kN-eCEajfTXE/l(l>`Ƶ/[?KcÛE<4̎v=6|!͢pT<}_1 Cqil8(g.|m|7R6YjwNڇgu˥ˢpDk2(~gs), G|.VGs Y#Xkbe/{W.eCEሕT6Dss Q#Va*KdQ8"/7TtS}[gw), G|+R}pL.eEԾlIy No l(E/Oes}q s9^8!}s {c,/eET6E04, l@(Z+E0\:͔^0am S=}i_4~/!u* N#{dl/eE06y\*Xվ|^, i}P+SOR6@Y[sKE0Ɨ"s468YY0Pnx"ewl@(]}h᳾ HCT}{O)Swl3 @CT經Ov {Ru{Essѩ}偩}:S>3.5O;yS/ۗ-I:->xi*Vߑɔ28Og~), |ߟJD0Z:TY{k\ziLc>#{s@6w/yUsqS!sRn Cx^ϢpHj_o é꽤{7RRJI~o-5y~OW~'!T6E8si,6!(_K*kLlFe콤w|a1.mvǡy^ܽ_Qս{[͢pv)ϤS {O~gS/en{#?ێ 2;Z(l>. L{yq|ɫlÇTRcd) ̢p%2[{4x3JP _Oagn;>b(߽$Uw4E70jԽ@_OݝW|KGˋrf7 ~JY@ZNj{qC]O{O>W5 >5@\wazJcE:矢E6zvrj)[TYxJI Sl(` P({Ey'SKO ^E2 CWߣR6Y`?}E>[@R46;YXoEw<{~7jě]jxo{TkR, 9ۥ@`cŇ{wR5W<~s3VlNBTETP6}JROrO i#Ϣp )z~J5yg{ъGoϢp@zY `u!^^a('RR*:O*·)@R>qU? {OKߖ3i@un=)>΢p@̈HݻI/r]'e/ DI l(Jq)ԹT?-=wMz92}{Pf0sg#deߤ]^*RwP9g:F@؍#w4{^j_ n;)@E4t'L5O3!W}(5l~IQyg*!@\~I eQTS/:=>;ۊ~z0ꇽ'ޓEa`Wz ۮ>!.TFX#;), #sw>!+w4{8un>.) *[RK;)s\}0$/m5Odo~kO9 =L`Hm.iX/}[*) )%>gQTEgxX;K:-~Z0bIcˢ09ۥr̓a%3ewyg|*2}ӹMEa@}08w4Տx_*?t`)ew)€W}0{JB?~0Z}>^>eQ8>> edj'wT:7}0'X&M?YqoDa '/yU$U_H,XgRև, gw> gk:!չLEl6wTnx" X{SwKS}{S?}D0-Q, g1>ֽ)'$IW?S}GCu1)fXQnj}?ѵ4{&}j0$}`ej}0)fi^v PI/elp]$ixq>Amk{?FT4un;%=5x ~f.Y}sѽEC$i{~qFq,(?wZwjVbTw<fKYyw>5wԹqE@ ԾjijT?4E,T_3RtRτ=ܜRꃣObsӱ{&Ϣpj_ X`>·H#,fYQe*'un>٥lw46YB㿹`f/ȣI3ܜRã~lI/K㸏|+ ilx(t PO9f9ۧE=3 .^F'™~}>Ovr0+؍sSO!?;{iij(߽8x`& w k$eY7GSsR/OقƟX(=wMێ>o.Lق5Խ# `Խ멵rnj)_\RϢpk0$0_}4 V}ɢptl @u=?ewc$ VW⩻(XE!opݟ} ])™jD1 @u9ϒP&}}*}/\9/5V| JcßE U_kg6}Խ\KBI[~;SX}d]XK/[}4w ?s%E վda9@tXe3ѿR}tL];v)xy_|7jE U~K\djT?R6wsTR-$z3T=T}8.^4/# xϟ?/%&y_ELS?;E7gԹ ٗ_45O/yU() r3PѮ O$@wN}Um<퓩~;z?%aʢpC ~H%!\}{tlj{j)T, om^o}HޕR+>!U}(un?5.Bj)_K&6Y=wSΡѭy_FsP/IdQ}0W%w}0h+8 n~VIU6~6lmjFSkISD{@&$(>8۪J C$U|n\abԹԺqSNjIʶEa?̕"QφW_Iӌ>>)}2)l Yw/;$Uٟ>4Sթ}y_ҷlvg$#~5+ T870Vꇼ3|.xSr{9jє/zy9!I,fQد 7%ސ[xB}%Q} >By>aT=un:Afߑ9ۇ?%), ' e{C&6gԽcF%ĝNIswO#ޟ;?%il(C##`+4w$m|rG% yVj]_)s$eCEa?ċ+n` :7/$i~]G& 9+{ x I1;#fLg+qMW?$I5xiQ ސg]c;?$Iik(fE_Lb|~OHt{cﯱ`Py_AIT(_[ &4$ֹ}BOX_\$, Q?_6Dח / $"©6gT֟qvs!I3䇮>i2ecm˖}w^$A͢p|K$i&_ZٳKiL[IRmh(bS?c?|ɫIڗ.>qWP4, oK$iVZT<}K .|Q$)ZS .{D IU+}2ԽԾx~j|SsZ%(JswLG/nYsˉ/Ο}_+H͓҇rIRdS~;?xߟ $i˗*gOaw ^$)ASy_Gtn>.^g.f35R經SO>}%Iiг(B+/{w Ia>߻&({ UKSg$IcۖE>2_u|߅w$EW/TGrtϾy'Swlv $e̢p  +>~'H Թ#yty_AIXu( s IARX}4r{9r^jє$eE68Ꮳv KE 4H/G;JfQʹ?T^{^ IRG4Rթ}Ay'R}[e$Ic͢pqF8׾tq} IXFу,RԹqEj~{I-gQ߿7j+T?-$ jU+$eCE4ާIߜRFU\<)Mᏹ$IوdQ ՗+"k@PtRԹ<볩~;R6gWlD(܆8eT~HҠ3s_Bܹ:w8WD?$eʢpj_(g'Jk_o] IRJC^ITZ[_,}[] IC{;{̎qŸ|?>$)M̢p*y g,>{@4$) k[ۂT=l~H]ueNZT?W$IcÛEVV_ k)_K] IX}{{ ~(?wZwjH5'Ij}ˢp+k} m׹{@o[6Sx-$6cYnr l7$i/}kJV`Sx_AIƪEVֹٛ.ew$i\{]օ_J#ޟ/$IR-<­x1%Q(_[j|SKÿIT, h`yٱ$I$f%­(5s2@5)[{@$I dQ5` PI}H$IRV, Y*y߇$IU$­}ѳ2@eʗ:$I"YnEO*x_$I eQ^=/TN%$I$eʢp+*D8C$I$eʢp {=+TO/$I$)P[2@t0$IbYn=/T}K$IRV, ]yrGF/I$IYŲ(B=/TK %I$il(Bݻ=2TJUg$I$e̢p =3TJ}~I$I*E*G8O~I$I*EZyr}^K$IX(Lo*V$IU4XR~K$IRV, 7SOGҾd_$IfQgR|$I$²(L뎈*%g$I$e͢p3uz P,es ?%I$)hx2G?%I$)p\H P ?%I$)pjv)us3@e._$IƪE&2zf ~K$IRV, 7Q*~τ$IU8MX:"ew ?%I$)pyDQ^/I$IUeQ*s_$I^ˢp+znMdž$ITZ׹2/?%I$, 's)s3@e4OT/I$IUeQ8y/*qo$ITZW%I$I5c}fG?%I$I5rb PC~K$Ijսs3@e6ܗ$I$, '2=^~K$IjU<|u P}I$IR͢po ?%I$I^T<}_ P ecM/I$I(r#ѳ3@% ?%I$I^T֟*x3_$ITeQ8Iӌ*x3_$ITeQ8;DQ|s_$IƳ(Pp2^~K$Ij, '/-zn+}I$IRE=7TFo$IZ/ ~G P{?%I$I^fs_$ITeQ8Q*{$I$ˢpBN P;?%I$I^js3@etn?5ܗ$I$zYNy_Eѹs_$ITeQ8i=7TE$I$& 5OT P^z,I$IɢpB3>=7T3$IdQ8=7TF}I$IREᄚg.zn=熟$IZ/‰9=7TF }I$IRE=7TF}I$IREݣf~s_$ITeQ89s3@etW]~K$Ij, '> [ PW$IZ/‰=7TFM$I$ˢprᗢf(;ܗ$I$zYng Pڇ}I$IRE[cs3@es_$ITeQ8Y97zn>ܗ$I$zYN|@V΋?%I$I^j_0zllg$I$fQ81Bٕ_$IT(*__$IT(R~K$Ij= |!zf?~K$Ij= }>zfƑ~K$Ij= _R__$IT(XF ?%I$)pԾfY P9~1$IYNR}ei{$I$e΢peyr*$IYN\yrZ~)$IYNR*}_$I gQ8IS?=/TNSI$I*E$52@t2$IYNR}ESY~K$IRV, '2@t)} I$IYE(|+eJ~H$IRV, 'k)e P9e$I$iYn.z^q ?%I$)hhM]ͳ?~K$IRV, 7Q؍2@/^~K$IRV, 7Q2@t?*$IYnFӽ_|MI&c `0nlhv0`0ƀ[AUJE%J PB9rN( I(RZ'n8}~c|ík5UgSe(܈Dߗ%F_~BYnD˒T\U ʢpc?>}_"km3 Ȣp#}2,IEg@*EFt軲$Yg{g@*EFtxG]Yw?T hweI*_&=R, 7ˣʒTdk@weI*]XnBy4,IU=vO dQ n/KRyUl&Ra, 7{'ʒTd+09}weI*_&=Ra, 7ߏ+KRU>Ra, 7/Gߕ%̪*>RA, 7eD_%_}m*EfTǣʒTd5  1z軲$Y>RA, 7cxweI*;T\wT]Ylxq3 Ģp3}W"M H(eweI*^i9 aQc>}Ubkm9 aQ8,IMs ¢p3_}m=Ys ¢p3Z}Ob럵"|BX@y4,IE6 aQ8+KR$|BXDߕ%ȦEw H(eFߕ%Z_9 `Q8ҙˣɒTl>R, g{Dߓ%غG}$|X@?'KR^>R, gɒTlk3Z{$+@*E UǢʒTdU. , ghweI*/ , ghx˩dI*ξo , ghp~dI*1, g֊{$[@j8{$c@j8{$@j8jKdI*a?[`3lUIRL]^? ˢpuEߓ%:9̢p}Ob9̢p}Ob\~@H fQ8_'KR 0|('KRU@j0Yh{$]kPwdI*ξo , gc钜{$[Of(у7Dߓ%>RCY擣ɒTlÛN , gݣɒTlo , g;?ɒTnaN[?'|(}Mk 5E,|CY{g@j Yjm;$]mg@j 9ZEߓ%؆>RY ɒTln , `pAdI*  a, C;dI*n> RXA#KRug@j9hwdI*Y[0sZ*,I6YƢp'KR!|(Fߓ%c RCXCk+ȒTtUY¢p>ns}Okmy05, iȒTt8|(5Gߑ%zG,H `Q8ˢȒTt+, {_Dߑ%F]> RXS{_#KR 9-*| gQ8_+h}Mkk`jY[ȒTt#?> ҄('Dߑ%~)| gQ8v#KR o:1| gQ8c>}G+| gQ8}Gkmy&EV ~,I M01/,IE;S M01vfYnpg@`cwdI*4, <ȒTtU. iBYIg?#KRV2| eQ8&m_}? M(1%)Kg@Pc4;$#g@PcԿ`uYnM M(1;$h?>(~/,I M qZܜQYn_wcQ8fպۢȒTt > (Gߑ%膷> (9Dߑ%C M 1;$_k4a, ǬۯGߏ%:+| cQ8n˷y؋#KRNB<, `uwdI*ukg@0 `pwdI*jm M…1}Gg@  sF_%:=| bQZ_}?y&EBX$WǢȒTtSâp ,IE7zY&E_GYn4is@ {'ȒT|>҄(\ ~Xw@ essFwdI*e`QF}GwE,H¢p [}GrZy&EBpϘ"KR|C<HpuǒT|c&| `QZ;<~,I MVEߑ%Fw_> (\`;Ή#KR[9-2|(\`o}Ekyj΢pMD_[w@9cI*@9…sr ȒTtϊSfQF}G:tI<H5fQW}Gk~e<H5fQ?S#~,I=@C IDAT1E9cI*9ۆTc\UwdI*wO , IȝwdI**=> RY. Fߑ%Z_yjʢp~g.KRuּ7|(\$ӗSIRl&z(\$_w$6yjʢpUO}G+|(\D[N#KRs ՐE"ꟻ]XsTC{_Fߏ%z}.|(\D:~,I7yjȢp1-]ΣwdI*C7(\d;ϋ#KRUZyjƢp/%,Im ՌE"$_φT3oDߏ%>RX.e[KwdI*;TXuaYK@}?yjĢ0@Dߏ%zg. F, w}]XoxӉ ՈEa[xYJ( 2;$_k_ &, /X}?yj¢0HFߏ%n>RMXicI*mgTQ.U;$]yt/ S,  o;3,I7/@@vKRu~(|( =/ǒT|v , V2~,I7yj0~}GsZULeQlxiWdI*>R0`sKRuyY$ҽ@ fQˣǒT|)Ea TO|?,Ie7s@ dQXÛO"KR~S<H, kcI*79|@59}cI*_)Ea iXo ({ȒTvU[ۼ0| 51+$_gĢ&zg.KRN\<HA, kwGߏ%׭ )EaM{qXzyXH]wdI*v/ )Ea ?:~,IYyXH/Dߏ%g)Eat$@ `QX#m_sUEߑ%`<H, kZw[Y/, kfp7ǒT|<|EfQX3S?}?럷C<H̢f:aXoxY -2ºYܜG;$]},[cQXC#KR@ZD54l$_ iYPOFߏ%>"(}?{y<HȢms/Eߑ%F`*|&L-šy~Y[@Z$5տ`uXwg@Z$5KR ;*|EbQXSկKRU>"(*=}Gk -$_iXXcI*;, ksǒT|û.iXXk\UwdI*A'@*Ea͍5,I -0š\}hXw?, kwFߏ%W iY\{Dߏ%F>(y؏#KR{ILZ8`tcI*Κ, 'ǒT|W, '@Eߏ%>(]-~,IWuiٖ3 -It\u#KRw{}LZbxYcI*>(󶏾KR .7|bQ8!?~,I7yEh}Eߏ%I(V |&`Q8A"KRuxG<XdxñcI*_ iXN_KR oҘYNމKR$|1(0}?$ 9mȢp,*~;,I-3`j|, 'ǒT|S=|1(@vKR F<HcdQ8G~ ~,IW=zW<HcdQ8;*~,I9 3 EᄪcI*aiL, '擢ǒT|viL, 'TecI*4&s}?$[9-{fLHc`Q8Z۾(窊"KRp~$_O4lp՚$o4KRU>XN~/~,I9vɢp-rtǒT|ݵ ScQ8F߻8~,I7dyɢpkXot5 ͓EPXTrk4WG_%I9 i, '%j ~,I?g05w 0)cI*g4 ?kEXogH̢:_wXsng@#h}gs$_ i, bcI*G4G 1$_ ͑EaCN$i=;JLHs`Q}7$圻G4|&9(lyЍKR .'~&L͞Ea4~,I7zyA=~,Iυ4K =#cIRι3 ͒EawyMXs]LHdQ$K䪽.~,I705; 3$iiųg@†韽*z,I9yKLH`Q0/З$;3 ͂Eaô{IX4 i, Zw{Xj=LE4C 4$i=&|&(l}7$圻MLH3dQ@ӿiSg@!&Z윇$衛gX6ˢǒZg@†_GXs3 ̀EaCuHXscLH3`QP]^}7$Mg@¦Z$WucIҰ??6͢~+z,I~Oo i3, 軱$); 3 mEauּ7n,IwO i3, ݋ƒs{"e i, Zw{Xsn6}7$Mτ  ;ߢƒp\LH`Qp}}7$MpNK i#, nųsǒs`j, 0軱$i='SLHaQX{Dߍ%I9G軱$i=遜. i, 5wcIғMs mEa .U{]Xs0, 1軱$i=W i, ?{UX4Ǿ>XwcIғV"|.(,DkDߋ%IO=sJZmw36ʢ պۣƒ^LZu{_Eѽ<6?q, 2k$?=|KLhչC?\ }Q΃&?vxYTSt$m֎/ 0iZۼ0w|g<o#Nt\yp=p]U56T=Ydųsp$7)X叽Wpx hSdQX/$W-|&@vּ_!E,>, ӿxE{$I/XhӿexWO| sxwLRMY{GBFIҏ^qYT=YkGIғ 80|.$WpuT=Yf\E?>zW\ x8^lF,SMYhxiϤ$Z_>g>M5eQX+IIғuX\p˷=g?SdQX&,IGĢWp%;sSdQXv/~&%IOV=zw\ NH.EK)BUn~.%IOUsZWp+'[ngjʢPk~.%IO=o^"+8Φr7UOϥ$W>{w{}J7ὂ nxñRMYSR6+A'B-BRMYn@$էξo eW~ jxISMY݋OISꟵ"|6L<&rjѩz(og50췣?֩ o==l)BãQI6ZLl+|~VTSJRw:h|ޏWpWy6۩, JRg@{B<2Ԃ4SdQHN+Jltߕ`!-]ۻjp_<9:TH/ɢF\JjGqim9}<\uĥua3jʢ-9$=={Uw(dE?4tY˷=ߐ}\~aG)i o?;ٙ'BkTG Oe潹yx9[Y7g)ՔE!zgU_yul慹s;syx JF<{2TS_Tz'cl ?^8$-HMՓE!?pUISpllhٖrvW>Ң5T=Y_:=Y$=G\[O^AßTS<D?`b~?^?Hkx1j)B~WE??kԔ JsjpQT=Yc|-y$= @ x4~#'B~L迎~^%IOm4̭m_> R1 >,O5eQȏiUY| JCŸTSKrA3+IzJӯx,*~ςz(' o>9$=;g0 -\~@0UOޙˢYIjشNGe_Sq J5mp~E)B~B?~f%IOw#U/{B|푹z fX;!, ts5~n%IOixqsr{IWG@<_:\'B6h u%I>jX+(59ğ5SdQM__T:-|>@ӴvxYyo<oY~xP?RMYA^JW˷Wd\y_]?ɢ [E:F?gPk+^NؖTӺMjʢgW| W-iP9jʢꟽ2ٕ$=uGXLU{<8Wnǒ&~(d:_w+IzZU\ =<ҽWP҂Yn, ٨ֶ/ʹ_I q^AIZ~(dFJV/{[? [TSl_IwE|ٽW)IU{7, ٤J^U?>#`=4as, ٤J6P'+oGEIUկ?KSMYi˞ϰ$i F smsy4zJҼ>ۢTSl3aIӪǜ@sV w{<\=q'I RkTSlVϰ$iuWp+ģ{/^AIe4tI9W퇣'$55, {gIg31YeU=Z$ .;/BflpY>#ֶ/+9O5fQȌNY@NK_{WEIjt3, ^~֧(do7IRM럽*~N0o=R$u>՘E!2gZF]>#_P%IZ?O5fQȬ&$mʭ_>'1(:3O5fQȬtgZz9Nl8Fg}1Bf sFϵ$i o;#|N0?w'Z;rYj̢Y=p]s-IPAnm3s\qP4FV>7O5fQȬ .;$m nxIѣD۠~Χ(dֺG}$і$muks7Q"Izs>՜E!U϶$i#U'rZYT=J$"O5gQȜT|K6Rg{s1"ImxTsoIF\O`"InpgTY2'S=$msZE`v;JF׿g}9B椽oI&jYt!Iw>՜E!s|+O?oYt`F;TssqIF=tS`vz|&z|HRg}9Bvϸ$iwY/J萤Fg}9B欳ϸ$i\>+GFIjt^~֧(dZL(9$ma IDATׄ fnxׅѣC]k, G?璤M53zlHRslͲ(d^K6Q/ f`V9cC[z(?B{uI&wE`Z_=2$эuY&E!eϺ$i3w~U`:#z\HR|rY&E!6z]z}.|Vic6z\HR\_Y&E!6|]F߻8|Visg ?(d޺G4y$mʭ~)|^q}Y&E!闣wIfouaF9}g}E]ϼ$i |VqUz0zTHRk>MBbp՚g^|Z۾(zJHRk>MBƢ{'yIf-#BhӲ-4, .~%Iitϥ=#B]4!, {}Ifj?o In4!, ߈~%IwT o8.z}Hfʯ uQ Iop>} ]{7EKysT3'$5_?(d=3W'I p(ǀ$5?(dAL@T>3JU=~_7>MBDg$i&U/ Ҵv|y"jm3?MBDg?> $I3wg@iy/Iͯi3?MBƊg$I3Ns˷ʹ~Ij|?&E! ۢI /ѳ~/IE;4a, Y$iu?>}KRuּ'OƢ5sA4Æ7>7J0}Jο~ cQȂsA4Fg@-"WGO|Ij~^N˞OMBT{7G Y4 zv4Y{ߊ>%F\~ dQZ\u>$I3ltIhI>%~ dQȂA4:Ah鋫$i럻]&E! wgI,\q`hm:FTDݣ:ܟ<,}>HfS/֪ےiw&DiY8٭3B4}h9FTLm_~ dQȢ\wT!IE_>;fteǻ$Q ?ӄ(dQNT9!Ie0>^s5>%w~ eQȢh$i <8|~4Ew퇣uI*eiBYh>+$Iiɭ/lhUDTLS?~ eQȢ\&$Ͳ) oV<}KR1uy_?5, Y4ݣ?}VHf[0:Iq.IEZ?M(BMkϹ I,0|-(r%{j, YT>2$IlpQ`b-"W}KR1(쟚\,ED6֎>C&Q{7GTTK ?(dQuּ7̐$͡ۅI?#\w?iYZ+}nHfYAN[T(KPūƟSˢE7sC4}2|Lo>%Z۾(O̢E;ci!ICӿj_DInG$Ugp,:eU&΁>G&²gmI*'şS͢ŷl\E94s`t#[/{ƼYbx1$i.UUn\}h-I=p$iMs+zYkrZۯπ4, ʫI\rK?>K{GOjI*a/m=c, S=$ͱY+@] 0}?5E!a}HXAN+>Kꦽ룏hI*Ukg@jBt{9"IG>>Kf=ggE!aZ^}HX9-*|U{],IE-s`jYjxyg$iu~(|EE˒TfLE!z18$ͣtI<},KRE&BB|Cy"Ig5 '|>RCXk\=q"IG{/ >,8bws 5E!$i' J/铤{N,H aQHG)y6 Jǰ$۠ӊgςk}rFG$iuZ^ΣG${ς KI<}Q<XlS?}JR/#|(g>[$Ics;g YU;蕤y0Bg}Hg b7Ǯ$_{A, e[檽.|$+ }JR[9-{fLjBjcp#F4F]- BVox 5E!=cg$iLu@\XMx{Q+I?o0,Fk\I@l4U>f%Iӯ9}3!5E!2sF4z'C\XMG$rkυf(Vzg.>j$IczV>7|S>^%I~ȢZiF4z1|Kk r>Z%I9υ@%zF41~i$MB蹐Ȣ\_y#Ic-stTIғwِȢI8F\sDi*Izo$Fφ@NkrtIusj]ST7>RCYRK[}H\/tI}Q*IzJ>?ɢZ/$iUniS:ʢZj~e#IZg 13*=}tJڠӊgψP衛IҸr 131SSw>RYR[ VG?hx3`s:/DjXgDj0BjۣI=s`V<;9$mSeQH}-2W IT=qnmY>&%Ijϭ , _>$I T= ӵw/ʗ$/'|Ƃ(ҳ%DQTPD̀ 8QPqAEjdtbB&!IB! YHwnIzOB],Oתnw<{NEC̕Lc~Hғ-.}: K F;CGS}0GuIl~7F؂/1P3 9S%EqX}{$to?3$C7~H&έFwLRk;GB M+>ֹ w$n?}0-$CƊwFMKv#ij%n;`VmPiV>rݽ)}GȔ/9> DŽe(Pչ3 >qn&?|َxc )jkQB U/A@.B#i[u2Eo,oB WIe ~*q{ ICJN{/C1PzKY_KwuDaLS5ZE#٘e(8*oOn/$ O?RYD_LSK1Pkvl>}^{SpHHӈ>U)~dcPCY禯DYi_{H`8) \wT}aB e4 Pk$ fկUk pl 3j8[`EjH@UP LuޛzALB m[O>Ԯo $ F^VFL̂/ W1Py.ék$I07H`lL3jh˗>$r)_s$)KDE̢A~dcPC]{gG_ bRK%I~R>E/g(P`_qB ua41D+SlIΣ@l3j~f9):廽0~475O9lVwM6 5cXuCxq%ivk"`t=2ZB }Kֆ S<|[zi=%i-:shk;gk 5 un>)<`P? yS_RX|,ewƽPPFi b)χU^Rc>tBP#SX}0GJ>$MS/|M@4OG5CF _>`{R}׆Wļ:s)c~4Sl;HPzS؜Hjxg%i˞:}Tg5RP­S=}0:R;>PtSK"z 5R5~Wi_GТ/i㢏uxi}ړ 5ZMOc+9H5RW?x#`ͳ9NR W}0dw}Mw4-!_Je@n;{8nRIB\}05w~I\7; T{ZBdŚGw Xj{LnZ|>n+R}U ZMDw Lo{Lv*V 4˂P,_sASNw4廽0? zj]ڳ2jd{y+ޝF& URKe:[<,gf(<轷_E\}_Nݻ/`:[Cڳ2jdwQJfM_3ryJv*CsqwjPsi#l>Mm(="c)m,CFW$`U!*>'{OH?4eJPnѶ}0VI}q{RoAT#26P#_;Dg|/w\W?M{r Q~ G-`Եu-.ޓfƑHRYF0ulb~ݦ&3j,*}0GLc~I:,i]0~Sm 5UKSRş)71ޛŏm) oײ`3j,ʗ;oyj_Ww)آmSԿJŃ7E0w_)m)CƦ]FpB{lj]T>oF\=նPcSD2_dۇ߉R ƝkHӈ` GS9j[Pi>s{SO­FWG0f:*M&Cƪ>\{wj/}^2q1U?jP?`~})IN/ Ū_b)~76 Uߍ>'ٺԹT?-wWO5uwNJE' =h#&PcWk>'`2u 5-:Ԁh8sQl~ݔRi 5vR}\Zrׇߟo;=6u/SؤߛJSPs%LI+R1-_<#s)#LJߡM)CƲƗ0i)[R/Qw|WٟHoC0-&>UmJ 5MOM2_..~Z8ݩ}^Xy] f}Ui 5Uvij=I41?}S w]k1Ys]4 }_RYD0:Gó){u'Zm:s{YJ9Qst2jA[NIͳ>~K{Jܺx?1خG/Ǿ7VmZ 55'']εGN^/ G[oH.u9,7Kڻ}ڂPn֩|G(*}KH>Gp{@k'4;7z}W6 Z/>G`Խ}yҮ~௦lvߚ_+){rݽ40:͔{\i 5{,n;8Pצbuo}_{?O|ekC_5 M_ߕfP>3SB,)uᄄоԺh"5DjOyM> ՛7O:_SҥCSSS?'k%^e(5D0yޛW+T_zܽ#w=o~Wm `Z_TL3JOԺ?U:eє/{~sj3F U:J}ŸU Sx}_<ڬd(R Mtn>)Y^YP(=ꓚ-;ZBd9 gxfw1JhsRY$ x vWm3J{. Xw{AsjPD?Ӿjgv$Co>`pTIBi35#FŸU Z]*a4W -Ծlsuz3jsPB/Oێ> T FWmN3Js1):\9P(f=? IDATMƑ> L?6 IV`VLْŸU P(͠/>`4gm2J3qp{}h3J3ib^*),kl kg9Hȝ)[u3j 61?}5Ok ,`ʚ'ys d(f}{Kgj"C4[-&>`Ǽ'yZiP2JX>`Rw~=9ZP(fKDyeVs e(fy}funrjPoVEqFyEҠe(}F/+YP(EKluOSצ|⟛1C4G.?}025c>C4-&kS6V Rj㨝|W?6 ~pT=z`̴.B3Ұd(T]H6XßU RU7DV Rk{1нg`Ն.C\}_0ʊNϿ ]B5V}e0WPf(yA*S Ÿ{U R@ߐRэ?13>̫f(pL):eßwU RP/OE#g]Ն:CXeW #}>ϸ }B)|R!V|P(:w CqŸmU Rt J÷F+ m?*JBiLE|,_gZF&C4 u(`gYFEVmâ¿i2`+뽕Uj#UeW-[c#{kteꇿ5V}>X-_4wNӈr` ~Um$k_u@5V~y#-`@O?6u?:e_Hls{?H 0:)T/_㓯Z=ÿ IO2[z!ǯ+S־/Hҳkq_RƢIHS5ϤJR{W+6$maoN,B/(|l_9VgVjϡUŏwÿ(I/gSXyOD?6^MO=}(l~a6YDU̱r)_cjcU~iPؾ/L>+RYQ4n5Og¿0I~S*:Qs}gNg0u;)[/Nk_<`.~xk6ϛϊnPX}=<V6YScYzѡyD(i5}o,kOϘߚ'^O;/ %M-'`uo?+R]#7=vJCRKSY_k Pf| xWo3Ca>Q)ir5~c̆LL~7|P!_I61?uﻲ_W'5.PX/e¿XI~௥m>`UMß%[<VJ|o֏ ([R_ + %Mۧbs}0͓?(-=k(,]6,0U?wR*s}0 kn\wJߏ%M4} ƱuCaDžᒦ6f%T6`uo;cCaj7SN_U?~`@4OD){|mOc(^{@k_\oLA#ß)_ k~CMa̯ *9eKv><^y?2R HzC޸'`T?uυRZۤ^ ;~+"izl]sLR󔏄?JS[m*;󡰒?hޏ+<ٟkxCa$M!WKRp@){jO?R_KLҴj_x&w[P?{$OʞQNҺrIӯkR0C`t8/e    {|"$M?C`o}8d3m{ųZU)!]疓g0Ee:2M6QEzPX|iH^+7;' (4}± 8) 4G=n{6xKʖ=?/LҴʗ=??l CXy}ʖ>7L6Q纣?Casim$MoH]`U2)DM'$dikWsq4 cRZ_PXi]O_QfiƊ]Ÿäl5xJe9CauɲHIlXݹ<"Ejg`҂2fU-)XR^ PX>p}zY?U?7SjeK.JʞQIEbJG)?!$MIp`J_L%eϨOmA6q?HZKSQצ,%eO)_cx|$C76,!H$:}tlY;O?GI ~Z;Ӡ}(I+_T6,:Tk/'O~NyߦiX PRwJlk>.R/?IkӰ,SSВ6ѢmRoFk_wƺ!p ?n7Ln/ wJŚGj_}`&|8bԽ  P47e`Tnx(H# q;R{ @8COuuɒ_~Zʢ` sPmyߤbwӨIVjpl^?S*:ѧ0:׭}lƣڗ|MU1DY]Nmƽ9>չp?I9kz]E?ZWޒ6 KתOMޓPsT?MuMŪҸ١𩊵{7 ~71/un>1F_7l;`Q-EX}{w=0:H-/}^ʗG=5O V޽2CFٚԹq?oO^/+,/E =ݻ.Xy]>pm>xs*} v#: 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*BP C!P1BP 0BPT 0Bb( 0C!`(  C!`( @P C!`(*B;v@0j{@ (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(pP& IDATD! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD(" QB@(D! B@@D! QB (D!QB@(D! QD[/B˜IENDB` (V ( ~  ( 00 ($@@ (@A(  3|~}>||gU||2|,|s|||X |S)|||f||||||||| ||||||||||}x|||||||||P|||||||||$/|||||||||O|||SN||||W#qq||W7|4|||8(0 @U ||cc |||$||||8|||||]||~||||PR||;|||||}||z9||||||a||~|||||||||Ik|||||||||||||||||||||||||||||||||SI|||||||||||||||~|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||.||||||||}S||||Na+}|||+C6~p|||| || |\|||X |;||| Y( @ jg"||||H#,{_||||||+|||||v|| |||| | ||||r||a| ||||}|||||^| |||||||||}| |||[|||||||| |||Z||||||||< ||||||||||||||S' || ||||||||||||||||~+ ||@||||||||||||||||||| ||tY||||||||||||||||||| ||%||||||||||||||||||| ||}||||||||||||||||||| ||||||||||||||||||||| | |||||||||||||||||||| |=w|||||||||||||||||||| |U^|||||||||||||||||||| |RW|||||||||||||||||||| |Ap|||||||}|||||||||||| |}||||||`L||||||| ||}||||9s&||| ||~n=D:||| |||||| |||e2|||| ||||||||&nj"||}||||"ph(0` UW"}|||||~V1oV||||||||1|||||o|||||||-||||.}||||||||||||||||||D#|||||||||||||||||||m|||d ||||||||y+||||||| S||||||||J|||||||||||||||||||||||||||L|||||||RH|||||||||||~ ||||||||||||||||||%|||||||||||||||||||<|||||J||||||||||||||4jI|||||H ||||||||||||||||||| ;nI||||||||||||||||||||||||||||||O!||||||||||||||||||||||||||||||||||||||Q||||||||||||||||||||||||||||||||!||||||||||||||||||||||||||||||||V||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||{|||||||||||||||||||||||||||||||||K||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||=|||||||||||||||||||||||||||||||||Y|||||||||||||||||||||||||||||||||m||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||~|||||||||||||||||||||||||||||||||z|||||||||||||||||||||||||||||||||k|||||||||||||||||||||||||||||||||C}|||||||||||_W!||||||||||||||||||K||||||||||<I||||||||||||||"||||||||p; |||||||||Y}|||||+#||||||||'eUm||||||||||E|||||||||||||||||}||||k(||||||||||||m||||||||([|||||}||||||||_\"}|||||||||}"](@ i"H~||||||||2 .`k&||||||||||s|||||||3E|||||||||||F|||||||_||||||||||V||||||)}||||||||| ||||||||||||||||t;||||||||||||||||||||||||||||`/|||||||||||||S|||| S||||||||||||!|||||||||N~|||||||||||w}|||||||||||*@||||||||||| |||||||||||||S||||||||||Z|||||||||||||||||||||||||Y~|||||||||||||||h}|||||||||||||||||||||||||!|||||||||#||||||||||||||||}4||||||||||||||||||||||||||K||||||||N||||||||||||||||||I_||||||||?|||||||||||||||||||||||!Wa|||||||||||||||||||||||||||||||||||~*]a|||||||~||||||||||||||||||||||||||||||||| =s9|||||||/||||||||||||||||||||||||||||||||||||||||||||eJ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||7a||||||||||||||||||||||||||||||||||||||||||||k1||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||~||||||||||||||||||||||||||||||||||||||||||||$q||||||||||||||||||||||||||||||||||||||||||||KA||||||||||||||||||||||||||||||||||||||||||||l|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||m |||||||||||||||}~|||||||||||||||||||||||||||EU|||||||||||||||c]*}||||||||||||||||||||||~||||||||||||||G|||||||||||||||||||||||||||||||n9||||||||||||||||||||||| ~|||||||||||5[ ||||||E|||||||||||||px=|||||||||||||R||||||||||||||}>|||||||||||||||.||||||||||}||||||o||||||||||||||||}[|||||||||||!I|||||||||||||||||||Oy(||||||| ||||||||||| %x&K~|||||!|||||||||~L|%PNG  IHDRxx9d6 pHYs{Rk IDATx}VU4B2&' f2f>Kɦ/مXEFEkEV TB@#\ AVhaϽϧy ssϞ3r)Ak `9Fckw_1k+Ax hT& y짱Y2r= xsw `5UH :?/$oɨ=; *q{ 1Gn)"͟']6P Xph qW vWI,\QuəTŲ&c‡!:Bokc-\tTJ0^ i.M.;9OHߡf 'pg䬆wiK V׃ ].;CMm#~ U==F2؂fFҖ o6X7Έ m eWW)quZ=QQaN_xe#9U2[?Gw̬ n9(;رܧ*Z^ł%]YM*pھ =$%E7~n,yX`qvC_|A$`7X8@ `R8C =O y΂71V >7 \I I%:A,MS'<~Ln1_t52'٨rj`OqyX|Ro]3yXxEDŽ+0$Gs?R$GɪЋ@5=b Və3syXNtFj6:QLW|o4& ޵b9_]pZsi<&GYp'm)dFyo/p\@1 ކ{ɓr9/֑'*غ)c>c%I0h$F= c ~I0`wm~J0`he:a,gQ~9)Q$R'(bk8sI4/z]3_4'*?#juҘ1 *RA`cg\O8`c$ya!xtc7jK{9]~;9k!nJ1 bAJjC,=_4(ǵ%tK%'{RM:UXqTRZk╢[7<+f⒚`@%XV2 k? rx?V7T{S_f`љ[%T* D!Xc/%NF@dSKߝg= F.v.\rDL_---:jTif6Q*-W>LS _GQsK*]'P>frx&|P`xbm +9@NRqG@l q`; OL5}b'#rjd*KRſ>83(G0 $UbU6>oPkWG1{j6V,[;T}/ <0V`\W|wA [ R{X^[/V%R床\GƋ% ƽys+~K\j,܎#x%7ά/j`_KI,L /(gT٥/xXl%bԈǣ2vtkU-JصKT#] pEF|2PrWKMXLZkSDX K&^ki+灯g+ <)`;3m=ƙ5EgVfb#2JA|c,X̰&q؏| Y7SBK]=HU0Fg u>p"k`M*uϐBԽ7u{MPK~` &(SlcE+) n(9nrS5ujh;_T{VS}.<_o F|kl%)lCy`ˆU).woOtb$X-C5 0{)[!*F][v3p~,05#Xs`15#*4IENDB`PNG  IHDR Y pHYs{Rk IDATxyإu}̰XcVMLbRcc&&6&&lib}Y`]vYqdUٗgohAY|s~aʧVsw҇}ܿ~Dk6IҼջp&C5 {$I~2Nt {E eA7GG܏Eߎ*y,dŁu%I2ǽ3_{L W]1e_cc LT :?.֒xJV1#`KҿJ4_-&߲/([;z*0uI98MyIkv1K%D_Ww^Î(x+0U VTcѻthњYQ;''Dsr$7. l W2f3X&F~27 Z^P6b+\" K$)=^/yo\W3&1XW/G֒MQ>rcI 0Uzͦ$->'Ao8x@O6b]|`*.tw`IjՒyuW5s2Xjc҇T%M|CeS߃%IeKw;FbM<8C~.$A~-`UUhwaI\qwQg@}FWg8s;>}4GUE$-qÿz[Z}{ f O9m_ȷ9s;>iF XI8É~-4*0]q`y].I:';b>n=Z=ߋ%IeÞ#b`< VyS>pt/\_#K)t\ߍ%Iv{YtXOʾ́)g ̹~ȴoJ?Q]ߎqL~,IDh A|0XLnt}#JYg뵢s̿J,IĶt X}S`be^(ZKw$Icf PcUhɒ$MtK_'W;0% VkE~H1[>xUXʒ$M|^w`epۗ?$i_6ACQ/ӿ/K4 }`$ѿ#H]%G0\sw{XwfIξ d lrC9#њ*$ѿc-P>(2$IҢm{Ǣl?}`xa0zW/#Icի>+toϒ$MS{Ho<5&*𼆏cޑFƪW}0\$ijEW=PswZ]IU>Ύߢ%Iao_x.WDqUnMZ)ߌ[{ VDk;Z3 HRZ3 cpݱ'2cп|Ғ$MkGeԈ*j)+̂\sd .tiIrW>PdUFk?P$)oVSs{wjI=~$9'j`\:'aIX['fdՒ$My/~0Wd@"UhˣkHRz[fdtsܿn-IҔW5Be.s@+$g 3Tݵ>-߯%I/} V!|OtHR-2V9TF-IҴ7 >b8Ⱦ12X>zK?֒c՛N>rQ߳%Ij@~;uf_”vvv{Y IE3 bp1G35W>zs<$IMhk` VaZet/qV ICƪl=Ekv߷%IjBK^[̾yf hЍ<DŽ$եѿ 3\n[&4U<8*LXcޑ#BjTg&TӿsKԤr0E5DqϤp:տt ׻$IO}oDc0%+֞I IuiPUM-IR*|[!U{.֒(HR}ﲏgɰ/$IM8|jU`„|+Z}IS>}<0>ҿKԨ95wg *LMEk6? $FX ~(vN.IR*1|2X տhn@T̿#)W5eH..IR*zm 9g Va>"Z3 HR~/"2!]ۥ$I{&ߐ3L0azW~KR~"a @ n>-Z3 ҿKԤ=^oZ e $=)1g4T+$w3D0!7$թthwҿKԴv?M` `pњ::>ע> *s{ӿKԴ!ʧ%l$U]_/xISC>#~;G-$IM8,$0Xwi~KRjƨZhGҿKԴGfD)UwEkW_T䫞?U5_M]"aOB Fq$թbDG4]ˣ5uuIVOe ^*M_O%N/ˇ}BF\wluIX`,_ܒT.>`";$IMk61s0X$թ%;KgpEh,U/_IIvjݣG3(=_^&U(;k@# |}JR*񨞼/hTû(IҘ? VaLQk+Iu|jo$5md1X1|$բ%;˲e9/IR*(~$'4*A3/YIE[;+5 :N|IT?b <^~JRz3 bp2VU</IRK`l Vaup*IunG2^ۢe%IjJ~;G}:'4*̣l/VIʮ{ևdΊ$5Of_0_(zc*IuNzwD9>`.Z_4u >g /SIJ}D[}$䩪%IjJ#5b/cd `ˋT2kSQVg0C>$IM?L5U7̊=^cg0'bI/IRZ'Z0~yJRjKvWd05_EHԀzCS`Ҡ_V1K٧1LHԄoe_0 VaG)I><(=Co$5,ڇd s|h-)”zcQ mЍQoK$iY/Ͼa$%#*(W=2=_6 IҴ9淲}:0~;Z3 /JIʨsD {G14ދ5u$I}*0: R2jOd8O'$ik׳|*^$bWGc{I/$iܹ<ʇa [}һ/FI{rG04[#ޒn Iod05 Va W]oWԼfS` "'bWH4 0ʇ` [}/DIwo,>~g}~fJC$iZk*l}_4_/,MG$i&*lIN%iu}GĠ}ϥ{$I:Qm`6pњY~JҸj3Q>~PuoHW$i*YʾafW$bWEG/Go֒/H4xU`6Qh->h{I lM1H4e&*l7򓤱4 7}{G$IW}2XMkEk٫/>IGKft}[$IQozH W~I8~#*@ĽQ,{E$If_0 Var'I:E ́Fkfa$ITg_0 Va# W]~I|WQ}0POAH4U-6+&*lYɿ$i>[C^}s*sEH4E:,c >;_t4o,ͧejyV\0~$iZ*9zb 8W/8I?Z` 6!IҴ[&*#7_n4_xKD>jq7 Ib&*!rQ=2Ƭj?~UH4 f`^DO_l4->ʕ+X Ih-6B ;ab &R9ofA n<%O$I<*Z` /K$i]Ωv!IҤW>|C`OYFkߝ/4It>aǣuo$Mrft<\~I\>Qu>^)W]EۤeH4&*J)0h,H$ibZA7 2Xg)K6}DUeI&rj`l?ξ$isj VQ LA7ڇb;$IR!ٷ7Ԗ*<`?iQK6b+\sw1 LrI&92XgKK61ky LG翉H4zc e >闖$mjKv>>~?HTfDy2چZ2X3&Q'(7~HT\}mC- W^~YIҦTOd@ hEo%$ոi!Z2X闕$ml>6*oHTڇ9Z2X)J6>2'vJ7$-.f_P;ް_V"~;/eHT(UXW}闔$XŲWDĽG&?o($ձ_;v V!"7~II 60w}\ODR$IY+Ⱦv VaH$_8xNû/odHT_+j`"}һ/)Iz:'nD9>*Wk"IRj`"闔$=W~D^}LA7ڇbۊ$Iuuٷ3Ԏ*h-&hvQ>xm) QշDko,$աEDTe bJOޟAIsԿ#`<8ETVg_P+4K/'IzvSQUG$|ߦHTʇoȾV Vi'_N̊v&x,X7Ikj`^(rn6Q\}4l '忻HcdUsI$W},̉O{$)%KcU};/'IZ_es*bצHU}CxŁoH$okD95kyfHQȾV ViH$5EDrEq0/g}8=F:'a5 bJh,L$5COCkE]d$Iwc;Z1Xu/&Iͮs{"*8W.Vo3$o;V Vi/&IͭokB-D$I}_Umpeh(W>gЍ?N#IҘ*j`Fvv$<(7o5$be_P+4Z/&IͫsFTUwL{$Icivkj`F84bԨ~4ufyAxk$Iz7RԠf >t#7FkѶ7$g3 \Ue;=](Fw` IDATymfau bJ?@U_=(>8$[[e߶P+4Z̿$M}җFG@픏EۦH4/n}Bh6b4 n<%Ks$Im}BhݯIT=CG@h+:$y;eV Vi1ItTuG@핏ܴaԓ#IҜx+j`FIth(W]}L%Kx$I Va*f*i_0YAxK;$Is*0X V%G?8S>rӆ.G9`Fhb:xX ?#IҜd # Vi4UIŝ ` {>o?$mi0`F3X4h0UWEkvI(UaJJUo]05z}< H-`Fh٭\uu0]E I67UaJJ=8J{/̂ I6+UaJJG=fgS{_ IYU`Ut(3(jU(!I65UaJJڒ}4 IU`U9G@t?߈$Iڤ Va*f*is*Dz0FZUoE$mt0`F3X,_>iߋ$I Va*f*iS *:'n$I*0X V%mJog]V>~gv$Iҋf # Vi4UIQ>xm@D,H`Fh6E,D_LC$3X4}/E {GP*Z3 ߒ$Iz Va*f*E[]ܔ}\z|4=I`Fh^{fU<6}~"MI`Fh^g~=fU-g+IU`Ux(Wߚ}L:7}Igg # Vi4UIW(6RCQoL$d # Vi4UIUwDTe&8$I Va*f*Zck>TU~-Ig # Vi4UInp͑G|hn$I҆ Va*f*uWDUeMl9Mw$iC0`F3X8>BUwm{x$I0`F3X:!H` n:5I$UeJJZ_ߍ# 99]Pg # Vi4UIn/#XZ}{$U`U#"IOGI*0X Vf9#*(`>ߥ$I `FhR[(ܕ} 0φw-$53UaJJͭGc=}Sf # Vi4Ur}0&UQS;$aU`Uj`r-c>oUfe # Vi4Uy/- C9?^%IjP0`F3XU_ 0JԠ Va*f*5٭|cdCە$U`UjN >}PUZc$U`UjF1d9D߰$I `FhRY.>nA7!-K4U`Uz_G 54oY)`FhtWQu>jΩ%I Va*f*Mw>f%Z)`Fh>bmI4UaJJYGCG `ЍoH$Ma0`F3Xe/LmgqI0UaJJWwFTUo])`FhҔd(ܕ}0EyI'UaJJU&X܏yI(UaJJS_&X~"=^%I Va*f*MI[EuG S_`Fht[iQ7~o`)`FhWKTu Sdx`)`Fh7G S?I $Mx0`F3X&9`JUOۧI&8UaJJ[ˢzc)ֻSb `Fhֿ#i/_I&4UaJJY_(G 01I҄f # Vi4UiY媫}$I*0X VɫwG\yefI&,UaJJUkj?}t@ޗ^&I Va*f*MV>}lPleI&(UaJJSߊc}$I*0X V iv(1ΓQ3Idd # Vi4Ui2-dqW~&I Va*f*տb.R}ț$I*0X V7F sN;$i2X4T:'^1ϩs¿IO$vG1ϩ|hn&Io0`F3X[#^P̿LW$8UaJJu"T=P&Ii0`F3Xӳ( g$I5`FhRj>`TuQw6IR 3X4TfFGlU念I*0X Vz=t )MT Va*f*էbEc6/Ij*0X VԿ#HLw$(UaJJ}D Glrh,H$$UaJJhxỷΩ&II0`F3XG̙ۣ5u;$U`UJnѶ;L&-N*0X Vz?} Zm8IRr0`F3X*|MTf$IU`UkpݱG̛%]N*0X VG%*W+J$%f # Vi4U)d7E$IIU`U >['I2X44fog)>oug # Vi4Uiup{gI2X44ƖU E3f'Io0`F3XW?fxߥov1g # Vi4Ui<{&?s勵IƘ*0X V4?|h,H$)UaJJ_7F ? O4 Va*f*|9:Fњ:O4 Va*f*ocߑj{և$Ic`Fh<6 UWg1کZI7UaJJW#Jӓ$s0`F3XEF?P[պG%o{`Fh;z?'I Va*f*}җFZj*bI)UaJJs_™?01z~:O4Oػh Sjj{1Zb奭m_4Dƨ@BP FdH N_dpyソZ?rw7u*f*l#_e[FF~"GY$i2X Uj`UzW-ɾ`8">I,d Ԛ4s5*̾`m^4Ox}g`* V5Ui*nRm ciJf U0X V][[V]g`* V5Ui+uE- cݩ Jv3U0X V]}od߾0ފn4%I*TRkҮU{u cw) Jv#U0X VϷ~MPB*f*|櫲o]޵'F(I V`Z3XvoϾm^|˪$nPaJJ;Wqϕٷ-N?+$BPaJJ;^}@=;<5Jv2U0X Vٷ,Vf(I V`Z3Xvf߮PoeUF/U0X Vj~ig`* V5Uk[خߎ83DIf Ԛw^}ջjIg`* V5Ukٷ)=h%I;*TRksWx%I;*TRkҳ:#26l?#HLQ<B*f*={Ŧٷ(,~03EId Ԛ̵NzoW!V6/HlQB*f*=sξ=]-J#U0X Vy#x8l%Iϒ*TRk׻[A/Ugg`* V5UZWFZٷ&'5J!U0X Vj}[;5J!U0X Vyċl=}[;ihL$iB*f*{/ٷ$:#3GI2X Uj`Un{G}ٷ$߾.sGIR5U0X V|=ٷ#gjg`* V5U1G 5vvSq%?J=U0X V9Ⱦ: %I`* V5Ubp߿fߊ %I`* V5Uս}3iPD?Y$``Z3XU+46fX맧)I2X3X VUZ'l-̆~;$%B*f:׿[%&)I`* V5UյWE;ٷ ;l?(n\o:{{뎋GD  ,:3:#g>uAOuyPgϛ?]ѹ~Eݩ߰"ϟoĽQveOPKehy@gT V`Z3XU]}eqPO"ʩbMQqwѽ}Y0+~3Zb!G<L&ֲۢ}Eod}1[nrjF̌L(Iu`* V5Uղ5?E7+ѻ^?%?yυޢ=yk$o-r 54(=4`$5U0X VU:[`4(/{Έy)acԹjb^4hk]7G}M sGĠ} *YN*TRk]b7o=V>yw_kO>+~3ZK0uz&ֲ9]ѻ(n\ szl PWGnlT V`Z3XUj`8oz8M9G(MuA_Dbp^+*3/L*TRk["nⶋw19uқ1O3[W>3ѹϣwbp߿F;ٗ+(:9L*TRkS?Qٷciѹhh1P`5?[>j99K*TRkSkOɾfNŽ_f?:g1wƯ ?4<ޙ}-?cIR2X Uj`Uuyԁf-kE uV;ZGcўZg~t:xfߓ}wADs$*U0X VU~0vae(6eOJ4asl5Ox}t.<$[>e9=99Jj*TRkE{Gٷ3+lߞ0Z(iW;ڟ/ѻla*f4~y$%U0X VU:q]sRt}g4yes4[5*:O]og}Ӻk?/IRm2X Uj`UuhpٷPg;P= TUAtyG7;5N:d Ԛƽ֩oξ*D3?1H6E{E_uFx8js!FT V`Z3XոbYoGqeѽ:hLKFE{F{[4me@M ={?IҸg ԚƹQFZٷ0[o>gjr{aEmٷ90gA4B*fq̾qR94'>GAtV-(ٯ*6_#I*TRk&web+ۏGD#_#մ汯÷f,cuӟy$i3X Uj`UZ{oe^*V/6757kf\cO?HXg ԚƵⶋo/`o~jhLK5xqt.<$ܘ784B*fqy"E 򱻣wՒhrPsݫu/DOF/-}I V`Z3X8ggTy]sh= IDATrh4A3$ePaJj:l<}kClluY$M9[Wd#s!24B*fqjam ^+<'+'JVW7EÊ [$FPaJjMmd)Ql^7sͣ_|"ij.yUtNFz, R~#E.U0X V5NN[ H0x^<ҟK$ #%Ԗ/`w\"Ic*TRk"J>O듴kM oeâ,uO?H8e ԚƥQ/5o)` nQ?H&ܑ u?H8e ԚƥE};m73T%^{Dw`-ٯz@^+G,E%U0X V5. ؐ};3lmG?sHp?PcK9D%U0X V5N9(VfJ9ⶋ}o6UI-+:OOܛ̱oGcrI V`Z3X8Կ[ MehTir\xHSdTssG$i2X Uj`U#l?}+h_E?_Hsu {Letsؼ.9D!U0X V5u.}+Dcb^s$Lͣ_K#R`N9(DF>U0X V5ʾUش:Zb$n?~efQO?{Hg ԚF(xew[hIڟb/lwy+ӟ;$i3X Uj`U\oݱٷmFFȗ??HҬh|ᯢl> ̰!I*TRk570|mEDc~4mZQt_R>qg4B*fQ}OS>~7 6&IfZ(e`ll29CF6U0X V5ɾ}v: 4LW._T| I V`Z3X(<5"+;:g$9jy@/o0Z')BF2U0X V5u.ʾu'PuIZ| }]K8_?=BF2U0X V5rM1s+FcrgI݋kf;׌Q?WHҨe ԚF}@픭G{xgI'xw~yvR?OHe ԚFge6Pew[8"G, Icļ\?l?r򱻧2yBF)U0X V5R-?TmoЏ5'EW?HҘU0X V5Fۣ_I?Kf։oC~+;Sӿ IC*TRk7}hwՒhoy^4o/~|$i3X Uj`U\Ftٷ uϧ%IsWgB~ޔ\ IC*TRk:y-#s/}4&H?Kֲ1x#ӟ $ih3X Uj`U\qٷ bhwIRn#^ŭ~[Z4B*faU"U6a]4DM̋Ɉ~zwy $i3X Uj`U3Yqy풤ᬽwl?vҽ}4B*faQC뒤᯵ 1x.#MA$ ]PaJjk Rh$itj(n0- j_N`* V5U c݋ߟ}k(;O>C+M̋Ɉ~KgI V`Z3X06[Bq}K8{IJ`* V5U C`\s[j^ %I'd1غ1VDw͡^~*l.I*TRkʮ{oY~t/~_Y[#a`VoEOr4a[*U0X V]qٷ̘h|{9[٨{j`]qxW.J?gKg Ԛ2 61xhs$IY s E/[7FGgh-ygjI]PaJ*ɾ`F [c^~Ɩ$i.~/T +h/?xz }v$Rkʬ[v[F}ג$es5UŦ]; yKȒg`* V5Ue<%E7]Wѻj$ն߉跳ߑse(69\$i'2X Uj`U?߉~$)Ya cp߿Foӟ' KҨg ԚrAl?OrZaiO%vZ9[]hhL~$pPaJ*Etٗ?rۃ:Ԓ$ Y/eU0ʩ-QlZݵ򱻣H?OK4uA?-!Pvؼ.zFgh$))U0X VQç/})o=Ǽ2,-IҰYvFl +s!Z6?{M%IC*TRkeKvXqץעygMI҈e Ԛ޺c/{!?$Iڍk!Pvؼ.zFgh-~$APaJjl%տTcUIf~[ 1غ1VDCIld Ԛ˾yZ~v$i}eq;@e ->/}NP9QT V`Z3X\ֽ/yxNƪ$N}4m6ʩش:k'rA4~yyPT V`Z3X\Vqq%Ϫ{̒$m UvEy]/ΪZ6?'If ԚGٗ<|53$Ia?kFWыw)ѹϟNΓ$2X Uj`UsUӿ}3^OeIR` o#Ŧѽ^~p4~$i3X Uj`UsUg_}~0,IRj|cP)ۏGqe]; L6If$U0X V5'M̋/w^/geIjZ#!meRmQl^KjaO?I4kB*fue_Pѽ|",IRk(;S5`oX5F{ј;,&IҜe Ԛʾ;6,I}ƯF;SNmb^ƩO?sI*TRk{}ǧ%IRQV6FqE](+~3G~$i2X Uj`U]G K'11/,I>*2t$ik: ̌-GoZep%#IR2X Uj`UYʾO53$Iڵ[D}Fɠo΅#Z'l4~$B*f٬K*ۦ?<,IvΪwg+!UMv2+Dȗ_$I3d ԚfEZٗ8u3(?Kw٧ `'ؼ.zW-yj)$i3X Uj`UU{of_PM? Klb^yNKE/[Y0ZO %$i2X Uj`UU/ojw1`I4 -/_}fà֍߰"kG-I4sB*fjٗ75ҿhL~$IS?e9TNmb讝< I4B*f٨(8ls$IZke=T/Gß.$IJ`* V5UF ,&ʩy$inlU l_B$IOe Ԛf7>}iPvN$Izמ} +;VDw͡^~% I4U0X V5M̋rۃٗ6,s%I7w>@mS[ش:k'rA4:0< IF'U0X V5ӵN}$IʫU`f(6Y0ǿ.}_$xPaJj^Oٗ5ch,3+Irk}4Ubuc~8l~4&H$Ic*TRk銻.;cGn/J?Jᨻ rDƳ:ј;\$ U0X V5Mmd_n#ZcW$ U>)DiutNF{hu`{$IiPaJj&kmٗ4cg^I4o \}T4eg*뢷~itV- $I V`Z3XLֽCٗ4cwI]I45mG,0l +s!Z6?{K$=kPaJj&+,` vϻ$ikA}tUNmEw͡^~7gJ$TPaJjƚ'Ⱦ3eQ?e(Ivg_`SDiutNF{hVI`* V5UTfTYFS~֕$I#Ԣ=S *I4B*f{/gLϹ$i>)de 1غ1VDw͡:hL)I4'B*f12x8ls$I+~k C9%77=N u7J$e Ԛf}"qmD7s%IH[w\(b讝<$IC*TRk[ |/ϸ$i ZW [}`mQl^Kja$I V`Z3XLԽCٗ2c$IXG8A?[7FÊ94ZE{I$\PaJj&*4R` #H?Js;9w7>8D}$I"U0X VMmd_Y$IcYړO; xw]ݵ^ Ǽ"J$il3X Uj`U[{ٗ1c$I/.yDqe]; y+S$IB*fݩuқ/aF`-8ls$IWͣ_Bݠ֍߰"k1O{$If(U0X V;o:;`DXyV$ջ޵djŦ];3'H$i3X Uj`US=ٗ0#dϳ$-?ܖ}4ke(6UKrA4ye$I6U0X V5?#ٗ/#}寧g%I:堈}<E/[Y0ZGcb^k$I3X Uj`UZwf_ϲ$I[w#1غ1VDw͡^~!5]$ICe IDAT*TRkն4쌲d4}uYV$ҢbpP+DiutNF{hoI$FPaJjWm ~o9V$j}'n>. (8z_Y8WNK$i3X Uj`U"n ٗ-#~~$IնZ9%Mv2+D_%I`* V5UlN;l=W]%IvyQui cۿɹؼ.zFgh>I$i3X Uj`U;` ٗ-î,u[Ϯ$I[Eݖ}aEt.<$ZGcb9I$i3X Uj`U;aF!׿3gWI0n i/?x׳_$I V`Z3X:/Y]эGCU$iƚ#{>eCŦ]; y_$Ia`* V5UL/}% ]}|U$ikFQ eg*뢷~itV-~}~$I:U0X V3m"x6eI$$Iƶ>nskwIYho]~=$IF*U0X V3 -`8*I4k-3[n>rϋCh,/G$I V`Z3XՎ~f$IzO>z;nb_U l~k$IT V`Z3XՎֽٗ+Cl~'G8*I45xQOޟ}͠aEtS$IRm3X Uj`U;Z /W?n>J$e~ rjKVGD{X_k$I`* V5Uhf_ H4ayU$i+n0(Sn{0M_Y#_Z I$y2X Uj`U;Rsɫ/UT$IRF~4Tq Vu[4:Fk^$I.d Ԛv7R`uS̭A?lO2Zh,3~$I4dB*f}۳/SLqϩ$IV?>*DiutNNqc$I`* V5U=_݋ߟ}0dZ%*I4ߺ"3l<m_|jⷦ+$I4B*fOg_ ޯQ%IֲE/;`[4:N_Ǎy$I1`* V5U=_/SH?H?J$ s}4nPLoÊ94>$I1`* V5U=g1g_ XW9U$ik(>rjKVGwd|{4A="I$fB*fu}0D/*I4 u.5Tb]$+DW $Id UԚ΅d_ 3#H?Jٻ`2 LIJJ$ԡB &M4i.aj⤄-6^&Ɔ-o«","el/Hٟ眎k?d?+=_7ѽ7>zvMxznvw`U*2XU Vی?>J$ii|)IWl}Ʃ ͦdhÁ^ V"U`k$IfӺKSg'D_rzVn[_6g f**u̵b~$Iz^} ,;+W?9N=-?+U`U3XeG?OI$! N{]} l5]zzrpuŠ(@ V"U`yyS$I|b:lZ|z=«Uωm3X V:U_uH$IhÁ)Fuj{s%VNw;=Td2 $Iޡ/M`u]uwMxT;E `e**u3{)I&7~tE?Qדahq={xk=znvza Y`U*2XU VY_|o]ϦS$IOxUm !MGFx;l9m8J Td~$I nzϵw)@`_zm}=ڸw1X V:UW[I$)ws~tOUtzy?{TdՇE?MI$VOrz-'_ ٷ8Nza^{ V"U`Lo\Ӕ$IR`}t_>:UzrhÁ+=Td걻$I_}=kǩmU׽PTdAϭj4%I졯ߤ ?Su=G{tpG=ݾo^S_y`U*2XU Vy?,%IhߤY;.sM[ɖ3zrbDRRg3 }k$IRTQ;7)@~}5xNWUճld=u_XfJEJ*4td$IRPQlF}zՎhzpGeJEJ*4g)IgN= _|o]=qoݕz}S=޼ۿ7c @U`U3X噪ǷG?KI$ԫ~d4<鸞S=zx=9N]w=Tdtϯ몊~$I h|1(@Z+gomѥW/};lRRgO')I'B= 7{R^~BRRg yK$IR@cw + G{pnT7k XRRgӍpP$IR@ Eҫ뺪=fzzzzp~ª(U`U3X&_L$IR@^~ɭzՎ>9N=G1X V:Un$IZnmw(u=njx=zqU=8u}H`U*2XU Vm^u5$%Ir?Pp[7k}gTdޑ/~$I oQJ~;hM[ɖ3ц) ' 'U`U3X)^%Irn CXpG_OSznQ V"U` /< 9J$F;0U`U3X)k~$Ij}P V"U`Lo(9J$f~g**uI$ŠN 1U`U3Xk'IyY $g**uyUoG??I$5oN 9U`U3XMF?=I$535r3X V:՜k^$Ipc^~wJEJjN-I$ŠN 9U`U3Xix[$Ilz7'Tf4D?=I$5xoNU`U3XiOO$I 6`U*3XU Vsrvӓ$IR N}m `**u9Mo~z$Ija/ 9 V2U`5٣wD?=I$5Tv `U*2XU VsF;$Ij{`Td[g'Ixr `U*2XU Vg'I}OoNERRg㯉~v$Ij_f `U*2XU V~MN$I ;GoNERRghÁN$I Uv + 9JEJj>~v$Ij7ߛJEJj>O~v$Ij-gߛJEJj>ӯ>I$~of**u$IP7v3X V:|D?;I$5~of**uɬثg'IoNJEJj.C_$ITUU/`7U`U3Xͥˢ$I@ P0X V:\'b$IRCM6(JEJj.$IP~*(JEJj.$IP 7 RRgD?9I$5wߛU`U3Xe|ON$I 5įߛU`U3XerON$I ؿ 7 RRgt''I{`**uR$IRMŠMTd2{''If TdR ~r$Ij]?I?X`U*2XU VY''Iv~ LRRgGE?7I$5M% V"U`5ڟ~n$IjU&RRg㯉~n$Ij 70X V:<g!I$vz&RRgpM$I ?M% V"U`5E~n$Ijޑ?~o,a**uy.ps$IRC-{` U`U3Xcţ$I5e**uyLn:5I$' 5e**uyL~n$Ijك_ 5e**uyLOM$I ;& V"U`59o~j$Ij?~o,`U*2XU Vs^x@S$IRC-zN ,U`U3Xat$Ih6 52X V:FWE?5I$5P5N 0Td0tTS$IRU; 52X V:&7$I@cwߚsJEJj-~j$Ij[oM V"U`5E?5I$5oM V"U`5靗E?5I$5WߚsJEJj{7G?5I$5ߚsJEJj$I@[ 52X V:~j$IjW 52X V:G$IhroM V"U`5j3I$ų(5 IDATׄߚsJEJjt$I@MGߚsJEJj+~f$IjՇߛJEJj$IP71X V:}䇢$IjM V"U`zG$I$FWߛsJEJjyi3$IRC.p 0Tdv_OG?3I$5ߛsJEJjOxU3$IRC.{`.U`U3X)$IP~oe**u78W$IjM V"U`g&I}ߛsJEJj ?L$I 5Z{`.U`U3X$IP ~oe**u7XTdv+gF?3I$5? 9e**u7'$Ilx7' V"U`&7$I`K?~s,`U*2XU VorL$I 6`YRRg}O~f$Ij57' V"U`$I`O9e**uݷ'nI$M 9e**u7G$Ilze7' V"U`$I`o]~s,`U*2XU Vo|G$Ilm7' V"U`W~f$Ij;ߜ2X V:]"I$`YRRg}K?$IdUU/;X`U*2XU Vo?~f$Ij?~w,a**u7Zg&I#w'RRg}$IpߝKJEJj ys3$IRO` U`U3Xg$Ip~w,a**u7F?3I$5ܷߝKJEJj g&I]` U`U3Xi~f$IjUߝKJEJj N/I$&7~w,a**u?碟$InrgN% V"U`g&IuE Tdv_OF?3I$5-w'RRg}oO V"U`5#I$v}ѷ'nRRg?~j$Ijƕ'nRRg7D?5I$oO V"U`5i$IBoO V"U`5 ?$IBoO V"U`5G?5I$=v3X V:zG8I$woO V"U`5G?5I$A~,2X V:$VU׳is$IR `U`U3Xcׯ$IR`TdQ}&I`Td1{d[s$IR g `U*2XU VwCs$IR .p `U*2XU VuEs$IR 6Xd**uyLo I$&[ׅߞ V"U`5ɖOF?7I$/ߞ V"U`5]V$Iݯz`Td1rus$IR&}OU`U3XctF?7I$TߟRRgwD?7I$T ? V2U`5/M$I-58'Tf18ע$IZj'TfJ$)G ? V2U`51/~n$Ijɗ?~JeJjPs$IRKM,0X V:DVSU$IBo? V"U`5j#I$'TfR=qo$IRK-~^ $g**uZ$IRK}Y $g**uL_$IR~%3X V:\G?9I$7ߟ@rRRgd'$IZjtO 9U`U3XecON$I-? V"U`5ƕON$I-5ٺ.3X V:\F{O$IRKR $g**u ?ߢ$IZzH`U*2XU Vs|7$Ij:V~JEJj.^$Ib#_~JEJj.,I$R $f**uV??I$ņgA $f**uԓa$IRK.` $f**uT;~v$IjLJߟ@bRRg[$IZjzE'Td3UN$I-?+Eߟ@bRRgs$IZ? V"U`5ɍD?;I$X~IJEJj>~v$Ij_L $e**u.y$IR zc $e**u {[$IR.zo $e**u g'Io:22X V:|':I$&|62X V:|zGx$IR;u] $e**u g'Iv<9JEJjNh!I$^ A V"U`5걻$IZ̿ A V"U`5ٷ~z$Ij~ JEJjNm룟$IZlxoP !U`U3XiriOO$I-6ڸ*2X V:՜W$IbOA V"U`5~z$Ij]Wߠ@BRRgD?=I$;oP !U`U3XiW$Ifqr;H`U*2XU Vs'Icw(Td;%OO$I-78uw(Td&9u]UO$I-6<w(TdU~~$IjUߠ@2RRg[$IZlOߠ@2RRg+$IZloP U`U3Xk򕳢$IZZx$1X V:ռƛ~~$Ij?~JEJj^4I$3w({q;U/Qctm;hl2Z&&1S%Q-MsTcLL,\D. B@JD ʊ;sΐCY9>ߙ5R`^ߜ~~$Iq_CJE:z>_O$I3nۯP"R`^ݣ^~~$IqïCJE:zuzzI$iƍo0~1X VUuuz'(I6ٲ1~1X VUuuk~$I,KCJJE:պM6$IҌ T`U*2XUm|gOP$I3wߡ@% V"UUj݆_h J$i??w(P U`UUgZkOP$I3nx;Td3X[?M?AI$͸7?CJJE:պ>'(I7|u*a* V=OP$I3y T`U*2XU֭s3OP$I:<9~0X VUu[j:P$I3{/oQ`JE:UP$I3wkw(PU`UUg_J?CI$͸Eߡ@ V"UU*o~$IqC JE:UH?CI$͸w(PU`UUgJ?CI$͸'ߏߡ@ V"UU*uoL?CI$ͺ.- ,8U`UUgJ/O?CI$- ,8U`UUgJ_H?CI$- ,8U`UUgOI?EI$͸Ef* V٦lI?EI$͸Oߡ3X VUul37OQ$I3n|;XpR`mƷ|.%I4ߡ3X VUul3(IY4Oߢ3X VUul3}(I@c_Ef* V٦m(I@3 ~ `U*2XUMW$I [X`R`mz~)J$)ړ( V"UU*t4M9J$iƍ!`U*2XU恻Q$I3Y;~ `U*2XUI?GI$- ,(U`UUgʃF7O?GI$~W( V"UU*~(I@uoߢ2X VUu-T%IMCR`t$IB /? ~s`U*2XU&N?WI$ݸ>~s`U*2XUFם~$I 5= !U`UUg\s$IRPJߤ1X VUu7$IuM U`UUg~WU$Iga&Td3Xegu>iOV$II9c* Vw$IBn<;~s`U*2XU+߽*d%IjrM{3R`]1Ɖ'+ITti'oR`JE:Uv ~$I =%#R`]?'+I`oߤ1X VUu1/N?YI$^uX&Td3Xet4g+IP[>Ia* VUO~$I ܷ9~s`U*2XUƛ.K?[I$M U`UUgʮ}$IR'^I9a* VU :l%I_oR`NJE:UvUI?[I$~M U`UUgʮ$IRWoR`NJE:UvLӕ$IR5`U*2XU;&w^~$I ࿈ߤ0X VUu$IN~U&Td3Xew .y_J$)woR`JE:UvG7$I=9~s`U*2XU;G0t%Ilr77)0 V"UU*N'$IRQoh7U`UUgl%|%I{h9U`UUgtnJ$)XoR V"UU*kx!+I`KI3X VUu9oO?_I$ݸ>~-g* V]}J$)dM Td3Xewu>3iӤ$IRMӥߥ@JE:UD$Iu?+h1U`UUgʞ',I`sI3X VUuWN?aI$~M Td3XeO /OX$IM Td3XeON|e K$)XoR V"UU*{sOX$I:?#~-e* VSMwkK$)XWoR V"UU*{j3$IRߤ@KJE:UL?cI$}h)U`UUgʞ\7g,I`5~-e* VSS/%Il؝.yl.Z`U*2XUz~K$)\K2X VUuՏNGS$IRK1X VUu,]J?eI$^qP&Z`U*2XUF7K?eI$o ~-d* VYK?eI$kI2X VUu,7$Iu~F.Z`U*2XUǼ8%IwRe V"UU*v\LF,I`] Td3XeL)%IlOoRe V"UU*etús$IR_ߤ@JE:U5,Idtiw)"R`?u,Ipݣ^K1X VUu,{$I7~-b* VY6k;'-I`ëߥ@{JE:Uo$Io0~-b* VYNNI?iI$k#~-b* VYNߓ~Ғ$I 9Yh U`UUgr;'-IpOF.Z`U*2XU:?7%InwR% V"UU*˭8%Ilth U`UUgroCYK$)7)R`6$IR`R V"UU*mp;Z$IG(~-`* VYn_~֒$I ?-hU`UUgr$IRߥ@ JE:UVB]-I`[/ߤ@ JE:UVKO[$I7)R`0O[$I:l. V"UU*+?I?mI$[3X VUu/K?mI$\73X VUuON&%Ilti3X VUuǷ$IMv& V"UU*+e$IRxw)d* VY)+I?oI$O. V"UU*+[[$IE. V"UU*+{/$I9.~AR`=8&$IRKU`UUgJsSK$)ٰ;]Z] JE:UV膳O\$IG0~!R`4'.IpKU`UUgJ$IRᆵ1X VUu~$I 7] JE:UVUӦ3$IRwa6f`U*2XUrK$)\R `U*2XU҆_hK$)\R `U*2XUyK$)w)`* VYi_~$I 7] JE:UVONIK$)Xsw)0{R`Y{kK$)\gR` V"UU*0q}K$)\K3X VUu.IpK3X VUuB-%InOR` V"UU*Y/O]$I&w;~3f* VիMwkK$)d<]U`UUgʬo2%I{>!U`UUgʬ rtK$)\?ߥ JE:Uf?I?wI$]s\.f`U*2XU2+ݏ4%InR` V"UU*3^d~$IJ6N<.a* V=7$IuzA.f`U*2XU2Ko~$I ?U`UUg, $IRᆵU`UUg,N}uK$)Kw)0#R`Y|O^$IΏw)0#R`Yk:[^$I:?/~3`* V^$Iz&~3`* V?~$I 7l] ̀Td3XeQK$)xU`UUgʬuwg/Ip?ߥ JE:U"x~$I 99XYR`7$IN}u.VTd3X%ati/IpKR`JE:U'%In|ӹXaR`ɯJ?}I$kKf* VIӗ$IR m U`UUgJJ_$Izv.VTd3X%e|_$I_] U`UUgJ_$IF7ߥ 2X VUux}K$)\w) V"UU*)#~1%IԂ:?3~+`U*2XUzմnM$I ;7)2 V"UU*IM?I$\X!R`#ҟ$InXKb* VI' Ip{Kb* VI' ItM3m U`UUgJԚNN3$IRމߦ3X VUuMg IpK`* VI]g IpOߥ 0X VUug Ip-w) V"UU*iݏ4H$)]L;>5~`U*2XUҊd-~{`U*2XUF#N$IjA_M=`* ViիM!IpߓMg* Viӟ$InXK=`* ViᆵC$IᚭR`JE:Uڪ־C$If9MR`w$IR [MR`ZjK"$I 7ߦ1X VUuxOD$IL.vTd3X֦͆?I$kKd* ViY?I$Ρώߦn0X VUuYȽӟ$IZPWoS`7JE:UZmiӻ/H$)oS`JE:Ung"IpR`7JE:Unam3$IR恻w) V"UU*m?kg"IoS`JE:Uڮ{D$I-woS`JE:UZoiӻ/H$))k V"UU*`"Ip[/ߥ.2X VUũᆵOE$I?m U`UUg<蟵oS$IR  R`y=r"I?) V"UU*saiӻ/H$)) V"UU*b"Ip.ߥ.0X VUűᆵE$IoS`'JE:UE}ӟ$IZPȽ) V"UU*b0A$I) V"UU*sc XI$ߦ1X VUu̓ӟ$I{U.vTd3Xe 7M2$I .yl6vTd3Xe׽1H$u~Q6vTd3Xet'#IߦN0X VUu̕իMGF$IFM3X VUư?I$ym.vTd3Xe 80H$)x8]m Td3XeN{M$IR ~)R`y99F$I-hp_oS` V"UU*#IpOߥJE:Uҟ$IM~UȽ~_ IDAT`UUg<\#ItM3m < U`UUg<#I.Lߦ0X VUụA%IxR`ylݔ|$In|yxR`y5a]$IRRQJE:Uw?I$ϋߦvJE:UU_O>$IjA3M0X VUu̫26'$IpëߦvJE:U䞛ҟ$I7]K0X VUu̳u?!I$kO<6~`U*2XU2# I$uza6Td3XeuY$IR GxR`0I$)oSg* Vw;MF$I 7w) V"UU*nӟ$IҍӥߦJE:U]?MF$IjAߦJE:U]ؗ?#I$ߦJE:UޚMnS$IRuߦ@`U*2XU&NJ$I 7ٲ1~c* VYë?$IiM0X VUu,?%I$I5~c.;+N 阮uKucmKƮڊuLj;ڎ6vhInI"% FB 4!*) V`!p;k'T:zg^#:I2JY:UAF?%I$P7ߦJY:Uʧ/9I$)b*e V[?$I\w)0R`i1yFs$IRu)MR`i{+$I y Mo2X VUuLΙω~N$I*GO Mo2X VUuL;$I}&U)`UUg42II$)?ͭ<"6 Vo`UUg4_{J$IRu}nm Jߞ`il>!II$z^~ҷg3XetR;~V$I noS`U VUuL=D?+I$7Oߥ V6=~V$InOsog*e V6y$IRu/g*e V69YI$gm 3X VUuL3E?-I$7])`U2XU2%I{~@ V,UU*h󢟖$I ?~@ V,UU*ӨOK$Il)T`U2XU2>7iI$:6JY:Uʧ/yI$)?@ V,UU*jk$Ik#oSe3XeZ {S$IRu}nm 2X VUuL板$IT@e*e VVӟ$IT@On MZR`i'&IƷ*.jJY:Up'&IF4woSe3Xe>9I$ _~@ V,UU*ӬOL$I_ߦP%U)`UUg49&(I$)͗ߦP%U)`UUgʴus3$IRpߥP%U)`UUgʴ~g&Ic*e Vv+4I$wvm 1X VUuL_~f$I*GO M:R`7(A7I$)їvߦPU)`UUgJ F~j$I =V~@U V,UU*5:;I$tm U1X VUuԠwE?5I$P~@U V,UU*5OM$I4aSm U1X VUuTaSS۹'I$)7ߦPU)`UUgJ-F@s$IRtQ9&6jJY:Uj1$I E)T`U2XUR/~n$I*'ߦP U)`UUgJ-:pJm$IWߦP U)`UUgJM{$I\w)T`U2XURg$IT@3~@ V,UU*5/$I M R`4 I$;M R`)N$Ij`*e V=N$I :inQ)L=U)`UUgJmן$IT@ݷ\m S`U2XUR{8I$zW.6g*e VM~v$I*.M`JY:U~z$I n|oSvR`|]ӓ$IRtm:oe3XFgD?=I$Pe)L5U)`UUgJz~Eӓ$IR >e3XF3$IT@/\~T3X VUuԪ}'I7#oSZR`Z]$IT@ M`jJY:Ujտ'IOoSZR`Z54I$7=6e*e VUg3SjOP$I|66e*e V[$Ikyߦ0 V,UU*5yG$IR5fm S`U2XUR< J$;foSJR`u'(I}C)L%U)`UUg\GѰ %I\ܗV1X VUun룟$I aIm S`U2XUR'΋~$I* M`JY:Ujg(Ixam S`U2XURύ~$I*)LU)`UUgJV>5}OQ$Iѵm}f} `U2XUSD?EI$Pe3Xuk$I cUm S`U2XUSRw%IT@`m S`U2XUSRo$)J$4e3X~$I* M`jJY:Uxˣ$I wߦ05 V,UU*<~$I* oSR`\(Ie3Xo:i)OR$IѵY{l} `U2XU·$%IT@旄ߦ0 V,UU*|󣟤$I e3Xo]')I}~{m S`U2XU·t7b*e V{usS$IR [m `U2XU6OU$I43)LU)`UUg [}~$I*v:k O`bJY:U޺oOU$I\)L U)`UUg #S0J$95>Ia*e V}U$I4ҵ)L U)`UUg `U$I%ԟKs O`"JY:Uxlz~Es$IR!u)LU)`UUg MD?WI$R~D0X VUuصd%IT@Û~D0X VUu؍>'+Ij~D0X VUuyC$IR!uxv} 3X VUu5F$IR!.=1>JY:Ux:kIG?[I$`9)`U2XU3>g+Ig*e V~g+I ܩO OhR`ޕl%ITH_~@ V,UU*<>ݷ|$IR!yC} E3X VUu8:*\ӕ$IRn*>JY:UxFwF?]I$PZ[e*e V|+IBnX~@ V,UU*<~K[ӕ$IR!e*e Vǣ$I igK} 2X VUuĴ|%IT@ߦP,U)`UUg Ohl$IR!uxv} E2X VUu=%J$z2>"JY:Uxb'D?_I$ߧP$U)`UUg OLg)',I߱'>"JY:Uxw~’$I*v|74EߧPU)`UUg Opϖ',IBj,>JY:Ux'E?aI$ີ)`U2XUx|$IR!|]} 1X VUu$,JiЍ~ƒ$I*AЗn7*`U2XU“3g,IBnz~} E1X VUu v%ITH:>JY:Uxrz*K$FfS(e3X'sqX$IvMs+QR`v@S$IR!u7bJY:UxF?)K$zW.>bJY:Ux׮~ʒ$I*?n OR`撗F?eI$R{ߗS(e3X'),IBc7*`U2XU1,IB]{)`U2XU1ܳ%9K$xK} E0X VUupxgO~Β$I*~@ V,UU*ݷbs$IR)yߨ`U2XUa2(A7IK$wpR`e~Ғ$I*a/ͽoTe*e Vu\$IRA5ߨ`U2XU>xW$IR!>9>PR`-WE?kI$0>PR`+$I ޛV~@U)`UUg WsK$I {Oߨ`U2XUyԶO[$IԟJY:U8%ITHÛ~@U)`UUg pϖ-IBj#>0R`IO[$I=oTa*e Vn<>iK$zW&FR`̢-IB~"JY:U~ޒ$I*[Sa*e Va~ v%ITP3~3X VUu0?z*yK$z7*,8U)`UUg sq[$I5e3X>xW$IR!%>g*e Van*K$:ߨ V,UU*̟D?qI$ToTXPR`OsK$I joTXPR`Og3Sj\$I4e3X5g.IRj9oTX0R`pϖg.IjoTX0R`Wg.I|7*,U)`UUg g.Ie3Xy6(A7K$Y;e3X7mWS$IRA5[^~0X VUu0Ή~$I*GO Q`AJY:U^%ITP>~0X VUu0:g%ITR~;iw*;U)`UUg }.Ij.zq `U2XUrUs$IRAw̄ߨ0 V,UU*,D?wI$K;oTwR`F.It}I}2X VUu0:kMG?yI$Tii `U2XU߽/K$~} 0oV>5xR`pϖ'/IoTånqj.K3io6D V,UU*,IO^$ILs SΚcRiio_qo:8NFN `*e Vat7%ITXݷb V޶ixi|`oJ1}:7(c IDATXR`̢g/I/T[zק) 'hg3`U2XUݶ+K$F Qǩec&ͦhgo$e3X5uv$IRAinՑw*0:kIͦ}Eْw~"7 V,UU*,e~$I*T`ʬ:*u7,Im 󼟎wA,U)`UUg sq^$I_ߩd[zק) RJY:UXxwE?}I$ߨdSRLMmTjE/ E0U)`UUg otUO_$I8sEߩ@y:Nͦ}EْIy`U2XU_{Jӗ$IRakaIm[ק7Ԏ${{%e3Xl>!K$Wu ,κũٺ, >vzߙҠ3X VUu:k'ISYl~II};Pׅ'e3XE?I$T0, S'lZW-i|`oJmj߃`R`bE$IJ Li4M#bJY:Uџ=)K$~} 7p me*e V!ΡB$IzXS`:2u7,Im`4ڿ3Q?lxe*e V!`$I*5~[RL}Cۑ/ O0U)`UUg qz*#@$Iu;&Yg&'Ѿگꆟ4 V,UU*u\G$IJk9] afQn<>H=[ޔ6[>=XR`b1 Ij.;ݰ$-OhΔF=}?ve*e V!薫?$ITXTY85[47K3X VUu)$I*,_PΚgfԿƩʩitۮ_3X VUu|Bǀ$IJkؤ7~ bfQn<>H=[ޔ6[9So1G,U)`UUg :kMGH$^~ݰ$-OhΔߴ9! V,UU*߽/@$I5Tx:f1FfS۽767\`U2XUB/($IRa;Mg3Riio_7_ZM3X VUu?{RG$IJkOs>-VCf%צ-i|`oJ8[4M@܁2X VUuI$XsoߪThyw'7Ji4LZcXR` 0(A7@$I5*Snqj.K3io6ݯG5i?c`R`0mWǁ$I kg t9&5igKjr`3X VUuP?$ITZ~[[ 5(u7,I8u|`oJ8[/V; 2X VUuPe8$IR5OU ~"-O=iD%jn@R`9I$ࣧߪnqj.K3io6E%=bs3fd*e VwE$H$;X5Ǥf߾" lIFm%=V?=`U2XUB9F\ IRg3oUȪRwÒ۶< o MGK%=:k[1X VUuPD$H$[Y8.=1 vO;S6_GIi?d*e V?$IT`ߪqjuYI}|-'iAG U)`UUg 8 <$IkߢoUSiio_{G2X VUuP?$ITZm{O߈UxJ KRo4ؽ>oT#=YſSJY:U(ӗD,H$z~ Cޥ'LiЍH*9:`U2XUBY'E,H$(VQgf1FfS۹'"i2 V,UU*I$X{m*>:5igK4u@R` 3_"IZ쟊W̢CLS?4Nm_ISYw/ĿyJY:U(] $I*ޕ U&Ugl];=H qxg V,UU*gI$oUIYl~II};o 2X VUuPeh$IRG߫EYlZW-i|`oJmU=?+c*e V<7xG$I ֟ W¬:*u7,Im`4ڿ3Q?+IߣAU)`UUg ej+A$I_ߪ nqj.K3ikRtnz~ V,UU*io6A$I6oUY{lj6-MO>stj.|Ag V,UU*)$I*\{IYƩW-i|`oJm͋y?wc*e VL?$ITh4`:2u7,Im`4ڿ3Q?+I X`U2XUBIj$I*{t-Ne}S$\&JY:U(}$I*ߪai6-MON};Չk.+JY:U(ӗDDH$FY}t TffQn<>H=[ޔ6IP%a1X VUuPEDH$К-/ W)ݰ$-OhΔD$Mh%/\#e3Xr$Iwk{uSuYI}mC7W`U2XUBf4FLH$w|:^&Rg3Riio_7_CҔlO}2X VUuPm?&$ITb8uN*PS u7=??w׿ kCJY:U(`$I*ޥ'߫@AV޶i{}ߙҰ$f?#c*e Vl^1!IB^~ {+`iR0 I5fg& V,UU*1!IB;WE߫yFj6-M+S_MHc៣2X VUuPۣ?*$ITh7x f3RwÒ{kpϖ4>7v5$='`U2XUBF"B$Iֻ5*$<"u7 I$֏߫0f1FfSZ4Q5o2X VUu0z$I*Q?uV~49&5igKjR%ik.|A; V,UU*L?q!Ik&ΪRwÒ۶< o MG2_ 38R`&G]$I*sU(]gԻ4ؽ>LiЍ%$UQw e3X17!IBl %Լ7Ims/%ںj 2X VUu09׼!#C$I9oVY}n}EْF2]R2X VUu09=#C$I׻oVwJ KRo4ؽ>o1vrIң ?`U2XUY I$w߬pu-NeihΔ_Kgݷl'2X VUu0Ywcdž$I ܓV~Yl~II}~+I?`U2XUd^~dž$I Siio_{ѿ$S&JY:U,adž$I ׇ߬VuOm[ק74E2Zc^;߯p;Vpx,ږvPkXgNui'ۑi2Giw6 DbkDE" 7!\_v]~~c;`~W1HqB*Y3XU3lPa/ Y%I$Ij/'u.L+Ѷ) _>?*5UfM-HEwIU$IMJݓߝNh=i/}3XUf*կD?TX~J$I!?O kx"0> S\PbJ V5? t*I$Ij@wMU޺Eiyem۸/{K>k`J VɚT7o Y%I$I|]p/uIJvW\d9f %d`U_{T*}VI$IRzԿSiu}*Zۣ`_٧ V`JlfsU$ITwOޖLפ-)EWW2Қ#PqB*Y3X*lx7$I$)ŻΪ}Soݢ4ؼ2mLiԏ @ZSF*.U(1X%kR=}寢*h?$IA24ش{~++)Kg %d`UgZ@U$I4KNşJS_= ១ `J VɚTӦvIE' ߭$I;#bÁix4޾% /̿k*6U(1X%kR}uI@,f$I$:Mu`4ڶ1a/k%LDY V`Jmp'*S [%I$IG|4xdT sx^g %d`Uoݵ~B[%I$)KJR_`^3XB*Y3X[פT6U$IizYo4qModo03ZB*Y3Xۣ*xU$IZ{Soݢ4ؼ2mLi؋3~lg %d`Uw3COg/߭$ITIݵ S4ں>'@-9 V`J*~J$IRj/+uWL[J3E}yg3XUf*ջαE?#T΋VI$IlӻΪ}S܏f[R*_1Fw^y V`J5o?PenjU$I*P{Soݢ4ؼ2m ;?*5U x>/^*I$I]{>va_:s,Stzn9;&PpPbJ V7O 7U$IWSÁixT(6U(1X%kRs'U$IR5k/'u.L+Ѷ) :_aGB*Y3XS{룟j`tᷫ$IK_';/NSz$ @~(8U(1X%kR*/Y:hU$I>Rw4qMoD*5UY o9+Y''v$I4G--uVzimcJA S3wI} V`Jͪ'j`iE*I$i2k˾7Nr@_*5UYuNxG@ v*I$^wԿt:OEϫu73XUf*5Li؋~Z@$IxdԿix˙xr[wb3XUf*5}ߌ~Zy-v$I[k7-J+hƔF S5K V`JkiE@ U$Iʵ}RwԿt:$A;+g.U U(1X%kR:tRW߯$IRk/;uWj+Zۣ ̋♇o1U U(1X%kRj/{]@Mt׾?~$IsRÁix4޾e;3g %d`UjfwG?/oWI$-5uVzimcJ~P*5U SX IDATo:5yK$ITIݵ S4ں>'OzJsE d %d`Ujf?Pc~J$IUd]_Sy8tmu@PbJ Vf9v_$IsRÁix4޾%>joo=g %d`UjhwME'߷9~$IŻΪ}Soݢ4ؼ2mLi؋>ixOB*Y3X;_~bb^~J$IsQ{>va_:F[קD**5U .?$&z_/$I4KJRCѧ6@~#B*Y3X[wD?1p$I=uVz~4 o\۷TGOߍ`J VɚK_(EԚ#$I7޺EiyemۘҰ}FfsQ d %d`Ujvo~f_%I\Fw_ގsw֟ߕ@PbJ Vf7g\U$I~s>}"0Kݵ+U V`JͮP _%I׿'2]] d %d`Ujvo~fg~9$If\vpy ,u>kw**5UM-HE_w7$I43XYjw**5UP/_%I7>!?~WB*Y3X_OE?5xڇ:$IF[G_x/Fߕ@PbJ V~jޙ~J$ImWFB~,TE2XUf*eA{4G?7SoXI$eᛣOcfa]7**5U)_PEZ[ +I+/4`\~S"B*Y3Xhp 5 a%IwEoGY ,R`J VɚG3>P#+߰$IʸŻTg10ܲ.T52XUf*Q~n-7$I}諣ObfixIw**5U)'E?9Hӿ~J$):G)`VߕHPbJ V|~'_V$Iy9m0Կtq]d %d`Uʧ~rѶ+oXI$YERÁw**5U):Ǽ5Nqj/{]+I[} 0K4TE2XUf*e.>P#s>J$)~"`k~'TE2XUf* jdV$I5ѧ09w**5U)_g:tR됟 c%IWO7ߕHPbJ Vj{XI$h3Yj/;TE2XUf*e?ҨP#Nc%IU}0ajM-+U V`J5):XI$`fh=~SBB*Y3XkiE@tOzW+I|*zOG7**5U)za@ t+IL7wS]ƇUf*WצT5R<-$IRYm=/T2XUf*;js[XI$5αEJU(U(1X%kR B@/c%I7` +U V`Jy_F??XI$5}0KR`J VɚgP7EG|-+If׿F_RJU(U(1X%kRM-HEk{@7J$ 6&`}0T2XUf*_~w. c%I[ERww**5U)]@݌}koYI$5}^f_ +U V`J9O5[($IRs+7`K+U V`J7{Jv3@[V$IljFSkjAmd %d`Uʻ=߈~~+3$IRj/{] ,O~WbB*Y3Xnpš5=oYI$5αEJU,U(1X%kRu{54qM-+I]0`Fw^~WbB*Y3Xtƣ)O$IUO]fixJU,U(1X%kPC5~J$Y .;8` +U V`J\s\S@ ;1$IR1ş +U V`JgO5TKŻ߳$IjN;.>s9 +U V`JjO5=$IᛣO\fva]e %d`ULSF?G?~J$9'.oߕXPbJ V%4*ZYI$տᯍ>oo-U V`Jw5=]$I_GVQᷥ**5UI3uVPS?~J$ѧ-T +U V`JԂTG?IPC5KM+IZ׿Sѧ-4~R`J Vɚ7' ?$IRg-4R`J Vɚ׿O55{V$IntEg-4R`J Vɚ97$jxԚZ~J$-`8~J$ZuyK t/T3XUf*~ nY~J$Zg*>**5UI/T*nM{߶$INGD_L@~[B*Y3XBu>O [($IRuyQ %T3XUf*Tx Fok%ITFL趯ߖxPbJ V%7\PwAjV$Imu 96T3XUf*;E?W4@o[I$¿>M~_B*Y3Xb|W+`tV$I/Di R`J VɚԂT1) 3U V`JM0~J$irw4K{L(U(1X%kf[=OM2W߹$ILœۢ/L&iOŻߙQPbJ V%Ͷ_~hy߹$I}#}Z0aG~gfB*Y3X4zE?e4k\I$>?;hѷ 3U V`Jm寏~h1o u%I4}>` 3U V`JDGo~hUG߹$I]Go>+޹ 3U V`JDk~hhjM~J$^OI [S5`J VɚI; ;o]I$z_s9>goM,U(1X%k&QR1~hߺ$Izy uZ9 [5 T2XUf*iR)Iiqj[W$I/]Rz$`\k~B*Y3X4W@K1֕$IKߌ>#ÛN 5U V`JTݵ 4x;̘$IRH̝}kB*Y3X4K^x@ݓ~J$7wS [S5`J VɚI6g [W$I/R OH@gվj*5UIlâ5h+'#sdM4U(1X%k&̟j0{W$I]G̑޺?7U V`JtV@SEo^I$={;/#ff %d`Uě#~+yy%IcҨ}.0GfS5`J VɚhtDž UM y%ITw># 7U V`J~"yzgW$I冷}&0GFw]~oB*Y3X4uyK@~J$:HEoG\utͩf %d`UҜ4 ;~hα߽$IYD̡W2T3XUf*itj@ 96$I^9ܿ 9U V`Jz_'%{߽$IٷxT>+EK^wB*Y3X4W>z~J$^wE̡≻oN CߜyPbJ V%e͟~hI.$Iʹ߸@s 84T3XUf*i.]po~J$Z縷E̱Y~wB*Y3X42 ɊqW$)W,cc~wB*Y3X4׍]p>~J$oG̥p0T3XUf*i_8ގ^W+IS~= `~wB*Y3X4uNxGS@ }%IrjiE rfݩd %d`UҜxTt~hcw.$IR-5;>cOߞPbJ V%Go% ݵ o_Iy=oO5 U(1X%k~Ko_IpJ5$IRSv~<l^~{!B*Y3X4_'L$IRkFsy; ?Ր V`Jf~U*(njM~K$5>'~=TC2XUf*i>P" IDAT?p]@&zgI+IԴF^}0:hS `J VɚlpgL)$IM}/Tg`-*5UIYwG?{dd%I%dxө*5UIA{4D?}dbt%7$IRZ[*ny<_?oP5'U(1X%k]_~H縷$Iu{:QߠjPPbJ V%w ?g$IuotDžgu7*5UI]糿(uWw$IR]ks;o*P<T `J Vɚ~co`I6sy4z^ e %d`URD>a7t,ITD_ṣw*5UIN ._~K$խ>gݵ P5,U(1X%k"j/}UJa@Fᷰ$IR3y^Oe %d`URT{7E?d`I^Ɣq <*y(U3XUf*)ק@2S<}jM~ K$աˢ7P50U(1X%k' y-,ITwOŎO7ಃoQ5/U(1X%kš%GA23~ԚZK$Uޙ}{ߢj`PbJ V%E6g N[X$ʍ:d @ E V`JnQ3@eu{X$uOs 3ߢjhPbJ V%E>) uaI*6ں>T ᷨ*5UIэ.) CoH$IR% S+ߣjhPbJ V%E7LuO@=,ITמ}{ߣjhPbJ V%E=O!?p߲*Ikڔ ߤjhPbJ V%xTt~TwobI 4 SߣjpPbJ V%U_~UI"GO3 B*Y3XTz~49 c5~K$E_'}Mg %d`URj!uM,IԂ4~dkI@B*Y3XTo~XĒ$Iuѧqj/ye]g %d`URUlZ$}obIF6Fb?|sMg %d`URU'uO~O],I4uO0 ;1.U3XUf*2gJv@ԚZK$S{}ww*5UIUjt"w$I|=ѧ9vT `J Vɚ*?E27~Z[m,I4׍]}zmIoS5~K$eS}rP{ MAPbJ V%UcwD?dxuOƒ$Ish l<26UB*Y3XTWF?~26$Ik~'"za} 2XUf*juO~Oh?K%I&O-*2`J Vɚ5G*z;GH%I&XwFXTD2`J Vɚ*6RR{Oǒ$IoWR}L2XUf*#4X$iu׾?BUd %d`URk/'~" Q?WY$iVM-H^}YP!~=NUB*Y3XT\DN~K$ͦY)JZ[L2XUf* .;()Ʃs~7$IjzT< }Y|2XUf*u{ ?0w?}'K$|<bW~* V`JlS♇I%I^BJE3 ]~* V`JrLOܝZ~'K$W.>HE2XUf*NgJ*N$Iz1 ?z{2XUf*ʵҨT|[Y$rf@ ;1VUfB*Y3XTFzS %kWɒ$IWw;+ޗ"^UfB*Y3XT|<b:ǽ-V$Iz֦vI^}1PQoYWPbJ V%U7G?cFw_~+K$=[sk@E; WaPbJ V%աcwD?c}0V$IK^g>g߬0U(1X%kOG?cƏߙZ{˒$Iop'?c72`J Vɚ:=%<~/K$9-)6s3F߭0U(1X%kj~2 ک}/̒$)=WD_FTX}** V`JK[d}+$Iʻ9>Ve*5UIu%IR}u*ZDCT\k~* V`JKe?RQD?'I_~7K^{B)@ tW~* V`JS^ls|Y$U;b}Pu^jgL3XUf*N .;(ٻ=MXd.ҙ㠶kvc[{_mN7$PVMd}5;}u}~'_$oq3S{\^/$آ~'5W-,I2i+R=7 @7U1X%k~lV"5ߝ%I׽lq!ѹd<3XUf*ikU3<,IF桿20c?~UB*Y3X4lu?, [U=D*&,IF+âJcoPcJ V% [>mZ~w$IY}`$3XUf*i)UguUZ$I3^R}`tXe*5UIXSMՆթx$IWE_q2?UB*Y3X4OT&{$I: æ[wYe*5UIX߫RwmUZ;$I=^+f?pq]V2X:Uf*iXrà|XKZ$ i vL7D_iB?>+B*Y3X4uB#&{whI4u/_}`H5ﳒ*5UIZ)UUc&ߣ%Ip:C) C<;i%U3X%krݍяQSc|{$I^k0 ~&2XUf*i|o,1 Sҽlq=Z$ GN0:~)N+Md 5d`U0<яQ~75w]Z$ v32k{4*5UI^au|X[]Z$ f̓~)UMWXU<cDPcJ V% {k~u?,.-IH庛* mg 5d`UҰ:#яRJ~}Z$ VU+o)ٟ J/d 5d`Uз`Mx2KSK}ڟD_O7o2XUf*i)lؼ;$Iy/lP>}Ve 5d`U(>?E?N`uԒ$)򱛣$ުw\B*Y3X4 H׊~Sw߫%IRL0B6OWe 5d`UҨԿG*lr}$Is[/D_C%e?K^~ϕjB*Y3X4*\#{Ϳ߫%I<);WFH{ V`JK*_&IR&KJճF>1+J/`j VɚQ\{]cjmL̓~$INk#ߊJ?*5UITXi+%5~$ISoӘFwd 5d`U(\OcfDcג$iߢ=w`j VɚQ\gfDτ߯%I:S*{W FT/y`j VɚQ{G+̌^+5W[$M&UgoAo J/*5UIVwF?Z`Ɣ?A*3-Ibk't-^iB*Y3X4(~Z[$mg;ˢu}-e 5d`U(ֽ+̨΅_ gK)66/n91@Z'^WRPcJ V%b͕~̪:wmI4W} v*~*5UIZG,̨)5yG][$mٟ: J[`j VɚQ{G,̸R5mIZ_ݔ^Lt.RXjPcJ V%jͣ?YѿXC[$iD_H_K[`j Vɚml~}41 b(~$I+IUk}$,m3U1X%kFF?f`ִl[$=_lT=pV~*5UI\ߌ~S߻%Iʽ‟OSF P~*5UI#T=xfMU<5-IRu7F_ QwK`j VɚQwQяZUO[[Zk꯾,*@};N,M&U1X%kF ~+]5$IwN{} c/&*5UI#Nj>Y׿XC\Qo|Կ7&*5UI9Ի-̉ު#ߒ$t vHO>\4 V`JʡI~\;$I#;VRʥciB*Y3XE _я\Uڧi=\QzR)Z|(,M6U1X%krɯ_^;$D vLN>`B0qG 'K`j Vɚ\jGя\["wwqISoF2U=YJPcJ V%eӢR40`. ;Kە*5UI9ֻ/3Z$gR넏)Xmj]B*Y3Xc hUs3?R}6U>cve 5d`UR-|EZD?` Jkl^\2}u?4-moPcJ V%Z00V%Iٴ`ԻuGf 5d`URNx#J5FU\15wOK۝*5UIٶ`T5G?`nJ?_$i+9>j`z~*5UI9[udcN8uIfqG,li SK`j Vɚk0 j<-wvI[ϦD}X{ZVPcJ V%eT=hR<vI;KS]g߭f 5d`URu=8Q z<߆%IJŒצE0m3>~*5UI<ף0Ъ<$MJՆO~7K^~ǖ*5UI76/U<8i~7.IVS[D0#]~ǖf$U1X%k3{1 g$I/iFF#*5UIWŽ;q áR;$I?XT6USqχ߷`j Vɚ$=_Խяdݫؼ{$)Z'|,U"̸߷`j Vɚ$=_Eяd*[;%I`_NU}ni2XUf*I<яd:/L=|*_}T4cB*Y3XT>~[c{P}^4h{"Y_su[ V`JO|F?`(Uפ桿~$h _W%>`u?Lf 5d`U~R>|vڛR KF抷򱛣9Ueo K3*5UIW>G3 M^4Ks>R>`2..tPcJ V%^;3 C{C$i8+.VqssҌg 5d`U6rbj~Ǘ$ WS(US̽{ɥ`j Vɚ$K0kE4^z7}t@˥Y`j Vɚ$YxQ=hj|=_4NTmZ}d@9 K*5UIziž{-0:z_%I_U){8Ҭd 5d`U^F?`TU^jKkz B Ҭe 5d`U^~7 #X;$)bS#(*.ZPcJ V%i -ѯ|,6I#-/I9KUcK%K*5UIrkWD?`tکsٯy;SoK*5UIr͕~LzRj,=/I햺W-KE704B*Y3XW>ywF^\$ijǩڸ&-Rx4B*Y3X~T@Թ<2 IDATD*0z~f=U1X%k/2q }v*wI[{\2R}h}lg 5d`U]eяkJ죩 $My}Ɵjc tjf;U1X%kg5䧪Rڃ}y䯦O JU+Ҝd 5d`U]߫R6rݍy/H~R󠷤ޝgD0Z|(n/IPcJ V%irF#KSc|wIʹbWO퓩|?aKs*5UI|~l?R>r}j+ 4NT3q#\W}_ V`Jkяm^^{p* IRCWD?`du.?~iN3XUf*IS|G7S ։_ayR0ڪ*~4U1X%k4:~t[пT,;AnzyяpBK9`j Vɚ$MLUsC`IZ~xc90wҜg 5d`U^+6ߚZF$ Z~3W_tXG;4B*Y3X>sяo`65WI ml^j_sMcջw)"U1X%k4^R&[% RcѮ4ge*$쵾[RDPcJ V%i~Z#ꙇR/ FSHҬxԹRqMISXW^8Ut//}A `j Vɚ$mgcSяq`|75w$MJJی~/b),U1X%ku/]*Sob1$iJO>11W)2U1X%km60zԽvE*|}$mbWwg6~r>RhPcJ V%iz^If^sP*.}C^\sRROJ`zT,ym*5UI^3>(fCHkb[>퓩wv~j{*5UIfvMU90Ks{R*iNkԽzy4 )~k#KU};pXW\|0*! DPcJ V%if\wяt Hͩ}RcѮ&EiF?YwiP2XUf*I3SϦkG?@Uc}^4G4 -!`pTڛSiiP2XUf*I3WoD?Ak-' OS_MkW'HO]K`j Vɚ$\?XL5}_NU,fjG{!'@e 5d`Ufڸ& _ <].f!oOKS}я`@x~*U1X%k4u/7 r}_Ƣa$Myy%Ueno-U1X%k4ߜRUE?!P6 G1EHB _Z'~X)6;G0dz7^# dPcJ V%iZkZD?aWSR/‟בFEuɻC9 f 5d`Ufުяx`;}g4_Q)ZQ>~k4B*Y3XiA 0ճ:B4K_ԻTm\Qs&G V`JߤUUu7%y{Scl^SK'lS \*3}H V`JG?TV+&{ߋٮuS%^C 3 7:U1X%k4{K^R~4REW5ZjRwx%i`3XUf*I[kRcS?M?$MbR'H*(|&i3XUf*I[D?^*SԽ:?j0ZkjԹSSR}ͅ V`JW>~[`*LU+'~ͲXwFb>ө{!|tUJnIڛRx+i3XUf*I_jԻԹyԯ]߯4-15{gjqjRy.qi^X4 B*Y3XٯwOrݍ#RJC95Υy䯥9kE 0&ދ=L V`J[ud#`mʵNl%ZGp_ڋ~h<⽩W]gG`NW_^& KPcJ V%injG>ܨTmx0:+u/]ڧqj+'4Kc>4+ONT& MPcJ V%i*>??dwRIs?Z_T,{cZMR`jԽ|Iqz*ݔjN)]N V`Jܵhxcz7:Sj/RbScl~;6s*|}j>=rݍFSԹdA4LB*Y3X9lѮjn~ n3Oޓ]z< QkwbÊ~~?w븏No}^q@|BwA*yWA)DjPcJ V%inQYRRXu5RON[}b:y{&~ŵ8 XY5bWbm|:OO}gS/KRGmʵץ{'m@ ~ZFi2XUf*Is[s>)UUw'ڴ.U|RƟL_?Ɠ/TLSo.U1X%k4W_\gj ( ]PcJ V%ik?0s?Q V`JR@;'`T,#;4B*Y3XW}н+`j Vɚ$T|_T`k~*94B*Y3X};wי`j Vɚ$:?FVpwEi3XUf*I-!U<}/|oҰg 5d`Ub\ (^FτO>U1X%k[qSwEƓpg 5d`UufqHE`j Vɚ$:cn*1;4B*Y3X|#H)n=)42B*Y3X}磏 \d 5d`UEaY?tyCi2XUf*ISedn(TPcJ V%ip*S*{Gd|P V`J`ջ>o¿J#*5UIZF٩OƢ]ÿJ#*5UIu7F ÿJ#*5UIguStHf 5d`UHsOD G#F5U1X%k4u//WUyÿJ#*5UI̊ߐR}LH{~Ai3XUf*I[S i>]P V`J<ף Y士¿ J#*5UIG}THj`j Vɚ$ v3<S>uoj(|PcJ V%i)U>}\Hi2XUf*I_FiP"U1X%k4BJV# P&U1X%k4n91W57bW`j Vɚ$ G}d^o?) V`J_suëJҽ¿IYe 5d`Ui}l^h7?) V`J`Tm\}t){Xo~RnB*Y3Xs?D0tzO2U1X%k4\GU!'e*5UIW/>>`h8=mPcJ V%i*R}૪<=l3XUf*IYSx{ 'e*5UIΚG7<3XUf*I[ ӓ`j Vɚ$ o~/:7¿Ig 5d`Uy\WQ\{m*;3XUf*I_{}h{$(U1X%k4K^sG +ݘc¿IQPcJ V%i4^/G k}wÿIzQPcJ V%i4*R}@* `PcJ V%it|BaZ'N7;I?*5UI+I*s7uUi3XUf*IUsC:I/*5UIGZs\{]w:I[`j Vɚ$^>^`δNX7:I[`j Vɚ$^>}(^}NV2XUf*I#ؼT>qGuo V`Jh_D10_]N62XUf*I#NzcfM V`J9E30+]=N$2XUf*I#]RfVU V`Jh׹Q;'iB*Y3Xo*~}(yI\PcJ V%i^(ѻo*5UI%MU{SAo &i B*Y3X<^#jew7IS`j Vɚ$Qu)ul^+&iB*Y3X|^Xۥ{W¿Iڎ V`JR>_Ŕj=6{`j Vɚ$U㣏;;`j Vɚ$U෦TjӺX[w6Iۙ*5UIʯm'G?0)s`j Vɚ$WsR#|Xc5I`j Vɚ$YӢ ت)]M43XUf*Iy<~eU>]M43XUf*Iֻq &i2XUf*I<~eӿ[$PPcJ V%)zw}OTejhf(U1X%kw~eAһ$`PcJ V%IΊ> n3_gf0U1X%kJ$2׽tQ3I3*5UIw}$>L g 5d`U+ioff!U1X%k׿c Oޝ v ^&i2XUf*IqCޑRUFMdu+4KB*Y3X$EMdodf1U1X%k<) Tejodf1U1X%kwIocf9U1X%ky/UfWeo 6&i3XUf*Izz7}D0:ob U1X%kʿN߉>AƵhob U1X%k-[2`Ooa(U1X%k-U _sMj &i2XUf*IZ>U+ Lf 5d`U{iDWލdž4B*Y3X$mK+\ޔ_Kg 5d`U^GCs?*5UId\OGCh- V`J&բRi]j߻$d 5d`U4:c !߹$f 5d`U4wJD] ~'5WKR\PcJ V%IS}Ƨ.DÿoI `j Vɚ$iJOcD_ S߷$f 5d`U4Z'}"`gߵ$ @PcJ V%ISˣ0TRcl^7-I*5UI:Ga6{`j Vɚ$i{{~1^";`j Vɚ$i{k'}0 TX(U1X%kԻ >ÿ_I V`JSqRGcÿ_I V`J[3"<]߭$ `PcJ V%Iӭj>ҽzy7+I*5UILԹ4TK~ ^%i@3XUf*IwNGḵ̳ IDATJf 5d`U4SOTQ7*I*5UIۻ& uU[mcG;NjNi-O$]E@ " Q KH] :Y>:/|>?ÓW͊W;CߜF%s ``Ufj`'h]16%ir ``U;/^o̠wGI49XgpHs*Iuc(+8oR$ ViV%I3Q%+ޗߢ$ PV2JfbK??š?%ir ``U4S.5@5/7(I/]W2JfE{W=P[Q%i*=8Xe9X$dͯ~,{0]Fԏ~sۓX }*#yߥ/&IpWm`Z-I`V# UFZM_L~{"*{0u+6w7'IY}$i|dUhO[~ܯfO2+Vi+$i+6]d=&}w&I]we2+Vi/&Ih!k 6boLɿ=Π8XeY$IQq@kKS8`Zqtb$N?؁m_MW45dH`II4B͊PGJ7WX`־$I'+f@y'ߓ$ OkW2:L_Lѫs+g)$IpվqIh`V>|[b$^!{ 𔪹1EMG4\un?'{A_qHn\$IYk~k4WGr UF[YI4-ݕ F2fCf8+Vy_$IYF[Qn$i8OdO9+Vy#ސ$I[yץ٫`dEb#UF^q{$ite;{k66;HpV?~1}*#񕏥/(Ih׾u0ZE)H8ٓUF^$iOAT^#3oD֥uw27$Ij0ج!I]c]/(I6fP~1]HWqqă`W>zg$iscQW#j^oBF#Uh7b_;2{3 rQs i'4w=8X-|u$D1o6^CjnקIKޞ=/9XJ<٫`4/tѩyg=KVa%/*I~ج(0ʻ.4R]=/9Xhtj$Տ"Zx2_#i*Y=/9X7I_T$=+`57IW5p`6k1>6;}YIy/j[` unR{ѫ8UxJ KgDzW$6bKz$^3>=o9X4$I[siU7_o7]dB[V)x풿$IZsw P~u$lޛ= 9X)#}qI?%@_j}HZ}.{B_s OӼd%Iu wEmUURn|-{B_s OӾ%I*yYTGW&@ߨ8 8FYQeDkVi//IvPOgL<7T?Ux?$Inc 3n$DG"=,{$iGՏ}kD6Tbދm$iscUx$IH^9I\`-s >,U}}풾$Iasw٫`k]9'FyΟdEVa+쓾$IHQuW'NS.js!*IS/fFVa+ZW/H_d$MKW'NQ56Dqg$'͎j*lEe&I+8 k'kIzzSߟ=a`8X-|UB$i5`Fun=#MF]ߏ0064.tB$i2un?7{}̈D1oIzFsvj *lCeKMIT,|UT+:ͨ/yG[$=~'{B@q Rvv+$IAzuߥHtJ`qL_l$MYQ޻<{Dy-o0>71 *lGgMIV?"EjÚ(4EVK9{Lq FK_p$M֥ޢSD}\$i[unJ`vyɾ NI76;^SZ{$m␗Et٣U؁rKNT?-F*򾫶qIV>=*a 9X (E'ITj-/{LX(2Eج>zG`&uݑN46;+W)UhIN>=-a`9X K_x$M1{Et`Z5]EvT{gfKXVa~"}I4Z-{lSyץ[7I^D *LPo/=Iܜ]MT␗翧Hj-?{d@s PW$iՏ;leSlG}Q$i}{`$=2I4WN~uN?Լ/G& <0 UcC=}J4݇n^Qqqf忟HҎu+& <0I>%IFcidT`UOłHDj C*LRwÃ1>PZJFUޕ^"Iѷ'' 0,}J4+A &D&XdMVa ʇo>X$M7F^7IL]04O(Itk-LJFDE秿HҤjUeOVa:L_$MYQ޻<{C򯿥H$*W]=>a8Xi[QV,z͖fDՍ&"Iq' 0 W/GIzQkV!պb,-D&[y5U L4$uVV!S޹4jcA$i25p`|E)It+2 F`7ITcЭ#U,%IA>VaiDw}Hdk^U10$ IZ<<$i.{r =ҸKS^T>qOjT#;$i*W,0BtEmދ$I~#vzLʨ5C&[ s =Ժ)IRj]97{z(}E$MK( =Ke;oN_$9Fw"Kޞ!ISqG(c{/QIzUq/Dܘ^~VU<4zATWeOR Vae*IRj^٫ckKϐ־1 #*̀ѻb|n U^Yy~zPy%-CRFtQ #*̐Uҗ$IXgTdWTO(C^!ISjn]2{Hq 3lGqU8w#n@qoK־Q #*̠r1>g+IRj_sXzUhw IjleOS9Va5/%+IRϚkt\^DoK$MEw٣FUifG%Jԣ#Usctn?7jc+$i;"{r ;Ag1~vIyYoEt LSQ,|eۃ$M),V!Q3җ$IuXzjn{9Htj yߦ/iIz(<{SD7H4|tZD*d+Q?Z^U6>aIj-wINa) Vt7=~.}iKԫ}` 4yG[)VOK_ޒ$7%{P޹4jsvI[)7g(,{;`HsbYK\^46+;.^vt׭b 47.8X>Ӻ%.IR*yyT^VTbk$i:8 {`Psgҗ$I~G HG%}Kԋ.+͟O+8eV-{S`@wQ; K_^<٫FNyUQ[;$MɿUsS8* vӗ$I󝓲W+#G1Ij>Usc8* 򱻣U$Mύr C`.m@XG0`ʇoڡ?1 It+}Tc٫VU_c%M@ZGq U@wFmk? $In/ND^0|hIj &fOS€>:oJ8$i[Z-?Nֺ"*{=`Xw#QwG$IjlV? {h-L4kfQ`8X׭?I I4*$OܛV`൮$M_eQ`9X!mG I4wDV``un:9~IJafQ`9XaQvyߦ@H4gaDUeoU8GmήKd6N`Lk?`VDŽ$ISJw Q;KdkZcIjZ I(\N` t /}_&جh-?fQ`'r C\sc}e$IS{ta:VmXO]_&Sqˢ $p C({$IS~[jn^ЗGMKdΨߗ=B$Vaص_pH4g}?R57n9_&SOE#H`FD3b|H4WF8KD+}9{z}*r-Q;?D$ITc5 v4po4'zt7{z}*nDԿI&S1}kTh%iB5ZW΍#VaUU;2>/E V?QgoQHѺT?fnUa#?H4} lePةZW$Ѻd߈v={l}*v3c0+E Q^qTo󒴣ǽ-kn@s lѹʨ-zm$I} 3sQLJ$qL_I&*U}}4.tgH˳W'̘k&/Iۨq VѵQW$I۫Xgt+{m@ϕ?po-^VUѹq l]ַَ񹻥HGe_a_Olg/I?ݢ1{T*]cwG#I6jNi+W/L]]̏D~UU`Ǫ*|:HZQ=7wIzzdH`H8X&UDۇF G$jxB)>r[,vIqcGz*0i'WG㜏x| I>7{gIcwFKω_M'Gt;BV)+W_IMX$+&ĽQ,zMT?ꗢs#ehU`:,w4f5#Q4ص헽cޖi.Q?r{Tз#UWFk1_Eq{v ?d%I}Q`[4U+D4]Ѽol-s뗢}ߣ=Q5̞:*0*OEOEGmb|lv$iV6> ;IENDB`PNG  IHDRRl pHYs{RkIDATxwUi`D88#XĖF^,(u T!tanAPRd~Y\`}}=+0 0 0 0 0 0 0 0 0 y o1*mfk3H*2.}k{Qo кJn@1}Yک:%Ylgmp+-|2in[ n'iCZ%w}wD3}Lۏ׀oT;LDp7΄dz$caـ?|>ʬ$7bnj0bdޜ~>X#!ݸg3*^kR$rv%s#Wn [@u:PX^@O԰d:~4 R75-5,M*st8rxr)\"ddyASEO0*nfo}@al>㧋"nRH9 =i3)#>h@.S8#PBh|1H* -*Y5 =q3%oF՚=TP]ώw1PY;>Z.'p-=&T澌 Ĺsc]'q]e-H[)DDs\>lOy bk@q@dNUΆ)4>W@T6_EB9۱aazV @u{<aW'v-e|(!Y3KRFvQr\j=u57u"!!@Ґu6#?#[,[YwmPt}^Z87<0؉,QMmV ʶCq!0hv^:duc1g<lв'|\Z1cLu {8!ƶۉA;'ofnn)oj%Ny~n69k1zJ#7O0K89vr"Ay~UMpG0AW:Wkଟ֔dؿ0r (J"4hЇ\):&#3hr7ix>/QraRE~e*Q g6d5rap_/=Q?tO.1a;S`)G9ϽH x l{|>m[@5\q 0ߋ]9+1rlHM] 231C vKTGk1S?DS鄝UG &(n^u;`_8d;uiL<=fcI D/i-zW(GxS{M0Q5e|䯒_ k?&;zY#Emfa'w#ߚT)}{_qj0i&ڻg\V[T܋D;koKX`4;{eoPלI|4gAX~?/~,Z2*[`\f3~.E &;w,TnSrHu8+8Tv-1azcvt-mz\h ) j(3v3t ے4ąϏ-4N+d>:ΐ_|9A'=w, So<3Snz nyd9^ Ng!=Jj>S(e9#޺2`@7LoNBk'AV xx%88׻£֝ s Rr.@g;- N v [pS[hqn4Q(vK-dKlx ^ў5`*9`nF@Bϋ!\ FMDbSY#j6QQhaO0qB*DlpS  BG$>JPY/Dewܽ$ -ڷ$bOoS~unc*#[8B|_#&)f** X3/3:Z6Jh\bcQ ڂ_pq}S 2u-:<7^%Έ[U,Q_VwWRB^*_נlD{B|vdis7nA]WCt$F4_tN4q'>P1ZS:ޠ49x<&>")|LyoJxVgد{d^ܦORd"8B- #B?+y9B qņS!/8G!7IgE  .8G!46.8G!td莲SE9yW7G$$Ѡ;F[jDBݱz\D^pPD@wW#!; jò/sy9BK Aw#{"٢.8G!4O]pPDR#?eEz\I]tAEz1{tWS/;ɋj{NuKhک;E5vF`u8A/4n{f B.G7&/#n*jh>K4Zh|0aΨߐG G6?D>A/4.ѝpk)`pB+Gx)H6#ڛ$=JzmY/G ;Awͳ#j;cۈ {fPh|choi A|ꄡ_35>y{S|8D{QZY9ynX;e!>Aݫ3+|0pt/03/yL/q#y2yޛNi6I%@geo펻 t6Jn2?+V D@gY/V%x Lh|jd V/Xϒ+u|-Ŀ)&qȄ^&JcLhLU2Jk%X5t&޿Ο51)R689@:nN/42P^sz9t~?;ЦL?;Ar9 !7ȅS>ݠ_V;Aw~?TChnG0 ?KZx> u ITh{$ ]Ib -^:/-?謐0;,;P [iPqݬ߁i9M=i ZCg-A@*ZB2 %wm*UBC6EM^h\aG5_:#$pB4Bܷ@/sAk7LӰ{^иؔ# vs|Ѯ#BUGu☖䷒}4L=Px[w`{,Lh-۷mh`,qܠӍ ]uXW"r]Z뇭¬aXǦ2Bӫ s[o+`[r>LT w=zm5Jp3N~H!q7X3HgOCZטmA2*4'0_F43-t6\2 $pe'TxM ȌK_o_ڠg4`TO >Mg9 ]TIQzK5dT!p~Bˣtfm ZK%CL|hf4,޿ ! ?N4B\'C;KQaգG툙,K5xF]⿁GF*'r<=ŏ%7+oAOR1xdaêU [GY@|N$7qFI~}4t'%+_>aF%z c'LHk@ۚ0)4/MF%ׄ1`dtD{7׼VЈ;irw\l泌;wڊ;NxFHI)MrJ!7QEl}/?B#e1"n㙨9'pfEr.xyr,~?Vj{}cycvػ0K)I**EQP > $Q 8ٴM={ $i$>kN,[ffϹyuN|ٙD3$Ix3ICZRJ/ڊөyŞMh_K[F=$Iβ ̮}~Q[\%mExj-za_Xݶ/H΋~H$I#Q+Rh{0wIj\ߩW*6V`N)E󣋢&$IHչr6F>=T5mFj^kʶ{q4XeFS$IsGD ֩y~y/w /~U$I$)i|_I;J.ڊڑwym*Vv$I4~Gz~R#iPE[Q5u7'_T~wm7EǴ֏?ZI$I_G(E/Vmm~~5#xȷ$IԪa+.Eob=hlі0?GozH$IeeTXuju-ڊ"5.)qT狶b#)_Tْ^5$I$`jT4VU{V$I֥;WTԟE[?^t'?ʷݘ7$Iq?[g.ڊ"Վx_5ݩoG$I׮ c}޾廅0]}ߚʍ~H$IgI?~gS瑛cmGo\6*$I$M})|JUOo wTgoI$I[R61/^M]5.ȷq*eoI$Ij^ #eRh~S$IfSO߁.K?$I$/vBX4ucnmwlfQ.۾ ^5G$I$v:N^!9YOx w|ǙsqFJ$IҌyV&6o:Oܵqo$ IDATкj߹<#%I$i5/Z~7zqmܢm@Kܯ(I$I,R[~Gz*_U*jOnV+R6{I$I TV|7ߕj^m'H$I U,.e ~gzfrbHo aMίNh$I׾{0S]?yI$IRHOļ{0QE[쯄QOGk$IZic4sm$b;<<$ITgجՏsmN-S>yI$IT,6e 6cNJS_#ѷ< $IAj,辗NJGnRg$I$ Ve;06+3vcN b>$I$i +Wޓ^~of8ּ|/<$I$ tk c3ֹ{xq¿_wiFY$I45X '&a;4O}VI$IR%*)_06mj|$aMK}NI$IRun>~t.ۥ/$I$i0Nm̽MRGE?$I45|<hg$I$Is_?ů c?Ţ9U;)u$I$ u~EsgіX~Gy#I$I#Q:6LoF3$I42 0m̉q>c$I$ijtl} 66ZkSY[}H$IHV?#B`ˢ3IsE$IFrղo!,(+L$IuŞC`̢٫)$I$o'¨kZ1+7MŃWG%$IevjE]mJoD!$I5j"d#̢+$I4U)FFE3/>;$I$I}#&6fyף I$I#d#Ȣi+$ITʧO6ǯJ$IRj]K]GE<¬I$IL*کo'!!mlPm_IU>"$I$I3xo(E+!mMSg$I$i5%6֫yעI$IFTVܝR?XN~eT$I1!mSF,,$I$EE'&76֪yD$I9s)~߄lYS~1gI$IX;'dC̢ҹ/I$IA|VNȆEXMܗ$I$wv{B6,|ǭS==%I$IL~lY$I>ԹwPȆE]>=%I$I}? B6d,>|/I$Ic;RywRȆEuٮ]$IPܯI!"m#ﯧiEvI$IR@ecUw~u!a6&=DuI$IR`kpha?=%I$ITwTȆEۈʷq*W==%I$IPγ祖 պ9.I$IGi]hA`I$I~\M)i h5GoI$I8V.8s[$I4lіwW*ʢm۽(<=%I$I\+de6BZW=%I$I^|&_~,FDm_Mӊג$I Ծ{,dd6":w=%I$IU>~b,F@GhI$IRqF}hv wDgI$IR{-WEېk,I$IhCOļ-da6^ڊ,I$Ip>~",چXʽ$I$M>(Y hRO݈ǒ$I!t{.d`6ڷ,Ò$I!|Eu!pmCv;S*9,I$I\}g6:]=%I$ICVm;/d̢mԏ+I$IҚ|5 h&7~$I$I̗|a|0Y i$I!yт/dʢmX,|~*z zJ$ILwzy=EېhY+I$IZ~lY |V$IQ]O.?~Ac6͏$Iu~aE[;,$I$i4S/ߋ! m7{$I$E`9,*,)*I$I< ,*u^#U$I4MMǐ OI$Iv~M=`VQw$I$uk]k=`VA?3sT$Igkf)eȂYUP]G$I$Iϩːh|ǭSX=?%I$IzNy5XfYUL;ENI$IZm͐h?&I$I)%gȂXUH3S$Iּp" YXe*R$IVV|ߣa,*yDJI$IUoߣ! `V 6OSDII$IU=m_hɟ$I$ͨ~,ļT*d=f6h&6גUtR o']w9~|1ZW]fJTYw:,,K4uZXvm7G>CG䧢6b}AEAn٤g'd=d6`:?0zIuZsũy)ɟh,DWvSFOٶ?~fB#m}ژ$in߲$5n_~N23/un?jI?'!2\I*T<ԼpO~627&!/*$ij׻f8)HԾT6VE$px>!$iT*:se[|iM#7F$`? ,DMsN4̕˵3-;"cԾ8Z*I_ej% lY 7$[S;_/֕{ʣJF5}1о&I&oqTS˻ ڲ2$ik)qs9d6ȦN3zI4O7C,c%ICZܯw!?s=$IUH[ ?bL%Is^)YYsâ-XmsMTwwا>OK~A6G,yO<$UCK/wsSщ~KH}m@gԹ;~.X]m^$IjVh /*gg$i+ԹT;-XNFc$I}ds-HF1IҠV.x{y3x~$iv)_ 7E[ǘ$i*Ծؔs f:$iV5/? Hmjz$ Xlļ<_=&C4URyϞE[֥;G/IҀT<|} z!󣋢f 8/6E[MlaT>@yM&襉yݿecUNT:\vYYF-IR`eDj-"L~miU[͒E[oVؒ$ET}Q)g>/dRIzk]GcOP`IwTQ[S4'S +fKW~S>= "E} RIҀXgd`GϏU>չ㌔*<-+I:_~FA6 m}ꔊN$DEUR;So_IҀUmgd3d֯/E(IRk߲$;,́*wڧJS'fȢOQ>q'֥ҒlJv/?`|, S*%IA/H. ?k`L.S$ @O XE>?g$ikR/lb^9èvṢtIRpŲ$feF&IV$W;gddc==$IsXʽR`FC"/I }add=$IsQ':\pԾ) I|ƟG0am=VR?h2>|,z$_**I|TW`'m&IURӻ_?=)g W/韏kVR=F$itvwR]R|_?  m=0(~AS#R`=6IAE;ݚ7g}_=hOK$UL͋懟ܘɊK$iv+J훎MͳjY@%QNjOg0K>H%icst|ǭg8dCm-]V}֕{u[R61/|^C6,X?USc g{=|Cj8Smlsa6Z=V%II!$rղԹԼhAޔm hc;$i]K%?'>=}$iΚ|LQW@/]G8;"~iums( sW:8`}SHf^ezWE\g})zK֬h~F}AE4uWtRM}qI~#e7@)9Թ,IZLS)|;,=$[佩}ˉyWS?H٢-$06',ʶ/H݈גj^8>/2"z4I&NγSmSy79R?[Zk ?S?㨤j0msu#]4GO>=lSOE)I\nMJͳꇼ'e qX(929`%I|0Z=$Urղ?5/ZG8;4|cǢm;mIRl^`Z&6IN[2u:7.Yy2~n ,@OG4M~C\gP!LţD/I\_=Wm*h훎>$i+D@T֟bXGk3ǚV} Gi\5 Ӫ$)_'}cS'$i*T<Ծ$i*2e7 hi^8=l<:\Z)Տ*@6 ,fMFfj{rF&sw4Uo\5uhDy42M~LFW뻟(sպz=W `|,f|3PFћ(q?GCi+yd窹dɢm_}&JhTv>'EOEi֕gRRʽRc6[Sh }NJHԾc?3@R%6@6,fuŞG$ }eXwxiX]?OU<Ծ3Mk^>?(Y(&,=ڴo<:zDj+Osvzy{hm_R}JP׹)?"e~T{ڽMv>&0^m3T?[I2~WXB9=9USseu窽"/c=a6CŊiI>fqEN Z,u4.߽#O>vAԮ|_3չ %ihk]GOtHsmb6] j6RTJŲkSʽRc6~0ļWh$qE;廽.|lJ,\GoNkK>jfwQ`6M-I7>JǪ֨|ԾeIj~J06,ڦ~Gv;g<\wxi*ǣGV6N.{W@O/~e FE۴_oD ICW瞋;\k/utح=W 4(,ڦiW$Is[[>&x;t+7g}1yOng e6M;xe4zB퀷`hC:-H?^g 4XMǢ-}$Is\wj_{hs^g,YM%IsV/+?wTVD]OK+N>j{sHĢm\$4T.-|C/,Rm}ySIقL !ih]_)4T~slQs`̢m::\}$ M{>qҰU6VsՖn_:@6,ڦ^FI>mr)Uيv*5o8*5Nl kg6J榲dʶo~7LU-KR/!I燿~UEԿGHԺb}ˉi*W=uYYm:ߢϯu(1K;,s;`2Hg~aѶ/$vۿ>Ƃb]ӚeUh[ASFƉ>IĿaj΢m='}QIYm>ļԾuijx̳KߝϏ1,֣uvSI|NYXG戮TK1|d}`Ѷ#7FO%QaѶ.$;ν߉aѶ.?}?< uSI|>>h[ɟJR+~(|d}dѶFQ%ҵ;<|d}dѶJRk,x,Ȣm:]}GV) #u|$iv>>h[O,禍TZW?ˢm-j{)*ItYEZ;$U|ׅr,֢晴TU8@m/7禍Tڷ>mkѺj{$Uy_YvJ=U*[q,EZ^}OjV)q9h[Tʕp,Eۚ&6IhGU%  amk**IyDȂXvۣ禍TuȂX~G禍Tj%|dA,|AN{$U[q,EZl}UJV<~{ Y}wUIdN Y 5t~xN]U*Y3 dѶ[朗T}6|d,Pˣ朗TGi Ynb"*I/q8mw:*Iլ,Rp9h[OcHf^3 fѶAJR%wY ȂY~朗T7>`miwUId+ Y0_3}WJ<3 fѶqт軪$Uɟ Y0մ;*I~g8@̢m5JR%h[M3朗Tů Y0|/*I,[h[M軪$ULEj|y}U*W m?61/}_U`6%uwUIdۿ>`6ϯEU%?2|dmJwDU%7|dmJ?JR%k]s E۔QJR%k]0|dmJJR%k )>}WJ< 3 mS}6*Iq?plX8wUId%h[ㅐ$ͬq>`6uvwUId?>`6uwUId>>`6uwUId#>`6}wUId8|dmJ%wUId0|dmJ3朗T~ E۔=GU%~w E۔+朗Tjn E۔k朗T,ƺ,ڦˮJR%{3 mSJR%3 mSGnJR%plXM)%*I~{g8@6,ڦ}WJV?3 mSoJR% )?JR% )Ŋ朗T}4|dmJ軪$UƉ>`6|軪$U) hR>`]U*YχplXM)W-JR%k )3DU%5/ )ex]U*Yg8@6,ڦwUIdw hRVDU%?|dmJ/JR%k_ )>uTfWg8@6,ڦO}WJֹ )Ŋ朗T:]>`6x軪$U⑛g8@6,ڦ}WJV'|dmJwUIdeD E۔朗T: )/JRe˶9hҹ{$U|+8@̢mJ禍Tj{rȂYMyV=U*[ Y0)}OV?s f6}{$Uƒq,E۔GS%59hҾ[TIl͋q,E۔ES%;|d,ڦ/*I}s f6uTIl;Y0͏JRe+*|d,~B{$Ub]s f6qg禍Tڊ9h8TIner,E۔}MJYhR?}wTIt+|d,ڦ~wU*]r,E۔~oJRkYhRwTIt+|d,ڦ_}GJ׺|Yh/**I}1 dcTTIl/q,VZy=U*[s Ej{$U=@m)W(*Iխ,R6Yh[MȍTIt?> msIU*] Yմo;9*IqGg9@Ģm5kJRkYh[M]晴TZ.YվYh[M۟JRsq,ȂXqFQ% Yԏx_U]3 Yx{U*_9@m5oJRyh[MK戮TGi<XnbNU*]gѶ"*IuɢYh[C;$U Gr,EJRsI,Xs׹wTIt{g9@m 훎JRR6yEZW}EʗyE:^IyEST*_c9@gmk$UYYvDO%> |d}fѶ|ןJRyV<̢mM H,晴T?ˢm-;$Uv=e9@GmkQ<~{U*_k9@Gmkѹ;SI|C?|d}dѶ[NJRk,&|d}dѶ}?׼hA<Ȣmm/}?׾yOmk8戮T:]>>h[JR+~(|d}dѶ}?W)gg:@'mk SIj{9|d}bѶ6 $$i0mP>hT*_YXC$U{sO,֡Ӣ戮T:w>>h[UFO%YXFT_t,֡q?D_O%i(wCLmaTYXCm7FM%i(j3 uYEJe}?׺r0{mQfEO%u<;|d}`ѶŲ戮Tws,֣s戮Tvl>h[G_O%i(3 1i8? YYGc6wSIg})|d=fѶoQTUt,֣/EM%i(}ALz̢m}hۀ|_JpԪlbEۆ4N3z*ICQ:xoXMC軩$ E>>hDM%i(jE4=4n*ICQg:@#my.wSI:\>hƒGM%i(*W=>hJДoE4_}/v:@m11/V}7qug-+CKDocĘ(iDc1x7&IΙ H@&UmQ:fv{92̙}ow}_~y3{@k,xͪ軩$e=g:@1,膓漣Eo%|m= .5n*IYT>rgL(Ez軩$QYub,S }5ls0G勒M>> h[_ӋRwSIʢ^uɲh{JRuZL(&̢m W}7,*-|fѶ}7|ytK:@1Amw?D_M%):+~1|dѶFTub,6@{}/l\s\(&ȢmǢ漣Eէtb,6漣E#wtb,6c漣M |bѶ_[}/ls 4-y_PLE+RIʦubB,6P{VRIʦ񝗄ubB,|軩$QH&s9znTs9\OT{;:@1msC[{$eSs9{RIʦ:@1msURIʦ XQ}$n*IyTS݋:@,hKM>d6GëJR6NPl${$e=:@,{EK%)F>d6GdTl?>d6W7Mi؋JR6w05wmafUT{:@,6pqRIʦ>`Ѷm}/l^Pl;毣勒M{ FhlTiOŒ Ym%^ %Ii/0g;Xm}GK%)zM\(Ȣm# ;*^*I48P̑ERIʦS:@1Gm{;勒M#wub,6RgJRVwxYl(mcMoRJR6u0,&`|eRIʦʏub,&`xRIʦub,&JR6z\(maT?>Pl h{$eUgׇvbYMH~ ^*I;s@m2{$e]:@,&dp>RIʦ-gubYMFK%)C^> `6!}/jPl i/2JR6uPl *5^*I48oPl pbTiPl 4^*IT>vw\(6EͼOH4;P' juT{ zhE=}/l`jXM莋勒MULJub=YM}勒MCub=YMX}/|*g;@,&D_K%)nl(փEۤmqTSϢmvTixsXm`{$ex sXmztTv>a6YTsvyX̓n?}'Xl(E|^΃RIʦvf6OF}/lsU\(E<\[TiO-g;@,IE_K%):9|mtzCTwg;@,MSRIʦvgg6w~=^*I4P<y4t{$Ӡ=g;@,,QJRVͼ2z¢muVl}'xmi)RIʦEvuhg{JR6n=7|¢m :$^*ITvIPE|{$eU{g;@m{oDI%)zG+|`6˶L,勒Mw:X-7EK%)F7>uh[돉JR6B(C>3RIʪg2|âmtwRIʪޱ>aѶ_ $i .ll(E4Fw\>aѶ@}/|SxP K_h}/l^llh 1{$eSmsh1{$eU{ǗvE;$eU>m b;$eUo`4EK%)FWvm1w]}/l*5socxي{$eU{ @Y;$eUȿ@YwRIʪ;v,ڢ,,A'^*I4&h 4RIʦH*7 @, {$eUgׅvXmz_;$eUvXm:;$e=g;j,HӛxTitHMeltRIʧA'K6@,ڂ .lTg;j$`6N*IY;Ch5E[~*N*IY5|ɢ-TvJR6*~,*`tW勒OA*}alZcV-JRVuǢYT'g;j h;$e#g;j(#^*I4~Ǣ"}/jŢ"g|:N*IY=Og;jwRIʪot@Q,ڪb4FK%)F?$m2{$eS{,7 @1,*dxRIʪ>VcXUHEI%)z'SlZaV!.N*IY5âJoRIʦUHMaV1۾}/|*^UlZ`V1 wJRVuh5E[zWTTlZ`V1]_}'^>V#XUPRIʦ@*v= pRTkg;ʞE[;$eU︿ @+{m4 y5g;ʞE[4r}/luylZٳh勒OA*}QlZYhUD_K%)5|YUTFI%)g|:|YUTg6wRIʪg;ʚE[U-rglR,*l|%RIʪ. @+[m6d;$eU憎 @+[m;o裸U w @+[m'裸U/@+[mU6(勒Ö́w ȢF:=Z*IY-heɢ.JRVW~,|,YU\K}'^dVq^RYFK%)|;|,Y勒Oe<`j,j`xRIʪGvwRIʪۆvwRIʪMgv:XF{$eS}$ӛw Ģ&w_}/bVKJRVNŢ&z_;$eg;ʊE[Mt>wRIʪ׆v^RIʧr˷@ʅE[n9;Z*IY=heâF_>N*IY58oYlZٰhJRVn=7|lXH{WFI%)T,`V3#wF_K%):+~1|,XpwRIʪ @+ m5??裸U3=V,j{oEI%) @+ mu݋S勒U=~"~,jh|uwRIʪ>VY裸U@,jw҇裸U5g;Ъ=;$UY?>VYMSRIʪa?Tgm55;$eg;Ъ5\kTj/0g;Ъ5;$հ[wU[m5Ǣ]5|ڲh{裸U3>>VmYS裸UN @,jTTlߟEhՒE[uwRIʮΞ @,j);$eUwUKm57uTjxAhՒE[ >4N*IY5ѳhՒE[W~,N*IyUwU;m5YMT{;;Ъ[yJNTjp.Hucі_JRV8|ڱh=裸W^* |bіޱJRvu|k|Zbі[GG%)_jŢ-e&N*IY5Z2|ZhhwRIʪP*7 @6,2?gqT;Ъ Lty[}Tw?wUmh/*JRV :$|ڰhwRIʪ7vUm^;$eW{WwU mX}Tw;ЪtVl}^~@|Z`і%4DI%)+~,23;$eW{@,23d$eWwUym J&;Ъ<̴w:>*I5^{c|ZgіX}'6xm>5>*I;=hUE[gOGG%)>VYe{FG%)k>VYe|2N*IyU+g<Ъ,LVTwԻ;Ъ,L R}Tk;ToLW~,>*I5!l:%OD^}hYFWLuVl}<Ӷg<̫ś^oHߟF_Ұ_GuZ,rd[$]ȿ0A_Iꟳ$n<%w񝗄o/*Ƣ-c3?6s檽l=ןǦ{cіşR4k;{f>z҇^T'?NUE[zǾwb$)ie3W{j?cі&I|#>hgW|?b,2WkAܛh~|9^?UT>|[Be?b,27Z}js'I5@jmԏϞ~$)qjo3{{պN7 3,*Ģ-sC0,g3W@{v/s-*Ģ-s[UJR\{FU{֔c^g]TE[_IRv"|P7{jǿ? /߿Up]~$:,`x;Iʯh_ Gxb>;ݵ}$EX5@Ǣ;Iʲa>_9Wmu>FEX5@g6ϝ$e]g<^eLoGunEX5St=Iʮ]x6j3yoSޫ6f!TuX5K=Iʯpo=g<;=^5 e"uEX5F?{e/Q`K, 4׬Qu?EX5D{=Iʲ=WxFWm^ُѿiBhk?Ýy$iw{M{f?zY) ѿiW?sEX5Ϡ$eYx^'>zg|/kZcsXTE[|]4>iͩhkʏE?ebzQśz֫ޗ?:Um YM3(I6h U\?EX5͒StCIʲ?iNB,h|%ϡ$eƓg<l=R-ѿ2)sTuX5F?eeDy^a/W$e^?Um ;毣CIʶ~>fh; Rѿ hi,:%IS @~;,u}{ꟳ8V^5U&_z*;Y,z^jnO|ՇU)e9:}TuX5'D?g~jos US͛ âgG(I=<PM_Iꟳ$n<%u6ޱ\bP݃~3Yl9k/2u?ix|_S;=ZQ!mM S GIʲ<P-âw_ hkLJRzʒK~)W~lv6^{Iu0Um 77?i<~.%)f>= :ǻDQ!mF?m>.;p4itY>}Kz:{)|vbXKPE3Wx{kVEےPgׅϓB,H>\JRuYo:{!G@w_jR&w}u6Rs?\JRͼ9zBWm= v^5);P)*ĢTL/JegSmY|9KSRپ?蕴|b**ĢYo%ٔ|tR g=l,UK6MEX9KMIʺ!>`߫6Ex?ŢYCxJR .#|W}|JxeUTE}okY^bmQ)ͼ1zcwJRֵw:|@۽U+cQR~'~MUE5gTwGg=[ޫ6Q?i?ŢgTnt<߫6Л^5I `Q1m|Wo~F%)E*n>>3?{DlgcQ1mśXs*IY==xځ_ixѩ|#L TX4JR .-|P17Kߔz'S^q`{mJa%I[Щjhi.~N%)Tj"x95ZTEOD?}d j} I^_-*Ƣio$s?>K6O}ߒ}" >4׬J,I?{Ţgsu*IY7YFZi;ipɞit) {G$-hTX oJRލ|y߫6Cѧ$?_sQ1mX-xG@?{$Y}36뫣UIʾwD{i棠{䟇b,X;WIʺX;~y#BjS EXN뎎~^%):Z_>xYM.*Ƣuy$i~E{np>ǃ$զΞ EXN}JR6|tk>$6wzE.*Ƣu[i*{E?}^?ѷN>$6۾0|ncƳrv3+I?1Ah> hY 6tf|3hZTEY񬺇- R{V3'OIE> hYmxJR}oW֯ڇh9|#$i~^wt;wIM3=|nd*++;ӛ|&ǁ$զ  EYJR#3-> $6u]TEϫ'_IjDwM6@jSg_ EY:+~~%>ltәG$զ EYoR~%u|}h}GT@.*Ȣ2gX=>} HR= R1(|ndzbXIZw_>iETSdzXS{>@t>_jvQQm4E?˒Ԉg|:|4M =%6n=/|nezsU,Ih|g>@N/Iixs(6F?˒Ԍ2w}uh$ops(6[?~%1Odh5E~IM?>hcq,IhtsIFw\=%6yO.*ʢ 2^*yfTS{MQ>vw䗤=s(66}gIjLS>>a>!IP{gT5YAfy$iaznhΞTm_>hcw~e,Iir=Ϣ'$զ`.*̢ 6~ϵ$5ʏ}q/Ii|us066kIjL}` B4]TEwkIjNeڻX莋$զEYڻhs-I 9+DzIM,ژۣmIjL. jǼ$ժ)> hcNWlKR G=%VuxG.*̢9϶$5Y>r4/3$I_g6᳻06ٟ~%Qu1l/IgwQamYϷ$5^?>r3.I=>hcΆKR]TT|ʢ,ژ3ﳐmͳ[GvIUO EY1g3a$-l~-|w_DuIUK>>hc}69F5lED%c]jU IDATO,(o~99FUvJ-?@FOTG3|vgF\W?9(5#]jUg7,(}~!95 ڻx8^]TEgzTv~%Yi.I{IwQqmlϻ$5 u6hQ.Ij|᳻66Z~%q8| G$ժgwQml~KR*g@--,~=%VK=U}mlśh3/Ikpvg@ uVl=%vW~<|~5`DVKR*N*o~M+=%vuy[.jˊ$ 7-IkwQmLDg_~% ?& El?=%^ :$~OUE1I*G?ԼFv=%v6|~5a|կ$i3.+?=%v ?6|~5aOh/I0uGGmI]&,ژ~:ٗ-@-^wRْTzm 6&|_}KZjYg63 6&jxϿ$5p*}Q9Peǵ$ղ-gxQmLTE?z'|0EjI]cF,ژ[GIjl\~TU{V)ѣZjgxQ#mL\ms@/EXQђTˆEX1q+=$ 80(I*|5b{_/R{KJ$=%uGs|>,ژNH,g$5~TIFfIm^>Njhc^6zHRc!Ӌ\GhZVv{Ԇhc^ .=zHRg@U=%n0|5cƼy Inx1g@t~SH6t9^ԌEc4EIjnaj@FOdIm?>Njhcތn9'z&HRcYm|uXj̗Df,ژ.IRLeTl JgŒT2m>ˋhctVl=$N ǰ$ն[xQCm̟MRپ?z6HRY+ف.ȝcXjƓgTX1 _`u;Wje᳼!6UGIj|+6+Iw_,ژWϋhc .7zDHgBznԕZ7Y^ԔE{;g$i慶~&̷ΞO,G$պ_EMY1^h='$GS{V|\{;#)6趯E IRJ fX=j%u}KL'6M[}}.̇ޱ=f%XEL/jʢG$z'~(\ΏTw]>ϋhcaL/JcD I/Oځ|I .'|5fƂ^}h$=Y ?&ixѣUw?,X0ޙ!IiMU.?[%iBu>^ԘE JG Iғ`=R%)m;q,XP\=6$IO6~~jlTvE;. EYn=7$IOicgѣTipgzQsm,=7$IOiT,4|/HwERI&im46MSy0zvHR?'G$eUgׇ,Xp돉T>|[*n~>lf{*ITM&},Xp3rBT}2|5ztJRVn:3|hcwq $=}7EŻ$iY?ߧϢ|#zH9K?S#S{"m==C$Ix/G@ŵT>~oȔS{Kg|6Bt}s$% ?#G$e+{ 6bL/^ Iba3:wyUJv򗭭h#g$iV~FâG$eY E&,=ѳD,u}{9T}~7Kڻ* ) :ѣNQ"CmTƓ$i=^~fZ}i|5#NSs??cFeN9#IZzǾ72`&I|_dʢhƣy#IZϗ)0)/%i^sX/2eF(zHֳm_MUFkY!IZz__dʢJFtG$5n?dʢJy#Iڐ=$q)|hrko; hfn۾(w_T#Lπ"cmTo5ΞKe%Iw_E,ڨ=w$Isw_k=$GE,ڨE|#IІP]K6O=$n0,ʛE4^G4Ǘkse+ǔ$5Y~hV$ͱэ'bzO|[|k;6*izT>vO $ͱזǟ%@e˔qhFW>~쫚τ"smT$ie] :SIʃτ,ڨ zI6A'uVby|<=$I3Իυ,ڨ%@,$mDI]^ SYC^UP4E6O[%Inf_aڻh*=zHltgCmTZ?G 4T,"\_{Wǎ$)CmT-R}$z&I&C|doFIψ!,ڨ5G$I҄c̏ίL3|.9p,ڨ=$Ig`ڻ&)zHωA,ڨm_ѳI42NHLE3zH((ĢZ^Ll$Mrzǽ/|6NgOe&zHX* (ĢZQIʰ(3Ί_LeI"Iz~^ cF=,}A*{F(IҼ,>6Hw/'$ygF0mCg$i>*_sX?>1oIRR{ٖF0m %I/NdY<ś7lώh>l= y+%6IR}h 6jexѳJ4 ?ڻoko N?ChVn$-@s9I_/ ?Ch^7IcwG,I4wB=D7MsIi?L5E3s3K@n:sPg4I{JK6G'ECYQ;~-zfI]/? OHRsuyR4E3(=$I RgƟAMf$я$i#럳8\j.6jip.ѳKS_? 7^FK&Tgׅ-EYQK}=$I=O!;é?dK&+ϗ[QW5g$)L v[YuitO$itt}6G0IR`OI/ ?nzG;aIҤ+ϙ[QW3$Q&I lOIP]_F7J5,ڨmG2IRpe;/$śi}V$I?gɢZY&I{۾B!l*[k+IMh|ۓ M4˫R%lHxڻHE,Pȓ$ռUw5Ǧ4FKj[aɢ .'zI2itũ{;R1IF>;h=+6e) {OԀw_1<3gOG\4IIRƍ>̣,cg$I :ixaIsy6(uVB|;OԐfL' $=6=m3P/O8{:w _ .\*3LԴCsh#_ӛ;G$׬JsxJMw:Npx$Ijx"eFm= %InC%{>B$wі}ǟ"D5QSk1MLc]664X1յlc+330UG0JEtP@.(0 e33g?_3\;$˵ϙ}'wjԻXZ` ? }R3fhLWxiJ 6Sm3uLj}?r3Z-u8* ~R{Ц r_ _E5|5mL-y÷+ `WMdh:r_` zezyjf4Sj~Rw>J Sޘ_Yڐ?7Uik2i[/E`U} Z-R{T.ce3 O|2*:CjPfa5s3ޕ}S_I Wo<'U$Oc3؃aЦZTm8PU@qe&goM/Ne/o%:_w1iSwsZ`o[-T7R4.w {AsGFolφ/ b8|vlY,b26N~Kk$lq]2>}g]}@sҶfhS|㹯G>[u*mw0NR Ow)*+Cj`R5?oUlW6ծo}-߶:YvghS-s}k'l?~fVTNx[Sc*;C~| 59J;Ms_C`joL=UP6ն/Ii}-Ρ*v8Cj]r_KAobgd;Mus_NO~>VMopXe?Ц>T'g?&--U侶PCޜ\MڷHo-}mfw^<"4CoC~9~'5iaڤr_c}kRcngaڤ5Xޓ"~U1ڤ7߳=ULl6)摿R5}` _ט[bb3I?3h`AϜ*&:C\W4㳟7UL|6i >.= U{c*~a&3^@b*2Icsv`RcɮϘ*"C4=U}O`G?_*MK6iW~ mԽJSMgwN{~6קr+)C4Zkۨ};'UL]6i꯽(=ԿHSMZGC4pf IDATf*W,9RTiT4|A#rkO}tULmo-=!d0,WOJ2=0Xk󣊩OKEJ㯻zy[RUuULu=Wf0ҬW.#U}IzW}6QSQ?W8zn`:UT侯ԓj؆Uf@R׻gB3UzU~H]s;WeMT.^3,:=NJ?:: ,0ZksG{Is;ePR]wJ֛ @]91PLֻǞg~E%ձ)`y˨clp5OZ#Zg?]R굞8u&յ%=?yYKW?)j#_hh97\קT rwfE e?ګ>6tO&սG̞^;5zM/l> +^Iu\:q?buC[fpRk_{Qj-~S1ӕ=ںWJ*R.=`fTSy>v*fCu"Tu^0g+NE-xSmCa %s/}`&=)yNE=ZkZ~hkXsuBޏC_2NOO|lhݺ:Z') `T֥_~nS]mi0HC%G0e\iy* >չcO6xx])Z'>+>Mi[߲CP W9{}.g_/3>?rhrA@ҖB6>0Eg3ղmhE<IOuSw+7|g2ճ1۪Sm)5'eA$m^âSS9>M)W5+w|hKNjOFғ9inWmpߚT.#YLyk g|YIڼA?0<7T?`8^_CIڼ[:^oްMOg|V4-}vs޲&Zw.շEipCiJڬ摯Ndr~j̥>}ݺmҵg%my?~IU=|[*g-շrtEKܢԿmLN#5zMsj]Omw?IKyAu!3ߝ|z_.^:ϳ$m??u5Iw=Fh1CpkkmHzן]w_~>R[k±<ÆR4LojU{Sj~淳T5'y: _Y#_Rxznjg"CTچzk/NK'igo[VU}{cehrA_DI1H|cnAcچz7Lw˔>{,߮x>z7(u}=: nJX_IUq_yd}ޏ}hꭽ(5{n_':K4Xwyj{3jgg,sAM- -Kh7Tw[y R˲<lhT~ײ%=RZK0\ն῞~o`AA<%r^ipߚ3joLͣ'F};Rޔ`n;V~ ?LU,`uukT 3L|#4AN`;?~Q=+W4M6Կ>M:$e~j1g7z$>oIz5'*R{d?~R4&chޚUq Ioniܗ` z5h4NO跒zo'ռj/ ~si3UWmӤQ[/Ia*?T皟픺e0AWTԽ4 &vhR璃Rc=Ju}'+zל0z^sj~I !U4gIHs;jX ?#5|oSK4bh{TޛRw}҂6(=9%d Ż?hf+:~,UNlG1NWI ْ]SEֻy D3Y⥣`ڛ,ʡQnK ?ĐPl4X]?}`n<Ȧ<+Ny[]fJn%S==jmH>#^"x/N;sc_ȦqoHOUyU31=^/N*7i|5zMsc_sUGZԽөxGM_M/&Iq^ ԿiM]W;=yt[{Qj_<7?Y}_TU jdVWwjѷ_Y5MuWIJTi~nONiZ\$4ytg MPKvM/Lͣ_ڧE\Խ_4twDжN3:uwBj<ͩ\4xOjiқ[zלU5z[ UD믽}7: \ S m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m moǎ `W݉XNmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm<IDATmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmҨӅIENDB`PNG  IHDR\rf pHYs{RkIDATxyUՕh8غ8bkt8ᬉit:D,;i dJF"$ $2;;^疂XUZ_UwwsIk<9V'oߩli]/DK# ^W6@PP2ǵ<< ]/w0?9ۜ[4-CVvgyuؔw _"6x/JWoޟ=F4byY4 K!VrO"/iW^(e"G_=?@I/l?R]so* udCZ+~P=̲ke~;BΚd!׫IkRN2ǿXsǽFo?d<YSד A)2'zJ[h.Sɚё/U矺k+_7Uz+u(O^gD2F~_F7Q"96pd Yw~ܹ] _jxwBvQO}UWH+C۹ @8 l .h׺ Sg+oGE7 Y NXA>]Wj&c@z5brPv:n7ŮИm޿Y:w=3TG6wMGE0?n~Mq@FxwE@Uc}=+u)o1 cC1O6[NܷqX߉TqšӝH.x!5TO Je^t+{aUT2@#g(ipM9d~B=ڞ5%Q0HAA" Uy: zYݔC.((@6K8 D qV^Pܞ~S{q1{A!HDA"8$" ~Skz{B"rM96B"pPe Q!WȚ[-(wA!HDgqM9~J2t! I a/(H`4n)8B$6|7pa/(H`uߔݷ$"Y o!.(Hv7<y؋ A"ޞnJs9{Q!H^SnB'$g؋ A"'n)5-{Q!H'f+؋ A"Az^5%{$ A"ڝ5%ne/*HMzx.S A"Ym7%ѻ_^Xai:הt{a!H^Syn"wa!Hn) ZA",{kJ+g/,x/ה;$ T֡1{q!H"$"'5%1^\T9%{q!Hp{MId$B;=$ƩŅ v1Hxb{q!HF;,Z A":3e1D 5%IOx$gn)5$R5Ζ vE/2c\-]dafn)ޫ {!H"4"-؋ A"{vȕE vKs{MI Xܓ A"{$ 2?D kJȆ[D.kjP,  ņ fh%הEr {!(0> ϔ{L@Z"؋Ao=ה! `/55MmNgP*zwޠjAO( =[},JeB*S0$2R2G7$䂠K]\NLeYzqWI9';KP=昿LevX{xnאlG.Z6rw,.Rxߋ m9@ 8єTNC"KPbNb )4s\K~)(ϸK(v`=nJln6e~G$,[%q߹pIǓL^T5-T1_̭s:;;FܦSE\'GrI<@na5c 7v"ـgw2ؠfd;un"{hr$ {6&&vw?;1'?H[\_ ͌$A EPx矫ZXc7!$U`$OwHyTt݌r6}%q $\{v3F-T\Zyd ݔ){p}{mpg,pw.͚Ձ)íy<V".ȓn7cH s6ge^cW5 KZx0!2@Ft -l>Q lVE=R=UcU}l_FH*{eoeS^1{8cnR`T㜱߻8Kgջm'5f )gZ UzW pp̅ loVp{ [|넳aJ5P.`QPmČױ&o'2;24R%kF'n ɚ_<\|dcxwT3Ӑz&d/O dȃ,w'^[9s3u={BX5@v ё{AVm7i':ג6)Z+"yUc(=e?׾>9 A%X2Lšhn_菻 { +>G;c]}` {Dtn*hԏ7׋ >%(+H5 AO5Jb r{2K[l4˞œ7Z>]! 6IENDB`PNG  IHDR e^Q pHYs{Rk IDATxyeu}T!8š&1m&JFIbL361I'vu'nL"$($XX* R @EPgJ"*CUs>ZΞ؛7PP@ n8z_:$:g~0G)Z{(ZSK?$-h/[/1 9>ZSK$ma3szQ|w=/@~(,Q:*Ul^ƻ :4$M@~_}L ߐ}k`L1*Ϗ|fjhZe_\}Q4i|xA `L!WceO(=o`elOHZ=)4W;ٷA8뷣I>׌4u}GD}ۨ}oFF ٷ ` Ft?y ǩs;gx뭚NH[ ` n4ڟ|g0bϾlyһgHZG)7Qٷ Ay]G@iK0YHߐU\0 `z:_Oښzɾ4̟!)ꠟ^/604̨1#V-˾|4=}} yA`0BoQOꦖD}/!`4utO}oǾ#^}G?gUm!Oꦖó/#` 9$r!4p] clp%m`_942hwIays4D$k >(Z3_ A@H'e C/%`D4j快H|a n>?P,0ԫ/QNlAW0b^/g4M-^ 8adQ|M8i80rFT}QISu~@Q 3?Isɞٗ0↷]OI4Bra a Do_O3lI#[}P a pOm<Կx+ 3kHI:@İ}ha tOTl|d lwM4zO^+0 oDkK&GVd_RwIWuiߟ}Hahhj|[5}I`؏#iɨ7˾KL0y2hi|ξ t7EПMב4zU:ʾML0y0+ФwDz/)`5jM4zU_ Gas4k9ΤG4MeLzڨv{vѫ:nmȾML09n)Z{H3i>{0&𶋢5C;ѫ: ?1 lfS:zİ}Y\}t{Ѭ}N( `MQ}g?IQ7F{8 ӻ߇$fy- `lz;Ø4y]4*DM3,Hhֻt2Jm1i>jh7J6E_N?4M- ggߥƒAV_sB0i~q4ܖ}ID~ +_$ivOQKm `l5Za\v{vɾCGѫ:uVm `l@`\vR%߼ Z˞$i|ٷ(b:_Ҝ!7}9U=;k$o%w.IUkdߝFA#:*CM[We_F y[Qw/I#SߏF^aߎ/I%mSSKbpWh-.Lٷ&cozKȾE$N/Uٷ&b0p|A,i[M},)N4:;H1`Jږ:1g_B<^N&i4}iĠ}ka^~I+ikk(QGkIמ}[a@_=6U{(Ⱦ|R vJѨ}/dߒFAPꐟN`%mU+]_ɾtFBs&i$~ku- `$Era*iZξtFǰ#~)}MRz$0 u>ٗ i7_&)O@- APu_?9CuOywDd_:#i+5}W};Hgw-}#Ue0&)Q5V (V-')dߊREM0%mI+Ͼ\XZ];:G%6 (Ru+?LIOTs}ުeuZ{oCi zG) ~0at~[}Hcw^ǫeѴ˾T^x^{ů{f߂ilS^wue017%{jEu- AP)Z˟AJzԦOg_&wG$-zg~REQc[,L^{C{mpawa@Q|,ChuN~WDg JQ?IW}Ha}[?DI_{knʾ<&OJZڇ. (ǠOM%}O+}u{և%-N˶>}Xta@1w]J}i׊WJZߺ" b:2Ⱥg}0(RhMo^(i|[3ߦ:ξ,[5n(i] 3>]od_e>%-lߕ}Xta@1Z?7ԚZ?}90 pSvyz}ٷEglL$;#ٗ0wEI W۳o3 (B}OR7F {ٗߧspm`QE\f']syKGѴj;JZܜ}XTa@zWL𤂛Zo~>2q oIKo1 (B?Óʭj:` t?gg^APΙIe9W"a%赢}%%o}wXTa@:'^'W׏D٧?[a+lwJI#o- (B跥xRa-.w\} zc{y~ٷEe:TV/sit}k-%OKȾ,*0A;xR9a?`;# ɞٷEe:TF.?OyAHϔ4};XTa@Z4Óhү}5%ͭ{gMAP^?I_-T` o$ZSK9%m{a@i "ihg,&SҶg (A1kEWJڦ E0BֻOqԚZ*i3Jc L U_OqAJ E0ӂӣpS "iG%mUa@i "i!\s\ "?)Ya@i "i~Okt?RI[AP0aϪ}_M$3^/L?e1`ykji o]}JlpI晴(04a@ 4_>9nTIOAP0a+_ogoFkSW%=~a@i "i^~*˲OeFL俳Jz E0\OcFѰ~2Ucg (AR{T$ix%њZ*3Jc LsKOaF\31`mwGO_@S}'=+3Jc LRODZ٧/cbce%`a@i "iSlαo=1`w?dzMZZI (AP0mOE6O[T n+1`-OE0WNxE; E0Ӗ;OW&Ƴq%m (AP0mI/S̛ + (AP0mOE~I 7|#Z;Jg (A&4`>w^ E0Uh:fLi3W*904a@ x o8+` ֜+AP0az7`5MtzK;Tja@i "Ѫv{V4e^h-.]X*104a@ h zL @Ag}0]X*104a@ u~OvbiDs߉2Jc LӊF}7OK _}P{TXa@i "/#T ڇwc E0ӿ^A7`;.Ԓwd E0ӿ7uU9ߑR2Jc L3uOSfߕ2Jc LծόfӺSC_.}Y*!04a@ ٧!|}T?'Y E0+:d,Mza@i "Ҩ\} teg (AXu`kpI$g (AXU>3>5M{C{41`Vf+>` o$=Z E0+A?1gz:'N41`V^Û>`ߩI (AP٧l93Z E0+pS)ۤin&(04a@ ʩw?fn0'wO&)04a@ ʨt7fn07vT{8=[ E0+UGdj0/_94=[ E06dj0?mi2Jc lxNijp$d (Ad9٧̿zwL=04a@ &%Q߹:1X{z41`6uO ND-sa@i "Mh;D}-٧,M心KcAP0aYdZ(:G-=\ E0]~8S ťq (APɫ U_O104a@ &jEݘ}Z]%Ҹe (Adտ|S RtOyw{4n1`69U{8_eR^6Z˶K?)04a@ &gN{KAP0aQ# R߹_ "04a@ &'eJ0ti\2Jc lkcDSgJ0k54}] E0_Ti#O_!04a@ ƻ٧k5$] E0מ} HҨg (A> Ts&=Aa@i "o5'd>0:wi3Jc le`, o>?^ E0zcc}Q (AP1iٴ.t6w|i2Jc l{f^6`"(d (Ahe"0Q\?/?=ϢsܯFjg?jgE{嫣sۢٿŻkD}W6d Z+3Jc ld)ci7;\s_~jg?}_qxN4ݙ}`u縔AP0a[L<@ ohg~~}/_Jgݟc>3_h#c'[˶KfK1`6/=lZ7zgV5$y=nUpti[.t-糔AP0a#ڊFSm>= Epf.֨v}FyR[+b}1d~XTW? E0ͺg}0[ IDAT4Q_/%`qYtPT>39ܪݞ=fMfɳbg (AIl;Գ#O naםQXbMk}?%Y*-ba@i "NSߓ}:c*z$}~4ǣ~t7eEgYSZ E0}1t1Uˢ}ҟݟ3{.5ՆW禴1`61iO1?ԄӣwG3S7?3E (APѨze@MDDKӟ*{yS~"e (A4O ˢ{{5}3Q5}tP4ߛ})w#yAP0au?٧i^4S3hzg_0ɞGi12Jc ,-fiUQҟңU_WĠ}P@vyzQZ E0˭M}06Z+쓶Mf_:{ӟBg (AXG/} 0s?ONIRĝyK BFkjIPZ E0KlvM}3]_?FY跳/U&ҟuBd (AX‡VdvHy0z~8Z˶KI^F}ײ/[&T;04a@ %~;zSwHfIPWD}W6{ҟo|f (A"6}49#suxeJvyz ~j%2&ca@i "-^ߙ}E 5;~VI\G+ ϧ?פ (APkهSwcgTJ~#ٗ>cnp4i2Jc lZh:enFEl<=%OfcMv}f3M E0[:'+P0"wN6I%W1cw_?Ϥ (APiS5#`pg%I?7۬k2i2Jc lZٟ`0z|,ZSKKԒ譚ξC0GRLca@i "-|Sߛ}HTsN#I]1g.3kOIs (APopiه$%"IO\wFZٷ Fݠ]_I~Is (APnSn>$\uDwIڇ!ٷFH1XsBpt|{~J E0[:'n!` :_?$m[C_M; Mbx9[5wj? (APmpqهE,-F3ӟ=j;7gbM}7`'%Z;?SQ (APg^_/ɭ%QK0ωު蜸sT{<7!Sa@i "-PSKxW`W?w$-h3?~oM-MHAP0a 1틻fZʠ3sDI_{kyi7kO޹OIK%d (AT߳&]c06¾}7k3Do?[U{t7fߕB۾8;:~qI (AP{>,w?c$Nc~y kc?ֲْ;04a@ 濙``oOH:'+fߥ4m >#OK7Kں E0?9هkE_Hzu `Q4cx˅[5wj߃%=04a@ }H'MwStI_ݳoYj?t~I/7'^~01`6Ѿtp!`> 9ҟ+Ƥ%1w.mSgM :"g~ ڇ.Z˶˿JZ E0ߚn>UD?MHmeP}-1);s䛣PIi1`6xe`>g9Qo)6C1_WtN9=_~4Z1`6ه9牤'6d΀ Q:WFEg6(i3Jc lpf`_?5ZSKӟ'ƿook$Q_5'Do/04a@ eO)/Fk'&g<LfӺxNVMG縝s�4a@ o>lYIWoqME9Q (APyxvC 6h}Iڲbx˿fQ6G^3޷K߿$AP0aS}C jgɮl+z1XsBpt|AP0as Pfc3DRcĠ}Y1}9#I E0{~'07I=Cٷ>`5ݍ1?x{Iڒ E0g} fcCRy >*̇aO?^uDtx_1ZSK1-1`6u_>li燤[Fbc{_E?'4O1`6f̿ `<αHfH)Q{m&V1XsBpt|5~Kf (AضWz}xOfHң^ho0Mbx9[5wWA%i+2Jc l}"iٷJ+Mra/=:'nT{(:q (AP9|0dtI^H5;&A7껾/3핯ԒkV&)04a@ ¶f>G Iڒ=f6a$~qpi;9ʧ$-Ba@i "mcGcſD4Vuɾ}¢7U9qxnu(I%f (Aض>s;ӟ << nE?xכ$isa@i "m[W1TsB]o07 kc㯩ח$Q3Jc l=#% I_ٷS2Mo`'/ON$I[AP0aVCIkɾ£yxNVMGĝy׋$in1`UDaQֲ'?'$iέx_]쿺9_WtOywTh!I E0IaQt}G3Boh[+^wu~>xhM-M$I AP0alAه 3IW}{eB5m >#IV<-ܜ}e5cx˅[5wjے (APlٓ"# ֞|s[t$[=/eDSվ?~KF;04a@ ¶>dd<ҟ U=+Mo$97 >yi$i3Jc l0"}iAi}e5bx˅[5wj租 (APCIZ̆|kK~=QsMTNa@i "mE+Q3:* IXWDw`D}Ϛ\uDt@y]m~nI (AP-}/f.`Iʨ'Vh6lv֊C$=204a@ ¶#poGRsAR>g߆yMt'+=H1` <,p;.K&HRfcߞ}+f؏z_2g/%$I[AP0a[^}痲9w噇%1L8Yf&h1cLf RBBT-,4YDYEEviλ/)8:t}}]USo T`i՟a3zfyn:GE?$m 4a@ l6Mӛ>@w63$jƽg? xՃ ;5}M%IRi aVV iw)$iR]w~"J4i aVwT xf/)$ibߩo$MC^֌W=LqwU3ʦ!ӏ_]%I <a@oxg5e$MSt7Ͱߌ\WE[H53 žg)jtO$MUiFo{oz}ffϟs$IA `ZDƝ $ino4jzv$i3 _߫>@ GϞW6ky~l-پK$m 4a@=sw@4цtGfӏ4vhfm]!Ila@0 AROi @Q$I 4a@7>]}ff6~I$IJ HcD0[>?]}(]Q$I 4a@5kD_}P_$I3 ֬s[{˿$IA `fsv> @-K$IRba@0 AZ~v>g1=,ަ/I$Ii ak6$I$f1";T ˿$IA `fU} w/K$IRja@0 Aؚy,1:'Yw_$IR3 ~4hX}%%I$)40 A lZtV%I$)50 A lڟ:3 IDAT=|Sw_$I3 Vs[Ocpۙ}I$IJ HcD0[;W F%}I$IJ HcD0[E> @޹_ݗ$I 4a@%gOsN}I$IJ HcD0[uGU F_+K$IRra@0 A n=$1Z{/I$Ii a7D/K$IRza@0 A$FR͗$I 4a@DuQ7_$I3 VT [Ǘ%I$)=0 A Gg$IA `6WsX}w+K$IRza@0 A\_W}SQݗ$I 4a@:_s}I$IJ HcD0s_T F,K$IRza@0 A\ݳ1ZJw_$I3 ]{9b~yw_$I3 ~`[} a3h$I$g1"50n/I$I2 rJ9"/I$I2 ~sD}|I$IA `6Km7_$Id1"5X͗$I$y as+O+K$I <a@F?N9" n@ޅ%I$Ia@0 AlB)b߭/I$I2 fkS}C}I$IA `6[O}I$IA `6[߮>@9%I$Ia@0 Ale;V F%I$Ia@0 AlR} ݳSݗ$I$y auN~{)bt?}I$IA `6[wT Fw%I$Ia@0 AlU} 3/I$I2 f{v螹sw_$Id1"8=ʿ$I$0 A lY[} sv-K$I <a@ٺg1z+>Pݗ$I$y auR} |/I$I2 fx)b߭/I$I2 fS]{w_$Id1";Ow˿$I$0 A ly>@ޥ˿$I$0 A lP} ++K$I <a@z^} .K$I <a@z}1@ʿ$I$0 A lފT Go/I$I2 f._),޶/I$Ii auܹQZ/I$Ii auOW)o$I$g1"=寫O}ʿ$IA `6[W J+K$IRza@0 Alv>@R$I 4a@ٞ&0z$IA `6[?>@]ʿ$IA `6[gَէһ~I$IJ HcD0 էҿo$I$g1">Oep1~I$IJ HcD0}oV sʿ$IA `6[Oex~I$IJ HcD0dSD=v{_$I3 fk}Oe#~I$IJ HcD0zi) ̢$IA `-ڪiƣsDi]_$I3 jz3Z}_$I3 ?p9o$I$%g1"5~sD霰S_$I3 =rK9to$I$%g1"5sD]o$I$%g1"5sD_sh_$I3 ~v9 n9/I$Ii as n:Q߽/I$Ii as [Z}(n/K$IRra@0 A؏%2n?Q$I 4a@e{U x$I$f1"ջV NkW%I$)50 A l޹>@[_$IR3 ꞹs9tNة/I$Ii asuN~{9tٵ/I$Ii asuA9/۫/I$Ii asspt_$IR3 jsua_$IR3 ~OT9YY$I 4a@kD(K$IRja@0 Aꍟy$qf>$I$%f1"۪O}kʿ$IA `z> @β˿$IA `z;VT Nw%I$)10 A l:$qz^$I 4a@%W NCʿ$IA `zKW 3˿$IA `z|$qF^_$I 4a@/K$IRba@0 AukI"7@$I2 V'>?$IA `zC~$:I I$Iii a']K I$Iii a?֢fЭ> @Կ$IA `f> @M'%I$)-0 A lF^_}8]Q$I 4a@5y^Y⌟/I$Iii ak6 ۖ$IA `_]Dj+o$I$%e1"YV Rg$IA `fY}HݳSH$IRRa@0 AؚuD_W I$IIi ak>תipӉo$I$%e1"Yk> @ה$IA `m4~i⌟y $I 4a@7^`i"zY I$I)i akoЍէ>I$IJ HcD0[{\P}HVH$IRJa@0 Ax\i"߭ $I 4a@0 $VH$IRJ~1"> @᷿RH$IRJa@0 A~/Oio$I$d1"W S,ں$I 4a@էU$I$%d1"4hP}HTH$IR@a@0 AغD.ߥ $I 4a@u7D_y@ I$I i anD޾ $I 4a@B%4z7@$I2 ]ݪimfoSH$IB HcD0[wS<Z$IA `KP}Xc\H$IB HcD0[w_U}X($I$ig1"4hP}"H$I$ig1"T _)$I$ig1"_>@w$I3 `i'473-$I$i!g1"=/Ů>Dw@$Ira@0 A띿[buNw@$Ira@0 A]$I$- 4a@oU ລ$I$- 4a@秫Ok+I$IZi a߸d"y $IA `LZL; I$I 50 A vfb$IA `3ꞹs; I$I 50 A 3_w@$Ija@0 A?>@g$IP3 ž>@c$IP3 6OiSd=~-$IA `ayTڇj; I$I 10 A lS$I$- 4a@ kpէջI$IZi a˱>@ ǔ$I3 6>@gw@$Iba@0 A؆9揪Ok}YU[ I$I -0 A lj-է:I$IZhi amfث>@qo $I$ie1"mx>@$I2 6ϭ>@_*$I$ie1"m/Ȯ>\]]H$IB HcD0z+_}.XE[$I2 6α\}.h_YH$IB HcD0ZsD@$IRa@0 AFhtOwGI$IZ@i a۪Okpw@$IRa@0 A5}yb ﻪ$IA `$rw*$I$i!e1"m\>@~-$IA `qu'9I$IZ(i aWkWV Z/$IP2 6E[5Mol-$IA `lF$IA ` n=lƽgI$IZi a+>@֒I$IZi a_̝s⟗$I2 6{.d[ I$I !0 A lk] n>-$IA `iW=T}:XGV$I2 6=V װ@$I=0 A lYvէ>I$I 4a@MwO{;I$I 4a@MsV ZI$I 4a@M_>@+I$I 4a@Moy|O}$Ii HcD0F\[}>\q{@$I90 A lxl-$Ii HcD0z}|Ѻw) $I$i3 6Ή^}>hk/ $I$i3 6|ц~-$Ii HcD0{-ަiwnfmUH$IҔf1"F>!@ց. $I$iZ3 ^XU Z礷$I4i a/f_t eQ[ I$IӚA `'6@$I50 A >lD=qW[ I$IӚA `[m g55^VH$If1"F\}Fho( $I$i3 ^xO>#@9$I4i a/ş>#@7PH$I4f1":'3Dwu[ I$IӘA `k-پU̢I$I 4a@Т#P}kI$I 4a@kO sI$I 4a@eէo$I$M[a@0 AwGO mxo$I$M[a@0 AsW $I4mi ag])Mkߟ)$I$i2 6_Ǫ sI$I 4a@U Z, $I$i2 6/Ю=7XH$I4e1"mZ}Nhn/ $I$i2 6_~Fff$I4-i a/oўV$I4-i awW Z$I4-i amgV eo$I$MKa@0 AwD=tc[ I$IӒA `y'653{=$Ii HcD0ۼl_}Rx/@$I!0 A l3hfyѺg=$I) HcD0 イ|[ I$IӐA `~vg6@$I!0 A l]d뷚ۖ$I4i aڇPH$IҤg1"m> O {I$I 4a@-;O Ւ@$I&=0 A l4XyZi {Y[ I$IA `e]Dw~,ڪ=$II HcD02uNة=$II HcD02~/I$I 4a@-׸D_o[ I$IA `~6o$I$Mra@0 AUK mת sN$I$Mja@KO IDAT0 Al6MoU Z$I$Mha@0 Aؖm'6@$I&50 A l R_>1@+ $I$iR3 ¶l>1@~?WH$I$f1"mGvu}s{ I$IA `M3W Zտ$I4i a[7W /$I4i a[U ;I$I 4a@-_/T xܴޮ=$II HcD0uX}fx/~{ I$IA `{oiƣSD{ok~$I$i2 wU I$I 4a@iSD=-$II HcD0zƣI$I 4a@s[O l@$I&)0 A l~jsէ׻I$I 4a@kԽ6o$I$MRa@0 A5sD=qw[ I$IA `6.DMk-$I$iR2 αo>7@q=$II HcD0Z⹿:K>UH$IҤd1"o'>9@I$I 4a@mp)'6^P[ I$IA `6.k}I$I 4a@sOsI$I 4a@vM3U Z}I$I 4a@omxEo$I$MBa@0 A7DhfmUH$IRua@0 A;k@$I3 Η~񺧾=$I 4a@>SM3V Z%$I$g1"4zD@$I3 jx\[mI$I HcD0U ^ו$ITA `VS{O{{I$I HcD0+jϟlaB{ I$Ii auF߿-$I 4a@/>?@a$I$Ue1"[k;$I$Ue1"Z($I$*0 A =^4n@ֿ$ITA `V-$I 4a@b@i@$I*2 j._@βI$I HcD0R#w?$ITA `V?4v@-Կ$ITA `Vk -$I 4a@Qc/$I$i3 xRH$I|g1">׫ $I4i am7Smx9$I$sa@0 Ad4hg. $I$i3 &5V(k@$I30 A l2x=$I HcD0ڇj@$I4i ޽G]wn^9vpکՎ;m=2T/=qNiשNM6 AƠ(KbDn0[ D$"bPQr߿LξޏZ[{d ҂JQsHz{ Ik I00 0 TmsHn?c}$I$Pedc`֜_Zk/{M=$ICAAAXs|w@z?@$IUa@6a@ aͩu+@z $It21R0kV[@j~ $I$Pedc`֬w_$rV{ I$I"0 0 fջ}O y&H$Iҡ H Yu'^I$I:)5E/(e8~U\$I$ddc`ּ?+YV?[ I$I"0 0 5S ևY=$I H yuzOH{$I$ua@6a@ aͫ_~o93H$I\gdc`QJo2iV=|k=$I9 H U[7D? 2ys$I$ea@6a@ al* V~$I$i.31R0kfK4뭛~$I$i.31R0kf3஋$I$ea@6a@ aͭ<Rx0H$I\fdc`ܪ{<k@$I*0 0 [?<|w$I$Ua@6a@ aͭ귣@zI$I l  š[딗RO $I$Ua@6a@ anO L\xD=$I H (>u@$I"0 0 f׻/@zݫK=$I H ٵWZHopy@$I"0 0 wJ @$I 0 0 7| .%/ $I4)5>L\{ I$IAAAX^G $I$va@6a@ aͯ /I$I l  FtSHnL.8,&H$I,fdc`6UTk@$If30 0 ѨiO ~$I$i631R0O W$I4)F~* w{=$I H lt^sȭE/$I4[)N=WD?:@$If+0 0 ѩw @zk:H$Iledc`6:uSsHo{ I$IAAAZ|t)*V?H=$I H l>zwHuOI$I l  FE?~$I$i621R0W'{ I$IAAAhؿ~2U[7I$I l  FGlm-'=/&H$I 31R0o9^k@$IfAAApzHw$I$40 0 ѫ{ [WI$Iia@6a@ aW?lҫ[?,  $I4 l  FG@ze $I4 l  F X+$H$IL21R0z} 7@$IfAAAhֹF??/H$IL21R0Z'z|r:7A$IAAA6vOHsѿ$I4 l  F/~>7|8H$It31R0ݺ;$I$M70 0 ѭ_~>T27A$IAAARzO Χ~=&H$I421R0@z>~$I$i:)v[Έ~BU~1H$It21R0= W(  $It)v3~& PJi/mM$I H l}4׽=@$I60 0 ѯڲ67ش*H$Ifdc`6g^ă@$I60 0 ѯs[co$I$La@6a@ a_kKJO 'I$I: l  ƣc[@z[?~$I$`21R0w~J { I$IAAAx[pPZ $I4 l  ƣ9~JR:9&H$IT31R0&*ߎ~Nn`M$I)fdc`6>Uҫ~$I$i)O[ϊ~Nݧ#o$I$M%0 0 {;~!&H$IT21R0Zg*9PJ I$IS H l}4I7{ I$IS H lBH~rk=$Iddc`6^n`OI$I:Pa@6a@ aU·F?)J)K~$I$@)W%/)F?+_Y~$I$@)_ǶD?+߿3H$Iҁ21R0w~V :E7A$IAAA[g@)o$I$/0 0 }룟MI$I_a@6a@ acQO j I$I H l<5iPI$IWa@6a@ aYֳo $I l  Ƴ~ZRzI$IWa@6a@ aYWE?-o $I l  ƷGVxNM$Iedc`6U[F?/J)s5&H$I21R0z7|0yPJ]7A$IAAAֹ RJuߺ I$I{ H l|k-yI)0Ww.  $Iga@6a@ a-O RJׇI$I30 0 np'@)w_I$I30 0 O RJu7A$I H l'W~T&~$Ilwddc`6MUJ(wA$IZ.Ǖ޺eiUnۼwE/)÷F?3J)~$Iiᑥ]37.+G(wև~"ކfdc`6o=+PJ}iM$IFO?vVP7Vꟈ: l  ƿ~fRmerawA$Ijz%/- Rz'Jem'~6fdc`6xU3`׆I$Q-~a8/MpRzv?u{640 0 >(_o$I#K{f^o\O?V9=7 l  r+oyMM$IUǔv/ =sok l  rԻO RJQ\px]$If֒΅o9ڲԓ<>_fdc`΅o~j>uwA$IQ_X:++u`Ӫ2ܶ.Mչ5kha@6a@ ay[F?7JEI$i-<[keںWFIw l  4|lKsRsEM$IUk1Kʨ~]650 0 < \($I(O?^RmY[me־7_fdc`O_ $IJQ}w Uems)u]2]W740 0 <.)I$i (ǖyqYn(e-Y440 0 DMUJ(T[>$I46S:O(;c_y550 0 \U(ԝvS$IF/.ӏw_Vg>[S31R0Uֳy}]$IR[㯫 l>~#ճlha@6a@ a^'.I$5GcKwͼ߸T[72F:oC31R0UWE?9vB]$IR\ǔJoD-u_Qsnja@6a@ a'E?;J)u2 IuJgo v}4T_?? 450 0 |m< s~$I4MO?^2ش m.F EC31R0W~v}$I4Zgt+JuC)Na朗)s[T~$I4ZK)'xL஋NS31R0WkK tI$Z'tVWzӏE4 yI{jja@6a@ a9>%K·I-<O?n? m_#kXC31R0ΕO]_>5.H$euwjR_ Cշ sM H ,g~z2$I8ZzL>OjR~+ ߣaS31R0Y_~zذ*S^~$Iơ/*Ǖ޺eiUx(=o]lja@6a@ aI8~+K$IFGcwͥ_hkkC31R0[-]_=;.H$Ÿ~^߸T[7oGLj>650 0 o93-wA$iJoD-uGѿ1ªn M H ,oKM $I]:++u`ӪfQ/fdc`~~즻f^m$I&*OΕeRab[~C31R0]O]wA$icJuC)v]$E,450 0 U[>إ~wA$i&N'-kKy2W,wa@6a@ a]'n^~$IRo*k 6)S߉U z🙦fdc`o~? $IGcKwͼ߸ aLY?G H ,y_Xp e $)}ǔJJuC)vI0#ׄ\550 0 0 g.u29qTm$Iyj-yi\[?Q-kK=XD0Ykja@6a@ a|t>A$i_X:++u`Ӫ2ܶ^ IDAT\uAAA{W3`7/- $i ZxDi/?t+vǪuUdC31R0S{k!~A$^ǔv/ߊcpFAAA&V֏"?6J딗IZK^O?^RmY[mѿ@ 6_s l  ´꾫"^|bm$I i w/MpR:)o^ l  ´O n?76HQˏ-5JRmPJՋF஋AAAYy|S`7[o$IZK)'R=p})_C`, :罩)i{_\J=~즽쟇I4{d~ڲԓۢ݀4w 450 0 0A$MJח޺ei{_?? l  wMA$MGcKwͼ߸T[72F*fpoEC31R0ӏ^n3;"A$ҽKMF@s¿M H L?}~_$euKgq;ݗG=˙ߓfdc`قKy*IMK$IYZ^k]G*̒McAAAvz' n~$IQˏ-5JRmPʠ}9һaAw)i_Z$]]i?~$IZK)'RmY[W8z׼/; l  ´{O' k0>H4JN~q8//+?>@< l  ´{S^F@s l}$MO?^2ش m.FoaW;{ l  ´g,M~L.<">HԄZgt+JuC)NF@?~550 0 0Ε=}c}$PZzL>Oj#i^¿iM H L{F?Kп I\:E[7ǟ~x(c 550 0 0Y,𻷅IfGcwͥs kha@6a@ a-<Խg&u+o$IӏKVjR $@-lja@6a@ a[C_~{$MeY}B魟(Ֆn(9}lja@6a@ a[/(i7VIvuvSwzU~s WLm7)iou>O=ԭIRcP]3 n? m'FAWGAAAVWD?M7IR?ؽmqYn(ߎ>ZjS31R0Ӿ>@` $i<_~o:T\_S'`V$[ l  ´VE?O0mA4ڵ]:++uwοO?AAAUD?OTK$MGcKwͼq;n @&uq31R0Ӿj/m`/Wq$5O?>o>T[7oG-p >790 0 0x`{>#$Iᵖt.|K魟(Ֆn0D4?nra@6a@ a_}WG?QP-'=7FH]GΊJo2شjǸ~gcw)i' ^tV~#$Is#K{f^o\VQʰ>=#o{31R0' ^ora@6a@ a:P}- ٩Mg`lo93; l  t~$k~#$I߈>+c~"; l  tL؋j7B4;On>+cw_盜AAATL؛aUZ;!Iyu0Wqw)i*O<T؋9FHf#J0ÿ H LSiO|!IYS^}NZg&gdc`F?UT~'$I_=-¿M H LSk+,RK]joFoo}31R0V?5+~'$ISuDֽÿM H L஋-Pݷ.NH^_>co}31R0~K/S^~+$IS{ї`?Kgdc`_~Gwͼ[!IZu-lև:[ l  t-<ݧ.P}[!IR G 6gdc`Twu`_:EBtw_}5V}&;? )i:@`?3VH{G 5|lKw~21R0tj ~ 6_~+$In0dQ H LjR [er $im̝OG!0 0 0MM[{ }>uѧ`o>-[? )iOD?_cpgo$iu>ѧ`֏Ba@6a@ an|؏L'`?sQ H LQ1)p 2fHRWQEop?1{?*)i6j}R譛~3$){[ϊ>c~{Q H Lp=~kBW=>jo(edc`٪9)h_ I\=X)kM֏Ra@6a@ a390N ?}^EQ H LUk1)zL.8m8( Pa@6a@ aͶp K~7$)S_{G-0 0 0v[5SP!I^'џ~W=tc~21R0l7g T uO I_~7Q H L]?~LQ  ޏZa@6a@ aZg)>NDRџ}׽mQ H Ls6S>wCƽ^c l  4 n_ 4zv`2Q H LsQߏ~LQ{~;$i=ثv~31R0\:u`{W퐤quvSk[ׄG10 0 0Um7STm~7$i\\{џy? l  4W¿AAAUS߉~GQ7DFߌ|:G90 0 0_ 0 K~C$iTj/mg x31R0ӡ{w6IVЗ¿dc`CUWROihW$53X+#AAAe|#0 o|&HR5@:ݫK31R0ӡOzwD}c31R0ӡ'4o>-HRc[RwTRKk7`31R0!oG?{>]ZK^K$űL3|8ddc`C]i]7wDXuC' +¿AAAukGwo$5GE)uHw߅߀q H Lٯ~@wIjR,4Yy|  l  Qw>4erDѢ痺D .D l  >3%Ԅ{W' oddc`w~K$ mp ,Ka@6a@ a䥥 <>HRdOO1@Zk:Ka@6a@ az 1HRdշ9Mw`\21R0STD?fsoIuKVџaai[0.))'[$EԿO0@ZǶ߁q H La-8ԓۢo)tkRzџ_>~ )0 0 0E6fz{"Iџ^z߂q H Lű`tSMC8.Qa@6a@ auVJ=1`߽L.8,H\׻o? {0N))#_1`t>;7EK=X  AAAfѻ#$U6S k AAAkfIwIf^M l  ނK? ̂ɭeIzO,֙ AAA`ӪfI~W$i6k-yIۏG^ҫAM l  Ԅ=GYROn+_~[$i|ZR`0) N~q)U?YEf*eЉD{_߅q H LMzK?̖Wglm6%_Tvi wa31R0SS]?̢ݗIIsXJ]GNخ. AAAR?,EՂJ-џQv16ia@6a@ ajR` g\px}{GBMK'߆q H LM?̲~_$`j->O}' n:~;>ka@6a@ ajRGH0KC?~c$io=+ ai0)QRw` #IS_(e8l AAAV+,m?Io (}-  60 0 05c~c;#IſT~?Fsa@6a@ ajZS_Qʰ`3ZK)u${ l  Ī{; QQIFck4{4JJcbb&&65іzf6PQAa (0\"0 }}c\f3zk]x~ϓÇs4hxy{FX}ُHbxuI (AP0b >}4X wMHc'FWAP0aڟ|u`uO}OFT}⧧{!s;AP0aՆ?9x@ƨxYFRM-YX IDATl˰j/&<04a@ 4 0NH*O0wE  (AFo>,IJH*:e?x KM_AP0a٦F#jEu9jsb<αogAP0aW}DX`L9ip}<=wIgAP0a:ǽ=z$#z|0 Է}=QJa@i "i[hfZݏ~)#ik#'3лp*QJa@i "iԫo8=IZ}~2G~0Cߒ(%04a@ 4uOOE2αIҨo9? 5ZS E0ӨWˆ Hg?#i_O Yo<3QRa@i "io]}TX,N|cGd=}O5f{_?J (AP0C[Q` %4u>n# Y=RRa@i "iiD3>.,ӣ5$$i[B 0I1`qwG Iw_IIʣSlAP0aOt Q}WlѪnu 4QwJ1`qkxD+NIX`lgSJ (AP0[ ?}lHNIʯf>R3Jc LV}l4=$Iy.Xy9-f (AƱo>:d=OI%ѿ'ֲ1f (AƱWfFAݏ $iZC 'l˳=Spa@i "ik跣N7IZ?3ן`t3g (AƵ>>~cߖn@KjkEkgk (AP0k V' do~הAP0al`Խ~Qa2wd?YX@Sޝ)=04a@ 4 *0j(M@~4MORݏj 9g (Aƹ}QةMOI[3?1d?IX`-秿sd (Aƹ#&0ޗ4~zHgMGa@q "iܫ40(I/,f8~ (AP0{s60%,I[ߌ{,-rWG? (AP0{~/`TW!ZwJoIzLSK~8ُY俇4AP0a[f%@aMT{=7%Qo8=@I1`I{cbxϷdK*%wd?H2}H? (AP0MBժ"^q`L4o!?kَѻcD$@zk'2Jc LRci?c~=%R𞫲>#}ЫKqa@i "iR qoGänji"uEI (AP0ML+Mos` <*Z˟.&WF}׳8#wއOz|a@i "i\#Qw4-!z|(GQ :e)=.04a@ 4Iu>{G 1ִg;}&s#8.JO1`jji4>V z|,&YϏeG S AP0aVg+&ຓZ[{MDM=ئ>/oI1`I}y|mҨ>_E}7*c-m=04a@ 4 6h0)&WIIRu˧υ? LuOAP0az}`4c~-'eV5zkGGq2Dscza@i "ixXъh-fNZV<+z_Ѵ>˴ E0ӤVoZ`B 1:wM-)f1=?Ӵ E0Ӥ= WtvT_Γdv;Ǐ=v-i2ݦmf (A&ω90z]Hj2Z>204a@ 4 9>P}F_KIsjswE=G >9=ea@i "i#@I&OIJ3Z[Muz E0D7$o>fຓ >J1`Ivy1Tu/W}K7mv~T( (AP0MzWD @zc~~{QU]h3$P߁Ya@i " _>jM_o ·l|bp"} 9C(04a@ TBݓ,_a2ɪ}Mf?|^2Jc LEbhg7xu9њZXOvG<04a@ TJ>nM1g35KtOo8}7(iJ804a@ TJ#ߘ}i5GbpQ9-NX{2Ѧ9GjxL*04a@ TR{>r0cGG ߡʩE=/y~c{ߤ?5 E0SI߳^݋F?ֲߧZ&zmԷ}=bXg5G'ߥ]a@i "UE :i?4''3[5]s[<|[[Jj1`?1跣~~;V3l>MѻcQoXQ`^fAP0a*/{Q=Q_y G~8]}\)04a@ T\SKb,{bp8=[]>ܚ#?wAP0a*>z?9Wվ/JOLv!)Gk#ah99e (AJl?A7@m'N6jnQZ|w۟=WE :m@i=04a@ Tjk}`4ӣwǣ?ꀗSsh'ѿxU7#_Ak1`R|7A7ozÚ\yT.Xt{{Th-!}=}䛦L[mϸ??3WoZ{]ۗAP0a*>0^ psԷkEo=9>>5Q9^ntOzWP./G}>!gO&F~e (AJ} u/MC𞫦oogם'LU|QtlXû]3ז?sV:(Rh-1n (AP0ܖX"mMzma@i "W}&x{QSwzma@i "ڟccep E0{>06GB]^AP0a3{_fE m_Ok2Jc LzF%F^w5o1`&egGiÇn;{AP0akf}$`d`]AP0aҏo>'HHj:Zk]AP0aҏ# #ip(ޮ (AP0 _},` Qwva@i "I{dK)k~_d (A% #_ɿkA2Jc Lzru&ut-700a@ ¤'W{p}< ]~Oe (A7}< k5$ (AP0iu>RuO604a@ ¤m߄ e;͵1`&m%@Ok3Jc LzVMc tW?3^ (AP0]}L`Qq-Na@i "IO]jhz*,z0ǵ81`&=}o}T`Q.x=\ (AP0|ep}\`A5MQzA=\AP0a?1c704a@ ¤>MNw2Jc Lyk,,n-~a@i "I3}d`ZQ{?04a@ ¤5c r2Jc L]Sߓ}l`4GZ[}[91`&Ͳ;EȝGEo2Jc L} ۭlj (AP0iU{D4퇳/lޚ= (AP0in/35o1`&ͭjGy$HZ1`&ͽ%faf}s{3Jc L{>?Mos1YwjFa@i "IW}`ƚG֊ E0jDGf{{ E0eexZ{F'04a@ ¤:u/8S| E0Gggئ E0#~'k>wg^a@i "I;>$~ghf (A4zUp}j}ghf (A4 R_: (AP0i~k~K#i?ժ E0?} z__wdva@i "I_un`;b;F;04a@ ¤auO|gXAP0aT~}(P}ǺhM-Ik3Jc LZ|T` h;#.E0j l>aOa@i "I [oc@!CQ'04a@ ¤Zk4gu ;߃5^1`&-| >}p_e;߁5^1`&-B{>;Mwgw&X糿e (A8Pq`B ֟~xf (AH-f4ߖ}4*կȿj,3Jc LZ'+0azNw51`&-bSKbx 1|hC|v}WcAP0a>W#&0:a=WAP0aWxF` rVAP0a>5u?0?04a@ ¤}Sݳ&^ (AP0)jEy$uEk51`&[G#q2D~_w@O52`&%bh312Ij_zP52fZ{&Gdh,*0ջxnji *Q;&UXTa@O:ÓTzv6&5ex,*0աO$QtVtꀗ[5 n8-G`QEO~6b~$0b;&APޚI_w#RoX%UMnߐc "tNzW'I؞ώfُF@WDl?G`QEO~\?~,0gUU҈ "t/\Io(@zH-x/QXta@t'I}"XuwEgap$=ed?H=wRQf,:0K$U{??, H-Z˲APA/ZSK?@Izr3ޟ`Z>g*u'e,:0_JVZû~Dzg{j? (FJk#acToXOEjq[sİXta@1koG(Ilp1ُ HS=/K{G)G AP?BIvժݢ|=O*-G AP[?BIz'yy6αMREi?DIz꛿`4^Mk̚wda@Q_$=uՁGZُ W3g~32xY Hcnu(IO_e?.NL_ܺ71RQfbxߵُ hxwmc (p}^AJ/G kE~T-! (N?(%iF8",uʮ}@*08K(%ifU{=7Mwg?6RgTa@q?LIY/Qch{ ojI4o> "?$͸3< :G%( (c?NIr5 IDATyWDݔ`z|4(m'@:0HMؼlTf^̿~twϋ{ZS4ޛ}$jTfԒo9?c4j-2 }$FAP g4j70wEGշ\}*FAPz_JDDk;(? H0ֽp*cWxFhCG/;8X 0hGvL`%ivӑyMwGҏV 02 uN~wG+I{{ [OH1W{M4~wl/h0h$ͺ-i=(B}:\?}4FA@D n_Jُ7|নznPzl]i}?x0>m$ͭd?B&V}4ڇ6'=ޅS`$oҘVbF0Bh9ߥ~ <}BFAc?fI[0i#ъW}<FAcn˟AKĨo>'ZSKzk :,0'$ͱ;ُ7|{Q{ĦD}Ǻ#0 `y4Z4㖤9>uv`l5>;iku#0 ͗?nI{s>OMߙ~VOEy$<0mh?rIڎ?q9ُӿd;>"c `!Z+"CUh6ߗ( Gkji}NZS" 0пS$ͽϝԆ|;Z+~V) 0>$ͽe?FFZQ~EMjv?\}LƊA~^KZ{u`4hn6_o);a30eMl`VNCi{٤mM0;a3[<#=ُһw5宦h1Ka35F 496I0) ]Yc 2aѨymG1Isl1;ُTNߏhZSdf0K7Gkn$ͩ'_MwS E}qLjSKbpq`uy?IS8i%l?~'UU`"`IK?I[K~,n]LV>}J&Av}e򝢾k=0iP)(a۩?I[/@c`AmK/i[u>& `.Ox&inu>;:1 V߻m;ӿe0OzM24'DkjiKZVde0zGY64[~̛Y--!<4L40yֿ곱ٿ}+]>/;!mx~^=Kzb]#0 {Dkd4ڇ!~YV"~%=j𞫲@ H}5:$ͮ4ُYkGПOWIOs[y#P 04tOTnfW{e?>f׊Q~XQO@Q Z3:㛤Y44~z̠cߚSbP$0Eҿؼ.$ͬj1} ;G>!t `_oH('ifUh[ {{N?|_P<aGeyjiG:IO[_{O'ww&G|c v K:U$=}s>xޚ=JҖ+u0LNtGl^c;IOʣ?$FEG'0}E_'i-fw|#qnOGkjIIEo𞫲`0Bם_QO֫}q4~T\ʔ}7Ro:+(4 FMK/H'ɵ}]4O 0ND*:ψh aws.0Lit@!J :G%63a#<־/N(uOsWxf?3=}1 `\ z:%M[G`wh}]_4Ճ?l'0q41umtNؼGa)>T&Ж?7ikkGaci?oէ~96GDȖ_~doӂ44ڟ]{u: `B #zVI U+w=We? P\c0k~67MqA>z_}ltNzWVdG^۳?0g v}[H7H`0è6z_qRڇvOVFko=G9'y+ֵT?1`Dhz0FCs_F7GkSPID#@뵥P(Z6B /1!ܬi)l-Cc4oG&,.pVb;:O3}^qĘ-hb&qhL?^ ֌V\bԏnL-_p|ߚ.X');G`S*!;HB{/<`spx$N6DODL{սjcӁv!Vq M  xFX eؠb>gMa@Б܉Qrf%:`m V^q00v-yŤ7t/.Lq7#h1݋}P3aEdwK `僫KLQݴ gKh]=s?u,Fxa .7RHc 8&,F)c(M ; [ꬍJR4/#qcٛs|IߝoZbԿh~UAjRHI>3 టg}5 cMKY S;jyS] p_U?@um:?zRYZ;FyX7~6A<TWټ/}}L[Έ]gl͋]ۼd\sKjnI) z[9 @?+RsşSJ{BMpSV/n? @ n>5+^)E7f_/XSc^̭&~"dAh <8Y'.I OW[jD7_{l|_rU-D"84V:-vȠ{/S# _0 p-;Pj\{OY2TLRyFxͭ_;1u;S 2@]TFx?2su[R^@녟oj׻W4k_ʇ@zgl~ƩH 0|o_Ӛ dudYFxkwڶipq9I])ipus\;o%|r7Qsӗ{jmۿū^'i֧Y9;Rꝺ: T#v9O:2cF(B5jn”:<N#w/D5]/kժ#f~+R٨Qk<=gV-_'/; b !|T ig `kwp5{—T瀿 ?#it[G_k>p9FA5gKO?vUZ۾>"go Fj,펲|&˟Y6r`Nzo~n-_' ~6wyGUW=070z_٩*E?PQߞ_~t9ۏp?Lk9<,Ucѿʍ˩\ss:|,mUE/F?Lk^7{VG6|UcQk}usRЭs Lm~1Ucv~~T7ڇcS8t:gRs?ύaaTMXTݣ>~ު(578Am^-Rs׆j,xI[4%1$o/_ 띶I,e=lћsX8V=7 >z D}b8zn={c5$ jno;a焟j; _ɫff|zl=k0; w-o n:9Vc^Y1I>V+MIꝱel*u˒Z>AߜҠ=[0AHYu{gG̾~;5~M٭4ig *cn5&cKe{M,@3\v _yX @ 2+ ?՘sGk9Sgs8jsSMѳUF/?ӕptϿ6ZfYƓjT%z6+=YY.G^{jrW5tkzV\Կl;{o'WqoKq _}wuǦRU)MBq\^}yQ>4Կ`= [RsӟYׁ ZbjƋcmSS^P)_[-~!_^qQ_gg}lm sG>범atSsWVppiї5d<<~{{{!\T/;=)dwV_dZ֎}=C ipv|k*V> uSkwY_I;mv!(2v `=gy_Ooˢ|Z^j~;iZ}&8|֗W,/7TDwtM^:>@kn; fZ-n4o9+Y%i X??V dS7N-_>Ujtѽ f<UӯG_P9[o;y*mGѳ\dTmE_P eڻV֪?R6~? `sH >u%㯱ssiP,|L8^P =fkѳS]ޞ\Cn(=E&bݔI/H~/|Fmg_=ʇosKeKS斯V >EU~5}e9ƎMgS?YeD_!0F=EU~ui 3a4 ]>zGkJnV>Eͫ ї)+wWS39voOltc9-j^ީQ5\Y{Ϣ&+}{< A}cq_*._LJZ}SsϢo獿{I>?[e[(Aw9b? fsY};skB5Hi^N$0e {'J}457,j^eE_E>kgY_IC>Zۼ.| ї/,UGb᳧ůw p0J۹ݣ?ڻ F\'|9%;gT,_7|qnpOEkHJݓ6H},5W8|Ԩ88, >o{ҊRz0 ?.N0x5`K~1|? af_n:9oS+>jvd*=᳦h:ףH2T>x>yPz\蹀Eeӏip)ї%5V>Կ=?S{<)ѳwfskA=ߍ<& n8a|ˡ~L.V#uJ L?~/z4<8ٰ[tj( /vE,*/"[;kRm7!@ݔknNM~:|T:M%,okt}(5 z3 >Zۿ)|T}鲄4߂小֯ ը|YG_ Rs_ϖ*gF_,Ӳ2 `̭TJխk@e{Ϥ.oO Ȣ,û.UX0{JŪJnٯA5k=Y `s7cM~-|Tzgl}Eipɩwڦ}_o}HEїLC]tO\>SQ<;$4;o'|nO Ub읺:zaA vRj+,ķ`9K\вUpkt^>Og,Gz^\KE @_o^+jGv5{_8D?RD8&T/5gIy=ߣ/4Կl=sR9ϕT6 `_7`^Ckٿ\פ 6}Y"-f~0{Ҋ9R^v~[6N}R-S砏V?KE yEj~I,)zj;/I vM#1IjU;{9R57~jq[{?JEM{ԧ_`zAjm9RJrFꝾ٣O*jL/Ձ_~P )󖯓7fNH[NO3N?[&L/ !ƿ]L2iu"^sfhxk8|.-s{>//QpPUc>C}n1R'>JjT{l%1fow] S쯦aOҲ6 `//a Kh&ygd8Hû/O gk_=iYpPE2|~'jt/Y%5\6,nfV7cS }nOZo3=G9L#IRQpPA:|~$I*v|k9I*.ߢ@Ռ>[=;$U]g9Lwّ$ؿh&gG.N>a2N*V>;$U]}D7>7$U^S}Dzgl>7$U]_}:}<|v$I*sYk+#IRQ?>a2^*6xVHTTu9Ldxs#IRQ{&ҿt$;o&;yeHTTy9Ls'F SsF +sHk7ύ$IEr9L F `귣s6|f$I**Z?< *~n$IZV+sF `kD0Gύ$IE}D>7$^@y_{HTTy&;k$xG0,I**L-ݣ5a"#)|n$I*N4abݣ5|v$I*&=iّ${rXgG `kE0ώ$IEem}7>;$U][2, :|v$I*>/,#IҲ.);9L#IRQ|&-#IRQpxUg9Llvk IDATtّ$8&濄ώ$IEek}zn>;$U]}FmHTTu&6ّ$=qyY]HTTu&ob:#IR%}T4|~$I*v}g9Sik#IRQkqJϏ$IEb8L{GeU\G}$,/-|v$I*!,$H3n=+,>;$U]W}a*V>'|~$I*:8G `>a*>>?$U\;M9S$8Lw#IRQG0udžϏ$IEbg4D0Ϗ$I˪ dg9LnOŊgϏ$IEmE0֯ I*.nMU$;ss= #IRQ}T>?$U\i9SrFHTTqlmsR6I*.ŪS*e3$IҲ-{>rw9Si#IRQpsqJ>?$U\}Tzg5|~$I*N]}T7>?$U\;}9S)^HTTqlsS gHj ~8ο>C$U[G퇢qJ簏Ϗ$IEF0iϏ$IE@W>?$U\{l}T_>?$U\GJ*gHj `kwF0.!I-{U9gHj ۢqJG qSG `mqJz |~$I*vd9Skn$7pZ>C$U[_SY>C$U[G}T>?$U\7}Tw_>?$U\{g}% zY3$IRQp PU~%|$I*w{wSw3$IRQOE0雇ϐ$IEQ;qcG F=?$U\{g557}Y ITTm3ϐ$IE@ LuO$腾_qp ITTmU>xc9S>p}HTTq8L,Ssϐ$Iͪ-ݓVD0>C$5@S$Y嫢pZ}gHfQes2$Ypp8Lg8HŪϐ$)**vyG I `簏G0Q!IRUrlm3ֿ`$]%b3R귣q gHr Fqa9tSgHȶ. >aj~%|$IlE0>CFUvl3;g$5 `sTq3gHȶ.\}T#X^ IYV8LgHȲJ/}!$ `{ߏ>ajv !IR#*6W8>a*DTUpqAV>;|$Iؿcm3$IjdWq' u$5 `{ߍ>aj!IR#*67zo\>CFvU~5sS_k=CFVb__1Sk3$IjdU-1_>ajc=|$IpZgHȪZ,Ū4D0gHr A2ejn3$IjdSm_>ajA IT>ajw IT뻢p#gHȦ,4E0r3$IJTp w^}Ԛ["|$I,ؿ`3gHȢZ-#1 N]>CFjlm36$5V `|Tv>a*egm*V?GT.kMD0ogHԨ}[{o}:GS Iv `E0{ϐ$Qj6|USse Iv r8L/ !IRr\uD1Sk$5j]- _>ajϐ$Qjz_S\$5j]-F/ lޟϑ$Qj{U9Skm3$IjԶ.>ajC.|$IV{ԧpZgHԨm][;zS~A I `3S굢qΠUϑ$)ձ.BzV1Sk$5jYY_>ajc>CF-9cg8L!3$IjԲZ/m^}ʇ>CF-8,>aj-^>CF839C3$IjԮ/ݓ6>aj3!IRv~lg8Lmxy3$IjԮ//I,q >GF8j 8L{gHԨUY,>ajw I*{pcgHԨUY,]}CX^I)Xss$IJu)p _}:$5jS6 `pZ}gHԨM,o|" kn!IR6e}Cs$IjԢlb:l>aj:~$I(pY# nNS락m I(w36$5jQV `{F0a?57zAI/D0/>GFjU% uO |$Iʗؿ36$5*_v `/F06+>GFnl3極oϑ$Q[U4E0q?GT[5΋poϐ$Q\}CX^I-}üv9$5*[ `k7F0/c>GFer,369$7}փXnIO߆K+v%w3e^H$IbG:}rwk`=Xܔ ,<|$iZ~j{S,^5΋v>GT-ͧ?n?}rau9ŮS[H-g9UGϑ$-Ju0ٳ~} UVv߯*z$i=S0G~}~Kkwϒ$֯͡});.!pY# n<1y鞸<|$iz lx%Xwkepis$)GۻdT>xSK}<_FjkgK >K2iSkwhf`xUݣYF_0o}4|$հֶoHo|"! o??A7%٫\ssu;+s$kVû}]@m^X$Us{7FKg繷~џ.`~r_ѳ$iF[~uZ]k}Y5,[п %I?;}G뵢_7ٹ>,3 ׿k$ijv\35k\{mgI5c?7~+Jz\G;skmY;*1۫-_Sf|LJ@Ս~+=KVn|n78;ך16`>K%oꝲQ\|*k_>ʇo[WU %I?_y\? %)۞s{A3~YW/F_0o댞%)5_Q ~EUW>xS,IuO{ǝ 靻\ǵ9) [k7ϓT6|O~n,G 띱euh'hxy ѳ$Us{;j|S=}n;uk,OCPuO %_vw|n%=fg,?BS ^jnyN2=ӳ3'xP6y5 s_ϓ3sȣYr b9SRT{>I5BՕkLuIZV>;z`{v<IOu$-V>Cvٙ - ,w;|ŪG 欹kgY륲ܟUQZϓH9kn3,O¬*U$-F?=a07A*>3?uOZ1gf[>Ob9Ss2yylŒtr/TΆwO)aOM^>SB;s9rF<6 4㢹=0:CSBwG 欽{gYP3 3ϔus3,sy~ܟaq>SB4P=TEjyl9V>tk < ɬݑ^U4DgqYXkY*tSsKJ֎o"췀NPι?0:GcLI9oG{—gY'!sa n<)|i띶IuX<> u?0JDOYkwNPkن &n:l==>0g~6~npsa (~ kmсC<> (us%MrQ%{ '8aݣ?}-ꝾY\IԿh豁9\{trw*6xflIsmxߵcs;sy,|΁-i57yiJe=20g,,Y's>W\jiy,S9&{a֕ejmْ{DO T0,LUR68_ E/ϗZ۽1z$`bN8V>'~{f\Y3&m9c葀j_R{TBtd?OptWT@{ 1#&o7+Y[:` ?>|1 o;w8:gLyV[TU.@Orz) 5ї?Lߩ, nR= ї=L/e\783npY3Z~*}T#X^=M{R"fKU*xR %  ,/Uug*wFs4, XU砿3ջˣ/s ;o]50ʇoKņ 5ճсTvF_0r26b\}`W TCUP_g d\6|_?oUߖp}uü f\F_u7YSZ4s.po}fWT@>oGnE]4|U<5 B?[*aѕ8S} umxߵ4IEhx󿒠>o[}Cve\'|ya&ue`M]W0,΁I.Bm_pW̸SsKNժ4G_ps5IEjxU tU_̩b7|^{Ge fxŕ ;u]YPU[4Ṱgk,Tk߈ai۩ӯϞf޹;D_{?|&X-_'}M’*Rhї(,nI.b,a ?. ?VjAyAE|ou !zm>{S[oKMp1[^*{M=3Z3G/GX4ͭ~>|Φ/3ڄAT\? *kDX4{>gf\Y qG!P}V*E_zgl>kf\V>Nj Y]nWaJfۻm,KPQ5z;gQiЍ`ѕU;X޿}Bn{n?%0a\z'fa/; >[^ !طW>'|p k}na& 45~m;s{c-K ]IegT?Y瀿JCߋD`&+׿?ukfWY޹{Kx޵\{tU3,MŊgBd\| <+KUKS|n\:G\V}N簏m77'W>xSn[ex7~† n:9vyG֩6KM׌~zauO\> 0џWgʍ>_ٿG*gw!]s)orUjn=?ޫ=5+iͧ~HugzZ~4Xyy^,u\5 uL婹g;_Mw0oe{M-'^+,ꗤoG_P/0 ?.upk֯Ios\}X`s0E_P_ΑEBR{޹;E?Pk>:b{mmA8z';ixDžrKb^uCnIDATukqpw^G}:v}gwoOޙ[5lHA:MHYgѭY ~w~vo= ._'57}Yjm}FU/OP,zGX,3PsӟPf*ܒw]6~;vpYSqSq^eOLw&=, @a?5`1H?rRJ ; ଴|_(Z? 9 =ߣyֳ8C57za*;G_΁cV[OK\sK*V<#|X,3anK{8%,yjn``I@V'.?2 ~?WGdM/?0 9Y蝾yYgN;gI_/q{—jw}DY1tzSsWcXgYDRm,3^sW4EK/Aٯ^c;m=2 `jm󺔆YZ(/ ?#VE Bz"}CJ0zfzB<4zn:G~*e]s׌F[ a4}==skO~&h84:W7GN8,.*R{wF?WsW-ޫ}FͿI+gߝ~sߏFo0ZVoEX2=bI띾k &>/gޫlW1~iO}yuip3 [i=i~?W~)~;z4`tO\~UlhlJ h0녟EkG?| `(-`<+ /E}dNW9CPZZ3r9:6ͧ8ҴQ׮F(,Ekn򔆃\g~7~Q*5 ʇnM/ ?W 7 pZ}0bV`a zӢ Nj_R+,џ ?G~q׳&?GZyy}kE|sx wp^_jV0U2~j;I1Ϛ[:~I+X-NKY۩cii!ꝷ>?[kR `-|W̺a3,jPsWkm?c}7`f>,'Taj!VEEAѦDj!-ٸiEwRfd:ΨPCfC$)$8TJ)1T>_<',y{y>|9{9+1ÓS)?8nfje/[xw[_A컮AL_ٍ_KiᄇZ~Is5>'zҾ,dY>_{絖a \eT:?X6Ϯ+源]:~28up9;s4>_ֺ/}A JwߵeMo/çrQb`M!]o-tMy|K2jؾ'4;__-W63.]SĘfgx&.y O{UepPHwJ,;.~LCeTE_.\֎K[Ӵw_Y߼w.<>Vz|v_UD8{tӾwhk>RM_M +=o@0K }oӾ{3wK\?Pzrumi ׾lf~.wm-#J7J782zX_G_=\ #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@0 #@?[:IENDB`PNG  IHDR VAK pHYs{Rk IDATx]u}Y`-bib lZmkڦOhZ55mzM{iZpѦ^i˃J!DEE)`5V EX!i}xrmkGzIlpzJl3WZj샵6$^~7ןo5>tMY]fV];ZkQ-^HkxZ9@[Y6wSjxBɷ\݋~fI6ȓ_Yu/ysMZ$+5}ky'ɖtOßhJM1=|翶uՏܞ5A4y^[O"=t}l_'7J[kKwU͟ [tC4ysko~]nf{ޏе{?uBv],OlMv#$~ {ћt[Q+F7gݏbM_I'_fl3O}Xx;nnf5>< I DrN{:f|_YIo^!ip_7?f$q4U;_Y͵'mڗpolHNkp_?fv諗llpz5\۵_-jDvv3;zZm4V3c{mi{)ͯͬ3]B6?hfuF&OVuu˜!i'#mA6嬵__ۛYg>F_b@F߳=][k|3̿'3$m$[j 5~X2:smƏA 5;zx2Vk~afxW5M{h2=Du?f։7z Inh`lIggMs=M6yZٵ}Uޅo3$M=pzc˹نw<4-w^/:zQ5{H^-Vao;Rݿ?}uqw5[3;. 3@""^EPT*^.S ^GUO$yt2y<'d;}泿wU%`zg??ZuJ׻}jWJl<$I$5xԘ}VuG_vHjzh)u2S$II_Il&s0:9$:,/_Y*ǔ$IN=~/|7q֪I[O y/J.)%I$i$I$U UlOݳCR?8F[4E<$I$ sFjEZ!?8FWs7d#I$IR+>$єo4x䆈g$I սt~NsZ!5#h|Ի؈g$I : izI'IӾ $ITC IDATS) LsԽ=) I$Ilbi.&ug}/b[2K|H$Ipӿ٤I_CRЏPuS#9$I^n~ց󇤆?eủ|H$I_^@۾g_Y6'VhhЇ$Iѩ{v{:%8Q/,>$I4Jw2%n;-aY? #I$i+?["~wcֽlvSI$Iz.{QcZ `aRQD?W$I$x9|FM:p0kʷ<''$IjPZruBt/u0k?*jFiUI$I5Y~8{ޖ_Y0T)I$Ie>!hLM~eP=?H$Ib4RïEШYߝ0Z7MųG?:$I$ո]K|GR`uR֓$I!~Gv I$I$h@.wy[C54w}[JfB$I~VSw%hԀCkfދk$I Lc!5ҽxg$I$0?٬sHbZ8~6H$IJrRĔ[og~&H$Ijk #!_g/I$IUO֯ߥ`l8$Z$I5ww)h $VR6$IƵ<|ƈqHbn_=%I$i*;5$~Juϝ=%I$iZu*|qHbnJn̗$I5M7;4FChi^$IfUC{9/I$I3Z ߵ1Xug$I$hEo #m$IF޵.6$Òs]$IfA ߽QaILj?&I$i8|WFIdƩx)I$IZA?5wSՂCRt^x$I$ލDŽ(CRE _SѳQ$I"5|g!"-$IUԿ!7ME{YL$I$^CBc9$U@;EBI$It| Y4Eͣg$I$iJ$4fCҐ^C$I$A %1KXիRy6zJ$I֤b=|,pHb $IwfCҐʷeM$Iڠ;fn 4o=$I$IӨwA%4fCH$I4"ߕӛwLh !тq'I$IzWcBc9$ ":+u/~5xTF$I4=k!)_Ӡ=$IYų=UYMCj|Ah+Ss?H>:g}/>( :~',Iq: k!)Xmg$䏊n:.uI#15/xis7Hߑ~fw*Կg!H 6NE&IwMsR|W?PïO&4qh$ij=hO_]l;9$OScϼ*zON4\ßsX IQIo]7?FW34oƍw,M|WoCIҴ*NV9IAZ?=$IU}N/ U}쿤ލǤmFɐ$Uޕ?Ϡo?=zfI*&~}/|ׄ?X/|ay&I%IҔSkc06uI;(K_oZijY/~e&sL=og UakO;Μ|Av?]~+u/5I"<5m̂9$mS?=$IC+'{%_Y33oɗ:$ikgMCR}.zFI:g~'o\|ͽ0]]JA STG(IR@Sw')Ypȷc^&IuŸMИ5zWl$ޣOHC>?N֯|(IRt|3 STޕE&IR J-HvPM&bV4#,IhПn4V!$,z4Ifs7P]/K%sț$հqH*I_L$F|=7͝a۾fKJjR 6AcJ2$I=om1.o|o$uNrT_%IQxtǎ/P/ޟ% Iߖ?wI%xY$If{Rԯ?WL9EIZ(c+4(sH #ߩ1gg pHE;ռH{80ZG]*OEIKß)xYm3GԽ`Qj(y?(M4͚{~3qH% $i}njbdo$U{?O`9$͆uSF\ŲRO?# @됏h$i-*RŸ%xC,hѳFӊ"u/# 7 >@|קWFEJ֢rH+3ҳ⏇?`h{&Il{CL~*EI}MV\!>)_5??4; $U\0Z&IR]u`I3o[S|ßPߔO+IJ<["4wT4/T9&kf*&z4bItfN밿+T&K:y GE9KV౛Sc|fPsEjU'|׆ sKKw$ ՙCLX["I{ɮ1w#swR*/qI/Y6ۤgʷ{}s:I3u_EIGVj}R*_T4xԻw!5|wF?I3w>cGFwP>Ҡe/I#SRԯ>|_]8$̈́uSsHF|W|aR/Ih-M;N%sSk'cfZrH=$i|BjI:jє1 IթH{/L݋wNc?oZ#нhQ%I#o~:þ3IV^NN㿐FC (;z|IU=cW,{0o9Q;胾cTGID2Iz>g<&~ĿKR*Β9;04Ct?G7I::/;b&iDktA^}jɔoy !4M.y42gSk? \J zdHڿkS}S{`laW6K$w"LM=5$iJyd3!i'I#>ׁ5ӽ`!I?Wz:0u/XZ?_>+1bw1sRF/|}>Ӂ0N]u@T4xԽx>3&Rl搴n)I#pD9?'FA? 19$uNZj'1E3!i-x(jm>!4-8 4zH Gzq,8~iCZ^]l6̙xI"'SSkc!i- .zJRe9̼LȪ$F?v>kc䐴ET#X*Yys=?Ҡ=j$ Cki9$˹$i]_ f_oDIL[NJ%s-_>l9$5FhI\[ON9p;fTqfh:'j#zY):XPܖJ5x䆔/xi 3wԿ#i&KR]R;{`PswDqIܿX6w|Sʗ/TOlh8$'oGuIN ,|vq{aJv442|nPsHZCNT:猅m ^G&FSγRuߦ|ׄ 51gTEIDOgzW=z57NZ/oKugUCҚ~k$i 9[,|nCdFiI͊wF'%5zWj0H!iM>YgG$ Vj 任W<@9{uRpo 5H:~=|^ë}'ǔT&{/L݋wNc?܏ 2ՖC$ u;^$`zW={4Eޏ$Ih-Mvo@EޗucK X`ptORc>V!i(GU>g5P];n=*=4M;g?K5RU9$MQS=494|N3ۥQ_ג45yOLh)EH{(PpHZE;D?%)c]wDXɊe-'Β)ȆCJ>7.ID<|fh?=+o &DFw xy$չ㷥`y3ox{&~D}{@6-I+oyc_ky o?vKʊ^#lsHZaI h>_>Vu_W<}o՜K/ @V I+3wI {ɮ`U&^]Կ=o?xۼ&@V[I+л/HRh7|Jsߜ|ȾCR/zi8$[ྋ0Tt/3{6 @c^h);>~LAξ*Β)?XCI/0ÒT׊ө`Y 0U,0u/9Lw4fC wHRXkdSObFpHzb""I59 }Qp!z7S_D$iXa/ͭ>8I/7IkӾ>VL{N{֩uߥ|_ !㐴uS6g`U R04o;uk4#j=F0zIɷ{-i4Z>oMV#j:g~q rHZNIp>g0L]O*}ђ)U4FCr&)I]% s֋`lt9$-{uNJ*!i9$:V] IDAT3|Y%8$-g$^s7_ _'g9I*c7_ UCm^IRu/!|Ye8$={9I*! @VIk}NʭI_ u[IRZ>{R׻NJsg/UC^IR d4zScF*!i,K^$?(|Y8$eۣw:I*g/UCXZ(zRk7*!i,K?IR6 @V9IsƢw:I*bكs*!i,K$>wƲԿNJ{ d4WDuTZ^ 4֒CX6IKo @VIIsKiЏ$:_'~jHʷ}]Z'I5x dUCRswGuTZk @VY?$NJs.UVIO^'I:s*y[FuTZ>wjH]}p^'I/xiʪ!i{$Rx,|Y4NJipe3*!ۣw;I* G\ NJ{ dVC) ѻ$R] UYI$?s*ևo$ZIJ!iwGuTZ#|Y:#{$Vcs*ևџ$ dWCRDvTJ' @Vy>$-IR) ,|YNѻ$R3g.U^Ik$z |YԿNJ{ٞ3*և}GvTJ @Vy>$=rCn'I93*އ'$'|1|YT,{(zRj dWCRNJ}߇\ ZRIR) dWC :I*?wTu=$ 7${;|YhNJ.U^}I;z^'IMs*o dWC$m_>wj{HjNJkps*C?IRi[o>wj{Hj:I*|W] L^'I/$|Yt◢:I*|K.U^mIS#zj,8|Yt7:I*|] Nf^'I/|yʫ!oGuTZV>w{H:;{$V.U^}Ig}/zʷymʫ!GuTZv@Vy=$3IRiۿ1|Ydn^'IMs*:I*殿>w{H:oa^'Is*$Ziʫ!E{$V] ..zjs*v$GSʫ!;EuTZc%|Y9$IR j dWC҅FuTZӾ>w{H:NJsxʫ!{$waF] :EuTZ@Vy=$NJws*ӿIRio=%|YtDuTZ{@Vy=$NJk5s*5z*+|Ytg:I*"<|Yt:I*A/5 @Vi=$k$Zp dVCRODtTj>{{HZNJ^ PN'I:*IRM dVCRswGtTj>{{Hm;$Zg dVCR;$Z]g/UZ}I[*zR]{XJ!1oNJHUVCXҠIRi &|YT$g@Vi>$-{(zSc| dUC;:I*|Mg/UVI]IR5w{{ʪ!w:I*ց@VY>$qfN'I>S*ևMEtTj3|Yet͡;$ZE*ևe{FtTj @VY>$]]N'Iֿ dUCRGtTjGn@VY>$NJh>>{j}Hj;$^c*և$;)|Y%]$^k?@VI>$$^O_ Z-_IRu dTCRc|ݔAN'Iֽx *!i,UؒTz7>{jH'I>*ߊ$:g?|Y>s$^}/UNIC>IRo?=|Y9I*c7_ m^IRu dSCRc)NJ/U3HU4""zk*!i,KGo$G}JqHRs9I*@V)IcY]wD>'I׽l d4w$>R&> g}7z<~[JqHRGsT~NjY/|Ye8$euG9I ) 3*!i,K=IRH>2Ʋoѻ$> 3*!i S*}NJ-g0!yE}NJw*!y$]>2׿}NJh<>2׻b}NBn>~8gѻ$Ի dS 6$)}` UCr}NJ@V I'I!["|sHZNӢw9I ׻g0 =7zG*|sHZdN.'I!u @6> ѻ$Ի dC!i9?IRH/ @6巢w9I h- @6/xi.'Ia6 @6^$) @6^`ѻ$93ȆC n8*z>l9$@Eѻ$Կ dC!'{.'I!<>l9$@GrVp9 dC!;%z{;|rHzy/JDrRa +xO$ձۄ` ZI+п]NBrR 吴k$)w` ZI+=w~.'I1 1o9 dC!i>zN䐴IRX#)|PrHZ|ͣ8I dn䐴"sKߍ$)Ga #l8$B8I u_a *I>K{$9+sȆC*Lk$յa *Io=Ns^␴*mFrR|2~i8$w9I +W0 t|'Iahᐴ EqVa I>s{$ջ9 dC!i5{a'Ia >|pHZ|_$)~75n>l(8$MAUNj9 dC!i w-$)1@6{{$ս`9 dC!i*IRXO@6u8I X`46$)|Mg1sH4zZ?|Y8)i'IauNzpISԻ=N]pISD=N,CTY/^;z?Y HIk`{$=w~PIkw{$տ9 d=NtIkx=N]}p9$Dq0!i-u2zԘY drHZK#)zК{;|YRsFpZ/b +Cښ^Jl9$̀$)g1:0wÔ=Nzr,lsH!$)bكsfC ]u`'I6 @6fyDpZ됿 @6fHk?$)@6fH)=Nxl,Y4IRXSwa UI3w{$U)fCL~2N'Ix,Y4Ze'IuNV,Y47$)޵b 5I3x=N<~kY4IR <|٬pHO蒹k$:fC k-x'IMY d!i~%zz7>lV8$͂8I x'sfC,=NBm>l9$'NBk-X,4 Z|$zк @6fAիw8I ۩fC,)IRXE9 d3!in<&z7@6f{ww8I @6fIFpZmg1(Yo"zw>lF9$͢wDqV^b 1Iw8I [g1NBkY d3!ix_'Iu/5|ٌqHE/KDqKg1Y6x=NRcfC,]8zК{^,4۟ӾIRh>lF8$Ͳ~IRh+ @6#f4Gqkg1fCR IR\~j,8|ٴ9$wk$g10}Ie|ONBY dT>$)޵b 62(~7z?4]I%ETۊ" _>lZJһr5NBkY dT'/GpZb 4zW'In:.|TkGq;. _Y! " ̨ Eaёqo/Iw;Cξ'=dN[{ߜz#!IwoUϽ>s9g;uŒ$I҆d4_}osX$IRcY$>jg$IƬHc}=wI,$IԘuIcۣp>%I$5fE8s@"$~K$IJ"i8/*MX$IHs >j/\,$IԘUIc?>^K,$IԘUIc.g8P{/ Œ$I")qq-,|K$Ij87}}X$IRcY$Eog8P!|K$Ij8Z^ T#g$IgPKR*80wbI$Igq^>%I$5fERP+>jY,I$1,jg8P Œ$I3")^>q^,$IԘQIQ-$n3lX$IRZ,}I1 TswbI$IER`Kv>j7X$IRcH }gp`=%I$5;}5xY,I$Y$WdEEʗ"|K$IjWIo>5ug$Ize`3@ΊEX$IRcH u'p>%I$_I˶~F*lj^<$IXgI%hح8P]~)|K$Ij3Ի3@>%I$5֙ER 3@ Œ$I"5}_ +g$I:H*C7K׎>R$I,JDBP,$I,JR=p:gs,$IXkI%iEwqX$IRcY$o>*q,$IXkIeij^*+q?%I$"Do;+ }gg$IfT/>^c,$Ix,JT?>}q,$IY$|WGbZ)[i<$Ix,JV]8Pͽ#|K$Ij^c,$IxVI%}_EB ,|Kj IDAT$Ij<+g8X3$I3H*cSS~"u$IY$GB oPѳX$IRY$EGBo9-|K$Ij<#>FBǧ?=%I$gI%- g8p>%I$5"O}>og$IY$'FB9,|K$Ij|K$IjLgT/KDBL<$IԘ" 1 {.X$IғY$UGB "|K$IjLgT:'} ֠-_>%I$5,^sF | zK$IjX$EmFBuV,ǒ$IERsi T3g$IER^3@Dn>%IIcT?}]X$I,*PsDuNj<$I&ER3@޵GcI$iX$U-GB Œ$IҤױHFp~>|K$IgTZ|"nX$I&8/">^G<$I "B Q kg$IMpIwag8X K_>%IlBHPS}:X$I&4 Fu2|K$IلfTmR}տ}E<$ILfIkpeg8X,e6 ǒ$IR6Y$UF5y,I$eERj/| \ǒ$IR6Y$Uo>xB<$I "jMKEH T|,eSg$I`H`[N>kkX$I&, Y(s$IMXIu'oz>%Il²H`-R*3@"s$I" Q \scI$),*Zâo:y,I$eERE>d`[>%IlHh}k \=y3Y$I&$hӔz3@n_$IR6,*ˢo:']<$I "u/5wQX$I&$ ^@b$I$-OI>Bs׷dI$կ|J393eY$Uy>k73Y$InF_>{.E);?,*^ӂmw$IUϥa=uV,^n;˥; " _xX$I-_s濤M'"{hVw"ϒgTZ|bc/dI$-_贯ՇCקTs;VoAlI/_Ŝ]U>+3Y$I{\*Vg^ER <]$Uѻy,I1?רwNTHEkPF{$I\92% "uNjP ͝>%I4m{w$5SVՂ,jPs߈J}_dI$FvHԼ,ТMs_g$IFÏ5W*owERM{YXuO<$I^sQny*<&_,jR]%RwzSL$I ?v_Fsl,>0^k })|&K$ծ*?h;9G`I5iMEԻ,IT\4\e%oER] \3Y$B :cs΂'FkԚ{'YdI5i@);1|&K$UF_*w "F r@Jc,|&K$75ɥq_J_RZ5}_,jTOD_Oл,I\Ǣ-~oERʗm1_.dIQosק?V#W#HYG}MBs_ ɒ$Isڱ_L\`oNk"0ջk :=%IfQIKwI.J׊Պ:#ᯑ,jV甯F_S0|.@L$IsGbZ,jX{磯+rRK$In/\#}ԟ.#Ha͝}]Ƥ]$FÏ sxſVHcS)_$I*GԺnF1_FfT}mg$I/5TUzF*+MY92Y0(|ׅeI49ǤbѿP#cWk<2:c@iLI4I5Z5>,jZe ՇeI4ѿj0aG}&:" @JŚ z.Ky렏ΊEɩR;~mDfTzW}}FseI|Qj9w!i)E,#>fT'UP!|.KZs<רeP`I5ۣ/|j\$iҟk4\#*u "HsSSZ}C'K٢Mg$I\GkPo0Z|":"MosYZh뽞kDi^`I5{ޖ@it]>%IlkZ~$z "d5P/ ˒$UFÏC);gdI5/_Ao ѳYog>h̓wm(I\B" %:(>%I s` YuE49eeI\ߑe`4Uf,&}$Ic{Qsejï,&J% Yxj9Skc4¬3 *IhF謉J}—g$I3}n'O%IZ[NoNcw]R}oE҄Խ`k 4ٍ͒$=sUk/}y܈"iB~5g$iʷzWwNGԊ%3-<|Df4!ۼ:Z([fI҄2&|N-"iZ9&/8~>KB?>3\#/k1xg4a8(~͒FE,˂H}Jg$i˷|3k45 4|sF|˂HG~:($I5h&zW<5F3oAlIVF_wR)Y4u/s]l ̂HO?Orl$=w=}&XbEֻkT7>%Ik_o,8 }D_{Rx,ISs_Mc2̺4G֪{ 6 ۣ=i,Ius:|iE$65/Ǣ?R^{|/}yj|Qp>c,&-G_R<~glʷx02Y 6 s΂tϒT_=FIZۿ}N ϒT{3zTs,8Im SwAR>5|>KRk{ѣ`"iwy5P.~ʷ~U|>FOrwxC͂Hທ} N/gIj&zTe6 "ikktz>% 5P[E6I[/C)ګSx-IU{c`ds6+AI^"@ZWI]#S=|f%"i]sxP:>%o:)z٬Y$Mx>Z(b̓>.I#`d>gd45xgPJ}~3|FKR<|SU٬Y$MzSSZ}=Ng$U"{(z|LlV,}=$Uy)`d:g[]ERgr/"zlTįڬY$)HPJ39|FKRUj 0R#>>kdmktw_?%"D>kd_}MO1H ђTe殿>kd-(I>% y&Pw֯ Y Ht?}MRg$U3lF6+AI. ї%@9 zI֣M'GOl)GlV,twE_>3Zk5 )|f%"IO׻k>%U`d>gdkW&@9)_E6u6|EJE_6J}쟅iI*kͽ=F{66+IIzFG_Կ-Ie}䧣4HuNZJEQڣOrSK$ߌ#5\Gڬ$Y$uN?>%u/#zDTsڬ$Y$5w{[ PZ ӒT=F*6+IIzfSR=}S/ՒTUwGOh)-4|f%"IϪї)@ibR) 027["IϪs?D_տ9-Ie绢G3H ~|UJEUswG_|WjI*K?=F?$6ETVJ}Wg$ΊEc`z>ke)*@io?'|NKRY]{dXgmV,u*@y )5Z룧2Hy7zY$9k*@uNZoҠ=FuGdnƩh?}Vg$=`;y($=o[ό^ʫ(Rg$E>ϣ1h-4|f%"I[ї,@uY-Iu/9zTY,$=o?}g$Eֿ}E(]ڬdY$iO쵢[Rky-IMKEhՇ"Ik-@u/VmV,ֺ.nJy-I㮽#`})|f%"IkuG[kZu:6+YIZ{K^R}Z߉ג4w_=~F.6+YIZg{.vʭLҗkI[6}6ygguֽ`Eqc`䊕w۬Y$iD Pz; ג4:|5z\6+aIZ$0@WalICGO]]oJE֫D_=oy-Ix#`:?6+aIZ:+F_W/e 7 ْ4ʚr֡ Y Hz0@%-I}WG-X4w~KJE֯::(lIaLgnV,o>%R(~'L̖QU<~WC7۬Y$i2@%tN-I[G,Xn8.|f%"I]swD_0x-Ih( YIH75/k*omI=^Ƣ}ܗgnV,4z?N P ْ4-3@5t)s[c/"|f%"I3*磯g|mI=VƢ YHҌsg>5@ehܖ ۢ)./|f%"I3}gk]lܖ s΂q 06S>wg7|xl*6@5 z)u[6WFOSi𹛕8$*LΊEs[6V"zolk5$ͪEG_śnIMӾ=FƦX}oJEfUG_>[fS G(o9=|f%"Ik S굣q~$8|vKҬ>٘^MJEf]qJi[fRc^ٛ<$ͺ9S8@?&|vKL%?~NX:gpV,4'uw>%iXs_K("Eʗ<|g"IsRsF_:s\z=B %|g"IsTdE_Կ}E4ۿ.~'z9U($Y `Z|(|Kܺ=tN9U($YcWPY&|*z iYU($Y6?R1gɫsֿE?8~ʷ|q,*E}GuQ4Y OEp3xYU,$i󶌞:\9ߣ@UbY$iNk9Pi&y.[4Ǣ@ _YŲH65?k^y.uΙwᚻ5|g"Is^廙g@ -e6 [ehwєM YŲHҜ>O@uNy.u/&ztr<*EFyFJ~R3]Rwz1s?䬂Y$i$8/z&T^繤ջP >> f93g}nQDO7xvo> f4|= 3]RMw_=Ja8jf5!6\ۿ>%UE3^}\*EFV]g@- an>%U|R 4ZGql*EFVEs]Ru^G(H6?>fѵxT0*WsHiЏc1xٜU8$Cb *WG/R]|^P,4Ea-|KN3=J}gsV,4҆;VjS=eK^>%|7&zlHl*v IDATEF^ G@t/9|K*ySS @ 6~F/vIySbZv|T:g{(Y$i5w~K#7l g);c ZQ*E@t/.|K*Y7OO4|gjgԽ`P?~j/|KA׿y$$ś&z~VShy/ilOJ9 gvV,4z=?j{^xj[)Zc{FjEZ{@Ejy/i;)k8Pdlj~jEZ'Rs_FSKG @e>$|vg5"Icspzy=%q6M;΍1msE^?# -լ-2|WFY$i^R=N&B%s_Y(zTNKwV,RGߍ'mo*_ԯEOJ3%_s%6@gyV,V俏+gpRIku'S굣G@y0$ooп-,> kǖHjO-gzV,Z DxBn~|s$@sgzV,ZoDջ`JT累v692s=iI -u)0zi뜳 zGQ|YMHRx;Ϗ3wA)[Q@n=jep}A}HRx.zL޵Gyf4-_7}N YHRx֯PI]Lm~_&|צWD_s>qI*E[ψ5 SSxT{3ji-s>yI*E"z$it?Rdї9@mu/&|g5"I(_zS5Tn<}~"I&e)uLvv% P{R65/|g5"IsR<~VJPG_~6Y$MA(VݓlBHRj9z(Vݝ{z}C*_E]K`u/1MPI*_SRYSwHlj^j{ &'$ˢg3)[iCu=~-()G~o&,$殿=ץ H#i SgŢK =wI=bde6LZKէ}5z6|7SuԻ气Ae/dR> m9S)[YE!uWJvzua#,To֪D(_lUS "IhMѳ )+Sg"Ѵx>3ip_̑,,T*Ud?57۽vzAYDCwlj^}&,T_Ӡ=/|"~_>S>zk{3$UՇD2*XuO^Gj/{E-xcӾPAEseʖ Y$5{<GzG}&K_~t[h]_3%o:9ǣ Po)dIliɠ\lZGqwxC i_O+H_Ҡ_)=5E*[俋k]5.~R/>qosu~x#jwqy06п}E}PgeʖoTmLr߉9ߦ?=_}oU7K]~99SR|/ ~T,Tz?;zӊ9,u2uNZj/\jm2NG5fEԼ4x<|SʦǟfEj[ԯEEG??71EZKRZ=)Ū{Rhs3"I{.9E5fEj]/4EHRdl ϋj*$վ='xJ ?'1,T{3hNҗ՘uI=/&^C56($MD?=/&[7O6?AY$i2\=6&VφJE&1_|۟ ?Y$irZq*+z|LƟ "$MT1z~L&LyP9W[$iE{ޖgA"IWes`"U)_ssE&|פkES3~TcNHDֆɷziO9"IYRw*@musE&GUZ*GR}jyIޜҠ=_js?IIzW=_jX}oʖ HHD/4GYh#"I_ڣ,@- &eSyj,$M|~5b=o*uiI҂Fp|gyI]I{+T RsyISo>5zTR廙tj%$驚f^+;|Nd$DNҽpc"I72˶?˩1,wѳ:cNf$TobJ^<(7l&g85ƚE<0z&ZO{IsƔz PJO ?EzFFoaY$Ik)h^sY$I먳bQ׿M ?{FH^KR==35³H֣=.7\F)H֧CGn+GSeJe"IZZQ_ ?Q,Կ06;m"IAÇ 2P{vjs"Ia=FbQKe$Ͱ|_H׊#3x䖔-,FHfQ:ȴHKR6|P#?T/OEHls ?sQںl=:i{7ToDw9U4K6?oQں4ZiV#UE?s}—ZJe{ӯF0Rj90'HԼs&F? a*ֿya:YwzsJ׿Luܗ5w~KJVI~R b5hu_=fǹ>Ҧ9it.&*ۖ/J{?5)Mg*JpN{!?TG60#SwYJʔ Ov;/ ׿Л_|M j}w~4 ) z7ud_}RRO_B456 ׽ltNzIսt_Cxg%U|+R=yOx^;/Hk X$b%~eQVM?09̤F%+GH\C%բőgi $j̪|kizԻLKޖRux޵GԨl"i^LmIu{Ҩ{ӊ|g$5*[{={4NM7OGqxR1H/|T\܋;TT Խhs.gϹH^<VC"$[YHJ7|HOkWYq)թ|W"{x `ک;CjT޵G>"iHnq2 9 5S?3IA55/o_106} ?)U{3Io A:/kLb)U5jQ׽HxW+ձ9 q&ѠZvGzxT_ERm`-$ r`t3R]jOE`iFR3{0A?nʦ懟wԨMz/~-յ>{0A5|ׄsԨM?Ҡ?ER?Tn]>{ 0)E:Cg:=osݔm^kޖR= 0 v>ۨQ0#X$,H5n0<߾"e 7 ?רQ:|u]$ <,<!նSSDZ03c~4:o Rk+)ZsyOI}+,Fjz uִf[Q9suKj}߆aԨ_6Yw#s4:/@Rw]8zW~Qcz_\$ ;YiJs]~)n ec#kq)_I5o&``rC) gճKfz\ER\e[᤺׻[:Rۿ~VQ=wxÌ?^v Ju/X}ln/@ u)okrIKno CJuuT f|1w'o#>5ecF/.Ik Ju{ᶳz<ÔmYx/ڧ~-,վE}jp!\ֻY>gHJ &{'/Lyr./]`~P[It^sH4Oj^FwQ)~PM[Q]{H_sHy(J_To?j00;Og6M떏u+չ)Zno ?3RpDؾ?j䧎>>h"$7_8N?n f"±CSnXiw]93^x⇤?8x\c}[zؾ cle!i|>nt}楓_XeN}`e阝ɟmy7;Ecg-/H;$fg| mw [ϝߖr睰豵>rö7>/R䧌{$IDAT:ȳ33-NyظıDz[v_q`fKǍ13f_?n[b! @"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I$B@"$I>TpIENDB`PNG  IHDR+ pHYs{Rk IDATxwdgyj@ d 6<lcqG{<6p=}:Hne3m%+'2(,Pʹ[RKޕkS\ ϳ::]S5`Y@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ X@ RCS3TSXm*7yߗֺG!XrfէۦoM-uԻYrL<"o=#u:XBjTu7D?"ZRdk;)e/JC>:g9o;3n3`l1 (O`o8:KƓFۥAq5V .u?P*&hdG) zQ=uy-:ԻTJd,.M?/9S*S,>8¯lI_.ArZjKٺ!~dw>}Ҩݩw7RӨz;ODn'8OuG*GgPw1_V?FEwɮяX]S4&5~gtR%#TDSkbԿY*u&ᣯ qj֩sS~ +vyC?ƣEO`9׈ҸS?k/CS_+JcXN!@ RS 9hX ?5w{s54O^TO?l/Scx||h057W_KJcZ ks0xTz]/QWﲽa <T,{Q45Sĝy^*vxI/OW=! x[+m7S|_ƮE+@%_[J\s++F{пF4~9{ï1qӏ׌s=+s0`T>ך8\4xZ5:MJU5CFMH!SvyC*3 SӏR4vMnSٟ2*֦֞o ƹ^Hek],֦!} +2PkPZ}xg/<}_7|;1;>0\Z<:1 gRzbVZSףR1] 㭩ZY~]*c\s퇟ŷ ?HۇGkjzm*}FR2R}ïObks3<-<;<_7'y:Skw_J9?1k˦ owfi,Zuw,S;5-y^*l*i}ޕR; r+4zW;w׭R1u/Z5 GiOyF:~&U*Ƶ/NSl>9 S25:V*ƴ>7 7uSe5¯gb* vv r=>OS[f|T,{auTa-'EƣWrPC+1m3[ +94h? 9׸u}_& G:׺Ҹ5( <@_ux|Kv@MUO;4zW*ƬisDѯ{X0[~yuTS;$'RhtC9Aw>uI)MMmлV]sLUv!=uW¯bjީ-Z3aT>0T5O~"ZX*ƨ7n~P8KA5Ÿ 9`|T,6XZ<u[@Hn찐3~H¯bLj3_@Ѭ}TU 9G?_6ƥ[7(7h~6U #~HuR1ukWp+_'Qˤ[}7hG?F+_^v_R@Yb8V+e?y5TxDP:~6rUOޛ+^~,#\}xлJS_L߉0%HĢkh:'~:h4A9`Z:}.:Z*F>@swP&-Dn^3z{4-}AJҘbv? 3R>t[b<~y%Q|>4$UW _WK6H˩?bkzm?=`_ x¯bDѽtFMlw=`NOܙ;4:[Z<:u_<|~4:gCz=`N:0:[*F5|n4|2QLտRUFg[UGvTHχI֡ a5wT50/bmjnڇ}xh4yWnipwg2̫4_hjj?1:\*kQ,qz jpRXk?=|.4%[0Z7={ D? [F93b`k¯˥" Qu7D\տks.-6\=k`$td5xaI[T,jտkuX,jEVI?~. @ n>9zȪ~05w|YuT,@93F^}¯ݥbȴoIUg},Wu¯bȱEis(Rdkyiea6z~~¯b,onkz,{sh_K' y c}_KO? 1{޿D: ԿT 1ۛSsTUu R1,ƠE89/KĢTL# g?~^id0-.UkFݞƟS`]SL6{ R1,FoMߎgfTRsb Yh[Ne.Z~~)d0LU=sTl! Qk6|# ug0buR*S'b3YP͕NUk]f`pg L#Tg0 #~=\!`DjyBթX~d0" n9%zVs}/b#Y@)S(ܔR,X]=99 ο̱{R xN-}A*AlAş9@`3=yR(_~gjvẓY?@Ps=yV5K_~ ;qvQKT?%+>/j" y|Y ?Q,!DtS|,UJCפ}HOO~\so;s0j" yhp39Vmxt6mLkKo/O6:轩Rsk3+^)xwj9S{?ww.&!,s`>~U=?~'oG"?CˇK$.Z0E -Q#,Ej{~-uNg|אթ}Y;o8z`_7: 9)u޺?V÷7w{sEt?=|"ջ|5`P{:'Ej}_ơ.oHSf(yz;_6 j6zP/UNKLc~~=0ÿBUO/ P; ƿ(9g@-Lzpsg:=w^ï%`USKYf0GM~3c&?پ}Sd_˖l3u6y=s_),G0G2 xxMs^?\sǗ_L嚛)Y*ޒE^e0.;zFda@9ycsvMkE?|2y,3^m;$U'*:. Y6!TL=5q<pWSxJ_g4Y̲kG(qx!1z~k[]_ 0 _>ϕr`6=Fߠ7G|ձ/[;O͝^?˕r`?z&XKjzMV| wJ[D?4J̿jdL[؈{o󟜓Z#Ws[2 0'~Yd0:'~:z[ۆh~>_ ~'|nE3lpυs`$_G5&JS?c6C3}S9\sSjU͡^[6Rkwk5> 4#~ uNT,:|+G ؄Ui5> 6(U~,!u/X4-q] psǗiq`+}5wM;z>y7Xg0;sX` 5W&U6Dl/M;Ί~Z, DŽ`5. )= o91usUӖ ?*\4NYLG?fmg4/M,J F?T/_q` 5wyUY:~2|J Q紿 @ު2knNk4,|]TZ:?|u/jCipw9xjxeUclB;ύ~H=GGNJv`ZSipyw>wFjdfjc[Q)ex H*\sS_:uNljNJf0= uO|FLUg&Pwex:`=#ը]ip˩ѣ`z۞g4j%b_Y(ij>ڇ| ~vJ#n~\0dx;o'`D,;Sk>7Q}G}0 0;n**/uNtjܷ4NYl5E-*#5w}c̔ƥ7~[7g~w-.|I,XR`nK]?31s ? ๪?{I#~=5wzy9`c=6_]>4M~&U0 ="z&lRVi}g3~*W:=Wk1Q嚛Ssk礔E|䦪RQ~_*(~HG# \#zMsRʪ%ۤmߌ~z3Tmx$ n==u_kTmx4lW-6|VHŘguwG;Ws'gTZBJfjZ3o?+8|&HEY<?=~HχFNuᇈ*֤mgKR{Rs+ßRQ,S甿e{E.Z|tobQ\*js 04T,}A\jVipYcO9}^ˤbM,~@jéT&ߒ\+zxܷ>ۗ~);u{gFj_|( 㩹QIigl3>z)>%{2z,@}#ueG?%5$ g|@GBI?̐GnHkMS?3|Kd睤Ƽd0ْmokR;5w|Y> %m־?R=-`v璤Fh3Pc>%mi=.`T>tM]Wo~HjTu~jjbXm47=6 rG:~69KJS`֩꬏@Z;砤)\=԰'MOݳ)Pj}sARc,`/__OG:O?s[q߾4~9ss;RE3P]O!ܔW}Ii!`{Z_ fѲG cZwW_:uRjT,{acYRS_^_`o8:|I}!=RQSM'9_NJjǬ$hcX{;!|Iz+}?ؔb#zoF^5=g9l nTy]wgËiK*ƤZ/,~ jzT,.|IZS}VgG59/瞤wn#9P( n=}GO lIR1w0(U'_g(ޚ%[>IRĝѣiOޅ+R,R~js=Iae?knsgSkwbbnj$ \m<|@T&`U9`}g|1zo* !IT@_hgR=vjZ߷UI*F.ʇ~j|6o3jV=٪:O]E+SK]-IUS굢_À'ia[M*>z?KRjB5OyL}_S/!0?%iW@?~j{y')߈Cct$A\.)u]VyFW5Ku7{/IJ?[GGVӢ_ .'|Isߦ޷?Vq߾$-j䬪Rkw:I#V|𪔥JcG=s?REsIRT[4w|gi`õG~2 <_߭$1jTY9gѪIi۟X{$5fU? dl/d:IUs4qo|K Is^+~26ײ9'i4]w saRR]`lτ9IYs+RzbAgR~}TĢsK眤{Ηou KۛE)>$x^'.>8uNgSd>IRjh7g 1e?5W:|I:۟|+u߾$)ͤZ-g|qRyn4&M,Jmɷ_6g$w xsg}؇^*}j099WRsׅ8IUkwb6?$Qj(}L24;M$I*P}[oG u'I$-|Y4wKQU.oq$IRjhc+$ITL,:~6dM$I*Pmw>'j&I$S6 'ETXm|$I)T@ g 3[Om$IR1XR>+OM$IZ$Ibb9 @f\>$Ibb= @fz>$IbbлhUYL? m$IR1j_:dg$ITLZ,w}V2R~hl$IiT@ k$IR1j:OG7|I$I4~a_m$IR1Ͳ_z{YL>$IbePK͝<|I$I4~9O @FsM$I*fP 9_>/):|I$I ~лlLJ5I$A/}^2һx&I$3(oEtO|\$I|ꏅ5I$A/#dϻ$IT̠UW5I$Ay/&JD\;X?$I/_JsM$I*fX ֞o>/)"|I$I {p/F n=-|I$I z0u]sasM$I*fX }^2һd&I$3,@>//sM$I*fX DtO|\$Iwע @F&o+k$IR1ò^>$d$IT̰}^2>sM$I*fX 'Gxw\$IgGOsM$I*fX {/>/i&I$3,@5 #U k$IR1^9dsM$I*fX { @F%ۄ5I$ay/5 #Ģ&I$3,@wCyEU4I$EY/R9>2g$IT̢|^}\ro5I$iv\n>$Ib  #U&I$(o>/O5I$E.ok$IR1]|[yȉ$I.asJ$ix`wDTe\$IY`wEg$IT̰|b6M$I*fX KYL|&I$3,>+ixEl$I_>+i&I$3,A>+i&I$3,}V2M$I*fX !>+i&I$3,}V2>M$I*fX X6I$a.| 0Gnl$I`>+&I$3,?}V2= M$I*fX }V2=M$I*fX o>+]"|I$I wOD7|I$I w @f׭m$IR1]|uYSg$IT̰|;<dfpwg$IT̰lG̔?$I3+m @fm$I♕`bQJU}^rk6I$iwRُ>.)o>$Ibe: @f)|I$I {~?>$IbXwWYL>$Ibe.9M$I*fP }FtN\l$Is @f, m$IR1^rJYLg$IT̠돊>+tbl$Iઃ @f^>$Ibe}w;g$IT̠!dm$IR1^tJYPM$I*Y 3}N2'$ITL<du$ITL~2ds7I$fY/ڇ$do$IR1Ͳ^sɯo$IR1Ͳ^4wK9P$ITL;4d&I$,diЋ>+~0|I$I4~Pk @nA*n>$Ibe(-dۛ$ITL_}N2:M$I*Q gF u&I$(@# @gS|$Iiw> Co$IR1_|{Y9$ITL3>d|&I$(@OE U o$IR1_W,䨪R3N$I*X ?}L2g$ITL]}F2>C3N$I*X b6)Ue9P?q$I⩕`q#UǢ @~5|I$I\sS9P$ITLZ,w]}N24&I$S D Uo$IR1j]sr/q$IR1j.09Dg$ITLZ,:'eT{o8I$BXELu?g$ITLZ,Z'dw^3N$I*P-]}F25'I$S b)Ue9P'I$-rX,nj GN*l>$Ib fP>xU1Ts78I$BYo>)d}Gg$ITl,z}F2933N$I*Pmݳ9dw3N$I*Pm8dӉ3N$I*PmC9d|'I$[6 ?}F2Uu78I$BYKM* @;.~I$I7]}HT8I$LZ^}F293N$I*6SO>#}{y$IT@}@>$Ib3j=g SE8I$LZtD pbQ$IMT@_>#k9'I$V D9'I$V ɪ3_ q$IRj(1dՁ3N$I*6Q[O>#sQ$IMT@ﲽ@bm$IMT@[}F2\9'I$v ѿ}>2>sN$I*6RKXτ9I$H[4w|iX=$ITl-&ZODL 8+|I$IF|3{g$ITlZ.7}FrUUsN$I*W-w>"k9'I$ϫ )}>29O$IT2ֿ9'I$ϫ bbQ:@ʵ9I$iWW>|]ՠۆ9I$xN]o<>d;$IT<.z>k{sN$I*Sm"|d{޿9I$xN]@X#$IT<.^}>2V>tM$ITdU3^+Ks$IRl^^}D269`$IT<[>sN$I* ޷E<|I$Iųz9O@>$Ijh cպ$IT<[Tg WU;,~I$I*'>"kKsN$I*,ipY c>>$Iz}>2ֻb9'I$93 c{. s$IRaHC9|dj?EN$Ij}\nou$IR ɪc c#;|I$I- F{qX7|I$I- F_}pXc$IԲhWX9'I$,c ge?^>$IT,& `D̵Y'Izg0ĢTu>Y'IT,%9I$; g_shg9I$; g c$I׆:I$5j5w~]\:I$5js coC$IRY<ߎ>sN$Ifz}>2V>xu$IRY<Ω>95SdY'IF-x/G̵yg$IRY$IԨ]ϫsE5xk$IRvY<;@:A$IRvY2ֻpE$IR[ s$Ij. ԿX>$IԨ]sF5wyC$IRVYlr@G~<|I$Q,6T@ƺ,u$IJu`ko>rJ$IRVYl>7|I$Q,6QܯF5W:|I$Q,6Q{Ǣ@G|4|I$Q,6Qsk@|9|I$Q,6Ss$Ij& 4$I`3.Z}>rVUg$I`3u>$IԨE=ld{g$I`sMlG:I$:d/>+!|I$Q,P@~*(|I$}[s碏@Zb$IR#, :F M.g$IgoR9>_uP$IR= )T%|d|9'IFYL D۩Xm$IR#,P/G̵Y'IFYL7~3lds_:I$5` 5W6ldwN$Ib@ s$IjdzZ٠e/ u$Ijd^$xdu/:I$5`E uOB$IR#,Xsk@>$I6 iT=u_X9'IFYL'EUejY'IFYLy}<2>CN$I,FoF\>$I2 i\ʔ*|d u$Ijd4}>269c$IYf07}>rVUUN$Ifs}<2o:I$5`H\N$If͝^>n2Y'IFvY̠ۣ@ƪ 9I$5`o8:|dg$IYe0gc\O:I$5`P\N$IAOD <7|I$U3\ssXZEN$IlaVG̵|[$IR#,fX/E uY'IF6Yw@z>$I& E) z c{/u$IJd0Gn>95SdY'IFY̢}<2?:I$5`uOB\ u$Ijdl~y7ldՁN$I,M^Ҡ}>2V>tM$IR! Y6yq0o1zI$1Y̲ޕDMn=$I,fY礿>Y'Ig0_>>_Y'Ig0&dXY'I4YAΏ>9\Y'IXg0.Z}<2^Y'IXg0D\N$I`jg:I$5: 9zY'If0Go:1|dg$Ic=g s<|I$1YQJ\g$Ic\KR* c:I$q`+~Y9Hu$IjesXâ@ڇ}8|I$1YaS?}62=kᆪ:˃o,7/ %|!$ $!%!7@%B!@ Qe\# IDATdc&7a^ ]lI~5c $}]kk3}fgNN$I`;D_׽Y'IDf0̦fԪF_{8~I$)MbC{E@|C$IRerK6 y쟇:I$U&. !b0JK:I$U&. !W@u4|I$2qYl:TM$IReAN< ~{g$I*j;+(_ u$ILT#qG_׹N$I`v~yJY/(l]N$I`D=(n u$ILL#s@5X$IRebQ%(;:I$U&& Q}ckw>$IT,F՜S4˚Rujf$IR,FX+Y'IDd0ڗ}m\φ:I$U&" <ᯣ \sX$IRe"7o6 Y'IDd0fHY@eYy'I,F\gE_8g$I*`ĵϟ}m\뼩Y'IJqe6 {9N$Ig0jtPpYsmN w$I: 1;(>$ITuckZs$IR%Y֙}m\ƣg$I*` 5yPpg$I*`6n;(ڞw$IJy`L6( u$I6 1չkW,u$I6 1<@>|I$, uSm症;I$UrEʚk/k,P$IRcc{y@ϟ>$ITec}@u:7|I$,X?6UMթ-$I*`vKKv w$I. 1} (_u$I. 1׹k:7>$IT]cuN@e u$I. 18@ m>$ITUc`zk'M$IR%WY[uSPp u$I* :}m\oY'IJy碯 ˲T[y'IJn/!(Ʒ0|I$,"k,w$IJy =F_׽Y'IJn}@ѵ:gy'IJ.yǣ/ y'IJ.룯 hN$I\dXk:>$ITEuo=%(hΞ>$IT  ֊E_%PN$I,kZS$IR%< j K׍6 sqN$I,뭺)(H$)Y׹k-|I$@pS?}]@s$I*YD}]@g1N$I,ku;I$,rP y'IJX9}@ 4Ol$IR%, <@ tn8*|I$@;IV:e1,rRk{%|I$7e$I~ίH#>YSe9yB@dO>$IRy}$10,rZݹơ3ORlwO JsfӚ~.D뜯s fD$Y̓$i|7Cdž?VG@oơs3Oa}6Wƣ 3D=3OM`8O#S_L ӣ _=$IzΦL>x)k7s{s4>~Ic/Gε?G{sDVߞq~ѿ)5Qf0/7%פ'I*}Ct:(|2 y'P">$I}Lğf0sHk$@ѿ`? 2 )[HYJ{׹3O4?k }>jYLH[O> @Yt:EsO@jSrR> }gmYLHA 0. {|ܷhkܷO)/50 qDD>$IcjEA|T2j?7L0 IiދSuPU+$i$v~Ejohȍ9;Qf0A6<%RsO4j_?R\S<_?`&%4!|I6GuѿN`4>,0 ?ƥ{'Izk_SZx.l2 FLZTm$a yye=0V}TgY(Q?Fս3H'InjܷߊPZ #`j}D D5w=I*}]C491,&7/L%E=$ibᅯ~t>;FU[]JnJu濅>I}sJ%;o&\}wϓf01\%ҽsEܓ\5e/~gjԹ{䆔zq Ao1#`\u`ʤ(zIR.ᅯDdFkg( 0Noq쓤qT[ _*zcT94,&ڢ7E d:W>$ioqv\qZ } Ug}ML>x%e}RދS4+#YY5,&'Fdox=$iۯ@ek ]`Bk(֊>IzKֹݷlVZLf}>{Q쓤q|ѽY6,&9[ԮELzT['Iϒ#vZ,u\C0N"|Iҳս{#pϲQg0/X}FLV쓤gȍ#p+e`k,HJ&>ekk_k,u\^ܔe(!>$'HtV|=|: sL=g$mмEFZ}1~8 G=qO쓤G#Pc>>FF@jP뜯?I׿- `:Y6, P_>/@ <|IRεߌ=Y6,МSjף P6Y6(unD&\Kg8(H{/>3@ N'ILGlYEEw>$3εϳ1dPG},e. [mWGOB>Ƒ@A-|eJY/%Ƒ@jg(YG Po5|# U5΍G@Isq#(ϳqdPz}vʚkSu63PRY&\x2|+ չTcGgU=zk,Wy_G:>%c{y6, VmET9(<@纥噛+[swJy@Iy?D=, gu;" %7(C@59(3zP?}l\YPRۖ@Iů`,zP3m\Y΍ߎ>G@Yu[択]GO;T=#|+ \X砤b\Q@o-lY}}~T:W=y6,)[*<eRm7BI{%ѓ(8(pO>O@V|=|J*hS[ԪF9Zg%~1 οF'z>%q@A4x@q/!<%W_c,T10,=W(rHYg (eBIsa (Z>uo[}˪SuVPRZ=ހȚٸ(x3\%XY(84^7z{6, 7?$zJ*Nk@Ato=%|; Rcg (n+vy(/9zѾh6,JPPr3-|J*F{/i@A4OtLw%Gzn mR4GPC~#~9 T-g y(ik;ѣ (. k$eO}\uP,4ٵΛ=ʀjϴ,JRâPrYTy(irY( {%3-" %MNշD-@:+ kQY@DIF+`Z*L(W~;o%m|svW@4Xll:V5 ޓ碤\׻iLm-* Yg`}.3QR~攲,zT5>Zs|JꏧEIuT {%-2 V?WӚ~6|.JgnQ@\>"(cgh譾/œzox u=[-YG~\ڗ=j-2 -@^t\>%娹x"0|Yj;"~fP}'%Q󸿌I@eO>ߪY}Yyl\w/z$ԹV ĵ// ^7~Kl[}_L`Z+>35}$ l#ڗ=jW {qJF9z()y/JYI 2~͊unQ@=g˿==~G :+g`Cj(i͞z=xt@ɫg>%ƷXsd=y_yxWt|4^=yks,:}}.QxYKۅϺjPj# YsWH%{#([\5'Y(v~EJNx{HIdsJ纥ᳮ,4{ET[}4?3z:ᳮ,4uNYuf4_yWIzꁰ/EKgfT4w=a˚kSujf$ =]=Yuo=%|FJn?=Z/]5GYW,>ϩq礤!5{{@Y3oV~59K<G PWEϼj4w۔Z3 𜚧|&~VJ^^''@:6soV~uo;-<:v~yϟ=J=xU̫, mPs)j_[ymR=Fh_Oܫ, mPmy@u[祤M{(1{՜eg-<{QΞ>/%m|"zt%f, =;GU7%= GEz>9@mR\}v6J禤 jѣ(՜fsg`oMIOURV 9@[;}6I\7=??w@jV6Z^>C(ު>PvZ6|&Vs^CDeMֹS*ES3SG uo?=~&wzZ+}6KτP赯? NXyzxkYOIdǔ5>hX,_V0W>KI/l V5Un>#6;GmikS<&ke>нY,՗;lL_ɟ$U[}ʞ7x'*JY z_>+6A>CO>[<8ȽyS:AYhӚ=m@dR_Rj,]3:AYhk_K9D*)Iێ>/3:aYh/! ]=|Ja͞Z͉>dsdeͪ0|jj|wg4d9⾲Yh,Tj{~.$[H"|V', mV}}FGQf74 @]=u?ZidSJY/lY6֊E{k_b)zJê˫S޸:gyZ,mRE\4Ul>w8lG `Z:7, @Ӫ`,wj ^>wj}n[[&]cG@ӪuƗ?)g)՗{{iNtz906Y퇩q_7붢 t>8~Κ,4?#zWZgś*|O=tMI77|V'8 M񟌞!}j;b([pN @oދS\=BVݔr,V=#5O۔_}$FѼvdgԹy-[cH{.>#W?gnu³Pj|@}o*G=~nfX^A.3kYh8"eO=e͵y [mKS9)wi_0|V Vݢ@n?!MYj6u>l?gM~Z=:w n6WxPVU+gbd{;Loa/ > 0z&W ZսT-Z˫R{SV_m.Ղd?iϡNLEۇl>0ԪF?JrsZ,4m >­kEjԽ,Q ;eճ^>W6coX[r֊$U e75;l~/9~sW?g+ D ɔ/\E:0Q3zW FRou/#4u(5x:|k_[}s`""|W FV @!?np{ zjS{qC`5>|W FVOE =xUjEofo//=#Pũ9?xYhtݭN#uo995OT[S3$v ռ ޹&~6cP_?Yh_ eYyj7'5-o 25}4/{;(@xH=|](v-u\Z+>XV {ypE妃w~P۬7T F^<ȇ.u8;/%5T[ciދR)ڗ\0t#?>3f7 z3@O%{KvOktGijZ<6u> [EG@c}y&}^΍N!l=xHN_|_o*_[@c#aR{ԽO- .w-HsvԿyRv0Ŀ};su==wSKNL1X@dkܺ@qu:7Z,4]=Wjj tekH9[_TKmRV}4z9:+*ʑZ=ZT[jIX;|//Z,4w=ghY/~KIDYh5}$z~mR-YgcG Pߎ6U,R/E HkïI%@!lƓsz=MԹ g@yҧg):T@iS<Zylrf>jl:%J&񟌞{PJ"z@@-RgJKRu@[=Hj[sU_4RJN B\^8cu{9w`Ɠχ?We}X"F]OD]U}):0r{.Lթ-ßomRxΏB1־hqbgv٪8O z25w[}˘1]l`i'Ywmc$ȴ/9*x=6j[sOZ?kF- 1`$^~= ?6w[r3F">j{\sjxxؤ@spi0Y,5XsiUrQ~އ˳.jw<\ϡUGS[wn}Qi:a3RuϡPϼc9w iR5 Ó=qOΪ9[lX !R@sgs>𴪩ϙUM3m:zCڒ1؛^< d?/k0ݻ{sdUrS ޿o ޓqRDNgNeOޟj&*U7mh}+j K؜9 ׮fӬ k?wJ!` GJ|`̛) d[ۭ*m|`:Aj_z}Ok_,,4{Խ{u`SuOdS:7~{Sk7h)" 8t$UnW\:Kz\m vRDeI)Msɞ;+dC~cKy 7U* EԾpi<x6Ys]绪ڢ7li?6{׹iԖ iMLݻϟqjzo uGzc nO=<ӾW|5%weC{M{:~7F qo Pb ?U%_6u:w,g5$::FPzVelg菵-R7Jwgmˇy(ꜭ*/<.Fa eyWaҘk bZj;<*ws]P/ywJ({aUMޘznn$ gqn;xv=RߊH#sòȣ@%Ÿ*3R?O] dYj<.U|cHUsM>mICR㛿]&~ڍԺpT]4j6ek>iX՟~8{)^c]j}oa.|eOv}ߖ mekj:7r޹"n;MZH v|WhRk_8(0 Op_fo떦ޚ|_?X:g|9|oZjR->Bl'ꜭSji˩죃w>$ulpmYdXzo kF7\ δGH.mqs4g*y@8JŬ ^`D&žH2㮚Ms4; 2y+4umxo%1 Uɑ` B\{}4t`[0O;iչbbLLo ^.S0kx` pMOs$;F٥z f4@C$@ *v.+@lٝ^y_Bxb'UL9XoUikFg# n0^`erh򥂒g ujcQ絟!3!4j".K4ְ v`{R_5N%Qoi轨b Z?I@':/= .W 3kMu0BD)c+|H,`i@y@e)VCQʎ`2<,XIKN-eer5⟙^6>ǂY~,XTEU Di+K"/zrVg򯣥;ˇ_s\Eր&ዬ=qߐwW أW+OϠ`8ë;xgPLO0wAwq]u29D<@w9O+O&'v ]18 tzkʓ! u麣#'X:"`׀`dr蠱}Ny29D\ohv21ۿt~ʓ! ^ L|Py29DLqg^y29D< dz$*( Ku29DL ,SLO0lyjdrx9a"=pր(O(_0QP`Bmj"TTPO0;ᾕ! -/]0*{rAS0?+O*_0 ;/1r cí,p]i9FxlLcnv' $q٭MjsWIWUd']q|W-T>G e 0 {!]/~q ;pcPAI`,۲ '(&;d&  [`ALF#Le:QD o\&v/_S X:lO&.hC }rr hJS6 流w@uϏ1Ķ@ V,rYn%uh9Ӥ!31F{x O*3T+P*j`:> gzxȓM5z.Ys6KNfWvT^/5y]cj9`IOS2모ۇDgNKAڧ*؄OuIv"ʚÉ$1J ']*:X ظ+%-q_a { FFI|}㙨C,Z5ƨJmsȔ03gz L^P p-j o0B!8L0lIa 5-j.޲> S7ɜ =?`dbf{e.!Oͩ^ ުs=H0g=QE['sS#0#Xi 2 (]8wiuf&E<<5q4%X\2gZ Fiľc 뎀eC׋!(w%5v$VfR7l8՜+Ut<KA Cp&} '5 @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 * @0 **H;.KkIsޝZ>^X8!5'~7 s_+z>1v'l)oHs:uwMUm6TfJggyy~sIj}OR/*O{Svj $U+_Zi~si͔EԱaP[2o(u.P*OT,ZBF9~; ޕ+}njT~⵩sߥ.q6 *{`ЏRwquS/i|])Uܗ27g=-I3ڒ~/X=!U4;R *O\S.pݯߔUKXZfr+RgT4)~Pl9."E_35$lr?fU4njPrA*yY_!˟僩%.':|U'c1TC}dTTmnjcT~_KRm7}v_q0JRq1eLW=T|~TV o:'TR7EVy䡩ڼ!SVuu\%n~HhH*MdKM\Tm>SS%vuXߵ.Te\?pcʖr? l9̹_KR+?iTĠһ~M*>-Wjb7u˲ڶ9ei{PRJ \Tm93:_jTwT[S.Rjh呇)a|d/Iuwk2xTxRS+=3UK5H5o_\ߛuTA+ShRǔ~*k)_\yST7TzLV.}zܳ>SaPj$֭x^{] *NN?$-9( fhwrHR[ԿTTWJ?M]e[n:,~. IunAKRdTW>zAh-_KŢHR: o:كJ!5`9zF IuojԻ+T:k'&79?_)}0Y$¿Tf *k's\V $-yjߵJå׻HZT#;ރJog|o亗/bk*W$+mwX|`o.y`/: ,W<79$ս򸗧6^SqٿRߏWbS'HRk});1T^k6/s`u{O3I*ipTz \J} 0K>5HRQʕ/HFkPܿ!K͓Z?`X>ZǼ4$5uRGcP:;|rsSm3}iU[nHg?{u/_<JwgfIMmMUufjbpũX_3I*ܢik=o:'7JjjS_K޺!$ia6QpT,vo&g p:g3y$-wJUg87GjjNKVj}$$sRK5wZoкk'g2Fp}\k&$[nYAq*"5Η?XrP3 I*j\XA/3&̿OiН'`to<{mmrUHRQ-HwPoX_4u{L<]Wbт TԨ-̠Y;ƽޜR՟"'ջg!T|vH\븗a% LD49?UܳoJi+~4Dawgjg#TԤ޺6>_4-Zw{!V=xk*xF3IZXnP~T,/!kN{!ֿH$IٻA{4uٸcOI*jPݻA\=٨}Stg`۩uog?3"s4٠2غ1Ʊ藤aljͩXrPI*27=T:k?hi*=+U2>{ӲHR%ٳA<Z&=>|]Q$iaʏ*-7fҸ[lwٰ#yYI*2Vmqի?Xij_R`UOd?S"Sޠ:M4.Vsq0cz:.$*U{{*`q\~H>W93g8~׍+Td<'T7Jc!]493jz8qsIZ8U?֓*7ơޕ+`V :d?kb[J4׼ՇcnYI*ăJzxmr?Hik𪔺\̞aڟ.Ta_{A4TT=p\̺a5^E9l}*oS'l`y9gKÍԤ7J7epҨֽ9cT~#IսP)=+FiRq0:c$kJ4zs̹jMX2Tr_Je`5}u{lzW6#I gDӃJe4b}b|۠>bA};?(iΜ, q*=39$ ;'&F:n~?<=Y$Xﺓ;hR)9?S~njoQeAaT~6TBs 4 u7'u5F}<\7ѿHMYoL{HR1õN|soIܔ6f!^+V,G\<47ѽ|*M=}Os$#~9nIOM3u˲HR1SMOiXM?MzG$0Ujg;TP駷gC#sSޜ`$U>_~#I mɯ`ީ;FZ㳟HR1Un~^(W2T~`y/I mP93 IDATTʏmo7Ỽ4z]&`ZhAܳ>}X]stsIZ slXFCur_[} ~$Aeٳ?)w3UܷczT,yj3 I*]o_DFYyspcw@TE 6~`UkIRT{澕hjˍ: ${AE)Z#wBTA5S;ɯ>$I w/]Uoڼax}F$IndPQck @>ݵω$؍ *jdg#w_`M^H Yr*s?_R3qu~n$IœdPQ*zQ?ZuKIRTԜ&m5 n4$-| *jL݋>@wd?Gq2;r!ϓ$ *&W`7;9$-|l}K?=1Re?W_dPXZܷj ?$?ϠmтTmN>$-Ym˧r`_TLTT4N7) z]I ƲN&ſ$ *zWo<3h}S*xFs'IΠ[}޵g?{ *-H}0RS JRjjM,6_??>4 *ZO7YֽϢ$M42FEo[vv?AE#_;_f3)Iˠ<%)ucS ٔFeP69/ \o7T[n\fP{s ޗJDc2h$+W0 ۏ @FֶTyh*IȠlu'e?4ш *:_z{E5H;Ϡ\4q_?kR19/ٕΠr}:gU+IcAE#S?Hi8nߔʥO~%ibl3h4Z|`%e?{nYz{CB K(9$!8p!!!$@%Ȗ䂻-nn rؒgVyk/EgֳҞ&I$nciRY0.ǒ$I$I\wY@c"Y0{vJn8$I$IԿ,1,TmO}WFaI$I$QC?IcH+I$I1x֔(n hL FVl==%I$I4uZИ(*GE]I$I$ie{Uw, hL FRE\I$I$y+ B3Ts_@cY04=W%I$I4+K6ύҸPa$t/\=S%I$I4u{01,T )T$I$I^y"^~4ƒ Ἀ^$I$Iê{01,T:3T$I$ITO+^ h  ^=B%I$I4eo>9n HB0ӿ=;%I$I4~rJ+*wT$I$IҊפlf{216,Tѻr)I$I)}gɀذPa{m/I$I$)r)z21,T]GJI$I$iP笯ߗ`P}*zFJ$I$I?l=_~o> gƩ|)I$I$\ w;ҨPah:g|-z6J$I$I\ů?#B0GG$I$Iu/# h4 {ɷg$I$I)h@cdYP|ץkGDI$I$i]u`]Y*ԮwݲY(I$I$=sE?5w{s}I*ԪϻS*Q(I$I$Q S#BZX=%I$I5,SsՀȱP6?=$I$Iiwk@cXPyg$I$IN@F h'I$I$sc#B-$+y$I$IҳukҨPr3=$I$Ig]qS63' h *oTfE:I$I$ZG|< h *Y>?zI$I$IUvWo~4BYP|_Oیm$I$IR-O2hP+i$I$IRmT`ʕ*<[ίM߉i$I$IR|]c³ֻY&I$I$^)A}a³oTg$I$I4n~'4BX=,zI$I$ICS6o{91t*oHE0I$I$i91t*G.I$I$iݘPYN]^S$I$I4d* Ig$I$IV)~O4B%I$I$:cwu@ch,TXk+U$I$IRxŊ ̝*|WI$I$?j;;1*{G(I$I$id*,h k,_z%I$I$TWШ k{.ѳI$I$I\~w4jg0UѳI$I$IZ~Ш ksLL$I$IFF,Txf[o$I$I$to/.HuPuNr,$I$IFX歟GoE$I$IXmwz@ O}gg$I$I4694NhB63'+A$I$I|j*ST>z/$IT>`l~4*c/r,I$=^*W޷z9rI{^FIC?{-廼> _F,Rs7澿Z>s7޻ԿT7 K$|?}P$InMM vcuGSsSf#$łSs7 CS1u/`qTg3Q ~lK$M]n*V\zW:5B ~>(<75}OjԻbT{)u?}IZ+,*Xf ^*I4ɕS/h|L~HO2]t*H$U^kğlY3 I4I;<}'}~o13'5w>K$I^SY@z,TDIuN{.IKvMe|+WT#}˱*o$IW ?WgB枿=V$I֪r~36x/G63C0:胃l+-$I7 zW=S$Ip򯩹ވ>C䍩I;Mߍk*I;~7 RE)u#E$+,7P,Pxv/H&o?{G$i^s h3 ?'I4 ݝzWGr8\h- i7Ϟ$IqE*,ufjS-%IR ?ub2Zq $IV7'm<~Om~.kBeo9%zHiZEʷu$[k;$I>!,TXӫS$՗% cw徃$Ièg ,TXg$Iotʶ4k#ᥩsS]I$i j?@cXL2{(znH x9s/zY9R및+$I׻sֆʔj!IƼr}{vۛ6P9uS$I$k~C65e2}/zdHq,RS{)A{Je](I&93,TPsߎ$i*=uFw,,{N]wdJE?R$M@)Qh )ѳB$orjjG>>(ލIkgF,T͂MR|4zNHlL+Mvݩo[I4?L4ֈʔi!IFR/l熟Y`ܴߩxocI45}Oyh<# )$I/ֿxgk3sK$IZz?8",gb2Eg'e2:9 I,Ro?{khMS߿$I?wq = )P/Pp/$IU8uNJm~RȭяI\^};z,T&ټSjE_$UU-NsS}8$)?鿲P`C8/I*繩o/iT6$IAo==<4~$Iz+Kc?W1^\($IEwy]yhʄʷyc_$=`mi6~2I!77AYH?e2}.y/Iֱbթ `CH$i*x0e7 ? տcy^$ee9+)Y/,|͜%I>~*(_g,J˩w%D#10oԽhǖ$IR?L~, ~K5l='n~~OO{o$IPY ?{ IT{yc^$ALN ?;㫹򱻢g$~*&u$I+eN/^I&2ql~iWZLΙ[E?%IԿ30ao$I5>grd)*.I:^&}^&WRē$I5pVY]i29f_N%IF{R ?+ӡuxO$Ps5 b*sg$Iz-Kv/?'e\yo#P$U\=M1 RLE?r%Ixo" 1ֿ1#I׿ܔos`Z}0^++IP*r/dY 4FʘʷyHTs2I`~|w$UZԻ9s{m݅f2ZY$i^_VOx_$il+[gۥKV1,TTG&I&Eg=@T$~Eo{O9$O{OT' q43'W$Mdg=hW)EYՕE*i{ONrj(|^a2{3z|I4uΙ>FM俏~/zI4Ye3`Tu/\$MxeԿԽ`ů/PC}WD8I&_ #mfN]u@Z4)y 0wK1a2&f2O~Inߜ/ w͡яzIғUR |twls S*c}gG$IcY??`0kFw*sWG$IcUS63'|L[GI~tABe o==zK46_fK[N 4r~,bREޓ?HkBe-x9$i~/_ @0=$)nzyr.}ԧSŸ4 Ν IDAT_]#0X .%i+zxo;xe6ШʈLIuN /kEI'ݵ Ÿ4jg2w}F$itKG$UޓE/ a2lR}n$i+%:=D IzԿԽ[߰kg(iTX0O$RslYӫS|4zrHVSuw}Ssy X0O$y k2z|H~' _\1V,TFXs$l[O1}*Q^'.Ie{ *jƃ$I\oy ڛa*~Q"iwS w復}[ *##$feZA`;y%i{2<>KEms TPQޟ"Iғ7 sgo#x$i{e2?E_Ssj~<$Xvfꞷmj}OS) Q4Ôy9Fo/~NP7M7GOI#ޓK0Y>>H4ru/Z>^sw .V%MpenLN>5~Ƒ|Fu$IzNsfG  e2z7}$it*:ͬw]=q$Ce{U}Q^d].zXrՊ$I#Sg3wybVWVCR-4m,TF$iueHʷI|`8'|!zH]t)[Is@*#}gK$Lc2|60\O?Roց<lXKP$Dŝ WKS==lL;;OW@6,TFLu*I+216DDdK'0wX|_\ I4u/+|.w1Hlg&iG.I+|2E/IO]jC=Pʷ{A.dBetϏ>IOSFdFCD%id*;O 1׽tIjEjQȦrjLʟܑdFGǓ4(P!F$I }'1%qT6QR=|rꜹe2"_}~$)R63'|&0zu*l==aM=4ֈʈhg:IBky ѣJZu~^xN^BeD$Iw>d#KZ >kF;@2*#yG?IjY }4r=讃>7 P3륲2,(IRHΈyb5ѣKSXz{Od29l(IRX}>s#E$R SS{٧Rk`2}.(IRH/iKG&'@ZS*#{GHIBj}O0'\"zi +rG]wd п3$ICx{Ģ0}ԧG'w_.4-k*BLI^/aZӣǙFnzyrɮ}_|ׇB%Xs$ S`9 xkz豦Qxɂ>g̯K LE5\ԿY>Gwmw@c*Y^CTSg0b򱻢*l\].Ie|]B%Xߍ>J4Ժ>,T˓cHߒ9`GXIW|}`a{OB%.K4M[>L<{O0@,YjGg\IZsw_&WGTV6mZ=ҤP 9ss$ICg/-WRKW䘿LoF;@6$*z}$ih;l6z0}.zMNe'W:']j.}Gog P Tono鴏lOg 6 @c,X Y/EsIT_nʷ{A*f2dKv$>kX YӢ$I>kX Ymw]$SY|WZ*4^u$ITY 0*C\.Ij|^jb2DC8Kj.}Gjb2D/$i+GR6^jb2D݋v$z>gY Q$IY,TXqu}$I9 Be_c]$U^3 ʐ _}%IR-u{jf2$ͥ$G|"|d5Pͣ$I|,@V3 !o]$U^Xl,T{;/I*w3  !rj$I> 3  !)A$IM3  a}GyITi->c!Pm}%IRo=-~ !8I&yۆXlH,TuЇ$I>c!P񟏾$^>c!Pw^$UZ?>_!P}%IRo;#|dCd2N$MRWl,Tx{/I*S " a|F{ITi+|dCdRT^$UWKقg,PYӫ$I[+@6d*5k{/I*  2 X$Iֽ` J'}1KJkE|ȆBf$I ِYԬw^$UZ3И:*5tb$IUfV,J͊{/$Y }%IRe?*|d,Tj:Yݗ$IսpQlXi&^$UZ/WgR|WE{ITi(|d,Tj\{/I*7+@BF>}%IRu,+@BF?}%IReC bRi}%IRe |dA,Tj=o/I*ۙ bRK$IV,Jz7}%IReu/\>[ *5߱[ *u~qF}ITY>[ *uRя$_?_ưPI$Il bR|WG{ITYe{UlYԤoG}ITYV,JMZ?K*6|d,TjΟF}ITY; Y /I* dR)}%IRe:0|d,Tj9w_$UV]g+@B&󷋾$:V,JM.$:g|-|d,Tjw_$UV/V,JMz-$MlYԤ˩w_$UVY >[@*5)9Kj P /I* dR/I*ۛg+@B&ی$_>[@*uRYF}ITYWWq,T`{/I*-q 07J }%IR;4|d,Tj/zY$Io PAk$I|W,J K}%IR_@*5h{/I*-~|YԠuЇ$IlfN|YԠu臣$I PAE{ITiz dR}%IRe7 ,Tj>^$UZs+@Bc>}%IRs^$UZ+@B}%IR _>_@*5h{/I*-+@BS1KJw,|d,Tj9^$UZ dR}%IR;6|d,Tj9ߢ$IoY t*KJk P$ij.}{|YԠsף$I~ Y XH&A Y XH&a Y tF$I^y|YBE4i P$ije|YԠs7$Ii>_@*5P$MZ3 Y ^:I4Iu]>_@*5|_$I+@BӾ}%IRu/#|d,Tj9$I5W,J '|!KJtB|YԠ}_G{ITi;W,J G&KJ+2|d,Tj^{/I*x PA눏G{ITi dRa$:Y|YԠuE_{ITyټ g,@B K0|dA,Tj$I|ׄX,J 'Kk PAs;$I~>c *5hw^$U^및X,J %KkEȂXԠ߈$:sȂX w^$U^mg,@BWDyITy Y ;4K]wdȂX _;/I*Y3 bRm}%IR_?cưPz)e$IV>vWB&G{ITie{U|ȂX$X,J]_$E/Y ^}%IR5wKXԤ;/I*X,JMw}%IR嵏DXԤIw^$U^ Y ~pD$I=wAXԤw~w^$U^g,@B&K}%IRo<>|d,Tj=o;/I*%3 `RY_$GoY tN;/I*<>c*5i;/Ij)s 2 }*KZwy]ȆB&>}%IR-5}OȆB&~?KZj9 JM{3KZjeȆB&}%IR-uΙ ِY$U]$R=,@6d*5(KZx|ȆB.7L,$I,P^}%IR+ ِY};/Ils " +$=|dCdRˣ$I YԨwñ]$R? YԨw~]$R/Yl,TjԽp.Ij{9 J:g}=KZ]}pȆBF$>g!PQ{]$RMs " .Ijl YԨ$m԰PQk$I7ZlH,Tjo.Ijk-g-@6$*uRы$}.~ #]$Rg9 J͊Gn$zW>g!PYqe]$Rs,@6$*5zz}$ITs  ~px}$IklfNȆBf$E/XԬ{6w]$Vs>k!PY$6XԬSw]$V XԬ$IvXԬw]$Vg-@6*5˷{A]$IU&|y]uyY;Z:-]:ֶ:km0DA "E aTwѪȔ߳ޟZ!ɻ}`z* nKJt y*)~%z%IReK>k9$0]$Ig-@^1Fם${k+栒D$IyTsK\w+栒@D$Iѵ'Zb* }WKY WA%aouIT].yT|WW]$UZO[B* ;?+z%IRu~]+䠒e9E$Iq?o㠒oG$Is J"E$Ig-@^!DFן$F7>k 9$2\"z%IReM[>k 9$28]$I5yETѫ.I*/["*{.I*{[-@^D:fK* { IDATJP+⠒HE$I{["*,ڶ,]$I5y 0W ;z%IRe:|qPIh|Ww]$Uװ[ yT^u\KJ+y WA%E{G$I-@^4z%IRV~0|pPIw;\$U`^ JBC~+z%IR֮ yT*|^KJߵ6|pPIiѶe9E$IQ s堒[W]$UZ -@>e*}qKJy OJbësITiS1|S栒OF$IW 9$?E$I[|T=$I6[|T=$I6g.@>E*˟$:{8|S䠒r2sITiQ_ \$UZK>o)rP 0{.I*mxA "+sITi 9,z%IRM=|Sw\$U^3 oqITy^>s)qP P$I;3 +0z%IR %~MJ/ߊsITik>o)qP 2=$I6y OJ{.Im13  F$I'1|Sw_E$I8|S{w\$U^\| T?7z%IR /LȧA%e9F$Iѷ.s[A%\$UڤNȧA%3\$U^sg.@T /90z%IRuy}ȷJqITy>sw;w\$U` o%@_$F}zȷJbgG$I}g.@TzG$Iɤ,>-|[A%ˣ\$U^ׄ\|+8^ulK}og.@T [$>sw{w\$Ug.@Tu~]Kʛ{sȷJbD$Iɤ,<%|[A&{\$U^W\| 9Kw\$U{âg.@Tj`xQ;.I*opn3 B*508g$I7 o!w\$Ug.@Tjskw\$Ud\K>w-Rό^qI pPIqwK o$I78 o^qdK]>s-Rw\$U pPޱqIT}q/yr7JMtxeK$u|u7JMKߒ$)I/m7JL#z%IR V>sR#o]$Fr7J $&>sR#3-z%IR]"|AF$II o$II o:YmY;.I*oxs`n9w\$UhE3 *53$I7m( .@TjfpN;.IT,~7J}w~K$u? o"-I]|9͎O((z%IR 0iTj"IR~e7J ?-z%IReqs *54X/z%IRM&es  *55$II;s  *5?#-I?.@Tj{ě[$%ix!s  *5U$IIks  *upA9mqIT}N/6~=2$>/ pPâ[$%w;.@(TjG[$%ip޲ ? $II]wJJ?7z%IR&>wGRs;;.IT ?|~~K$u{CJ ./z%IR}$|A>ߒ$)I5]8\߉oI.@Tj-I4g/@0Tf[W\$%闆]a8̀ gD$IJR︿pPˣ[$%ips *3ſoI_ pP_ߒ$)I .@0TfNO*8z%IR]"~=ʌ$IIs 1*3btI-I?.@cTfܥ-I4 ;-I4kmʌk-I4Œ^G8̊ۗ$)I_?{~AeF~K$W}(|?Ae $II^zH $IIzi $Ii6?,z2C]2z%IR:,|2c&ߒ$)I>wsP1ΌoIE{]Tf=[$%it9s >;[$%iҽ.A$ImX ;̠Eەߒ$)Iݣ?{Tf+[$%ipNs wPMˏoIUs wPM?ߒ$)I>wr]C~KdD8̞bgG$IJV?4ٰ>z%IRg|,|LTf/E$IJʣ.Ae6 5z%IRw ;-I4RߧY(K[$%{^TfբmrЉoIi?{Tfxe-I4sh76\sX~K$:|2~8z%IRƣ2IZAeu$I[ZAeKRq~K$O d2w_ߒ$)I5+.ʌ~$II~erPq3?ߒ$)Ma d2㺇AzKduzMVrPq.ώmI^ k%wK~K$ /;4|Y+94h$II_>wT`pΎ-I4@:* =O[$%sg/J{>/z%IRz'?|Y84Ĥ;z%IR>wuTbͳ[$%i|%sZA!ߒ$)M^/>|Y84DwG$IJVg^ kݖ$I}g/JS,ܦ6D$IJg/** 2Z:z%IRƷWVqPiF$IJӠS拶 @* 2y$~>{5Tˣw[$%wg/J,~\Y{-I4 m0E$IJK.J /=8z%IRF2ZAaz'?z%IR::|Y+84LWE$IJVog/Jx1$E /L6pPi /$_@ * 4NO @x* 69uA^Ԧ~8|Y94KZ#g/P6JCy1$-&|Y94KZd\K}drPi(/$g~7|Y94KT^ k4bzIR^yt&sPi0/$w;|Y94KZdR˞>{T̋%Imb d`^L/IjS3?>{T̋%I-jx(AἘ^Ԗ&>wT΋%Im'g/5Jy1$Mu|KFrPi8/$sAo_n~K$֮@D*-0ע[$%isAߒ$)YŞ @8*-;ow[$%? @8*-F$IJg/5J,ܦ6D$IJsg/P6JKn>?z%IR_&@(*-1X{QTZ/D$IJk^ kX߉oI^lpf~K4eg/5J 9z%IR:6|Yc8HE$IJV^ k )ݖ$I^ d2 E$IJsAeFkWE$IJdR˞>{TZ$I d2#ے$)Y/GFpPibD$IJ/^ k{s~K$M6>wTZhxq-IUfJ XnKduz[Bے$)Yw @6TZXԲ[$%iͳg/<qU~K$Mmg/49,z%IR:$|LsPiF$IJV^ i*-9ѻ-I5x d3Ao_N~K$o$~,sPiѺ[$i4(>{lf9OF$IJV @6TZw_D$IJV@6TZ/D$IJʣg/,6[wG$IJg/P*]$I*v d3Aے$)YϽ5|LrPig(z%IR. @6TZ9ѻ-I5g/$6W64W @6sT(B~Kdu>f eF$IJV^ 9*C;z%IR_; |qPwzbY-I4^&~qPamWD$IJxXK>{l8𒃢[$%k.g/6ݖ$If u}YnKd :.|LqP{nSNz[$%irߺ A|^~Kd?7|pPے$)Yݣ4|pPz_ݖ$IK{|nKdnJƒL6ߒ$)Iކ2_mƒ֮oIξ>{l&8 w[$%wg/{ěw[$%kx!f R̲L[$%i|f 1$Iibg/՞ 1-I]CsP!~8z%IRgυ^ =skw[$%ktݩ?jǗߒ$)I;epA:sPao$z%IR:RZsPa ./z%IRz'7|Y9z'unKd /90|Y9:ݖ$I d[toI,>-~e]9F<+z%IR+>{TxDvmIY@V[*{Txt;=,$IibS/P֍ i|ף[$%{^ Cw[$%@V;*{6Td3?ے$)Y>=|Ym8ɺ!z%IR&|ѶjAMV,yƗJԖ:,|Y-8Yw|#z%IRz+?>{T,>ے$)Y+ @V *lے$)Y>{T,~#z%IRҊ~:|Y86ϢmIݖ$I TlϏmI{^ f\GnKd]>{, ?mIaw|BP*lbE$IJZׇ_ lXے$)Y3>>{, [dtIѻ-I5?g/rPaѻ-I5). /qPatW1z%IR:{8|YHe9G$IJV_ yMnKd /=8|Yp͊ݖ$IqU0*lD$IJdR;?+|YXgWD$IJZ? @A-hѻ-I58wI*lѷ.mIэ_ @A2X,9J{-I?ȒsPaM6ے$)Yk>{,9hݖ$IɚwȒrPaDnKuyITjג$)i>,)Ze9G$IJ/%TZے$)Y>{,)bxѻ-IV d80UkI1@ S9{-I6>ȒqPa:o_"z%IR_LA[ے$)]QY,{z$T꽢W[$%{ě/%}W^K )|Y*LM{-I6 dI80UmIA?.|YTUѫ-I9+E IDAT*TD^KO dsPa)z%IRFמ>r*LUe9G$IJ֤.@V)n|׵ѻ-I/_ S7轖$II*W}(z%IR҆W>R*L]WF$IJ[/UA[}Yݖ$II+??~eUTh轖$II dqP{E$IJC/UAJyg^K>|YeTD{-IW dpP2kI=*TfvU^K ./|Y%TLOD$IJo_ 轖$IiLb` :*S,{zYNѫ-I=m3ȦAJ6z%IR>lTãZ$%m dSB>ג$)mƏ@6U*Ts+Z$%{` *x{-I68 BFVG$IJhE.*7XW^Ke3ȦAygZKuW>ljT\;-I78g @IJsosP!G$IJs/Qw{W)Gߺ, ;}y 8h$I eg0gZ]UN:<ꏠo[A$g}"J=wg0V̲{ěs;l?pP!o`M%IR럽0|P#/;~i;#Wd?~A$eOʃAYjtWg0uzI? Ɍﺶ$I{TZޓ&spy 8Ó=@$IK^ `O-?_THI"I3hK{OCAd:""IRF7>ؼ{2͆_\[*hI6NO<{O-pP!ѺI] v?ޓՐFם뛷 I Vl$)ys`VLэg5 IygE䍾uA h{OM]{ I˟l$)}~/yrh{O.xߗTHn$I 0k%Oi{OkpP!ڕI78oY txe~4{s\9\~H,'g$IɛlX>{ҹ'Gξ/ Ap;~H xGw]u(/Ap5+5$_stնw5 z+?$)5'aࡊ^':&k'o8uEF&{72z@='ߍQAڢ:.)o8-ڮ,yFlHX#ɽ7GH M57 NJg[d#TYu7l*`$I!n83|@3{ҍv_JZw_y9P c$)AQ;>>|,){)'ͼTbϟ~HV3>`f{砒UAژ-|@ݟ[vz[98ort{_wRqYT/xIZ>`Z%Oy{Ow^-梿sP>vzƿ+IR\o,-h闖޳/+8[luu~]`TmG?w$I i|s'NӒ*&7 2I*za,?t?ֲhrRmGsßy9P+4T;iHp*J瓿ܑ$)LJbZ{O-sB,\JZۤsO/6~؏\H ﯅?ksPvFם$)A ̶b3o{O򻢿͕Χ~%7 ?{.#IRXbfȒ'?'Ig\9P;B6xƏT:{895l*Ne9E?$Ii<,eO'?g堈nUR+zas+o8ji|7?$bҚK5{"ik*??Y7 4$Ia .7|P!=TA?|k6jſ~Hg1Sh[= 5 4$Img&=UO?sP.('{A$;~Gwo#%b?sPF7 $)LJb~NO*vҿo|sck6jkpΎ Išty'^;>!9l*VȷD?$I sk1@{2]{k2ip*?QHMSESDR3vßy 8PkF?$I k|bxsi)WY_ޔ܏~5 6\"Y$IR\ƿA=fHjq ?AZ@HzǾ;|{O:D&Ia/y 8Pk~=Y$IRhM=KVvy>G&Ij|׵T۔#Išwm3 {O?{OߖIR_k>jotWG$6"y Pb{O~I5ZwQHR~!of럋~&Ip͊y C{R|'[#Iҏ5y 3?F?$I mepALޓ $mB !y 80:*$IRx_>IjL +slX]Y$I3dЉF4. 3y 803Fߺ $IRhlIjW>>{pPaf .=$IRlaY,{FLXdGwIZUϣTݣ\$),|&o_v|u_#x$Pk>?{Y]zH5F$Il1k,YiM1UIM1rцC R 0i]Hssu}59Mu)_s <8|&K9jbMͿLʋSt#TP+~nm=YV W}6@2{ edI4ůz<}&:G|"|e BEjϙK>%I'RmYPQ.\g/ ɒ$i=qj/ykWix) +c;㟅jU{ۢ&7,I^VSX;OG_soYPQ U*˔,IRO~'{=}S_>dUrJ?>%Ij\^=)kl&srBEwGO3YnFOޓWw+<[?7nF*]>}D@5. ˒$L3| Q>qV:_h\$i j6|{4kH*eû/> \}g$IP{Du=Ҭ!Y/-p) |.KT:~8z>KdZ=O)˒$ս=`ڊNYCPQ-2JsY= #mpա4kH*m#GU,IRֿxI,jã*WS+$Iu4kH*m!JsY:׿tq;?gi֐,TT{=J,IR\{d8iY5$ շ Sy4pe-4~6KTӊ[=`ں|&|f BEw+?>%Ik{.0m |f BEwT$Iu\}W(ik/}W,j]ߍ>'zfl$~=`]^>Kdz)3 *ofIߕPc-BEϻn+eIo@m :4kP*}>/|.KT'zWҬAYu}*h,IR 6Y5( վ|ǟ>2zWl$Nuli+n;=|f BEcQgTpsY:;FoGҬAYh,\ |ǭg$Iu^4kP*z'}),IR]\wTi5/|f BEcQ{_>2[>%IKŝ+G7L/GҬAYh<0Tàm^?%IAUEOnOҬAYhl*n=-.Tl$~;zluY5( M ~hpYo 34kP*:|((lfY*#f$_y5( O^p}@et,IRq W)I<ƪWFcP ͒$U =`Σ4kX*/>Zk$IZ9=`چn YòPX]s *sgIG5Lp4kX*& EYV~Vix\,Ʈ[228e6ϒ$UDҬaYh\yHYgI*׼R*cwӭƮ}@ .[>%IZ.?=`Fu<Ʈno>RA$u 39C4kX*>R&EgITFgo YòPX6nYyҿd,IRꟽ0z<ۼ8|f BEcY[}@O ehIâ3L_/ YPXGTN ђ$U G3LҬYh<0UTJg$I0mҬYhl+{RR>~_m>%I.ecfdp4k`*zs *sg$IMN4k`*7\\4|FK]0#oy50 o6Ne *e}iI^OӬYh+n?3l-IRdwO0#YPX;k~3k3ZȆ=`F]_>Ofs6Xl>%I i R*,71Yh[EJE/|$I|s)i,T4w]}@ [>%IhK|Ά?6|f BEc_8~E[iIFOa'ӬYh3*{̧$Is]qG0H=i,T4XsZ9\}W}_i,TԈ+/>z^ʷ9-I\oS)e|gj,TԈm}@%u9-I\9ѣf;gj,TԈ:}$J*n?+|NK4WN 3635kh*jD-S*gTO9L?>%IW=y`F#4kp*jLÕGwPI+|NK4 $z *|f BEbqy4|9-IҬ7)cfdpq3uf9;>%IK=n`>SgƔo󢔆3*Z٬wҗ-X[>SgF53*Hټg$IયE[ YPQꟿS5zY-Il5|Q 3^58 5 .fk Ւ$+am>WgFo┆Eo|ۗkIF]FOYͫ+0Wg5*{gg$IwEXݗԦWZi/%*n?+|VK47=b`- MPQ|׆kIFYfbqLmz=**wD$iTw #]J 5 k6yA&6 ג$ =Z`$:N\mzX?! ג$UFU|j+-T:_*mpZQ>:+T,TnҠ}@u :)3[ #1𹪖[qǹ TZ/kIfR=N`$>WղPQs5?J{E$i& .?zH:|e9 T^{wlIFROU,ToR/> ?%IF[TѣF;gZ*jvŭFPie{Ul>%IZߺT IDAT}6zhÔ-<|ef;+!T^w٧g$IຣG(DsU,TK}@>%IZm #1٪4%HV/mIֱ~02۲U,TGPyg$IZѣFwҗgZSYN3*Jق$IpEѣFsgZSYz{=3s[+) cF&U,T R"T^q-I] ˦_FWPnuGEP ~9|nK\ Z{elU,T`Zjs[6oTGKGWg"McwEP egum>%IZS_ wU'P~pm#_vFmIT$T? I*ҏ\4|Z-Iҳ WFI7Xg"}>@m{O$驵;z<Hǧ~a zƪd*ҏʷE9 0[?w#Uua|UiYHOix%$CKWnI~FOGWn}N@m^>%IǛ"\/X:} (R`-IRycFsoXog%Fؿߒ7|US=czZ*3*n9%wU$5wGC;gZBEzFoky 9[= `>czV*3j%c$(O z6~*=3 Ml>3>Ew}} $5a0+GyUYYHkhpףL;oIR\sxY^9ֳPPؿ>3V#)[.IjP^#FoMټg3PPV)e ;_g$9uLY19PNS6.IjFώ}0+W>gZc*Z_[ _pIM*V5f"a>;v_ $i_KYZ֘lR}~@t9.Ioq,SO[5e"=GŭFP;pIgUZ֚g(R{㒤lrqjpVf"=G=}@-7>%IW{72zZ;>oZk*:,S{[$i_{Y9ZkBEz}@- <8|KƨE/Le{UxSSYPΑ}@=Y.Iz'sdY5|ysf"=O[B\,$A6JUE5UJϕw}@}JeׅrIR.dDY?\3 ijkpY.IwÕG3u>sz,TuϯFPRy.Ig+z+)[yU9P֥ R}*V}$7=` *|YHâUA7;&|KU{_LFO1uj=o*:=*Z$^/7z|f"c/Q0R$s3crv@٫f"Gû/>[$i]-hA'e7 j=o*z?{a 6,R{ϷtIRw&}IUkP֣}@ ?&|Kಥ LgZ딅>Ml3,S{uIR%w~NQGyUkPֳՇEP{mtIR5\95:e"ge>c`,tP\$US^9S>zgUkPֳ|۟JGP{û/M]T=`N =2|YHӨ9g-Q>%Iը;K3XuBEFS#0\u[l>%I7=`ε:g"Mo>k`lo][F#se(|YHl7j+;|vIRPWF#sŭaBEfD06>%I1u.z @ޙsXBEfCg cX^o-_e*/z @W^Fb+ i-4']gwIҜ?g1_,jW* *nZ}X.I^R?=bxXBEA 5|A$~돉;ўXBEA[T/i>%I[簏D]yzg"Ͱ}WE0^yw}}$R H#GO5𙬴YH3̗(7>%IS |(=՚V* k3ROyIhk>՚V*L00;^ >%Iib4\yqxpw\VN*\yp9 cs^4z'})z@%VmPFP?>`<-^4JeguTj%~fZBEE 7OG0;ϟzML$M Rq*aM7YiYH#iyy cwʗg$izNb٬ִPFT>`|$ijT"P e9ִPFTR2L6&zKֱyʋTLPFXqskc$i5?zl@/^>՚Q*}ߣeo,廾!|KRяP)oQVkFYH#/F0N/Ir HÇnP-"۽4~N+$ iM ]9|Kಥc*gx3Zg"yG0s_|:zB@%W,j8 iĵ{o 0|-,|K~X{_+:~8|V5,TQ7A*'F_k$|іiMcl Z3BE}L@3e|_ip1*y4,TYh07'OWIjj[(J5?|^5,Th>}V@c ԰kLHPf F(3;|KR{_o>I*,_F,"u;$5ʋO~ҨPf|ۗwce@w{$_#js[iTYHUqnm~qG=FkgZ#BEź] _8 Iu7٭HPf|4DV:v WkYH\>%4_n>Vc)9HPf|+Sg84Vqׅ)[i@XK+r j< i*8/ F\uh}@j- LSJBEz|9 wIM 6MmGPOe[g*ꩃTͿ HR囷Q\L 5y4YHspg9PR $Ml~#Z럻mLW,T9j5#@:z{@*ip~4^ߌJ4G廾>,~|U@TݣgHm>՚,T9lxg:۾$~ IMl},X\,~+V*;g:Õ|іwI +>`lt4[YHsX{7E3$iΛI\t1 cX|WxBE_}PtKjV 6:)8/~+f*;k^CG I]͋Rs];okWkVP}kѿtKIc]OݗF0]_>՚,T]}ka"i\wY Y2/z֫5YHNJ<XH{=>^`lΜjz*R@ίM,y9XH:Tv>V`֬g"5\yQ9<TzKJ"86\ukWkNP"5GlwIZm/>B+vJsTV~S jiyl~u)_e*nV }_9BE 9=[$wzuwu Q>Ml~PkNPg>&"ƽYR5TfF(˖Ԛ,T_Rя>0{$=wWRtwBE w}`=ޑ{9!IUzjTvMMjY*Rp>}PI~K=b 9<>֜f"oA7u}*>!yu>} @u;ZsTGt ?'$5|ۗE|@E/ 5YH{̧G0C;N}1tB6G<kpñw<  -"^=͔-,n!iZYX<q@5t;\g"UGG`Ϛz%OBx6)c)[y=A9BEH#0z#2jܼS̉~<"P2(z#RW~/!v廾!w}k9#BP*T0JA;4ԙ X_{RD*RĵUlw Iխ;pE<~oP+, b 9z.`Mw Ik S⩿hsoP*Vys%e=Qr XGN3VX*R2e|fQ%)[YCRL=ޔN>Կp{ZYH̲7޿~4-<ΚҠ}^Rd*R̅~;) !iv'iS[jg"U|4F `7 H}~3w]}3?g{ZYH9̡h.|DhjKip1D{jg"UΑ='-|WE$M|E{4D' pmCJd"U*z^=o|Tm^,JE!Nj]CJd"UF PS{7I$=G 6K9G02廼.ΡT,T >D ZOS`𻉤/2Nr*'fjU&  %zn0|{s&Rӛ|WﴯLc*VeP*^s3R{[(Rw;k~*;F){OLUj=Dd"UnozW#^1ۼ8"{NILGslpAw*T;΍@كS_$"[ޞW8soIԪT*R 7r])0"պ hzJm; 'JUBEC He9TR?H5+wWSze1P3;VPjPÕO}Ez}~lߏ;n~gRtP5/R/yʷ{iIZd"ո>9ϫ|:M)w(NWOSqߣԪM*RsyXwEoK{g.">i4Aj/y[.|\@{OJ.YH5oU^u_5tXʷyJ.S?NsSR^/`Ɔ^~RVYHGLGeK?u s5/H%oMe᫻n;=$fERS*ԿxI=" 9 ?&s'b"Vmڻ_Ltr5:{4/(e뙅4M<4;S?Kޞ*ѼSR޷1/=7bq4/(הꖅ4&wCP|TuA\sDꟻ].baQ_~wq6J[I_LvT^9=kNtJuBE|&zǠ;t87-Oΐi9.:njkS))pw||cr9^i=R/YdpSg2ZS*sßU,TqiG觲b|'>4V; F迈T,T1N*k}瞲if"Qs VmPƬӢTOK[?SYHcO7gwj: iܚq*'z>@yg;:g"aD'g?SYHcXkRTBO?SYHcZq s ^&6 ^VPƴ!UwҗŸթ5YHcF+SI-ßө5YHc\wg韷C3:& i[y*̽.Ҹd"yG̹6Xe"yN IDAT@{O9*  nf9Sܹ"ZcԀ:?z,T49|(yZcԐ}6zgqje*RSZi*?z|-&eOBEs6 @/#=# IYRg( QvO.&eBE69 @CNj0)[C*nҰ{RpaR,T$S뎊L֒u) >xSmL֒u |Ͽ9PεygJe=[3?BEzU|r|`ej/}Ws/){,T$W=b#kK! I]DYAKo%e됅.fϺlP4NXy4ۿ,9c*U{R*sg\RYHvkP)[y-)[,T$MnRяL? %e뙅5 @?;M# I3*)s:;ŸiI4P4=KŸeI4P4~&ǣ1VW|?˒if"i$!z&Pa! I#)R~$z.PANټŸaI P4zgNDf*sŸ]I P4E[2{ z>P!k n%e#BEH}ߣg4Uo|f%e#BEh[Y*;zTP3^%m=,T$_|<˷ϪlDYH}6Jn|SI[. IRGl|JFYkrp0njgSR6,T$Z}ޙR9̡YŸKI,d"iV\sx ` /W,T$jNIGr@?YBEҬ_8z0WJf1 I^͋R==%e{UwxEs(),T$IS=%.r*/HÇnXq) f"i'Q*zϝl*Wgo"iN* z0"s $esTS[ٶ/ 0ƿ~I,g=3T>zG0yQegԿV+?f4y uXs&)Ҡ3o#廾>A7z0M $es\*S[a$5;G}< $esMh{5IjL6/J_ $esZw Iͪ{_Oq)ϔ,^A}G?5A*\z `ݔ))I[}ɟV$5>Ұ ]$) {ԟ=/HR3\eVzF#IYP;{Q~:á֬>_ I럳ɟV}??^ Xυ?;Dko I nFikB/<]q^%mJ]>s*1Ijv~3 $#,廾!Uh^ۦQRxk 'CHʪЂ͞#LRwzu*{ODϫ֓i?S |{?$Nj]^ڻ1U1yBs_0IouehI_>$m]J]?$MG U_RY7?$oEl~gBRVw={2|&I?.uS`u}2yU|=gej2)P~\@ Zs )`#>JЏ@Izy}W1Gm^Hں_HJEPZ{Rs}0u@)h]}2(IϬўs}{s4}zyzbTR͋Rs|_{.K?9kB%/}wg9csuo,=RVn w=JҚ*n<~cy *[Jeg\-Nqg^R둻wF2Ru㉞tPA/Z<&I >B߱}jh;ȃJD:&I mSvw)v^9^РRܺڇw"S</*~#M-hP]_$-'[7Zjj֘;l_$-uPv+?REj5m_ܭgoXB%i;0pGi4hޫuNynDJ"Qu9QwT"bˋ4i[`9#Y>Ejz|fQT:/$MRgDE9@̠_U.EjzO٢={4T*H$uxcD5Z`.|O;Ae/$M;;fu[gsl~}F&j{r,іK}jyHD]M٠2~%> $I>Qv,1Ǫo3^{ӣ~EFeP/$MHJ+f-/sh[uhJ&mxًvLl؍#fE[Guck|VLORuQ~D:^o5cPn,IjG". 4 x-ETz'I6aKq$J9/Z*~'"5{趋]A%F/$MctKr,jZw`imղ95ƷztvGzj>% 782UNCjzk>ӠȠ2Vm/Z^P!I sK(ul QvF)~!5Ǵ(6U;~MH~/" L |S; 芘&EjhIZ`k6>:iTѻ=.>YQw]LXy$ڛ_W$I j;1G'0eW|:_C[bMŠ2׊?Ԑ ?}gug[LTƪQ.yo$-E {ONі/ͿE }{İlG>>VU(IY/C#(h;>>cM26[w`o$% ? P=ps|f }^>xj϶D{ſ>1F?f#XFն;/KH {hTƪ\IUc>2ePo7_>BjdkFThTuh̭ާ7[i?왺`tN|Y{u6({MՌAQ{KջݥJ`GWXFݟ&kԠ2׊E+͗kcJb뷢s;HM1㲘T5h? Zwn1 ,a/wR>++2?FΊ*cUѽ1WC~EuMI`OUw R򚨶уcw}+>JҔ(}D?ԔGZ =1,Ae^+>sk+C#I=  4O[Ѻ+gPyT?@h Sh&ڪw Էf]wQ?rw37CcY +kP_O%RʪEQ~V5a1EzÞUn$~<ʊT3^1?VL3 b/}7dc4O_j՝m˩Tݝo9?VFs:Kb o8ݘ]礃Q=tGDZ *W+/s?ВfV>`E^1E+I ʮu6zqEҒ5X>O3hez_AhIƕ{i{$Fkm_,}m4_qYԝK?r3Š?ÛύE\ER[w@3m3?JkZ_tN|i>|rAT?aD5*4b,)zW|8:ga?C%QzVT?q3ix')ft>uh}{/\uD }u;~QWɠ?o6ڛ_cY$=n /zOK_0s-M[1~W pHYs{Rk IDATx{u}]. *TZmPӪMM5ƴUEhjkDjم Br DTDº¢+ bg/7zZ%i[[WMtzw^:uf|: 4 F{EElO4I-~V Oe-]feEGҏG9Qoe7% OιDu!mSKw_+S?hO4/:7bԏ]Ahk 17RZ˟ ו~تY{/IsުL}*+"җF2=]`9}Q-{ND}ͥ0DཊbY`nrc~z;VGGRZ;J?1?IKR )믜:fƖ/]{g0Kk PغQhŞKt ~lCKX2_8m_+M@Qpg?4GknKXhhw1XwYhTR=6 BNorzy4AMZ@ 7\ղ]חquF[GFZ1&v7?+DIs]KoQwS1\ETKv._ƶCkz$& B[~[>CZK4uN(})twjNKXl[cL Tw6EC:h8iBֈ~0;?onSt{O I{{#AL7*~. IMor B*_dT/4/shTwٿ?Ƶd]4b+0 B_#ET݋>1K_`Fѽ $ye !h T6FGp~׻#2ŰV@٢{'>= _ա/,}ߎΗP@Zȗޛɚ9 zѽjqT + |gQhݫEh BÇF?\e 7Q/+~ IM}~hF B[Έjٮْ\O!F?+ZS&nQ-ޱ9$5zxB;VG9ZDҗ ` n9=?oƷrWc9n|T/˓_Gc$ӿ~U3IPk1Xe:/LuzXĴWك$hSc܌ Ts$M[wD l9 $)E G[G876cy+ 4mS:b-}f[_W,BԻzYРm@:eĠSJ̑Qp?gch I9MS3,kbg &x}%H QwsKPp7ZS3 IRڕ8mΠsSΗ4}c0FE.9{KUHRΏw0AP]G%Mۖm/ x_y$ivѿ}.iZ(Ft/ ^;չ'%M[ߌ%hz}$U3T[sBuFhwZG`.@}1$)KUE\ޛZk;W4-%KpM}| IJRDP龨V]N4MKv]_HO)~!II A/'i;S4-!k/KpB\A{G߉itl>7[CxW{ Կwisl= ҽ_sHRZ5k>pkTK]Γzr6$swHRڧ%2;:iZ"Fs1&Ө1ڟ{isIR[G5c^w9L?~xmQCRd>f%IOxmDɧ; tyT/~"IjAw<z8{$=1mֿg!AsIOub鞙zzQt{o3IJcx-5 ]V|no3x/}6"Ij'pLQگ"WZuՌ\$D}˟HRz77P3$J f]ʟHRk{ԏSvscT +~gHe Lz^-}^"IU{@A?+~'HeK>ԻL$P/3o9 uNr13Ew?;O| ԫp"̦Qwsg(T5m_A{7Zk7nE`.ԏbg)T5^1 T?PTKw-~%͋ʽc؆z̵O}F3I\f^7VҼ>;껿UO|Rz}`sIZZ^U%z}Q-ݥ&cg(Fo)"I [fw^7RҼ_w3~QP۷$U uD 3ՏՒHi^y0V껿g?k B;H*_7F {[ `o|IZ?Φڽ&ѯQmy0v翿$U mo Ի7JZ?/wnk+4DW?u| B~Tv%MlKvL]F$ZUF4EGq B[*Im9{&^W/: )~#I Uogfj7Fz__4wՂ1T5L}6 BGKΈQ=ۨΩo-~.#IU6uW&qG|9h3T5ކAh؋ҤZw{_J4G}ZSsIҒn=uiZswg6^G4JG?ͩn?4i n:i6^?4h3^F9[1Z&WO4j,Z^\F&x_qB[,KTԷF|H=7Lr> n> Bm)Yc^|hk?Ñmͧ=S_l_&F Fwc>ˑj[KDIhv1\w\dhQPݧ$-d IDAT|zPaIsZ Ꮿju$zW| B/*Jh.^'堳َ$Uc\ Bo+Jku7k$eC0 Z[^kjdZmr~r2 a0AA ֞$ {^OHr眽X)zuGx$)j6Oeu/:Jc\>oTIZ{$if|c7?!4HZGF¿ iTki ~$IY@yY\Rя>0E|t&O9x5]_HU.]*/'Iʆ_T}6`:t$)Ɗ'<٬-¿uZiԿMl*y׈B})ZgY̯EIR6MYIjR g|wR4sQocC>:NR,uG?>/$),TfE=PW|ϷQIR6YI?ČԿ;8'JfN]BO9k *}NwUMQBsj )uPV|7YIR6YI٬-RTH$ig!$GKG/lf6RЏTTPH$)ۄ,T_'>WPa ǒlR]{dy+:cwYmdBuc/((=esӒl#RmG~%IFd!ֻNE?~%If!Z:oIRYv廽>cFX/sIRYvn95+y4 뒤l=Rjcw]gBM?SEY!#KBHhbFqn1S0:s$e/QqU7O$)[GB}$`{0I֑ƺ_> P?~&Iًd!-Tf+D#)5b% !mN>P3+ߋIR,4@}cDB]_UF~jҔM'9Yi]{T'|.Ld!uoT+W=_~_&Id!i|Y ߙI5Yil.[=ک;$)Ҹ<)ӿ3I,4"_=`ZG2MR+-4u~0=E+nM-$; !tE;kEtXw!.MR61#|A,TW|SꚅF_z~&Q,4M4EZ=`ej.pݚF-Hֿ xMl~&Q,4r }ڟ߱Ij. !VsM{g6l2{,廾&MRSBKɺ~&Q,425{oJnM梟sԨMB&fEi2[OwꒅF=`ʵ7IZd!ʗn=7צlb;8IBHwAsM/Ij}Bt?Rя0mʕl$5: !UR]{')sBl=`(ʔ]f!J.[~/'1Y=`wsc*WRя0tO,T\=w LЏIj]BT?=o T)~W'1VY:&+}IJ㔅*S9s*|:NRclR%xsJ,z@et{;IBHw *l>ۇIjEB uGR* ӽl;IBHMlPMvz[=4Y)i=Rz~'1Y)ۤ)T[O}')rB ѣFB$5F: !TWEQ e?^ORcdRH=B`o?;^ORcdk. #u$5F2 ! gDMI{/ ߓ,4ԚK~eyi{>IBHkbFwyV<|p~')RBZ8zVXh}IjTBNJœwEI ţ7lb{?IiTP c}ҟIjLBnUFG+œwl(d!is7g#~'1YiZw}u*'"rCO艾Ԩ|Bֺ=`u{@Ig!i+TWGCkexwye}FҴսla,Z`f}FҴ3)usjl=]_~/(YiZ-_=V:[FeҔ/|{JNZ)'KHRz,4?6z@-uOBHSZswTR?_~O(Q,4?&z@u{BIe!);v+y$es /ԨTBz=:kBHSRpQz es7ԨLBz=hWBH\RwlVBH\o!ѳ Xi~(Q,I{o@EOޕY[#Jjg!Mw3 X);#Jjg!.) XS6kDI,u/[=> Yi6s XŊ[S6YFXBڨ:̊ah{EI,6يlⱛ4Yil1_BH֬-Rl1JJYijS6A~(1,MHE+`o9-QRvBZ&?_qe+QRcYi߻4zTSFIf!3 *vw{GIe!wӉ# S#xTy ?rS|*n3!{nCBH/Y[S*z k ;Xfm~6>~Ek>Vz e?IJӝYE$Vxw&?*m|K~%廽>7.{-L\0+n9u?r2O`dLQtӞ^|<_a.JC?:xg`I=nNČ3ƴf!m,XrC.kSj.~jpz; z˗ .=/c>~^Ԙ,0zTBz:2IiBHkwQ`h&œ#6qb5}ScS&^+ 0^ ?IJӕ^PS굣)3ux`jG)_S/UR_|d`}OY_td!F9-v:NœwEr!}ޒԘ,fmʕDMVo9|&R<|mJRcJҚnsۙ}gS6e%i*,TqnJe]NC?~* ! j`x9) g$i:kԻ蔊^Zn>9$1eYiPXԽx^j.1\$ |wA)ZߊWR[KSRE":?O\fo~&SZ ISRã P#Swf|7*n=Rf+]n~F,j^+R^=W߻to< $D;|>t/Ps3665 >/ 0&|Ij.~OG>;(clbFHRcyWF` O(uZwyeyGoO `ZGVyHRcq=G1Ses51cёߍ~L#{3d!T:}ltsl-i`q !W~X,jRuѳп"F|я.`S1/P j.~O\lL3<(賈^;Qi^* Խt Qo}45T>}_# ŃW]$5^2 qob@MLu?H&˓= RbERcYyC>= !tR6!i E^ 1T\os,Ƽg0gM~?!ikŔPQe癔3Ƌf!4MlG`njQWyG9f3 1{nѳXk|RA]Pݻ IDATyATwOg1|~KjtBcR3 X2"5PYA*Č[~HcJW}S/GR,Ơ|7 ITK}/$Mlz*T IRzT=P<Ô.| IZ+SяsX{Vܚz:g55g$eЈ7@k-$i -; 3)I&f!4O=GDI;G?MCB#pbܐ ?HҸ}l~0n^*yo3f3YܓlYpSZGE $i\k=,SwݷR;_O̓?9[7Iʂ\=V&Q?~q}/R~'7%){NB#Zk {-{#< Iuɧ#}a^ y%IYų6z@-S$n/T?s~{$ig!46S_ ?HR-eIZo}3Hn?$ig!4O=^sȣTۧ;'Sq̃fQH$ecѳj󝯇$I\l>=eԿwi.[ڧ씚ߝEd!4ujZ.3|KaR=؀ >m3Dg!4o=#z@mn> k%O:m$5Ш5kTP Wz$U}G@-c٩s:wEIR%Z~4z@-No u4kԿ0:HBh^87J̓?>%I/]R0ZU^Ԙ,FeGoe'I̗$̓?R=AF?N#??4s]_Rы>+X^[̗$mx3*zTZH;Y|ŸݒPZ_gk_Y|IջQP n*{$IYP>Nؚ|D$iu**z Hf_B#TG O8W`K6|Ϸ > 9ӃW D?{%IBhDmRYD9`,M$e$M]~ǿPOsSO|7?c%IBhDj3-yI׽d~0fwY^OjRIRc?AihQuS9 `Ej3^4}{9]3RԨ]B#'r:=%I_[RYFFo(v-J>o JYFSࣄg$i8n`Z`s> IHB#橹h.IbLWDO ` L^y$),F g$i wHe1SSRN=廼2Y&IR YU|W^z llbF|$>ѣ2~^:%IR6YUџ>xd;g$)ލGO$ ZnNKRRsS6YIlx݋v>&Xs]_kR}c }ŸE$eYU/>7+O}JuS*LrCYs:)}3G"YUY[LY F[?%IlQ6Q^.|?O~[I g!T~ l#{.I`sNţ7F)`}5>#I Bu~3]T͚@Ŕe*Vܶ?g-5`fo̐$),*\㣏`0ZG}"|K]=9w}uAl pG`dM^*DrI4YwY؂ژ|Ws3$I3둅PE|k FW’/ f0}GFXB}m0 咤j򣪀)JZ|$es ޖ$IgheF`$Lmg$iĚE*:z(W?:{j)5ǒ$)+ VEFR/|KFK߉eP9#IRc,bLی>)1e6咤sq{$Ii`1#u'$i>:C?$5jPkWA9ᒤySwGLG,~01A|kÿ$IRchYUՇE`4|8|KƧ%E6sq.3O\z[$Ijf!T& ߒ1k6xޟG*H$*e!Tn;8yg$iH-{.ZG~|p"IBbs%oIֻQG͕Sޥ{:) $1YUι}<$i|1㎺d數{^}| $IBb3Xݒ}WG{$IJBbO}$:[T&6K.{??֡IPwyUJe}FP)_CUIl-YUw}PzgKmS}cg7%IftBwG[ 9|nKY/DA\PvV\0{G.$IRYUkϺPye{uw}Mܖ$շFCA^ߖ-J>?wM$),Ҭ-R굢ϿPyےZ\Ȧw|%}N?lbF-IlH}wS[$I/$IJYU_>"@?&|fK4Y˫RZx$IRcYU{G?|fKxeԿ{{.u|^H$eB"y))K$IkbFwy􈬏^+/KevI럅PE*OF'}!|^K5"zLXޟkL:5@fo-IpB(gPie˟%Iwѣr ?WIl̲@#; ֽxy-Iҋ:Ye{`);| %Id!T:]y| ג$la-ޚ~>˩),K$)aBwGtɏՒ$dsMR{Vܚz:g55*F$Ii2 Tܿ,:3Z}S3?I$5^4 &ft9*|є2~^K>MH?Lx%I6$ =}.3|VK!5JJeFH$qB(џ>@e5'|VKn:)LŊRo_K̓?9[7$IRcʳ >@%M~N$ic=~'UQx{I$1,]sxg~%|NKu?z*0u/]AxsI$5² x#@;)9-IƖTWqvvS}y$IOf!Z9 ~v$iSXR~hG:#)M^I$5*P`7N?`O9-IҦT>&$uH$)mJB\ 9-IT9o6h gRޥlQjӚ~I$5F> ڧiIջ-IҔ5kTuCⱛSﺣSoH٬fI$qB(={#>%IEm&IFm WnP-yY$iJy:$I꜅P`ŊۢRz7>%I$I1B(YD߻@Ob$I$I9~YZ~o>%I$I1B(1vJ}a|$I$I4 :}TJ眿 ϒ$I$I٘f!TD߻@ wϒ$I$I٘f!Ts2o͒$I$Ig!FY$I$),"R}:$I$IB(|7E߻@u,I$IqB7fI$Il̳ }{`"|6K$I$ecP@ fG߽@e4|8|6K$I$ecP@뎎{jd)El$I$I< &ߕ$I$IRV,"z0 *{,I$I a7{" *u'g$I$IBh w{j()Y$I$)ABCuدE_@%_>%I$Id!4'1 *{~sY$I$)IBCJhS\$I$IjА7 ˒$I$IYMrώpe癔<|.K$I$e5Bh\}. ɒ$I$IYwpl,I$I( a6w7_˒$I$I3듅k.7~ ˒$I$IYb#~+ u)E\$I$IjkS+6|&K$I$e5Bhu;8׻,I$I, !ֽla3Y$I$)YBCwqwp}dI$IfY F@ ɒ$I$IYͲbŊ[ V[dI$IfY ?vke5y,I$I0 a5ewpw˩3Y$I$ifR^?}ẗ.ɒ$I$IY R%p3*|&K$I$e5BhH;8:3Y$I$)aBCj'v ɒ$I$IY R=be,|&K$I$e5BhHu/'B ǒ$I$IYMR돉P{cI$IY ߋP?=%I$If!4G@EcI$IY ?{ T̯cI$IY ɢ T;|K$I$5 a4w;8\,I$I4Y |ϷF@|dI$IY 恿}9/ ɒ$I$IYMB#?}y,I$I8 !>Ꮲ Ty,I$I8 !>p $I$IRV,P{=p\<$I$Ij^%I$Ig!4W} ǒ$I$IYB돍Ps.|K$I$e5BhoN=jy,I$I8 !Կ{8:3X$I$)qBCx{8:W$I$IRV,yՃp{$I$IRV,:B{%|K$I$e5Bh,Pmg$I$If!4;"bX$I$B[OG_@2|K$I$սBhzk{8U~(|K$I$սBhzk{8U%I$I^i!4u} ǒ$I$Iu޺W,Pǒ$I$Iuz˗D@=$I$IR+-i@u/]>%I$I^i!4n:1Bu/>%I$I^i!4{wli]x63j%1q:LljJ'&fbfhtQM{nYFA@eeZhd2{<9[~IZ*rZNzkcksp$;cy tx(z'IRhO<hAhF^$)ީ>r7F$I wʧ1@UBy`IZOc$)ީMW9]$)i MW9{8IB띱m<hAh~(z'IRh5K1@UBc~{8IB럵]<hAh~;z'IRhwMW9W=G$I g1@UBUWUN>rϊI^g2@UBc|$I/#~&4\ 4F=/z'IRx W9$I/dhG$I op!3*1r$\{LLhAh|Zۿ z'IRxO M 4FB$3g2@UBZ$I B$h3*q$G_>r֊I^3*q$ MW9$Iu]uMW9OkD$Io MW9Wp$,l?Ahm$)E 0\B㴰EMv 0\BcVWUN{rL( 4fh$)~o Ƭwp$9m34ИvNG;|&sI^>J9;ߋI^Od`B~wwp$;s!|&s?voN>J9+z'IRxK l-;8I\}DL( 4fE$I ox7g2@i01;z'IRxUY>J9ӣwp$7eaI\( 4fO^I/ lpq7IRs4И >"z&IRV\( 4f+޿I>JC9Y/D$IJQePBc?o$I) PAhzkE$IJQo PAhz~:z&IR>JC9YG$IJC2@i(1$I)8 IDATtr\( 4f#$)E/Ƭsۢo$s4Иu$I9t2@i(1k$Iij PAhڻ:z&IRڟMl( 4f*z&IR:9|6r֊F$IJS? ma$I) 0<BP7IR?k PAhz z&IR>J9M⑿$I)^ PAhF믋޿I]e@B0$I)z?s4 o[$)G>J9Mo$l PAhW{$)M^>J8Mwo$g3@i 蟿kM4u PAhzgl{$)MS!|6q ޽I?9=J8M@F$IJg3@i Gѻ7I4 PAhvM4U>J8M@{WG$IӠ[%4V8z&IRZ^>J8Mu]wo$3|s8M;ߋ޽I!ۄf B~hITݯ]l( 4!uE$IJS4Є o==z&IR>J8Mwo$ixI4Є .'z&IRF^>J8MHѻ7IT A&wꧣwo$4Єt7{7IR3@i 轛$I|gBE$IJUgBעn$Ϊ PAhBZJC8MϏ޻IgfpzЍ޽Ig3@iI>wE$IhXe[gB4՛$Ij}4 oFMTu PAh)z&IR~0|>p9n$wƶ4NDMT ./|>p޻I-gBG$IJ3@i j{7IroeaI(3AhZ+_v$)]^>ʌs%u=E$IJUoAh={7IR=C8 ʌs;F$IJ߯=ʌsɟ޻Iv e9MXG$IJW{_ e9MXF$IJWmg4@aBWwn$wg4@aBZ蝛$Iꟿk(3Ahw$)U?gPģ?轛$I{u|(3A(he{7IRU e9^轛$Ij}'g4@QB޹I~o eF9蝛$I PfP޹Iޚe3(s$)] eF9h蝛$I}q(3A(uUE$IJU~(~F&/G$IJWkKg4@ABAF.޹I~o e9p|MtuP(3A(H/D$IJW3  9z&IR> r đ$I?he3  /~MtUGg4@ABAڻ:z&IRZ9 PfP[uUE$IJWoA([D$IJW+>ʌq 4Ε;7I?{e(3A(wn$kp13@޹I?A=ʌq ;c蝛$IzeaI(3A(P?޹IN?> q 96IRi2Cv}$I)9 PfPe[hs$)] >?gP{wD$IJSg4@!B޹Ig4@!Bs$)_ը.=/|N fiMz](3A(XE$IJYi2#usM=)9 PfP?o$)eeF8E[XR׃NMt]?gPn޹I^y'4@B o95z&IRZ<|N }m$si2}$I)9 PfPݣo$)eVi2h6IR69 PfPU/޷Iꑻ4@BITGwn$嫪֊i2wMM9 PPo$)ec?>ʔsJ6IR?{e(SA(I޷I?E=ʔsJs;m$lݛ4@rBIW6z&IRFú,:|V) vϭjr$)e^?槗P"#wG$IJYi2޶&z&IRkWi2\oM 9 PP"S>o$)en e9%96Ir6esg5@RBu$IikY PP&˟SףaMuY 0?}$I)럵](SA(᭧G$IJc4@RB/+z&IRF>ʔrJw'm$lد˲gj2MMY PP2Ͽ&z&IRںGY PP6K|OH'[,~VOFo$)eke 9%4}$I).|N) P=m$lد˲gj2eu$Iik~m(SA(o޵I1 e8%ѻ6I?{e(SA(-zЍ޷I 'j m$z9 PPRo$)gUUV0|V) Tm$g5@"BIuѻ6I߆j2Ej]$Ii_{(SA(֊{;$Iғ޶&|V) X}$I)Zi2EvfMvY PPbVG$IJ[?eJ8%;ѻ6I;j2%]$Ii\v@(SA(N/޵Ij2%E$IYeaY PPrn$)m]>|V) wm$sj2ѻ6I;cY PPrk$)mk e 8%ѻ6I6Z](SA(ϪA'z&IRF,:~^ 4F]n$)m#|Vڣwm$տ %9)?kyM/=|V@F$IJg5@IAh z]MUg5@IAh,ߺG}$Iik`>/)1z]$Ii$ 4%=z&IRzgK(9M;D$IJڣg5@IAhJt~oM!|VD{kwm$m4v %)ilm$okkwm$ %))2]$Ii_:|VH]$Iiqn(I9M޵Ip]ki]$Ik}߇k4Yآ{%z&IR:#~^ 4eF\k$)m3g5@IAh 8(z&IR>JBBSwʧwm$m-$ 4e:QMU 5@IAhʴvU$Ik;$ 4ѻ6I;#$ 4wk$)mK %)Կx]$IisI(8Mމk$)oN]m>J"BSs[Wm$$ 4Z+_g$)uc?>J"BSz;ѻ6I?Y PqR[N޵Imkg5@IAhJ9z&IRڪCuYX>JBS{wm$WkДj=$Iy PpVKA7z&IRg-98Mw޵I LJj\qpMU>JBSw'wm$$ 4:5z&IR:A( 8M֪D$IJ]OkД'z&IRW>JBSnxѻ6I6ZY Pprs>k$)oa]{^(\F$IJ]{7kAhʵ=$Iy P9MϪ~+z&IR?c9̀=F$IJg5@ 4k$)ov]n>J ;ѫ6IRW5@ 4:%z&IR}(|^@B3ÏuUE$IJ[5@ 4#޵IjAhF o8!z&IRڪcuY"|^ B3vEMԵy P8͈޳I1%Ќh=$Iy P8͊%uy8z&IRچ1fD$IJ[}_% _]$Iky P8͐qg$)uݣ,|^B3Wl$Np%K~;z&IRچ?'Ahƌ$z&IRڪCuYX>ʄ9͘E$IJ]kWk2aB3{l${5@0 {6IR?gU( 4k{n]ѻ6I6y 0?YB3h]$IiZ efCwm$υk2AB3w'l$sĻ5@ E$IJ]y P&AhvxQ]WUM o:)|^ r$Izrcj2AB3jpqѻ6IRg5@;c=$Iy P&AhFu&z&IRg-eBfTkǟ޳IeBfXؽѻ6IVg5@6]$Iky P&Ah׮޳I=|^ pag$)uWk2B3?#I-k2B3z]$IieaI(c 47k$)u]>|^1sq+l${{5@39{6IR?oy 0nB3ˣl$nxYPTk$)mU,l>95Swm$/k2FB _"z&IR~ |^1rj޳Ieˣl$nxyPCTe}M[uYe(c ÛO^I׆k2&B ?{=$I~/5@=$I_W(c ]^g$)u/ eL*wm$mЩ˲5@|JMԵP!z&IR_y PAA:G+z&IR>85Hk޳IѺ5@]$Iy|y PP o:9z&IR>|^E 0G$IJ]ďksۣl$np5@YdB l$nt ,2'z&IRުn,"^U$I,"/{6IR;5@YDB 9l$nk=$驫;|^E Po޵IN?>"qj5GF$IJ]wkHw?D$IJ],{6IR7y PPSm wm$<\-g6sjwm$/klpA{6IR=,=$I_G(A>z&IRFw}3|^E d˟S׃nM :uY 0ynU$Ikl&\OMNH(A_=$I\~`(A{ZMԍ_>frjϪ^޵IjTVXtB;Ϗ^IΗ~/|^ Dݿ`=$IOl!1޳Iudžkۻ*z&IRꪇ e38!ѻ6IRel"!0=$Iy P6O蟵&p_ 92z&IR_y P6w'l$l!Uo޳IѺ5p[u]ѻ6I6el }U$Iy P6?dpɾ{6IR;Sl$!~Hg$)uk e#9Cګ_g$)uwka [U]$Ik3`~9$F$IJ]? e#8$sw޳I95@BZ e9GE$IJ]{k5@@B<_޳I&|^ SꝱmM .b(A9l$ntl !Rku5޵IѰnm P6Okѫ6IR9-l!/G$IJ] e8z'~,z&IRJ(A{6IRW=.|^ [twm$lg 3}qMΩ IDATuy P~!Q{F$IJ]5@xF>g$)uo>ʏ 3j {6Iroe3<!’j?j$)u#~f?=!~᭧G$IJ]Ŀ8#!z&IRW>3pG=$I=xk(AOE$IJ_kǟ i8A޳I?Q=pb ;6z&IR i8AzSM o_>pbtxKMJ]n>Spbl Wm$_O wMMNH(OA 6=$I\yH(OA =F$IJ[5@y BlcMUUZ P !6guD$IJ]?exy{6IR?{e(l$nxYBlQ޳I^-g6@Bl^f$)}^>pbU~'z&IR8|^ Fp|M 88|^ F띱mMԍ)|^ Fl$宪֪l}Bl/jj$)uC8|fsb>z&IRkWk}Blǿ,[$=} $>g$)uUѺ,}V(Bl޿g$)}^>lVuoG$IJ㟨 BlD$IJC5d v޳I5@qbst~oMvzYT]_c$)}#4|fTBll$rbs o<1z&IRFw}3|^TBlޙ {6Ir7el,f$)}SAE$IJ]τlln޳I LJkl+޳I@]l`l>z&IRڻ 5oE$IJ_>rb-۪=$I\ M Ģ=$IVAEѿp=$I3k$!EG$IJ_mg60HB,nޱI;l`X4UYg$)u׆k`X4ÛN޳I~.˶ \8hzkE$IJ_{ \8h:_/;6I;3k!Mk뺪l$npQ3k!7G$IJ]=k!Cl$υl`QXTo$I 5wl$g60(B,eϮA7z&IRF^?IXt/޳IjTV8|fs Ģs5$I3k !]F$IJ_U3k !]ޱIl`1X| K=$It| M X o>%z&IR:9|fs XZc$)}9|fs Xt&z&IR7~#|fs XV*z&IR결Efc3z=$Ikk3yBãwl$wGg607IޱIGl`n916}c$)}#l`n91>˟S׃nM> ԳA}qMu@fcտhuM .'|fs3A$Iwmfckwl$寪֪m`nf91^ K5$I ԳA|JM)|fs3A럵 u&z&IRl $!ƮO|Y$Iz:%|ns3A=xkM, Lrb"Wc$)}[Lrb"z'} d,N];6I;3s/{fYz{L-B ! @B $@B9Nr4,Y\qMƽ܍qn&˶lkzkqH3Y徯3Ϟ+YBX;/g$I$Ij. !M;E J>mI$IԪUBX&wlP ~)|nK$IVjmѿ_J-I$IZBHkj^*7-I$IRDpr)(|nK$IVmD럹(wlP >%I$IR6YiuV|4kP %|nK$IVmD˗<C$I$Ij& !Mу7F JX{o̖$I$Id!7߱@%-I$IZBHwW=$I$Ij" !M5+$I$Ij" !MEMiЍ^-I$IRRH;/TB$I$IނM7+ !Կ`߯@%tlܖ$I$iZIjqFw_5YY)៉T`^s[$Io9c4{)Oywx)YòRHo-WjP=ׇmI$I|kR?NO/ysٳe!"_=ǿBzȷ~}$I$i Rgމ_MWѪS*YwBHa ?i]=s[$IL?m؛uG]8YY)f:!I$IҤ;catZJ|N=pCsְ,VgG@=xcܖ$I$է|w>%I$Iޟ$DRx v>woے$IuoHvaX{_􏖥e!&ȷ-I$IzvkޟoNB [Qݒ$Iޟ/7' !75/*a)-I$I {Fg5( !'E=P wmI$Ij{Q:YR)ougg$I$?{7' !ΊF=Pݣ!|vK$IR˷{O#^uLD֠,TeH(nI$I*{o 3S}49~B:J{$I$|ɋ?HCD:?/k'kPB*MO;ͷnI$I i&Ϧ=zsd!;+TOQI$IjJVKC??5;__YRijTCg$I$v֯O%I$7&#kPB*]җTgTF?ߒ$IJޟ0xJo=39Y!,蟻U$IT?:럿cP֠,TW}@e?=%I$'? w JYDEP(^>%I$b_x53xBHǯFEP)݃?>%I$g 6~{6EsnrBHlsRt#EoI$I3zn:{h?f BHmtThu[$Iғ˷xc~;gUPJ[#|7oI$)k{`ip塩xW};9Yuty=o$IԘ6o/oNB*m}@ ._>%Io_yۥmˢȸDR+}&@e>%IZ`N .7=kPB*u ߒ$IRy-Ni{ş󛓅J]}&@NJ$I*ޟA75xsa~sR;gTk$IT^:~,XأE_فӿhs"kPB*u4FKP,e>%II/yc~;ipaп`#kPB*}{}.@tP$I洅>cHUWTWq`fy29Y .#\J韽E$If|xPϗAYu|2-I${bsϜAYw|GRR3\$I{._5Fߦ ꟻ<<.I$={FWg Pgd!J4 *ep[$ID_韵8*+3|~K$9y>g. ?e!J9gT=|3\$I+_'[@EN ?Ӳe!JoRϔ.I`sg`̪i/ߜ,TF>RƏꈞߒ$Iޣߺ~{}{YRe\oR3\$IyO@ hީ~f BH{>r:|(|K$)| ޟGoc֠,T;'|韽E $IR{Ə~};kgd!4Q*DQP)VpI$]SR{?`4”k(:b9:9YR o:-j)F)_.Iz'zs5kPBTDQP9C?>%I4~f BHsEQP9K $Iznڻ/4lǖ?Ԝ0&*U)E9Rأ߆@ew|~sRjs gO/ $Iuxn:-~}?۳e!`TFUP9oY$IHxjo>kPBd[ώ>r+ $I{B[>~oNBds>rG $I-{J"_09YugTs\$iy@yB3zNd BH,gTR $IsޟNY}j3zvd BHx *gx3\$iVZij>a/~oVBl}d@ {)_9.ItoVlH|߬,TƟfsqIu~o5W(f&kXBl%J_[$I%/~?G]uX*}]`5ϠaY-4~;)?%IR37Z}]\߬,T醷}n@%wx{$I5{x{U󛕅*]m-I_ $i?}Fw\>e!J=/-፧qIT/K>zO=fhx˙,kXB0l g$I@6K={8({`kq󛕅jE L>%IRʷ{O}myYòR\ *ir9.Iޟ(4D`ְ,TSTأ._n`ƬaYw~Og$Il;ko{ѪS*FWީ߈󛕅Fh?}~@%>%I?TMYòR-pr4ke$Iޟ+XOԬaYN}~@5Eʷ~},$Iޟ~U7pCjQgߎ>GC,$I@t;YY-~AJA4Y.IR_sJ^&/߬aY6߁^ErIso0QvoYòRmꟿCYY.IRwUu&*_5, !զ>>%Ijr#wF_`߬aY6[TU<|{,$~;|f BHXs[Q=\F`"*S7~o^BU|;,}?g$IM,_kLh7k`BU%,~^,$k5&jt50 !ժ.}@uӟP$5nD o>#|f BHjjTt>G~.~K԰:~&jxQ7k`B]O>\%I|C?}\v@jWTW?O$5_D6|f BHFgPi$|KԤgn=`z7k`B__h}@e .7~KԠ=`GCjˢ4" e 6 $5ՇGη,|f BHgTZg$5gG~ YR-~篣44/$irV]=`;=|f BH,gT$IM0QW߬Y}@w~w<$Mmh=`rF>7/ !նDmPisI^嫢G>L/co,Tz9lJݵ2|KT;'zD6|f BH{6H6?>%Is>=`>f!`Tt>?_ IDATz)~KTG}!zD 92|f BHnxiTsI\q5Xgj]ͣ7a?K_>%Ikw0Q߬Yu *{gg$IumcG=LT YCR˗80J^sTL$4zDulj+8A'K^>%Ic'=LTgGo,T}@udL$v-$b=`ڻJ ,T}:\.IRʷo54 !վ|7FqPyEom6^\$Nu`HVXBjDŚۢ9>%ISj@>lX54 !5FuPy+ $թS&j58 !51_>)[Y\$. ./zD o>#|f BH;:΁ $ե-gFv񓜢o,Ԍ"[}@ .?~KT5Fvo,Ԙ}@5)[.IR[IJAh%Irk0QEvmzTg߈>C)[.IRUq5 !5EMiЉ>:.IR[IJ~(^b nxs>+$IUۣ8L`^3BjZ>)y]9O8L\E3BjZ>}@mtxl$jN=3BjZ4DP >%IZK0q?>^a!&6aIvI'8L\{WX}=]*U0q׆WXuDžvIRG7Lްp+,/OEPl$U΁=`F>ղRs{E9=g$IUwFmM jY!p$i\yH+|e!9ϣA0_>%I*{0q㿐jY^=B0z9|KTmh=`⺇}*~+YэAY1.IRkq !{zVBHͮNg!J{wwIZGj/mVBHͮ{ǣBYK$IeG5L^ysX- !5;UE_ixG5LkgZY*LZ]ҵ`zY^bVg!׿p3jer.IRj#B/5|5_>V)y3^2=#BNzVk: !5|WT"JOxI3 ?z54~ЪE $}WFg}sX,{.5\z R53^Rӳ(_Y4BH?OFP;>%I*C}>= D}4|,{`(|KT/&9֏oj;g$I >"z$@ j( !}>@]>%I mj^*U#B!~+WBujX{on>%I;1Y֏/_Q 9$IQuQ a:^,VGYI?ˢHGxI\qP(0oj( !ꟷm 3|k$I= F/~^,V%B9I)'|K4= iLѳX'd!$X4GP;d$qu\0+ j=! !'q~Y yI&}/靱0|,g%bs^I6z a}*|,FPKEoYg$I(gG/jy~E4DPKݣ>?%I@9z@Hc o9+Z9/I$^{L0#wbN>3;3|K4-4GG.|z.X'e!$=U 6IEsjIϏ$QsE[;+X'e!$=MN>7G}>|K4W,z@>zRB;ߣMѝzI|kR*Q m>zRB}&xF{IfNF3Y'e!$=] 6NEjkp^Ynp#B"|YI#O^-^>%Im W}'~&+=UB3;O_$V8z@ gZO k 6ڔM $FK? j=eBҳTz,uβj{߅|I֧ˣ(Bge6 !i;g)+g$I3nj^*=F/JO.-|NJ,<s_'BsYgBHZdž7}@ 92|K4=>ם>z,uwEPaʷ{Kܗ$iZTtDOO({g3e!$c]~!LF蟷mܗ$i]cJ{اgZϘ47\:_/Iҳ4 YgBHA+>Wz)|KLK_Ҡ=2-4|>YI3{EKj`/I=JctYgBHA֯>[1~"|Kt zT@i .VlVYfkWh]+$IOU{P*S>z,?~I~DH(Ίg5 !iuV|4|xj$ mTP*Jϖ46^Jv $I= ѣJXsk|Vk֣፧D>%IFw^=TW>nYIQ}@sφIڻ|T:e!$G}@/9|KԿhwgZ딅kn>k9JB0G'"KQ|i) !i=3F韽E$5 _P:ׇh9 !i=MW$I liMѣJgpAsZi]ֳ|ɋS\hY=#JwZ뜅 o='F!_;$Y z@)u`Vk6i}@\~$5/0l gZ뜅wc<-^~$5GG>(}Wif!MKţD8ӧR*FcJip~Ze!$m`˿}@5JH4/-z@iY֌6a>{zH[RJǯkf^h?-^~$ճuP^~m>՚QB,4#֒{$+zkKZ3BHg->zYʗ6. IW󶋞pPjj8 !ij3.wIR}uBVkYIFVEL~joIR-ѓ Jυlf4K .V9 5$ xvE:eSZ3BH~$U;FO4(Gl+ !iʷx#kNH[R귣^>Z,Ylx14Zg HTB{m+ !imte-Iq]~>0z@ :)[٭ze!$b}$@uL@T7=>Z,YnM24Z])[;$uX蟳eVkf;Ex3 $Ih&i1 EVZ,YseN6o H]/GO,HWo; !i[TFx˿/$|"_=2F jmPB4(IR9oI2XWVk1_>'8?eSrRtTJȿ jmPBoO%G|6n I*QS3TNoJ4G,OV|r=sѣ *X{_ WkYKiqwH˗| 92|YIsT{_>RR{$I .7z"@%N9g!$US"?7Ҕ-8 I oz+>,9lpg5cz'~5~ I hsh5c*=?<6|5+YIsOߎ>3;wIjΔ;sf% !ior;$i-$8z@w~wLW,9{l'kMҗ$Is[-GTZJԼ֬d!$qNi4>0[I~ 4֬e!$MES| 9h  T^?וf+ !iNz <ѻSewI6dgZ4ۿ5} ٫sПDZ4F_}O(RgG y\_lWkV&T-piޓ-_~_$m@S'E?ߕf3 !iB3x_"fS wƂQo֬f!$M?} W3Hf\gMi4#P_Dwf= !i V}Ϥ3Hֽ|NEvZ_sWkֳ&X?>g1Ҕ-|NA-4 o?/zt@txW,IhTF蟻< IzƟ^fY1Jҗyf= !i 92HM1J 7Hw:zZ@-$|Ϋ5'YI{F:(賂;H\{wyOLh6 !i^h}`t'$I%+U?e0:fWkNtZ;$Ih4ѣj>|BH {?E tLAԼ464WYI_h}3\{ CHR럽4z@u|WkβzNhu)wIjb_Ns(RO}, !)މ_>xJl~&5~uGKZsT맷@]~h?}@#Z>՚,Fw}{gTߐ5F>>՚,z'[9A'$յ|WѪkO{h_f 6 5YI۽9Sӟ^OHRʗ,"F\yH@9BH nt%=FN/ OHRmixwhP,z[J٢)$m4c|kJs\o>xԼ{$UuGH. (M" !26P-Tlo> _HR0 o>#Ə>/jM, !$wEETeL/>~{&TF=Y~w{/!Ie(hG3 5,?kIfYݟ;'!I۾dG]Af!$(/$5M#wE }OPkYI%ktUEjw Id~P.Û'5,;}~<戥&;)G/z9ijJVo\/v;$Y 6Iw>nS)wIg!$ݗD`54K^ם}`twBJXG`4[[!Rw꿇?$i \yH @ew²JZ)3;lj{$=[G͌V]}l3Wje!$gD`EC$ٔzYq P])~P+, !ub%/{E]DТͦ;'"JAi؏@}W|HҸoM{> wjf!$'E Hȝ{#]OE#E*e 6 WTG~.z^9wI+ix1 0 <.NT-^Ҡ=3Hn{=/S>Y ³*#g(RM Hoҗ}xv?G(*P=7^w|ʗ8~"~uw?w{ZBHB 7GF ۽9"m?wyJ(x@{7ʐT=;)Sg Hv?n>92Z}]}Cd!$U@ٌw”Mm~WT_>96B j" !BV_=C|zʷ|u]ERZiTF]w|gC,YIwƂT+[gJUDW,V*TϤTѳ(GB,8"<_,;ڬ? IDATJT=KzNʷycERp 6I㿔Κc Ho() !buqT@~(uWwI1u4Z}]Q<>V*Ve) 3U|Wa$M6W@J8^V*𚣢g P!E*u;ۧpJT?CT^h}%1;ZBHbѳ" u|ʦi$wYSe P2ݣ~WQYImSix۹ӻ4fT7ʨN/ U,Aw/ ͟~̍?{i*:G@ .VEf!$UyiM3⑻RzT-_zg,LEξ~QYI3-g.?~ǑJvoNwK>uQ5eSc*mBR˷{KJE=k: Uo;# .; 4*ZBHx[Ό5@?wyʷxI}Gj;BW6H6NV*^7@٪;K)[iG[ _IG7xFg!$U͟Κ\{S`T|_퇢;ZBHA/Ћj-hjy(0ڔ/~a}GYI5DaFK#?Qrҳ/MT̹"? :챿w0Mp;k4FEw1f!$ոѝE(:!uxʷ|u}LSEsLdx譍R [!nVej\/D)P~nIo iZ_ wI{.Ki4R7R]S/ ;~DIWٚO%uPiЍ2()U9 !1zV5G S?OvoIԼ{\ZRO9cR*F*a|wʦ6)U9 !w|gh4d;?M>8]i[qʷ{swܿONHO?7Ԁ=ٻhI#5{LF\⒘}cL&$1c4Lb8cow5K"" YdQ"4ր 4[S{=9uH/wߪ_^O}V% ѹԺԼ?jʕh z~;S=5,NM;/LGoOӌH~ſT B{kA'MuQg٩ufIj7SeT?ILŲ}lQ*Wb/kJ/nj|/i{7:w_k곗@EMdAH&x$jڸ>u+u!ujjizfjtJj_{}ԺrũFur۩z_FCطş/*AHz~sEMdAHzm>`t4犚&4Fu(LCU{"+^~l2IcT?牚*4N-]iğ'*AHNFmhtJ9& $Ypg9& $agG-we& $a#lAj" BҘ}{}'֥bCMdAH}4|~nl3ISU>}zؘʽ_nk!ik]u`}H)>8PYgƸצmG`u;\Gy& $ygE`uF9& $y}V[焚>}{?XdgM}R?XdeR{wbJAHT+XisAMM!IS*N+cڸ> 516$m}A @MU!I+>٫Rb@MU!Iϩ!dfI9&.8CVx:~ $M.LE K+?T BW+}_ T3;F!IsyѷZaguR Bf]}X"+_~V' $iNu0 aZ-?id4j5 !T3:F!Issϥ^w?~6' $iOxwUw)lN*AHR_we=MI 2IKV=EwXCT ]]~b$)}/j=+N*fAHR_>xC=N* N*fAHR_k'ѷeuGI,3IoK^}oRoeqys7C!I{4EU<ʽ8M*AH@7s?~&s $i`u"^ s}T,1M*AH5I?g>d4:w^}YvNT)V/TUnN35S!I7H}դ$ g~&n'Rm| +v ?W>f4/o:9>_IE3Iʃl}W`u&Kv?O>g4o_}?v[Ѥb$[JUAsT (yu͡uxd*yT (yoT5s4/xٙT 0yu>wجTL~n& $i+Tmz8>S33p!I!5:k?+y $)ɝRw{YL=ʤŃ $)i0ƚ*L*):]}` uu]lǤb2I v̞)UUqRuSطI~wK2\$KZWqs $i(jgѯ LSlQٗTVL=&ɝ$õs5ѯEU%-?5ش|#IjQ\ybyT A(yig=;#*K/?뒊!(UݩDFvOnDf`5s.&n~^L&I/]/3.^1Q$I_bTm| jlLAB*vn~~LV5I_x`4pT Q޵1Q;$mνW`ttYϭq7?G&g}(IV}!Ukϳbjw'oպ ƹ ?ǒ!uϓWW? IZ?rC &ZƓ6?W&Z7$i[5h TH?!sߕ.@͖ uFk OQϮ[qDwHWm^)UU Gge*NZ&Tu7?g&z&?0I]0T#J*aoxfo`ʕT D_WYT yP $i:5/d @+>s:J*e˞?5.Ti5S>z{ "5T;gT᯽BN `4'FK5)ALfR3^ws۹gRR1"+vI>Jv4(Jt+W"U'^~0T=LJ*F ~{PJ<$̷ͤJ~',J*F[~4JҌZԹ~ /?_hKvH?$AKƔڍAF_T?JR1ՎsO BL/ 4N \$vPQκRtAyx.g>0Kk)Uՠ^0GrHR1Տ{vo[R}_H\k]w^З {ϏbLA<6܏4+Q3ώ=1A/BPwTuYs ƗrZϻB=ao B$vx^0UH*xeyTdR>5<( ucwu QuSƟIvRBMM ÿ IG.[~F$cHzg| ~պ搹n`:^swT57oj"Ꮉ~`|n4|zFB={aԯj5ng_}7τ"-JjrF'I}uA}  .;,H*2q·g\ ?JRZCmx tuIX B)"%>K)uZ3p}ՓrπjY='=FS*IuY]<؆VjGbُ] Sz%t_$eR[fu`gua?6ԪWjG[IX hjyRJWђZ{E*&w ?ryɧ W%-1u9]PY/ʕǟHVjnA':3~W#Usv#Վ3|Gʵͧi:Av{ÿg~pVq8:RVRU Bޒ6-Y~׾9_\ƅϝ& }yzio$r.؝}b٢)ךSߞsoo$ڱoM 7զ>>GʵrՏ*citj7EQҥJ~~#eےR5}}y꩝GIwK^:.e +.Fʸ9/P IwKU~\*к3)ʃ,Usi]wt7IQ?ץ`uX Fʶ; ۷A(UU,I@o~oKQ}dm*yI9sW 9< ¦GS0I{+^%`dTT;g4RՏ{{Jh B=;.L'Iv̞)uZl v=Վ}kٌs/OSSPO I j^A\6SUƙ ?nԹ?2V#G%(In Rget {ǟH׺yy>f}Ƈ|,+W`(מ5cbk ^մiPIw@? RS|3)jG9f Ӽo$ e} wWH9Wڸ~^zg}(+I<{e`~4T/şHW}yz :T;dIw>OFMKyu Sge!Oy{TlIs׼Y[ o9=9>oPOR'%eXsU몃W[Cjp|\lf$qYκSlQsA ӹXKBY7ԪE]ZݛSKSl[Cj]2 A}5X$ƙlWTs)1ka:]/$eWїW-jOg~:DʶɝRSӰ z:뿑}$$Ij٢}їWjS_?;rm S0Am8U?,IS? їW喙qL\+{YweVC3t+C~U?)u;їWԼg%R>өzb]fC5tRط$_5/ds ?#r_OU4nҪ?C~5"ͧb#R5S(AR+aJR_Zs>++0f:w]Ʌg#Rnx:JwzFSӦ;p%i.UţїU`LtzFHU;썩ȭi yT$͵ NێSIKBjjlLh$nT??lIk >}I2}T= Dʩr(AhJUՇM4<1 dzT)Z/-< $i-[4>R=PR.-aj]y@JNHBS:X4mZC/$͢rR񻣯@vԛ;\픓ѾTz}/$ͦڑ?їR`j~!746AhJ*mZc/$ʹ)RՍ]O~!|KƹIU!*A?[_őּSїP`tZ~kH^sIޔr 4MN~/%4QuSK5AYݍƚ񿨒5/LkQH^Z_;G1lB75ŕ-!oB%m⤭WԼRoE?UGAh :=XK/$ SgїF` 65/D~>na BmlJ?1NiNƷr]S[/<|kj^*NT'ڍKgĊ>w9Ԏ8R}RsS=nΩZ?p֞YF={"NJi6ugp׏Kϖj/AIk2cs~7PM)TwL<=o\;XZ_2j?}[˨&X GSӲmKO7oߛ3:˶F>䝥:{MizLޓ?p}KdxmRa!mM0wlȿT$<MsJ#_~ǶsK,أ} ndƥXmVo'cfӽ@ekz}r t_KP4v` :ΝLْJ紥zל3|u /7^!Uu;1s>x6ӴuW@3_HպZ2gtK?wHz`;u34GTƨyoiZOo~z?gpPڇ 7AsS4@}4w}A=DSTe[E]z E_kNj};6ȥwwZ_˶-7gpœ_6M~nu(Rv}a>| agMi_6掿Xw\) Ti]ES?)e4>qoW7 _gC 6ht'9hٶepݩs50Ywi:ZMz 7jG|RW5g PO6iJ7_69_+0RzyIm~?5gP#*.#U먹sʰ{O]_6! Ic~odžqڄY `bxߵIo}Hwn/;$^$Uix~~٪sǢ49#zyuU K"4V)Eߓj>oQڰ+^XFkn<jxǏJ%W?~ hepّz/7$-~J6SK_ٟ>Tߛ'O_*e4>ԨyOi u-ccpy__ ZFGI` =i(5j[MKh=-۶ o8hoJ]as?1Zw>6Q{<>F-kɷa1Z{?}Ll?(ՒUjԮ?7ʨ&lӗ߭Ԩ_˷|5{6ex׏&17߱TjՒ&~=_zP0w_UeO gQpP.B/uy0/z%F*vi- #5Wm7߹ԨMC%[gECjxZMK {J##uO[},^jԢQ^gj; zghׇ۪H3-c`A ︬TKd<GH\F3qw25fD?@1jO V5O< >1| o|2nF :e05w45e\2j}L񃜢ij ȏhT-F nkJw65d,`~ uO_~oS#M6wl=^~wS#E9/1)2xQ6>85f>g\u\y0s]*3ϵ`fuO?95f:g>eϢ k~5^2wF5*g#03n/ 715<XK;3wG5&gѯ]6ĠW_SV( ]*Tdl@O~#$}A K$ ;% ~.ϊ'YO/^;g;S:t@iͥKs]Z_Go*Qi7>Y|b_vH\22A̔}זjɖM54-ݺ)na=2һ`/iڇzUr}P:G~h2ƃhx zѿ[?s* :Gykq?o>;k|j}ߖjٶgtɿuwexixBf7̠majk<3Eƀio&o>a2`ƴ{KƼUd2z0F5wg6O)c>VFJ_~x٥2_v?O[Yg6+9>%עv >!LѿLMASZ2o3`cyƼT32GhsQ[GZ{*|RcN鞶(u,UǗ%5tN(0Ez~61n qXL{o)o֓WZjvg\Uuѯ!` nixa٩sGK鵢u)9/$5Z +_?<u.?~h6k2Zs{1lxsV}⧔у7G~y4⿉?o4ue3k#5 o~~bD5Qs_(kO/7,RcN_:u׏3F [moq [J҃!gls IDATkJK?c[޹GhYS7]zQ:|4w{i٣2bV)̱OY;<3|Q=ꝵ"[ 47=~cgZ-O;G9ԿxR-*lQo}`#VWU']iJg ^-+_o\J?STߌ^n-+S>W4w|VT~Q $0Q~HӗF^ ?Ԙ?lGG'?Ga ex녥wޥsKkWLH}13<Ό~;v?w=< hTN<5~D|].iR.FJk%Z[E_ ̴њ'ߚhwϋmd+L'0FKk7#z[u\}bf惢FU@1l[kiCjn KUs_<2nFb;xn=q` ' 6./~\]:ɿ-.lhCڔO~;nTf$~>=,TFUϾ}FasC?KJ}K,/R-25%UY|Rc@UeA/+xR5=H?-.#UP3`&+_? 2~.*u"-ZRY+`CZ i>jrO %F,"5!UA<ӯs i> M&?t} NϞ6~Sly!-D~KKĿiQMO>'1ɧG҂t23h~M;kGwgin4r~i~SY!-dJ5~1nEs_3GӗRDCcZ exǏJKOޯ)Ւ¿G*i;Q1 G]/C/?t?K{ߟ<<{QjT>O4`]VkgOQ;yOe ?#i}i,F*P3Xw掿~FHӒ$eۆ/Ijh,ޢZGZt`!MS˷+{~i5OU/}GvzvRg# ?i[|Puz}7M;w#-U'K`-5|+_|G.nE(_:`pg4-{jj\r`|ӏ<)rBf? "QiA_6oyNFx)Osg9h2+ ?Yâ_3g~ =ܡ}wiKSY3~0]Z^~6HRs 'X:ex&9˽FR?b1ן~.H]xy7O ԘR %DcsAlY_Zn$U\3x+}C)ajY/wsJsKjoϒ-K5pQc?.H3aRy$.w_I5gE`:TK ?Yn#]2SF Mw)otH*>G5L24 lǿfIRuX}A,LRd2ew3ѴIZT3GQ~Hj݌ =<-ﻑh3~V?s)[ϴGB8_>f͒Tq3=x?#;aV (}}^7g $IlszP{~H$UGRCΑ ? $IsGzPoQiKg$IRq?)3$IRע{Pk ?$Igxy= ?$IgI@w^~H$U)ϒ-K|P[û?$I%<͕/Axp9 ITe<}}߃Zs@$:xڇ7>$IRut=$IUN=Q3@$? ?$IԃF?v ITeα~H$UO}|P[E$IUsQw>o ?$Ĩgpiw>7$IU3;VkW$IUsO|P[͕/ ?$ĨgMw> ?$IԃyOi4*Ւ-I*)*ԭ_$IUxRFk;IEϲF]H$-Jw>-G$U3L /Am<$fk;Ԗ#Il~oAm & $I2WCj$I 6[?Am<$fk;Ԗ#IlAoAm<$fk'w>-G$U3l #eHjs転|P[n ?$IԃDƇE IT<_|P_v ITe $Isz;=;<$I 7EW><$I G񣩏Py ITe<Ւ-KzP{S)<$IZmoA/9 ,$I2MF?~Y ITe<+A5,$I29EѨT˷ ?$IlLJth@$6xڇ7LM@$6xZ{&Rzg,?$Il/D񣩯8*<$I /u_]joxg$IRq o8 ZUy ITe<+'@$6xzg?$Ilɟ ?$Il}F.=(<$I ֞}Oj@$6xeO-e4A:jg$IҢLgxPJi|Iy ITe<Ό'}I*_{0~Rw6<$I I}J) V$IU><ɏF$IUU<` ?$IlZm)a]?mƟ $I2 /y@) ?$Ilgpݩ<9I*? ;o@$6x'}=<@$6xڇ3ּ'<$I /jxQ ITe<Ւ-Kwy@)}ğ $I2 E2{PJI*_qT=(/;$<$I ˣy@)exǏI*g<`l-mITkyZ_zu IjT˟Vh}J)?&HRr /y@)w֮$IR3{0~'$IO/DR[Its_FG5wzN I.i;o ?$IR֥<~(R'] I.1R~HFK9x?N=( o9?<$IZr?ݪT~&HFmK9x:G4<IԨm)OkFGug$IjԶZm)~=(X&HRrE2{PJ\u\y I-_yt=()<$IږvtOٻpK+ (R<^# G`E="zD;{J&mH^&tIBH%I2eVoZLZ^|>سwE$IRPeL!y Ƴy IJ O3y@Oʋ $T 4/.U IJ O}'x@_>$IR0b3׼b IJ Oyjԭ=}RJ. $)b,<{q9H)ukRyj IJ0 O󊽢y@_uwIT*DYxM諟 IJ0 Oux@_e3A$ Qa◦nFރ ~&HT,(#7Eރ jOO?=1z&HRji]x9IT 43W?g$I*e_ꁿ}W>$IR) o0&_?$IRʽb-<<|C9iVSyV3A$p Oڃy@_uITʺ-<1տw3A$p Ou_>}k $u[xʋ^R}RJ $)\ރ V]}zT^ IJVȅu} $m\x C ^g$IJV̅}zT3A$ O}y@_ITʲ.<}_L$I)NJ,(}FNo $]^x#Վ IJU腧~x@_E3A$ Ou>}; $]^xSns{pA IRn{=oGʮo $U_x}+>>$IR) ԏ3 IJYU˛x@_WLg$I*eUo³y@O $Mރ n;5U}OL$Il,(mx@_/IT& ςRg}=>$IRiU=x@_/IT, ZUv[ } IJg=u3Uv}KL$I³Z7}EL$I³gkk^[L$I³zkYL$I³4V=j%sA$I³:>}5|&HDf@+>}>$IRi"l_>}''FIT,<绢x@_ɻg$I*Md 5YV>}eo $)MZԾke諯dL$I³->} $4qYx6R혏G΃WIT,<xT^ IJgSߠ>}C?>$IRil-'F g$I*MTM8g<}g$I*MTMT;x@_l*/"|.HdTK^R}R\$IiR̠#7F>$IRib̠5F֍DŽIT,<3Ϳ>}ݧ $41YxfPu_>k IJg&Mmx@_OI&! k3׼b IJg5/Y}:]>$IRi"̰OFuZt IJcg$ >$IRi3׸pQL$I3ڷ}w $4YxfQcg$IRiֵ̲Dޓg$I*uYV?xZ{L\$I3˪'|Ϳ $4Yxf-%$u IDAT GI5 8uy |&Hf楻DTv[\$I3@>k IJcg*9|usA$2 Ϡ߸gWEIT,<־3n?>$IRi Xc;`->$Iʵ?K^u gj~(|uݡsA,vRMLGoMM3`ۤiGΓwI&[N?W]Rޟ%( ꬾeuUv}k\$i,{cǩqԾ, |.H4.y_ gW|2y IҌwӪIҸpaq,P~g$8Uj-'nyɲ YxPS?`-#IYK^fjԺD(e3+tA\$QeOny7_A ڡuTv[l$M ]}*Xi^Ok4HaKIӎ >MGtU_A [A`- 1#O>j⴮90 ϐj]{H57SI8c) k m3zcI|?j]x=H!U= y_ oGﻹ}5Һk`,|6HR[?/n=8$ ϐkݼ"Za=$)<=ޙgk 3[d2%)v?}7H Yx\_>}olIxMWz}֧y>YxݢԪ"Tv{|1մ%;{ Ҽbw,<#z I]eWOُwS~,z3~Mg.`n=)|6Hwsƹ9==zL]ïA񟎾utO-$ }77OԺY}KJv%s͋_dA]}=Q=7$ }7J5AkXGg$mR[7$ ψjzr5 I/hWnq 8ƹ_]vSeOIm/_Mk7'#XԿ3j̯`O Xﻙմ&^Ŀ 3oom` yH&秅gO_}cy.AxV IvK.IQY06yvM`~$z>H/|͚ Zuw߷d7M`=z!=$cwsVYxF\~uC8烤y|M=v`Ung5J G3烤|MWӪOEOSdq%֧YI%/ G3YxF-S&2<I鿴OAC{} io=>p:o35/Z}} iUvySiy?hyvD_T!ivUӾ[Yx~0~}-|FH]C~'zt@n9!4 ~gkzr l@ԿfV GNuf{ l@3gySYx}Ҫm焤M4YJjĀ)/:0 |h؀񟎟6Ze7D (ncM?,<\Y`Z76^uGNdz`M?KEvܟE (Ws3p5 lD? 6\D (֭'s3-yyJFu l@C焤 ּl1Ӽb{.Yxjyu l@o(n>'$-'F (y~% O@͋wn9!iu6zD@O|?,<Վ؈ IijS;w9d ᆩӊv VLE/ ^XuPH=~% OPUD_FԎxj|"z4@!Un~% OPvv!Xmhb~F݂Dg RkV&ojxtd<~G?,+$R?PH>~5 O`ސR}yY!>z@!UYx/U'o}(a>g l:k؄ hՏtUM3`YxƤΪki`BTo{(nc#g0IKvh^gTo{(C3G,>gjkn7U!\e6)w;Vu_3FUke )'|66RyKS ~C40ǧ{>7Lk||my0,g >*:f}3CʩW\:V`Yxư GE_@A)EW?ooi(n~]3O:0 R.nվ90, gL묾%zf45/Y}+C3 ϘfdVJ~,|vHۢn[ {iC?}8iR[hVSyV`YxƵE[i0ݧ[!M`/:\> FgkvJuR ҤUWo] Լby0,?q[RjգoW Ծ0, Vz=Fg[EV|Z&Hォ"i]ߚR}}c>>Fgjr"0ASeׄik]{H- Fg]di^{ ƭNӊ=c 3UvIIi>>GqL`-k 3!un /!ҸT;oI`& 3!5/Z LO)E[ΣEߎ:{3~>0 τT=7׽6 }FXm[~,6 3I<5 L)n?R}hvj|u u1^$iVSe)ωhaYx&O:&H{i[؀ 3I-yyJʆW`BOy"Se?WaLu+OsbYx&GukOʮo 'ț,v-l@Lh7:y_pԺ[Pn??1 W]{v3Վ#mSc`Z7g>uO}BjVfuw 0ɟ!gk^g}Ho@W9#INo#g«[3Lp~k-u*~dnǢ`zOdybh&Wϒ,<ԺzΪkReׄw}sT-I[x2ȯA1t!Uv|}Q>T}%ї?0Gǿ>OǾ*?wTxGww/ukOG_T'F}&Tv}kQMm{JVe I'6Kݧy}TGTYMjrb Y{ϗ,<ռd gƚT;cG_u_N'}I#P;C3&2 OF(v#O 3%f5JFy[Ϛ,<{33P@nj6|iԾUgMtj\0n^۽"|i[}2Fvoϛ,[:}E<Yx2kRjգ1`LtVߜ'|6i~uI~ ĝ3<&Yx2u)0NԸpQ*/"|>iUv|?_~Aa5$|$ OՎ CUW>4*K_9N{;|&$ O-z "Njp* ʎ<z:^>c'z4O߮7Y:Uq)Lƚ #3)|>( OU ԎD,IkNU|qӪM?*zN( Ou)&D+S-mS?N5`Z7W + O50g|өq'lJ[1S7z,)0#7iʋekRHHӎ }vX,<u0z8k6$ՎXjpTJrLwve / Ov#n=iz!evܟ֍GnWdn~sme)B 'Na͔$V7aUvT? ˣ}Sϻkߛ%;Cz0ϻ㙅 UY?d>@j~wT;Re6/%/OC~'5.X?87f%e2]H*/*~-,<}(N+unj^cE z.oJc45/}ϛuO} zO ?S.,<qעS}o ?O'$ OAYjzrY`4/=X,~+gGo֩?@:ܘSǟ䗅Gqעg@j$W4 6YeKs KVgь=1!vRuz匳hf-yY>PHJ놣y £syX*)W< fޢRg@+?-? fU/Fyy>ە GkgDs݂bdѬ0<4Yx46KoL=[P,<ynrh?87zfLs ?Õ GW)uZѳ`"ԏ[Yx4Z=;^焟£9UYS)53`|5+<IDATmfќk^][s~^+NT*/* VRw#ѳ`t)n~^+RSkMtӿ=OKF9\)w}k o>`-F+xeo~-Jh􁔺=}>+z=5z*6 MFXnsJL$ bG]ޔ5c L}d*MW_פT;K_r9tJ?<^`u)5.#QF-zI<~G_e;#g1kxKSjqv0W~SuV]3ڔ:O(ڷ=wEx*ۂ[v)N'Y/HyU(G|%*GSk5`. ?s ʯQʰ[CE Gh3Һn> Oÿ(eOv,F9U|gYK7YY…'5kǣռbi0|S&zK/x~𤔪~(S>`Z~Ri5/PӿR*m[G6F%&Uֵn=itvl_E;ÿXW0'6Y`gt/Ye|(9isJvl5|S;ÿh_OsҾTY0tv OҚ-¿p]e׭e:ݞ*K_~^RiF_.<=*WՎDJ(@S?'6OUWLgʾUG1f۝~WH87npi\4xY}0G@.?)ͤ?:'V#U?/Ԭq\N3E*\Ҍjx̌^׍/< =BRƬΣ ?4j$Ng8 OO/T6K;5y0+㩲BJ3Os“TpʿNoj`v@*ͬSzK3VmjGGU~>*͸EKgxi^wxRŨyɲY_Ѽx3J3vRGN? -Smx"ۂɩS{v׺49V? ]gթ+:*ͨL5~g4zoC~'Nk `mݧ3J3R{XO>MP5Vn;[~,UJ3ӏ[t}8Uo :F[v_w?CIk\(Ҧ,5jJЯ-<}HkoMS @4'ܢ&Ծ㬑]C_xzګoMSMmZ8KD#}|IGz-dԞKW7QyVYPSuɩpJ9˽25/bFmd 󚷜ʻ9<Wح<1K ʋ^~NQiMm'}.u}hޮ/Qin{_#UH7[yU?Kycе%*Ma"RmŧI+P5/9R@ReׅGTzA>ڷRz},蝿W ֜kem`3XU>|g>1_PH Tg.vDkvqY$|D#wep)XQQbp?Eqț5(.MY1gO` .;*Z3[IHصƯD; QY<K1ֲ;U=60#IuZ|ѿ(:L= Cѿho?%Ȅf Q,HR.ao}<κS,a?|>ګ?%=̢} ?IjD33ם1dy`W9Z+wJzlc#0B_=B&=_ݳg\wkgVڟhlPfUeO `Yv!I gDeȇd2F8uPIOޒbpIa% C&bDE :c&,޹ˢKIOӲgӳ0z$,C/p臉`P}dGIO߲bxY٣US&LCvٳQvg?`Y0I˟Û͞~6$iysD~ Xj؏7֊?$mr;EyǷ'02'I$M]{$QO+` n:+ߐY{0ʻ!+9g4\ nZƆx qII/򞫳0)|W<$iZkKݜ4gHݳ5ZKKI^7dO`Tu>Mg4-1z1f?`dY2Q-eQ>xc(&Tպ76 Df?`$Y鵢-XrzhM{8,Dm>׉A'#l5Fk?$qL+9g"4>w]Xa6G%_|d(~sF$i[}GD9~4@: L}EqțJjUz4Û%ۥH'=ʇ~4@* LGFk"I*~eTݜ=R)7bufH֊3 ӥ߉>_Wɞ*s~^"If`Y`jF_H]ϫZwkXx~n"I~c/#ُXP 5}KFRC_I+x] n&^۟֒m0W|Q]=V\UF~"I~; ,0r]*Q{Mdxz~t>S$I?1OwLntNF*VC~.\E,ٳُW8e{]?F*vnw]=Z6[ȝQzE$uOO$D)/?8$5S۳[٣`mIb礟H[4#wGqj1P~{:E:~ĠFY`"KPHje;`R /.͞,){bgH~Eѿُ "+3>?%5VK+7mi$I?Ԓbl6 >?%5VGTUhH7I+V%5в\{aTKgw$Iw^ُxR9,}pKj%FŪ*sIc[} <)O#e򇶤l)ߎ~>G~nFèȨ#Z>%կ#`bTnbH[DZhA-~f ozl~#If~DcX`$lT2t4opQ?ǶgZb8~D@.Z+_>%իQzO?~$Izl ~<@ޟ>%ի}蛣m'Fg.AW(ׯ~B 97Z3-UQm;{L.d$u̱@rAoJȒbi0uDC7X OC-zA(ZÛmω$Is? ex`Y E~(ZSmf\sR(z ?+$G+~40,{ڇ-o?, ݓޟ~^$Izb跳 L1 ,5Z]eckE7I} L1 ,lJZߋ~)1ݞ~~$I*;GGS jxњ&}Jڇen4h,J?G$mo)]rX`Au>GWWʨ6ܓ=BxsY$i(|o 𞫣5uy>+ʻ!lQ~$I*z<0Vf6M o<3{|}Qzyْ$MyŪWD ُDͫ!-P~qn~$I^ L ,>>`%m^/C>~$I^_~0e,0h-VuVQ5u?gM4 ^8`X`"}Jڇ94aЉoI?si{f? "_~|i`i{4G̞4zhM~$ISےpO)ay5*iZ(o8{l07}%ZϠ$iJcGS}.U&4(W=2GsCIҔ>ُM~RiL?&\UFwEIҴ6'SwA*,`{X$Mc?` X`~hzE Ե}sDȞ,d)I=^1g?p[>D%=uʝZ6{\S4 ל`Y`^tO@-(~3{TsoSIҔ;oL8 9}JzfٓdU(|Iy$MQ^/(G97}xJzz_c1h.N?i@:'eu͹o=~n%IӔ?c>YYe/N_{DY=%5UOZ$MKߔ=`h҇W,f\="QwDX4,j=٣ eF{Дf#nxsgIY4 :>{3,Ш%}`Jzl 6E􏤟gI4=/G>);룵d)ur=~{k$Mz>?=PhL;K_{FY=37E۳Ϸ$iҫݒ=@hLKJX(NX`L >!K&Ug{&SA)ih,wN O~%I\L 4!ZۤJI[E͞L~;!K&o˞L 4bpCRVG(&ZvH?l {3a,Ј޹4^Uq\rXٗ$Mj=Wey&>z)MuKGso矁I6τ@#Z{,}@J[LiwGo}XK?#Iixc bZ^>i}[#[iV_L?+Ihp1S bz}_$-`ύjmw>DQ,f${ Vet&j)\>ifQ ;%пs3Izg]8gXMgEiZ/ٷ<i_]55#wEygh4uQ@-HҤWܨߖ}^s4IڇlgX>nfQ ;%V=i4@-yY}&z>>SqXsgXwEiRkֈa?6M6њ]~&Ic7RP&bz[6[~&Ic̢L RCQfSoo2NKfgT Qz}(ZʵSY)r(MRogP[IҸVfBXMĴl(6fhs7I6Lhji-1} JOdШm߈go4v`bZZKK$=ogS>~&I^ : aZZ34{2κE?~'IbZ4n۾}+9ISdXa({g 'Ey$jhj89m06QuGr4Y)%{JZ۳Zwk- jxY~ @ 4dCi\\:ݓޟ~>'IbZ4u[r `I(eXa([^/` =5NF) 4dCiYȾm`$tO3;I, Ԓ= qwGoYU@+_~n'IbZ4.|}D}H^{rٝ$BhjXt("v̻$)9 4dCi_*VU_gIRfhjҨ9W#2VƾgybZ4-1oʾM`h3=IJM@-P}($Z$)# 4dCiT|7"*;o$)# 4dCi+v{vTfߞ0vQ3>IZ, Ԓ= Qlpٷ&'IBgXa(Zc~'9$i!@S,PK0Fbpwm cZ[˟~'I bZ4Jmj2L?󓤅M@-P'7vR}ϦIBdXa(Bʝ*Ⱦ`k/g4Y)%{JoEX/3@I, Ԓ= Am꬏bϗJ|fXa(eVx^Tɾ ` <6+U}[5TeH?oM@-Pjm[ h@3GIڌ, Ԓ= }o')"UH?wMM@-PjbEې}; \:Q65 4dC91VVUϧ?JҦdXa(խsofF<3HIڔ, Ԓ= Z->}sEJdXa(թwΒ[gdHIz, Ԓ= -=L`JN3IIz|fAS,PK0w} jŮ?~.)IObZ%u{O,WwK?'M@-P÷g:B뷣egY)%{J-_`: .;*R( 4dCis*y(LoI?4dCis\sR-$, IDAT|nY$phjҦ9f.3KI, Ԓ= Mjvqw_}#hnv)IbZ)N[1ݓ"RbZtUquo>+ S6fXa(=]ʾM?wi$mM@-Pz>bϾMQoGgdXa(=UÛʾE7LI@S,PK0ggr^~)i@S,PK0%F ٷ0&W)i@S,PK0ޗ>}k㤪}6%MohjW6ܓ}kcfxi盒7 4dCmEm~)i:@S,PK0~bFS[/H?4Y)%{J?ಣo `uNIӗbZ)*o `̕w^Eg+ 4dC{ o<3v&DM?4]Y)%{J|ײo`7Z>%MOhjRkf(vLޗ)ij@S,PK0'YmLj-Z]M@-PSZ[mL)*i*@S,PK0t;ٷ0GֲB%M~hjՆ{o`PIbZ}S*bM?4Y)%{j:+v{NT퇲/`JY~.*i@S,PK0tڊK"UoC{ lTfXakKv}$L=G%Mnhj<0QŞ/N?#4Y)%{j*~eĠ}S}I%Mfhjd%L~/L?+4yY)%{jzjڈr}S祒&/ 4dCMOϾmbL%MVhj.*/w9~n*i@S,PK0t4K?T݇}SIbZ&~(ٗ:cY~~*ir@S,PK07bue8Ug}=' UddXaɮOD sTIbZ&eGe_O*bgJ, Ԓ= 5F^J?O4Y)%{jr|iUQ,fM@-PY^ Iz$\UxgXalpٗ6&6eH?[4Y)%{j8竒7 4dCM^ʾ6[Z}M@-PUyVe E_笒3 4dCMVg_[Z[l~*i@S,PK0|Ǩ/iZVIcbZ&ɾj+)ZۤJ, Ԓ= 5!-v&A査J, Ԓ= 5mJ,IQ}EfJ, Ԓ= 5,k/eFu>篒& 4dCcߝ}4nxY篒' 4dC /cy>-g# 4dCw#ߞ} ̛UǥJ, Ԓ= 5 ?-? }^~+i@S,PK0>"*`U QzlCkSyuQyu٣GcA籒F? 4dCoo},`UUTP~Scp1ѿ蟿2zg~4zutO~gtx[((v)Z}]#su^:ߣ}~ϵs ޗ>71łx dQx~M@-PYs^z^Uq\ΈeyFԿg%ۦ66Q91:G#zm_ wΒRI#bZƳW9`UeTnᚳwG߉IGbG%\:/ZC{M@-PcؒmzKT퇢\鹯s_Zc$-~_ ;%d-񛠲-%nhj6F+mmߘ95)bDS/c 8&P=tsfKJ, Ԓ= 5~})#ztV/?{_|}fNSW+cx^~%fhj6)#GD瓿MoT3>+:GV5|a(v{̿hjל}LO[K[ퟻlOMF. 4dCO>(ٗ,}D俌Ao5zLŞ/W BD}Lg J, Ԓ= 5>o 0D俈~IԘ};Ɵ Q=ts 0ڇl;M@-Pc˾\&w?4>W|}(:2H+M4ZY)%{jKKӔ,$oʾ&G9Nד4:Y)%{j<*1`ڇ%LgXaѪwΒKˢMikcxyc` .tM@-P#Q5|U~):G=J==Q_=9ϠwIZ, Ԓ= 5:u`Te :>!]Jf|ma/{̋9\4 4dCNOȾ6OKT~ gdOU{t-I bZFb澖 ` s'ߟ$5[g;$0q'i{M@-PQ˾\9eGEϫߛ$[X, 4dCFd_WU1h%I Ɵ(^=>߯$-Lhjʯ}?9M% 4dC%4(o̾ 6(V"GT̻j?= 3ߗ$OhjZڇ5&Tպ7Ij(:{,<^Uνd/Ij> 4dC-|s_ а'D:όwN?e@S,PK07uTߑ}ꬋ#IO̢ѹUqn$, Ԓ= ux[%LEKq$%QӤM@-P [/9`T݇H>ৢ 0gxWߏ$5bZQm'\y'm$i *v}V B(>GM@-P W瓿}Fњ&Fj5u/?{DIj, 4dC-\K?}cZ6:G-}Fwڇ"2{Sꬋֲߋ$5bZ%FU<}chWe>#IP8RuOz;fo bZȾqSwG5(]Faou_T!IdXaip/5`Ts;$-T}_7d_`J!I@S,PK0tߒΈba$i+V(;._Y)%{j%2AUE%њ:EZc ?-{"l؏oEC{};L, Ԓ= 5 }de!n{$DG30!G'D=Sk˞#i^@S,PK0<78}ٗ0o?"Ibf+ם2jjҔeXas۳/1` o8#wJglf<7 o`}E翿HJM@-P*_fH/\W Qyi/>4'٣ߢ6uM@-P̢ߖ}FԿW1wG7G|htZIbZ~>FL}$:wIOqlTTU(Vu𦳢wΒ~g{ CxfXaݲ//`TnAoHGqſcm-_{{X IbZk//`Dw~;;H$;`(,xt?.D.N4Y)%{j~jK ÛύbM?Iw3םWEk + 4dCOs_I7IweyZUg} o:W3=^n Ihj/ʾd%4]=`Z1}QcDY)%{/K H`I$iZmDy1wQW mZZs3S3vi,Zo23t9cgcgMrAr!"B! A.1(*McKDAN/}V%;#;7%Ijk͎mie}^8`>RYPVÐII}U3Q{E$e JW(ߛǼ$,TU0I$fGkF?xb^1$I&4ݾ9:uvٸԙY~,T* *zR9I}QӤ=xj^7$Im:Mp᩿Yr` YP,(aH99I}9`OkJa!Ixyix_ge.{N 6T* *zRFJ$Uev? .$틚i#S?Hc~)._OI$FT=7D4}cm<1 @xU, jd@!esr$IbJdY׭R$I x_ _uH,9(`1џ$IKѝOoPgO.j$-~?B~ 'd@!Zg$IRӟ^=̓E_1yV3ؑ&[L+`a{,v|?EF$i/ؖǽ4@yMMFt7(J_-`@!v0IԾ; 귧4D_9};4px:$u~Pd:$IR&?uï[Ge}^8_~oXP,(aHީo$IRvz73I׹Ln8._kߙ{8T* *zg&$IjO|*}>4+HTMi}soZ|(V:3#T* *zgr7?!IT+Rg3{~55"I(S!ϝ$iXP,(aȞOG$ao`Xr`ym%I{fǶ4ٲ> _uH,}V=`@!{Sjџ$IڃvMg'X8zx쏾6H,N5/ PYl$IҞ4މK y_-&I߰&[UuʃSgfQLJe@YECvI$-_G_eMiz44z?Rg'KT* *zw}/$I!X=;Ma&I5;ɖs?gIf@!{Sjџ$Iڍ={K,|O.Q7jTYM1=# *e= =d$In6C$QwyBoS=X(,TU0dy|'#Ivuk 8Imh:Ix4px:$u?#|Be@!gzOF$bw=Rӹ;j%v~忥gޜ:˞>M,TU0d7,90 $IƿhwD_uqM1=%s Je@YECvlI0hC_sZ'i>4鶫h4XwX<8uf(W?H]H^v˞}IڗM'i}soZOUyXP,(aȮlYH]hx 7PުߞAIٱm /YSGiz+?NJE<H'g.]}=J4޴: 7I% _T* *zGIo[/+c,~FפjvlK-ũٟ2XP,(aS|JyXӤީ<'HWi= z+NJe@YEC\_D$I5'^V'4[Sw5M޽e;即#E T* *zg;$I +?gPTjc;j_8dq94u 9^T* *zFIaQwGߞRv4zem\Q/Je@YECK?Is:5cߊn:ۣPiכt;Rgf?;z|mIWi[y_Tf; *e= y|iHy9i({쯤fp54ݾ97N (>" *e= y|KE$no_kVfǶ?Y!@[XP,(aK9o+?#M!^?88&G8h1 *e= y|̓G$)4|y*U?߸" z+NE@M,TU0䱺_YH_6o]NInߜƛVS!?!;<'I_sZq:75?kvlUK;g3<{i>ؖ&[֧%S͡{7NT* *zB$4px[M_O@4c_ *e= ys?Il:Ic^jOMo Mwii[3( x"T* *z]E$UοIn|Y{G?wW:K Je@YEC̢FA*'o/-g^͡ џ$Iu6Q B0ڸbf#M^9GwOxE,TU0dN)HTe^?t7ipRo3n,TU0d)HTesd?4px:$u>3?DRYPVÐ=1$)Q/u=; goMݏBG,TU0dƯD $Ud˗i9S$0 @;XP,(a~OAj{Kz+_HT]Wh *e= /zWg IRu /HRYPVÐog IRuVzRYPVÐD$U&7}-3$F^~.T* *z_wSg IRUvRYPVðzGdHTOqO@l"},TU0]߉$I3?c@a0$zRYPVðvK$I@q@@XP,(aXuk?IirÅw?d@ao$I*,TU0]O?I7U[&$&YrP@+YP,(aXފ_>~Iir۷~Je@YEÚOkKTM+>~^T* *zlpD$I?~Je@YEÚ />~I{~Je@YEÚLKTE[}Je@YEÚM~|QKTE~nT* *zl/IR /{vRYPVðf$~nT* *z֪{s^jKw?f@az+_}$UQ>g@a}$Ud˗}Je@YEZ G/IR$,TU0裗$g7,TU0;>zIׅ裗$Mǩ{RYPVðV7F$IozϏ|`@ao>zIZJe@YEZQ/%Ij}˗Je@YEu?.IR ~P *e= k;.IR>O}`@a%%I T* *zhp]t 5~/]7vu@=,TU0c]7|^@=,TU0Ӣ]7;zXP,(aXɖ/E$Io|a@a&}+%Ij}o5c$N|u@=,TU0Qӻ?%IjwM:K~P *e= s)5c$5w>URYPVð6c^}$靛|b@amz+_}$ɍ_ _F$Io||b@amOKF/|?F$Io;XP,(aXGKg;XP,(aXѕF$I7Je@YEڌZ}$'^~P *e= k3#$u|n@],TU0_>rIx~P *e= k3G.IRkv~P *e= k3#$M >T* *z֦}$m IaK&7\~P *e= -IRo;XP,(aX0%Ij}'Je@YEÚV6%Ij}o, 5ϣ[7_Je@YEÚ$ |c@aMg+%Ij} 5w-IRw|c@aM?}ܒ$gE@},TU0𢿌>nIZ_ 5}cIqKz'&>T* *zd㣏[=ew>RYPVð&}ܒ$/5$u='>T* *zd [9;XP,(aXG$In<5$5{d@aMwn>nIZ]:YP,(aX=7D$Iy'=uRYPVð&F$Iy`k}@,TU0I]-IRk9NT* *z֤?}ܒ$7Je@YEÚ$ݦwo ?R,(aXE)5MqK7TJe@YEj,9(%Ij}ӻ~Z7;:YP,(aX1/>jIZ|d@a-ǿ,%Ij}ӟ]@,TU0EoūZ7[w>uRYPVð>jIZoJe@YEZNzCQK;NT* *z֢}Ԓ$ 裖$M6NT* *z֢}Ԓ$]ׅJe@YEZO{KQK7Je@YEZOkQKwo ~[QK~P' *e= k_shQKo }gQKo 裖$5~P' *e= k18}G-IRk+NT* *zbpZt GG-IRk;|d@a-,H|d@a-} %IO  IҾ9>RYPVð8%I/  IҾ{ܯJe@YEZ }Ԓ$UQoū}c@a-,Ho{XP,(aX $z)>T* *zbE$IU?->RYPVð$Icm3S IDAT7W=>T* *zbpG$IU?]>RYPVðs}Ԓ$U? oZ*\{XP,(aX}Ԓ$U𢏄Je@YEZ׾#%I7Je@YEZ}Ԓ$U[~{QKTE?~P *e= k?Z*_n@},TU0Es}Ԓ$UJe@YEZO{KQKTE7Je@YEZ?裖$7Je@YEZVvQKTE̓Je@YEZ>OZ*jJe@YEZNz}QKTG4ufJe@YEZN|uQKTMe 裖$~b@a-vA$I7V~P *e= k]裖$ys@],TU0EF$I_XP,(aX%F$I48w?URYPVð3Rj$}$*T* *z$M-IR.?:.T* *z֤>nIh|թ>uRYPVð&M$ƛׅJe@YEÚ4$%I-Je@YEÚL1%I]ׅJe@YEÚL^qKTECwJe@YEÚLovqKTG~@],TU0K[j,}f@=,TU0 [j+w?RYPVð&ω>nIw~a@aMמ}ܒ$USs~P *e= k2-IR5 }@=,TU0G$I4Je@YEÚ.]}ܒ$U~a@aM_-IR5\@=,TU0p-IR5M~!T* *zdp[jn:T* *zdp{[jjI@=,TU0Iۢ[z SgfQ@,TU0I!-IRUuz~@,TU0IG$IU;5?uRYPVð&^}ܒ$UUJe@YEÚt0%I96T* *zVeɁ-IRU 7P *e= k&#$F~P *e= k>rIi|g~`@amn>rIirÅw?uRYPVð6ӟ~?%I׆Je@YELn<%I=T* *zf \zjYr`@YP,(aX5>rI{Je@YEڌyBKTUU~~T* *zfx_G$IU58?g@am,%I<,TU0G$IU5RYPVð63~?%IukJe@YENycKTU[/ h? *e= k=%I}?h? *e= k]#$FRYPVð:GR3>vI{5jD$IUJe@YE5}$UUh7 *e= k4vuKTU?~nT* *zhrף]^rD@YP,(aXD$IU53?f@a=%%IM_ h7 *e= k4|yKTU{nh7 *e= k4/]RgfQRYPVðF/iKT]ݣ_,TU0wG$I? ^T* *z֨[]|=oJe@YENzCKT]ï7e@aǽ4%IoJe@YE*-90>zIj/ƿh- *e= k>zIjRYPVðVӻD$IUt h/ *e= k5裗$˞,TU0s^7d@aF^}$UW~F$I5 NT* *zj?>zIktQoJe@YEZ裗$׭ NT* *z֪w^7d@aǿ,%IZrPKTeeω:T* *z֬<}$UW >T* *zlz/IRu7c@a&[>~Ik?>T* *zl$FO >T* *zlw'E$I57c@a͆D$I5ݾ9 @XP,(aX>~IkKEJe@YEÚ׾#%I9@XP,(aXީo>~Iwb@aͺ'<%IU[$ʆ,*T* *z֮> HT]k.T* *znzџ$I5zEvRYPVðv[ HT]Cwh *e= k7޴:$&u=,TU0貣?Iwkp' IR=,TU0]?$I"@{XP,(aXާ~#$F99@{XP,(aXF$U䦯h *e= 7(Q/3$ƿh *e= /Mqg IR}5Yw`@!-F$UYoJe@YECKMHTeT* *z_]<3$ʆ}$@;XP,(a~iϢ?Il|թJe@YECK303$&\,TU0d;7?Iyw`@!/ $IIe YP,(a~3ȥ IRP^`g=*e= 3OA*|=> *e= 3OA*~,|T* *z2g5џ$IU6w ]~t IRM^`RYPVÐ9 s IR5`RYPVÐ9$I  YP,(aȜɿ)HTm+-f@!sG(S$Q[Je@YEC vD$UK,lT* *zO$I焿X,TU0-?Ilz,lT* *z?IlK,\T* *z˞up;y8g?x~g cVe=?$ۆ'D-1P TU2f}UXHmE-1P TU2䞦::},$I[ `U*}rO>$uC/X?jJ_>$u/X?jJ_?>$ur{W=z1P TU2^9,}4$Ip=Z1P TU2-1}4$I+Y-z1P TU2ox[hHm~?`U*}rW8}4$IOX/jJ_ܻɅOO Im@U/C_K Im9j-z1P TU2 Oѐ$P=0P TU2>9$}<$I˿XjJ_ܷNImroևZeҗ!m$I6[aVe}!IRo,`}U*}r&$ۖ;oևZeҗ!mtC@2PUː6xNIn_XjJ_܏ IM{t*U |2}D$I,`=U*}r׽)}D$I  *U >?}D$I[`Ve?$I]7x>@U/C4}D$II=3P TU2 GDi@2PUː{W)1$fW *U y`[>>&$uX}jJ_<'ސ>&$ur~"O=j3P TU2M/;.}L$I~$`U*}o|JHuE=j3P TU2䁍^Kc"IRM@2PUː68c"IR>{fVeȁYnKImkoVZeҗ!f~e"IR'ekCVZeҗ!fGE{eVeȁ\Q$Ư{eVeȁ"IRMut=2P TU2 "IR?y~=2P TU2Ud+}\$I7,@U/CKIIm(gW=j2P TU2ͮyuHuS.`5U*}r&IHu7>%`5U*}rgzHu0`5U*}r'LHu *U 9{Zb>2$u$@U/CGF<VZeҗ!gGFVZeҗ!g福$I]7@2PUː3~o$I]7VZeҗ!gxϥ$I]VZeҗ!gpw\$I6=@U/C_HInxңVZeҗ!o~;F@U/C'$I]7}sVZeҗ!orJIn~E@2PUː7z?MIn/@U/Cؿ>6$u: *U 94˭[GGVZeҗ!fGG\{aVeȡ^qbHu2`uU*}rhё$_:`uU*}rh/GGOއ@U/C臕\$I]7|ߍ X jJ_WoJIn| *U 9tO9}|$I *U 9t<7}|$I oX jJ_9OLInuk=j0P TU2 OylH}~ & @2PUː G^b>B$uU*}RgGH3P TU2O!Inѳ *U 3doIu[>gVeHٿ>B$bV:<& @2PUː:>B$udU*}RiσKH7QjJ_[|#c$IRMxQ=@Zeҗ!fW>F$u *U 7y$I]l~PM@Zeҗ!Fg>F$u 1P TU2y?>F$u߈ 1P TU2ݻrQ$~NM@Zeҗ!mo<}$IU*}ʓGI[~K9jJ_1>$IR @U/C$IR @U/Cyw\$I]7yDU*}I}ujJ_3I7K0P TU2;{8IwEgVeH;>N$u#ovZeҗ! #$IRMgVeH[#%IR>{gVeH[Ͻ;}$I? *U ikzŋGJOއ,@U/C$'?&&`gU*}x IDATAHI}7vM2P TU2/e1K+In(@U/C[${w=2P TU2N+In9zڽ+&`U*}>V$u?s *U iotƯ$I7>ovZeҗ! $96&`U*}=[$I]7m;@2PUː1%IR-@U/C/H-Io jJ_l~;}$IѫaVeђ$::&`gU*}M>8}$I@U/CN/In[vZeҗ!g$I78oZeҗ!g>^$uU2&`U*}}bxI}Kl?@U/Cѳ<}$Iul;@U/C+ץ$I]Zeҗ!kvkGL7@2PUː5yM1Iot7@2PUː5zů$I7OoZeҗ!kYr>f$uo ^jJ_lWoJ3Inl/@U/C߾ס$I6xl@U/C=c&IR^oZeҗ!o>f$u-&`U*}c&IRͮ='&`U*}3߼%}$I坟>jJ_ oO5In,c= *U ˎK5IotoZeҗ!;cJ5Io? jJ_ 2}$I^= *U !To$I]maVeΙtYIwe<{o3P TU2dLxQI}ОZeҗ!;gI7Io? h@2PUː3<累$I7 *U A{+e:L9In՛o3P TU2dg-n2}$Is?&-@U/Cv$I7:o2P TU2dg{rI}weVe$׽)&-@U/Cv؞JN[~7MU*}7_>v$u h@2PUː7)c'IR^o1P TU2d{rI}KЎZeҗ!;oxcN_QM@;jJ_90}$If *U X|eI}hM@jJ_dL?pJI}=& @U/C2=9}$I{ h@2PUːɏI=Io~;o0P TU2$daL'IR-wݻU*}$'DM@=@U/Cr8%}$ImM@=@U/Cr=9}$Iϋ gVeHǤ$I7ܻoU*}R$떓oʿ bVeH+GPoU*}5)#(IR}RM@@U/C=9}%I'1P TU2$kxcGP}7u *U sX)aJw]M 8djJ_-1$<6&U*}7Ec(IRjM3P TU2$o|P}7@2PUː?>$u 8tjJ_ݻrQ$̿ 8$jJ_g/MEIo_ 84jJ_eǧ$I7y@U/CVHEIo@U/CV?>$u@U/CVrq$gVe_Q8J}3 8xjJ_JGIorgVeq$zKM3P TU2du q$[_ 8xjJ_"}$%I ~,&U*}Z8/}$%I~+&U*}Z&o#)IRMcVej${OM1P TU2d yx)eXJwAsX]3P TU2d,!},%Iɏ 8pjJ_5IKIoƧ8@U/CVg$I7gVe$IݷGoZeҗ!+YS)YhJwYzw@U/CV▏$I7:cVej})IRM.cVej?$I77@2PUː4$uoZeҗ!mt#*IR-n2&U*}>2}L%Iٸlux]}3P TU2d-LJ}S.&U*}f;;}L%I[KM}3P TU2dM.zfJ}*&U*}F>$uoZeҗ!kਿQ|>$rY{eVezX|#*IR<2&U*}fW>$ug;@U/C'$I7m7@2PUː0|>$urղ{W]=U*}&v?,_OWIox@2PUː1U{2P TU2d}L/;>}\%I'ܓZeҗ!c|o$Iݷo@2PUː1x>$i>-[ogVezY~#+IR OogVez$&=3&k *U Y/w$f{mM3P TU2dN|J}˯~.&U*}^<"}l%Iq?W *U Y?>>$uU*&U*}~fW>$uω +jJ_ɛ>$u3@U/CԟK[Io9Fo1P TU2d ux)qJ}Ó~&..jJ_H]Io|ޓo@2PUː4+IR>o1P TU2d=}RJ}[ @U/CğJ]I\1`veȚڽ,w$I7:wjJ_H_Iorɞ@U/CǤ$I7[o .U Y_W$ zgVe+IJ)/w@ *U Yo˯}>}%Iy@2PUː6$f<-&Zeҗ!m?LaIoqoU*}F/'#,I28w@ *U YogW)yK}@2PUːc,IRM.@2PUː7X_aM3@U/C$IݷYv zeVe1$I?@2PUː LGYwNU*}7]>ʒ$uSo^U*}?/}%Iŗ zeVef7GY$-epw=2P TU2d3 #,IJ)WJ]#@U/C6_LgIor=2P TU2ds?y~8K}O%&Zeҗ!c/}%I{W]@U/C6ǾsX$7jJ_l+eHiIo|@2PUːͲ'GZ]7@o *U ,>Ғ$u zcVef\{#-I28w@O *U ,?#-IJ)@2PUː !Lc-IRM.ٛt@2PUː3{Z'jJ_lNHkIo9zjJ_l~+}%IR)exߋ zaVeڒ$2>U*}|O)ExK}>?.Zeҗ!kqۧ[[oU*}fW>ޒ$i>-[`U*}&o-IJ)`U*}[$R&o`U*}>0}%I'Ͽ 6Zeҗ!mOqIo9ll2@U/C6G\$R'>*.djJ_l$I~'.djJ_l '}%IR)eMfVeȆ۽뮿wX$e[`U*}_>$i,|o] *U |K$I*<2.TjJ_l>$2}1w2P TU2dq~$I6w2P TU2?>$iU>$.DjJ_aW$I* @2PUː>L_G]$!>#.DjJ_axϧ$I*̮='.DjJ_tK][~`U*}ҏHwITJw1P TU2>$2>wMcVeH?<1}%IR)e@2PUː~ _.IJ)ۮ 6Zeҗ!ٽ,$I* `U*}җ oKyITJ@2PUːL/}VKR}'@2PUː<2}%IR)eMbVeH_>2}%IbV`SU*}ҟ7$I*^+w0P TU2?k^>$2do]) *U g$I*?sq]) *U %>$i_!&0P TU2CG^l>$2l@U/CU/Il@U/C4/IJ)O!.jJ_i|G_$R[_)[w@2PUː> O|TKrm *U ]e9=}%IR)eƧk@2PUː~ox[KRï ֝Zeҗ!^$I7@2PUː~<2}%I?26XgjJ_kp#JY.ITJ:3P TU2o;nL$IR)ezŋufVeHf׼:$Iŗ ֙Zeҗ!}\G@$k(c'6XWjJ_m_H$IFg=!6XWjJ_tKITJ^2P TU2J $IR)eqw2P TU2/N $IҾ28a:2P TU29OL $IF?>6XGjJ_0|O?$iw#@U/Cڽ,? $2{o5dVe?GA$k6.[G`U*}>K(H^@2PUyd I7xwmn *U a(eL$IR)e~;oucVeiqǍ鏃$ItP>46X'jJ_f׼:q$IoubVeirI06X'jJ_𗆧| I7[oubVeQ2?$}lyp}& *U _*$I0P TU2^GB$or@2PUn| I' @U/C቏J$$I]p/< _wO)@2PU]e9=$I3P??\̯,w0χeҗ!uO5$I\{fpwiGɅO/,y~]uj@U/C릗F IDATXH>6ڳ O2evͫg=0P TU2nt鏅$Irֻ6?^>L8oٸ㯋{aveG\?$it}hp#'%{ rx|w_+jJ_powܘhHM.V.ӎ( ^f}Y~;}~;]*}½IȏfCGO-([-e}wtY5@U/C7$i5ZnZv e/sTWX7]rлF]*}½鏆$I[Ó~&>08et䒽e~e9z[>u@2PUQ2?$i7?->G?N;⮟JG/lYw@2PU?$ikύ ʞGg|IYzm)Eلb5@U/C/+_xH-`~YWX7]8)Hzcvee|It'?&>{Gg=L.[]pאjJ_p_/C$ݭ}b}VFqg|GrYv@2PU]4%IZ8/>/{+Ó]>>oarmuxsjJ_p~k#"I ~P}f(kL8omkpzgVegzQ鏈$I[S9?: er2ܖڻ i *U GD$ݭEόX?gWvD\2o(5m>@2PU9[rHͯ{S}sX2>Iw(?TrJ _U*}Yqcc"I}lyp}(eǕM2v~,@2PUW?&$n58{Ǖ%{ rp[k7<wjJ_@P$iuUFqF;WROWJ@2PUԟOL$Iݚ-}HeXf~yYRWPD3̟U*}:RfGE$o9ZC68etK_7UپZeҗ!HT$I?80c^F?L.[]P[_I64zU*}GE$ݭk}xwiGɅO/([-eL4~ͿɟU*}GE$ݭtoaexcه^V|yg&amJE/A0pxDCi)?xI$IC_ȷS{]_$}H;WR4߻,P_ ;$I᪶p8cZ9'u-OE?j:,Jtj_570ooF$IAO>Z+\c TJ#ÿQ8a(M?t-t]#H$If)'ކ)?@Jt-xcJE?h'Z I$gZ+婨=G`è\PJ0[gBkŗwI$IWj۩Iݻ/H F؆όQ8a(M|-t:|G$I4fIeE-)?fԾjnJtRj_'H$IO7_wׯJ]PBk29 = i7{T6EB-=A$I+|Wo떧T|9 = 200Xګ$IQnWKMKH5KSo?&3 ?rq@)P*SۇDBzׅ$I4{T_Oj.{ݒR @I#rq@)P*S [Q;m{$ITo_{h_RugԨ\PJ0T;џ ?'H$I^7iHsRwTm^ֺssks@.(%zJe+} 3йA$IKMKH5KSoڔ"ze#rq@)P*[玳?#` E46k=A$IfIeEʿۊ^!?Ϸ8a(m<'H$IPmީq~)k:PA>F=RT\OkŗI$i8Tm^́Ѽ3ps@.(%zJ[Jzl5{$IKΚamJE#y_8a(uџn+6|O$I4{T_Oj.?W/J&v^AѼrs@.(%zJ9j_wDls'H$Iөp}v[R^lW>;G=Rh>:|O$IvTo)+떧blC* 0e?>OG=Rm\'H$I/kn~{SRg۰6^Jkg3vs@.(%zJ*8svI$hwIS{]*N3zE#rq@)PU?'`+u IѨvO9M5̘9 ãrq@)PUGNVt<'|O$IRWj,wOu^*6=j<9 = \՗FlEQ{:9|W$I7gT?۰6^uJߍ#rq@)PWmERVOx_ Ih.~̻RJNLoK׉^i^k-~xDC)gGnh]9+|O$I`V[wj_j떧l 0'JLJRګERVt>|O$IR|J%n)KŦ'WU9?9 = 5X'lMj +H$i[/'5/LYz֦T7Sʪs@.(%zJ9џ s?+H$Վ|{j.WKV;-o#= />Y[ѹ=A$Iy-;5/VIuSQ&zy~y/>R=FVVcv $I4j.5Z0SųDlؼ=ߌQ8a(u?+`ǽ'|W$Ivk/g;7z֦TH&alȈ\PJ0r8?+`Z++H$jG}/۫U`Xu[oJRRi[1wIp8cZ9'u-OELJR?=vklMjp ITj.5Z:k7Ad#Rԏ7i<Ể$IRk/g;7z֦T>fPHDCL[O $I|$W/'Rq]$Rԏ_}GlCilN$IҰeRk]<9P5oJR_S*6F^6ԏ}A$imj,7.9 u,S0 8a(wyкỂ$IRhwML3?{얔^>pU&dRԯZW~%5Ể$IRO=4uׯJ]^ur@>(%zJqD^:vI~T;G'rN[S׽ODC_|]Jn'lC#|_$I*[mkScɾufimXf0:w&8a(ޓwFb6tnZ I4rj^7s멛|rr;)dR:7PHS I_}GjgzQ=``?*ݔq@)Pg?Q? $Iƫ8rN[ѫLZoJR?Sџ+/HldԺYtOEjֺJR+^x43 Ể$IxwI'~ʿ~UJVY5/7WDCu֞RR $IRu-;5oO߷"v-zk7XDCߵ. ؎ $IpV;/@ |PJ0]_]/H!hRg۰6^e` OZDC+ZwI48%OՋRw~8a(Dh$Ip8cZ9'u[Rk,z=R;s9 = }џg_ IfyI/R11zW;p7^DCi&jFjv/HqEP-E/9q@)Pjab W$IRkkTJx>}JL۰6su? $5/lR; $IR=u*}6\PJ0f;^uX IWou*rv9 = mΫRjף?;`;zO/~g$I}dҺwm8a(tFv3H>4kzU*l7^9 = C?;`Z+3H1zi,7^s@.(%zJ3]?;`z3HՏ~gS?}o6\PJ0f)Sv؏ $)o3zʩo6\PJ0"m'vowI3zʩm9 = :|-vwIb@t^8a(E_Fzt۩vI֕7 Gwrq@)PwDz$4X I*]/\PJ0*6=;йA$km]/\PJ0sa@x>yU IԽoEzp~r@.(%zJQ.BLB $)ODP)Nr@.(%zJQOLJ $)OE*rvr@.(%zJac Cx46kA$kkTNkſ8a(E]*&~⯆ $\E?R@47^/\PJ0"k_{h'LBIT)^)r7^/\PJ0"kGџ 0 $\?R@ԏ7^/\PJ0"-xSJEP_O I_/FP9{z)R]F$V$Ik>:z7^/\PJ0zJgLB;I4:kEP)E]/8a(E׼௢?C`~.|w$IӫwW 3JRtE?ֿ$iz/<J@!}s@.(%zJPџ"0 n $I4{JE/zJsa\PJ0?E`Gt I_79 = Auџ"0I˿;H8+TNkŗx<R4Տ{OLR$ij5/l Ӽo^rq@)Pfsџ#0Ej-~$I}TN JҠԽ IDAT֥;H׹*~̻x<R4(џ#0IwI4z>@7^/8a( J%FdT[c$I\]J4U)kџ$0Io} Iv=3ſzEDCi>xM' LRwIǼ;zmO fDCij_}`' LVj9|$IۯyΝ焿zeDCij{џ$0?H׺++TN#x2R4H6^'&I:2@.o^rq@)PzYUvIz1@4_o^rq@)P: >?HmW4^r'fW\PJ0YYS{A$m½WQ?9 = AM?' WCHW8kT=y2R46iSZA$&@xm=R4un:1$Ize&@6 J <Ϣ?M`!|$I/ˢW}+xm=R4{K LQwI^r:k9 = A?O` z?H-xczԾj^;\PJ0-'GՏo!I68W72s@.(%zJZsџ'0EU$isK?@%5Nym=R4جICsѫTR툟J 7o åCHJn^ zz46{w^[8a( r[OD)jx|!I7{*xw^8a( reSTԟIcsw#$I^ J W;џ(0 8|$iku*sVrq@)PgL)BQ}TRʯvDCivZg LUj GH4u[ @%5x;m\PJ0723ygIFY;\*Xo[m\PJ0oLi>t]!I(V?kTVmᏅvDCi*[P_{$IVsٟGPMFs[m\PJ0mG4V #$I7@%n;\PJ0Ti=sĿCKH4J1zJ~w^8a( C#*S~ү$Ls^R@%un:!vs@.(%zJRLJ$J5j]^8a( K5PԟIcsw%$IZ*yΟ~DCiXj^Wџ+0MI.!I(xgvzm?R4,Վ|{ LSw IF}!oJ0U<`' LGjH.!IR*hk9 = as)џ,0M)|$5Ds{^;8a( Sc SMcv '$IjO~:k9 = apO(7 I+k9 = aq]g LS疓w IX7TO=TV󜏄qDCijx\g LSڔj.|$j?c1׎s@.(%zJVG@ >OHTY@u46o^;8a( [oX}}B{'*x^8a( cD@ OHTjCy5J0־O(}}BR4}\46gBal)u9TZ环ǿt΀\PJ0WG@Iͳ?SH45q9o&rq@)PZ+gG@I?]SH48k7_8a( s%F@YE~.|$i=s_+W?=o&rq@)P얊֦(}Q{$ICTwG?P}Ek9 = a%gؼׄ$ KI<orq@)PZcg d_$ K'n~떇ZDCiث/Ƞ {$IP툟~`$98r@.(%zJUxOȠ~/$ z>dHhw_S8a(UΚџ2A%{$I^wO6_~5JRjOȡ]Ko -$Ij9^74]~M-RTjHJE9BAyѧj o 5JRU=yg dPt]n!IҠZO4k9 = 4o:OȤ~ I9`f_S8a(UWG@&5[H4(Վ"yPԞ 5JRjr' mao /$IZW~%eѽ_8a(UI_H46~`d?*r@.(%zJj.?YcW$V?O2 5JR]Y5$I_̩+₩rq@)PZ͋?Y=)|ǐ$)^|<9릱y{VDCjՎ|{g dX;$I=uo\PJ0Xџ6Q I"}A3 #sy₩rq@)PbN'/|ǐ$i&-;^' Z9;|s@.(%zJU?:k1$IZ+iG;rq@)PbJێ^{$I3ҬS܃ѯ/_ 4JRU>ȬsI;$I3Q0Shr9 = ZȭcHF=E0r\\DCՏ$c7̼֊/*rq@)PlvJŋG@fET;$I}rvs #q8a(UΚџ8˿gHԗf~j`$)~PJRkgџ8Ŧ'ؼׄ$yGYIų*rq@)PrE@.9 |א$)wGn~b`$u:7|PJR=zSgA~@T'V #u?*rq@)PzG@Ệ$I[j]@s@.(%zJUd IJE?런(Ej!|PJR国K*D@]!IR:7m\ (ODCiu^Iil$IӭvN]~R`dun?#|PJ(ԼSџ:G͋&|ߐ$iHk]ʓrq@)Pjeqx46U;$ISnkR1!)XoN,9 = Qџ;G͋>oH4Zc Mc 'R4*W}TXG!IҤ {@r@.(%zJRD@.B!Idk]F^Sw8a(LswO5}TԞN^wH푊MOF?0Z6~/PJ(սO5$_Տ@r@.(%zJTOG@R ;$IfL؆F^|!%~7PJ(U[wJE}־Cmպ⟣J {\PJ0FE@u۩~O$"? ֕we8a(ZG ~f!IҖ/O$vn9 = Q~PR_ =$I-xS*E^gy8a(\vNŦ'?}`t_{Ho<.i]ћw8a(b5K?}`4P!IRwmG?k_@s@.(%zJX?{46wC4u$I~@ʟrq@)PjҺs$itkO!ao ?R4u:fHx.)|$`vNn~ P<@\PJ0F_ԾC4z5/tls;rq@)PG3fRǼ;|$NMŋGM\PJ0F3E`uy!I^[Q?'R4ʵW=8C;$R[(ϥY; ODCik̰=IRS>pUlEKw-R4=0H*[OG?u6V|9|WPr@.(%zJ^0ӺT?IR-xS*jOEt64N}A8a(z M]DT:my{ _DCiԫ-"z"|$Ui~>t]\PJ0CȍѣPlz2OỈ$=nlGy;rq@)P֊/E HwI׾' ؁ɿ39 = %PQD)z~ү#~/Ok'~'zoPs@.(%zJ\E O6{M>"I:+)v{߷=R͵;2zH꣣0`ZA8a(is3zzT?};$ixj"&F#Ro.==@Ls^"Ij!?tP4rq@)PKun;=z$WHΝgG?Y$u(|w\PJ0RIH:~{I<ѯ0K439 = %@L] @k؜W&v[Sx.~̻wLDCI/nyX@{a{$ik>xMLA46k=B3rq@)Pk^ Nn"I.~)B3rq@)P˫z GSmIR|3?RQD?M5/=B3rq@)P+>t}hD wIRl~&碟$`jG=|\PJ0ZWshHO':5)xn}.8a(տ X/E4un=5sỄf6R۸.z<Mil;$ij^(y lDCI[} DŽ(~{dfEj )4DCI[70~4|O$!oNsF?9@ ׄJѬSc#0EkS$?}u=:Jj_sp^8a(i۵o86zD]ilỊ$)svJ;Ί~f _f<Rm8#P;H! AQ65|\PJ0fcP͋>HԼS Isw \PJ0:7/S W$Iۊ~ULB19 = %m+jOڑ?HW蟟`""C19 = %9LX5il{$iJ)~3d{Cq9 = %mG `u:/)|o$Mځ{MP-8a(i5P@Y{$i#uvAk(,RI4wT4_+<$i=uEAQ{:%~PXDCIsYFj,7|w$mٻL-@57}C9 = %MG:/E9un?3y'w\PJ04Rk,zdCxT;GwIRStBSKCw(4RY{~HћSmkwI.~>=rCΡJ&_܏E `t-7IWϏ~ Z9'|P|DCIoKzLg҉{:zjN'!(<R]wqPcI_}tfH1ѵ&r@.(%zJZe=6!վj^.#IosY#ANA49 = %MAoHۊj]O$U9J=8C{"R׽ H ?HR嚿g޷"z3hmJc^h r@.(%zJz^75DN#IUCGOw @gỈ'RW; Ij9_= ,|ۓJW P#e54տ{iD'~ (z'\PJ04~4z|U@UIE)~Sh| IDATDrq@)P4G*ZGP$iJ5/E K4X9 = %MΝgGJG|2|nΩ jh~8a(i5TIQ֥ q$i gsaDwDrq@)PRߜk_{h#ITmީ >hr@.(%zJ*WӢPA$isޓ{/Rr5~*}qu#IQ5/q w)JJ6{Tm%@Eu {M#I3WKG00Z++J׹QTXڂ7<4տ`[b΢8a(|S=Jm'ՎGYs#`ų,J24kTh8*xT?wI]SCS*Q w lDCIyj^=NP6?}$)W~zC7 nDCIyVj.?|,?_{*zCx_ca49 = %ejNxHsw IFJOi_T8a()_f% rĿIdk,7/z|C~⯆2JU?=#A{.Jc ߅$i{Mj^4 &SU<{į4J{wڑ? IzEJ`9(|\PJ0ַ%z#=?|huS궣G$0Ǽ+~\PJ0oME`Tu۩ygw"I{T@oFÑrq@)PR-rrHU^uȦ;#R5/dhHפQ?Ig엊G?bF8a()J]/h|$|?TjG=u$z{]GÓrq@)PRyvxج(Rw$Ikr M<R?//۰6Տyw$5Nym'zUVR=J]SrZj^]IV;s׹  }4\9 = %E#`w_j /Ij!]R=Ѽ;+RU?WG 6cR3IjCgSmw! UDCImdk^٬R󜏤0^ir@.(%zJo_3;Tlz"5I`8wSۢG0š߉4|9 = %oKEI[j5|S}/w=Qiځ{FJ_G SfGIǼ+ue` t<'|?p\PJ0~*zLYR_ ߥ$ \RQDX{3R7sU]7Swmh5c&q3YƩPcF#$2bљdFo@ -4 *ʾ4[ /MuC}ϻ󛺷as}{ϧO4UyS}{< n:6eKN%:nּߗ49*(%zJ}3zl!EԔTߙ49*(%zJ:a(-_ws;V9sH7DW}ߟ49*(%zJMŦ#SA>߱$twLo}:=2ߡ49*(%zJ/9)4픔3Y/ x)UgmF;TDCIWM}@ә-ik[pxJvTz,e_NUq@)P6|0#γɂ\4=SixŎ6VP= %n:z̨)!4eKwM )>Tscis@UPJ04-yz)tE{}]2z̞^+W}:=Lj뢟f1u8Υf8a(ikѣ` ifej[T}ޞz~!n~rfVQl{߿ԌP= %Ŕ?yg3|=yԚ}{Tz+2}00]8a()+z˟~}RugRT>G`uOLR[=gSSk&xۥ῕W-O3D?~aZsRw=j'_:u-%}MyoRimcP GĿQ9*(%zJsǣG@hkѧ=Mڦ:QYG v$ԨP= %6on*6==jxԿbſI/פqK>bO8a()K(4|=s)[w951'+w -P5]N8Uq@)PRl7`+4|;)uߒ'7g~FNћLׇשy9*(%zJoUѣ`(_R԰:G^_$koLȣiS#s@UPJ0_E?&/]ڇWGiR;;{7Nƿ9*(%zJ/[K*@#KG7lۣT:Gv]ϛ^-@cScs@UPJ0T=B>?~7f]޳P= %է^uix׷S1ިW֢SU_>py*uf{R`ފMkM)Rj͛>psRᾔ<_ -P= %իUˣb؟O:+?:1kSM~?hΉTs@UPJ0Tohoy׮NOMK{o|C;61'eKޖZǩw秏^GMŦǼ4\QߘYUq@)PRwQh`6۩p>tuqZ_{P]4g}.uO9ߦ!"e;e_-%e+9ߤO>z~!XkIûM7p?D X;WGJWOE&,a7&6xӿ]?ݚipa_bo߿\<y͟q?s[%l;wP= %հysSimx(e@5|ߪUq@)PR=_8z<YwP= %ճa&Ĝ]'TDCImG6w;VWJ[縏E(VL ߱jr@UPJ0T&K3D)ҿda~UcRztS;wP= %ջ4G*-23TDCIop7GiWwP= %տUhxEToJFToJFiW/)Ԛ.|Uq@)P҈թ|TzP= %~ץL8nLٞ?^*TDCIͨq4X8a(e 03-5|*\vTDCIi4Pڃ+8a(9xJE=&S߻+8a(Y :+z 2XsLSڒP= %5k@SEj[SڒP= %5CWG64TDCIͫs'G0aj@SP= %59)M߈uJ[Rf=0ʿ8a(-xu*6==4X}dSP= %5w=Q3l{8a(e{116mUq@)PR_FŠ}ה%TDCI.[S_JV4mUq@)PR||ꮟlLi[s@UPJ0bJE=_o.S*Rhx^+eKǔ8a(iUq@)Px6|ݒZۅ)*s@UPJ04us(s@UPJ04^=Y6ݤ49*(%zJ:'~"zS&Uq@)P71go}ap7 8a(i~Ϣ 0-oNRP= %yۥۣG!0W.GJ3R$uOL(fPy&e{)|)dJԚ77 =49*(%zJTo}:z3xZSRP= %iRTl,8a(I?{'G"P|ӿ{f#TDCIz9)TYUq@)P^Xݣ"P]7JR$x.@^j]49*(%zJҏ9#ѣ(=49*(%zJҋ5lb-~}QP= %j򡔊"zD[{gRDJR <#zD[!xUjM -J9*(%zJK>p|o(%TDCIҲEbccH)/+|g()TDCIښg}.zl+6>2 ;BN9*(%zJV5o?q{9Bf9*(%zJ9cѣswRs@UPJ0mixw'~ JuUq@)PLȣG(y_ JuUq@)PM߈06oM;8a(IZ_9̰"O>R$1 ׿]TP= %LץbQ ULKٞ? R$wXoYPҠ(%zJRMwFSh=)E#KC8Ĝ(Ieq ol{wH4'q@);EIWDThޅ'|'J٢]Y>%_ _ȟ/J[Q[zSPzrXVsQ*[O. RZ>%=m3=4je (OEI% G+bڔ4jǗq@)Ti _g0r:=i{K8a>%'Ix24uGq@)(|(JL4 #WK?ctN(I3Q{R,^ϓFctRPW,cxҨ7я2 Rz/ 4Se_MEZYכxҨ7Ǚq@)4uOQ 9; O8 (ep%CQf9)q 2ݝԄ&KiЍ~iox ~0J >C)yZ(&e?H0('ysÇ$tGFO\ IMsoQtdIDATG?4Jk(I3]䭩<=r wuRя5 G^p٨wG.)ZOltRZh0(s‡$J[.';:a $ѦaPZڃÇ$V~7zzRnNjbETM8WGI}3z)6>Vя7 Ԛ>$%i6_ʊ 3SIMsO8 J{w٬0WZя8 JxYmb?rm9:~'5F?4*ѻl!)I]_Ni؏PA7+;8͛'r@%\?(%)ˢG0TwwoRkǜr@549a)Iצb}S*3䭉97Gr@e>>,%)αG`D=ܤ7ǝr@e})|XJRT[OPZ? ߵIoTt~i(TfpSy{*G1lG٤qs俉~i0TJw U=`KׅؤqGs@G)IaMI/uAj4&n~i0Tw)IW| a/z_ |&KҟL({>qW,EIyswjҸ;E?4*SB[Sʟ;z*:Ϥl{i5|Gs@)Iu_@uOdMe?RG?4*7|*IuhfeH_"|&[3PH|e$e{9'2RkgҸ?r]p^CTP=G2<<_4ny6Y1|A*Iuip2L2i_,gL8`d>L%e=c1׿k2i,?ˬq]@=/2c,_wKj-|MLXffL~&M.2!I?lxѣ1T&SǤqmxc1֧Ç$եlO!z40f'inL_X%NuOlh`;8|'&s̸‡$թFf@ؚZS>LײߒR?̸$O4XћL ƹ% Gc3oO T @Mퟢw`XȞ!̊eK$լFgA/iߢGc"lLůTTL4Sk/i[S*6>=S5s?p%fuN @C֦lwDqwc&|2>t%n =u~]4-9GOƘfUT=ߐgY sIzU}1YgSkÇ$խʏTc4Wl7!z$00zTVDhFLؚZݖW5Fp;SkﷄaI] vJGiFDz"e+~%)-|=17>%/NA,Is~Ti);CXX/EOijwcI\ODx %u"zT0Ah.JeL*"R甿TW=Ao`?zCh-Z;Sg$ձ;G53jEIҏ4XsLh->qgj-z]P~Q @Z$=_;=`8&k0%uOdJE=@)[𝓤񑔆[=^W0ڊυ$=_|$ղ;'5jM+~$鹲ߒ=`8`$gSv/|Icپ?=}%w%I/hNiѣFFZ/I5sTѣпtq^I . 8-z4@))թpIa=B5+SkbNNI=4]gɉ?$n!_=x{Ο$=_)07L_q)I?^Rz2zL2t-%|$=2YG|(HR{)1 )6ܟ}?|=Ri`:ֻG4/PdO Izw=ry+@HR횘=o393л|I$լl7GhS$yۧ EO1h޵ɯ̉>R굢G4wD~֓(4J伹 T`,/]ls843?H$NWce3-Oʟ3z,p@# &~k$զysK3XwqjE5ש|ƹ_Hj(R$}/)z*a/ufRXsRexpm);?$)qX[#I HZixѓj {Ѽ49XU/EOcP{߅sl;MFO-H𒤠7=jw?qqHGԞx~w1Lf;WFOb]oOgLa 91|>?$i~s=jjEF;F?0RK)_slj-9Ir*0@m VZs6X41'uOTl/ч^I,xM$R>+~ɩ5o}4uÔ?zCc#lGR甿L_q)i<ѣ 𮳦 2fAސzV,Ie P%.i.P]7d$mcKES҆\ZvߵHR[R=RGx {S%}GܒMIlxE~_zޝԿ%"~tWj<:g]j-{W$bFO6ZT&l{R?J O~j*6~Tmjjݩ9oS\Z-%^=2K_c[t>é{ʟoA Un~48gளSũs);I([򶔯7zLbr]ǩR#Ꞽ=Sϥwo_< ;{Sw4D?,pMõkRRsgSI8@Ҭ-ٔO>= <%)IENDB`PNG  IHDR=2 pHYs{RkIDATxwChb#ߚT)}{_qj0i&ڻg\V[T܋D;koKX`4;{eoPלI|4gAX~?/~,Z2*[`\f3~.E &;w,TnSrHu8+8Tv-1azcvt-mz\h ) j(3v3t ے4ąϏ-4N+d>:ΐ_|9A'=w, So<3Snz nyd9^ Ng!=Jj>S(e9#޺2`@7LoNBk'AV xx%88׻£֝ s Rr.@g;- N v [pS[hqn4Q(vK-dKlx ^ў5`*9`nF@Bϋ!\ FMDbSY#j6QQhaO0qB*DlpS  BG$>JPY/Dewܽ$ -ڷ$bOoS~unc*#[8B|_#&)f** X3/3:Z6Jh\bcQ ڂ_pq}S 2u-:<7^%Έ[U,Q_VwWRB^*_נlD{B|vdis7nA]WCt$F4_tN4q'>P1ZS:ޠ49x<&>")|LyoJxVgد{d^ܦORd"8B- #B?+y9B qņS!/8G!7IgE  .8G!46.8G!td莲SE9yW7G$$Ѡ;F[jDBݱz\D^pPD@wW#!; jò/sy9BK Aw#{"٢.8G!4O]pPDR#?eEz\I]tAEz1{tWS/;ɋj{NuKhک;E5vF`u8A/4n{f B.G7&/#n*jh>K4Zh|0aΨߐG G6?D>A/4.ѝpk)`pB+Gx)H6#ڛ$=JzmY/G ;Awͳ#j;cۈ {fPh|choi A|ꄡ_35>y{S|8D{QZY9ynX;e!>Aݫ3+|0pt/03/yL/q#y2yޛNi6I%@geo펻 t6Jn2?+V D@gY/V%x Lh|jd V/Xϒ+u|-Ŀ)&qȄ^&JcLhLU2Jk%X5t&޿Ο51)R689@:nN/42P^sz9t~?;ЦL?;Ar9 !7ȅS>ݠ_V;Aw~?TChnG0 ?KZx> u ITh{$ ]Ib -^:/-?謐0;,;P [iPqݬ߁i9M=i ZCg-A@*ZB2 %wm*UBC6EM^h\aG5_:#$pB4Bܷ@/sAk7LӰ{^иؔ# vs|Ѯ#BUGu☖䷒}4L=Px[w`{,Lh-۷mh`,qܠӍ ]uXW"r]Z뇭¬aXǦ2Bӫ s[o+`[r>LT w=zm5Jp3N~H!q7X3HgOCZטmA2*4'0_F43-t6\2 $pe'TxM ȌK_o_ڠg4`TO >Mg9 ]TIQzK5dT!p~Bˣtfm ZK%CL|hf4,޿ ! ?N4B\'C;KQaգG툙,K5xF]⿁GF*'r<=ŏ%7+oAOR1xdaêU [GY@|N$7qFI~}4t'%+_>aF%z c'LHk@ۚ0)4/MF%ׄ1`dtD{7׼VЈ;irw\l泌;wڊ;NxFHI)MrJ!7QEl}/?B#e1"n㙨9'pfEr.xu$Etįޅ~uL_@L* 6XҸd4S3qI;-hfyTyMobiZ_Osi.@咔WξeH#ƍcoܳ6uzG*V}#>l-'u~W"1&{S91\q@!3FwNܕǿ> yzJ~d9TScg^oDi+Wo4g3uIjD+LϾ$n[wa'M@Q/Iƻr?YF۳nƴ٩w?%Mh޶'F&cM~@3{d.Ijg_I0Ͱ%MP^@ :{e/IkAip)i@3+\}Ho$i~u}?%ZmK3yIjbq]q5v;R猷eƑ&ΉoLuXҝg]/IMsRi]73 X074uN>4&^0W-g}/Im龩Q)Ugbwm*W:74mU캳)ZxW*W |IjrߐߘA5.@*fM!MjS~'s_`,Tz*=;}IjtE46k@3T sʛSۚrceT,yVՇCj@S SkF\gy2Rh%-';6JmӪڴ.9\𺧾%սm/ 0ֆ7 @R35UcMZ3 (E&= \yXIjMGhQڢMU='fŕ&< _gԚ<+ nDjF4Ugs_PIO3'r_`ugԦz~0a?5YcƻSy+%Mɇ5e&hg̒TD~7UThFOœ4:C;ͽtRo~V Im\Tm75Qmb/eI>μ>ܗo gԪVFܔQMcR1G/YT,?ro*W@TixץI3^ $:Ǿ"۾<76>CVx4hzka$VSܗyQ*,AZբ=3Rh*_IG$՛g,;nx)$#MM@SU{_BH<ⅩtwKk Ժf4ޥ is]Qשw/HR+ֳ'k3Rs*{N!ǥ+n Ժw^<MU?ᒞlitї`9$e˞F_7ϦbfAO4K`՛ץrՁ$o1zhJŒge$Kzo+o\O I-Rtc=^*_[=O{BX@3ϮM?lpaчGHR_|E(ɶߐo~.!Ikiv4osOz+;`uo[Զʣ^'i@3zT,/'OTn\զSԶ:O؎fIԄ:')'i辯ɞԶWl@ӻ௳$MαHu1~~f!Ik4 hw\?Y҄WToo.%ij9$~́zT|AO4OCS7A{0$hY>́sɑ&ji |,G,Y$M=ޯ6krVO4-+\< P=|[*W4$i=uּ&aMUnͤMv΋ShT˛1t{oO4/_4'` ><ن$mjɳhM̂ i}T׻}1&T]޹~!IEj5I&~?Q/vS~!IEqQ?xiTw߭ O<#_CY}pJ~@SRWҤV~R]~<RdgTOhzMZjހ o>#$-\Tu 4wb^?hi"[Ow.=vT DQE1Mwg`lfA~]za/uNzSIn~_NUg4G3RW.'8??/$-hgYRzg3'8,~6"IE+hF~+3{d Iɷ4=n\yXI*ZP3t~WNʣ_]wu$T4r Rtvߐ p$U8 Uݹ;OsnIc^D7hz$%MT+v `NUߚ?79s7Tݭ89?(ibY;DN$i fnGg`I\/̋~~"IEs3Д&oj.hQ$hjNU 4W@ s¿M_=#^ `^_E{e?WuN>tܘ%d o>𵹾Gw"Ilm6?>&ge?_vm)Oys/{|GSyįf?gauy4ՖS1 ƹ8j4_FaF^E{f?oau5Ge8YsH}@e3\$hX+@SZß~ ^5JO5ً$ so@Smן7E{=kv zRyHtsھ@ 4 =:^ ѝ4rڎ 43$Ʊ9q]~#IEφrtStV:CJ2 uNg2T4rՁ)Uhw9ƭr޼. !_~6#IE4K4-+]y[?|F7~h3ƩuF4Ng?C󣁦D*/ qwowh؝}g5Tds+y<ƥ_Ҡhobl$̂T~_,ƠrtO{6TdltW~Gfw/qxϽ#$MipՊhßIm9mZnIQ/~#IEzgjۃQVݳv>ˑ"Ήoفfx%Ϗx4} @s$n~)O4kxam{vvS?בɁ{{?( qbVf*lGF.Ɂuݛh$";0Fw_ρ$izZS׼I-̿HjfAJhz7=? y 2u{U I*橺ur79?f0RT5oJυ$^_Hm/ۘ2TTToJ7@fƻRdU4 4M@C XJ@` f~s+I*~Fitu0{ĴW4mֿY@C{o+I* 4ʣMJ"y.7e?ǒ@ifA2xnxϲ$M|FR@U|h,IFcQyRݒG;-Qm_d}%ijb3h,}?hy~%ijb3ШoBSysoI 4juKuh#qI 4ju[>g8m6ꃳsI 4jmOq=kuI 4jgKv0&y{3/Ii2Ш _g6c޼.K~%ijb2ШuuN>4jg6cϾ$MML{r` T~$I@Vտ|Q. =~ Dr)^QW%^A/x)rpQ%45*ӓL2i&&uȤ'0 LzBzO&I}>ezxI|k}qXff?$I$I4 n86 hM [Stg$I$I&a~& 0{4,I$I)hM)E& ;sY$I$ISTͿ Z͂k/|U*ڏGdI$I$MQE^15,hGDcI$I$Ma+ Z˂Z)E,$I$I46~ #ZɂE=t]$I$I7mE=& W$I$IJ#~+ hM jhT$I$I[^ٛߙbAC- n:1zJ$I$I߯wߙbACʨ$I$ITHߝaAC:5zJ$I$IO+?_π4),h9sV$I$Izfޙ5wh@k"XP=ސR=g%I$Igh@k"XPO$I$Is7wߥƳKO(ǫ$I$I o9%> h5 foF^=W%I$I{Հd4T$I$IڠF8n h5 ;"٣T$I$Iz'Qj, B/'zJ$I$IU);6H49*I$I$mt~ɂ0O$I$I ~/: h5 !G}(zvJ$I$I߷ƱzsLn$I$IҦiK=&r>zdJ$I$IՇ߻FR^GKI$I$i6ξo ZaAC=*%I$IRp\j *)sR$I$I*H>h5 \="%I$IR{84T՟KEGI$I$:K~jςJ <+z.J$I$I48U{43Q$I$IZfACfoF$I$IR*e7R]YPɟ$I$IRHݣ7~hՖ 噻U*;zJ$I$I!q 3t@# J(I$I$;t@,h(ǂmS'I$I$6z⎔2HucAC)sfE>I$I$&hՎ \{Wdܓ$I$IjQqЪ 6 g$I$ITӾ~ojłMۏgN$I$IUEhj/xiЪ 6eg$I$IT9hՆ L{74E9I$I$ ? 65G8I$I$9hՂ DgIi4o$I$IR+>/Z,h$+=$I$IF!>hS~{F$I$IZϊ5 ,hx=$I$IF{=ʂכ$I$IKܭV ^5E2I$I${@+ O4̣$I$IȊݓ[4lUKg$I$Iz':haxߞ$I$I^`'Lٜ-V,h(+]$I$ID;V,h`"A/znI$I$IћS6{{?U) 6X}g$I$I4Q{?U) 6H{Rʳy%I$I$MTGn[40kXаA͏U$I$ID=c@24ۦX$I$I&Ѫ)Y= `AzOb$I$I&JXа~nF'I$I$iE] `Az}Ϣg$I$I4u@U: 葛$I$I4 o9%NHeyu$I$I$MOE:~/JeA{IH$I$I5 RY𜺇z,$I$Iaڻ>~hƂ4Q$I$I$Me X:)9$I4ݍ<'JUצwfpݲԿԿpcO\;ñO#4%Iޝ:ϟG3)ߏ;// >4 o^>cTOF$i9sw~y=!* j_%ITRx1ipѩ)?%K9L`3sk7:kݒ?Ni_/u7F\5^.I$is`A3jTk$IR0]7z=7Sg߷N?2]g]^9ҙ͜UKsR$IҳWyp3,hxF3yI$=O|c;NK=Wzsfo~k[ⷧI g~E$Ij>6 mj4<ݜ-R#ITF4zvgs.`j)Ym~+a?$I7şBY0;ѣE$+wO__[D\텯N^RQDї$Izf7^0 Ɔ\=W$IUiU)?gvsөS~T<@IUO bAC|EI44 #9[1K;[5$VUY H/ ipAD$Mc(:M~&-nh?G$))e7 ?#fA3;<y"IѪ)?KBQ8NtE_'I4u6͔W=G$ITy0/'ulJ3+#L$7/?fA3foF=G$IҤo/G?e7?@:l\, o$I YeA3ź/zH l怙cj/|UyMKN_EI4%/; 6xB$IR{* <0uxw꠽kSE$IeVtWR],a=?$IR=t}--6|u啩$I*~ẐfJ)znHVS2k)wH=~>¬池$I[~,/X{!,MipӉ)E_iI4au~06,yO$I x򮔯!e_~I9szK jxgA,hâ$Ij@.Kc?D#W=|C_wI4 E_7@kYLN/KE6z\HVix7S~n1gT~H׿b ͔֗-9!I꺘.EW`Zw{m\4$iS{ ?bA3eF_=&$IR*F3;=|$Iӿ~Złft{g|$Iu Ǧξo ?`)?K證~ZHU)UY|"2'I*no Âf [$IPOG!)3%ixG$I I3oT~KlWş!4E~яBITa3?ḯg$IZբ$I^в4N~KX}oK}ث߉~DJ в( M)Ϣ$9rJjs3+h?$I%7zΔ<ndA39z".Ia?}1e7 ?3<ⷧ{D?5%IRIOݟ99w{mȂfr n<>.I"{4uj/.))I^`EwuyvꟿK^s> I1oTD?%I5zMg 4u/~Jm4bri-b}j͂fBt}8zHjpq)sj4ǩ$Iz5'|d&6̈́\sxL$Ib3w`2,6 :'*IReoI7EH/$T$iA7D`SRH$k \z'}jWET =7$ImUgR" V~-Q+Id1_8zH4>s@( =2+IR3+4zo}KR @bAt7KNj$ISγR{ş 0{4G$I S~WRJ_?ǁT'4 9DIwNNټm&D?%IME{c,hGW}?40K~Kޘ|s{6MÍ9z$I4}k n~*KT{cnK떭[+~HMzs$i*Fwg1o$I-Y{J]^?k4,hlfk/I*l4L?~/Iûϋ~JK3{ iaA`;Έc$MO~{ ^F]$4~O-z~͂lҠ=$Iy _=ZTypWc.~۞s !4 5sI$I*hM#;|4E{7ޒ)I[s?0=`AP}$Mo4HE觸$i3ҤiٛD$Ie7})OsIR 葛`ҔaW*|dMuxwx$i S? M]K%IڠƜ;7uxiY4P~y)IVRO{I;寣쒤Vdm+-c;3 MEg;R]$=_~=xu_OYvjiY4 $Iѣ7. ӦwHj/ IDATGnJKSb]1*M+>=%Io *?ѣ@7ƇR -Ido΁=|LՇDOIixéۏ?hY4ܭR$5H??H-𞋢'$M{cf쪃1?HĂ!7zK4|r0zڻvU; x.\4 ѿ`a̗$ o^5Y򞔆y7Gß^ =pU9@F7z^3OBTtw>ڋ N,h+S*FgI[]:{%|=2$4Կlqǩ[S6{g2Y4@F$IjnEz~<|8&zrHR& @`AK>;H. oJE!I$ {4 0ZumyBF6)E,`t}xԴyvꟿKuSZfASs?#IUdz*@&InWI:W m( I6He sL.(*x6% 1I6p^^oe$UYf~oW?hM$ I67lg8Fߋ-&"_\4OO⷇?hM I6~g` <0zH4zԿb;O-cfo5,hjg$Iڰ`6ije-kfՋMy$I$ ɔgFRsJJ[+Ÿ[= =xuFfg[g7-LđT7lBXՂmS <$5)Tbx˩cGRyԿwiҤ}$A_mY],k?J|o"6?sG M: ϙ}&$ z6.H *K;NsS*dASSO>'IT5|fcp!cH҆gOo߂`ʍ,hjhOHgo)e ƂmۢǑgj4HGnJKSbu_U6w̪ 裔$I(Rg{g6:"XRl'HIi_,hjwgV$պGk흢ǒ4U#ixR~]^d eASC뎊>oITۊޚ^]&lFOd1dASCœwG$Imi_ Kgw4G(ٍeAS3^}$$\[k1%5ɻcS~R_M=lXLE$ImݯNm=WtW wKݣ>ڻ&,,hjƧ$Izw;|NPo~i5MT7уW{o ̪? yvQNUs4׿h%ž7fzٛdN59 @lݿJV4Ԕ;wWs@X45>ITyj9 @sA*FLzAS&MN$I3\y`?4,hjd &I~A/w @wAI{cYXK$ժgwF27V-XŜ-R귣ύ$է~'m?hmEO4MQE4NéۏZeAS}$V/j|{1<k|UU{c63Â&z裥$Ii4L> =Ѻe̵GϥN-lFF7%IMN L9[ѪM~ȍ9Ҥ}E?%IM%|60Y: ~/ <+9u};T :3$IhxE41Fu_Uri-)M t}[U=^Tuɻ˘|d&!@,hjw>JTFS*F;Uޘ = _(+IR- 4Z2zV֌>wҧR{7a,hj`xǙg[I+GR6sY򞔊"zi}`db]Iϙ>_}z*x78Yɂ&X{Ͼ$oWeG{OEwu57Hʂ&XwÒ$7 ObSixy{R{3 /gdI|g2Shicp2聫RS?YOgAlpñfIBsQ<`zVMޘWZ?4!-IRh>>nOX7{`Ai) zgkI*GS6o TFXˊ|]z'}jW@6,h%@).f8 z,7#7ʥ)_CyQ?lBY$IqEjy 3ڻX*45z4蔯|+)M?lX^I3!MjE{ixޘ], 0F4q7}F$)I>?J_=17~Mc$I!5)[m,;ƽ7f4~?1&-SGyIB\}H,g1T׊5-#ޟ/ y(4A:}$)Βbx69^UeyM&cAwD%I iĝ޼<1{{)g@T4Af~]i0<>oߥF;I+|d*3JY\t9}Ij^gwaXޘۆo΂&՛/IR=|C ^WmH@,hJ$gk  ?glwKI>:=keAhn$IQ>`CwzY*G1VcYc$U聫g0l^{cHMDߑITy_ YMX_g$I3 [N#$Ҋ}7|d5bAC{2I*  "a?LJ3`V}XTOEߑITiEg0@V#4[d$U/@V34{2I*YXTnd$UZ{7_f,h*6{2I*kح ! \}W&IRe//|d5dASx]$I] ՐM;H=$I5g_jȂB}U&IRe2|d5eAS1+$>{P~$IޱYMYT2I*h ՔM7/+$FO>w5e$U#.@Vc4*>}_&IR%&|d5fASy[Te$URgw^YeASo+$2|d5fASa.$F\>wH?/$W>wH~W$I YYTdĒ$MC>woEߗIT~o)f$-@04%+G$I*5[a,hJy$Iֿhy 5Ml}g&IRgK,4%j;3IJw_\a,hJY;3IJw\a,hJY;3IJ{o\a,hJDߙITz1|d cAS 3$:{%|d cASEߙITz텯YXД(?s;3Iʭ(R6g 5M͏6$Ԋޚy 5M}o&IRkV[,hJ4{3IJmĝ k  ?:LR=|cȂD[N7$F_>o)s$I*wYYДý{3IJmxi k ~$Mj>o)Q{3IJmpQ k '$I*UK-@@4%JN$Iֿty 5MYfoRQDߛITjvǂ,󶎾3$?sf5MI;s)I}g&IRgcȂ$C-LORȂ$#;LW|>|d dASQ3$o}Ȃ$c>}g&IRY6MIzA$I 5MIz'|2LOrȂ$$L1|d dASs)IͿ3$ YYД$_;3IJg.@@4%Or$I׿`aȂ$Y}g&IR/\>s)I~W$I*{\,hJ3+L_oȂ$9$I*\,hJbA#I+\,hJ;'Lx|Ȃ$4ihx˩3 k XHg\,hJ;7LsQȂ$4ih3 k XH#7\,hJbA#I' YYД޼;3IJX`Ȃ$s$I*dȂ$_3$ 5MI9LJl>w)I~?FߗITI]^>w)I~$Io YXД$_2I*φ]a,hJ$IΒ]a,hJ2I*s k &LJs k e$UR>w)IOGߗITI_ YXДwEߗITI]a,hJ;$I{]a,hJ=e$UC.@04%.@}$I4 5MI7LJqfƂ$%GߗITIYXДs/$'YXДFߗITIE 5MI:5Ln>{)I{7EߕITY]_>{)I{vwe$UVg߷^A,hJG$I!>{)˼m$I^YaAS4FߗITIYĂDE2I*)?s k kVEߗITI ]A,h>~{}$I4 5M?U+$IM']A,hJ42I*ix.@ 4%qF}$I4z 5M99LJ*:O]A,hJ4X4Lj**|d aASD_ITY_>{)Qݣ$I>{)Q~2I* k gC]$I; k ~.L1|d aASI+$>{)Q}W&IRe ?:|d aAS}W&IRe :'|d aAS$I7^!,hJ]we$UV=>{)QgDߕIT](esM`ASn*$ڋ^>)Q{K$I΁>)Y$I YXДlɒ$MK>{)حwe$UV]g/@XД2I*kp k o[}W&IRe <;|d `ASuˢ$Iѣ7^,hJֿlq]$IUtW^,hJ?o~]$I^ Pw4%OB=$Ig/@Vs4%'d$UZ_,hJ]{2I*w_,hJ]}=$Icj΂do'$-ugASn'$99|d5gASy[GߓITi͂)Ϣ$IbC 9 O}W&IRuEm>ޝG[Zw!xhLǘ7IM &^\o51PL 2 (d12h1*Bo{?]Uk8g{PuVghf|5U$I3whf`r{2IfZ?_`430)=$I3mp[4 <*'$i[hf`tѾ=$I3m| ṔfgKzO&ILtn|4 N}[zO&ILn1>J9@צd$Ͷɰ.`P43;5$I3334 tL; PʁfVPUޓI4kߘ @3#U=$I3m} PʁfVܐޓI4Fhfdr=$I3mv֗ IDAT4͌;1'$iM6>JC9Əy$U K|r9K5$I334͌ N{{zG&I ( @3#_ޑI4')>J9H#/I$Iy?3=J9Hwgwd$ͼGg0@i YYL7 Xjd$ʹ/@i YbLVMz ( @3C[/J$Iyahfh|I$I3+34 .;$#$i Og|q9;2If}34 N{GzG&I3 PƁfǽ&#$iM*>J8Pwd$ͼjp|q;wd$E8s4͌գnzG&I}% Pāfֿ|##$i N ( @3cM$IyVg0@i_}lzG&I_ ( @3c/I$Iyۯ` 436J8t~LHOa4 q?#$iM&?hRnL$I}n]Vm%́&dry$I=+>JMʣ1I"?_s9Є YJ$I4<9 PhB'9$)s9Є|yz?&IRM0@ s $Ia@j;2I"uw,XqIsCz?&IR/a@4$I'%>JM1I"&>JM ޏIi|9 PhkߐޏIizu9 Phz~z?&IRɰ.;?:>JMPwϝ1IbN|jpz?&IRqa@ ~LH3%ā&l1I"td|%c$Eza|N$IT0@ q ~LX=wb@;wһ1Ib?Y Phº=1$)%=$IF%߾,$)ss84+ǧc$E3>JM %$)Vwg1@1nLX#_ehwӻ1Ib N{{|siӻ1Ib.9 >ʌ94Dս'$)ds̘MCLn$$)Rus̘MCxz?&IR'g1@!nLX#^ehbݘ$I-> 94DލIkt̐MCtw{b]WUz?&IR7όb2C4 R=xWz?&IR0@!zaz?&IRkvb2#4 2zLX,(3@ óޟލIkpg1@ݘ$IFeFhwwc$Ś_eFhdiz?&IR`i6h$I{ehfryݘ$I,(3@0/ލIkx;̀M |Oz7&IRg1@nLX[/b24 9ݘ$Ij<(+́iVm_ף^z?&IRc@@ӻI$Iī0_6$) e94]һ1IbD|@@OUz7&IRWg1@Ya4 ;ݘ$Iƃ<(+ȁV?zLX~3?VMCM7ܘލIk Y PVMCMn\z7&IRg1@YA4 5ݘ$I&_=%> ri)oM$I5ݰ>> ri/K$IUMyrz5&IRe84Xݘ$I6~gz@`K$I5,(+āFލIk_THbBhlލImbBh̟wc$E~~ߥb$E<(+ӻ1Ib ,(+߾<$)ڵY PVMÍ:&$)_bhnݘ$I<(́Ǿ2$)Z1@Yf4 ௥b$E<(́fT ݘ$IF,(́fLn($) ,390nLXU.>2rݘ$IѺ=+>2r^Lh_e9́OI$I62rwwc$_R|e@3'&7ލIkz7,#91dnL\մ<(āfN N}[z5&IR/cLhD#/I$I68y Pͼ >E6<XZ4sMݘ$I&]e8̑?ލI>XU1@Y4sd=һ1Ix^|e@3G')$)`,9;齘$IFe8̓][דQz7&IR7cm@3a$|'>2p3kצwc$E<(ȁf @z/&IRchLצb$E/y P͜^LhNchPս7$)t,(ȁfMn>?$)WU5;1@4shtA՘$I<(f Nykz/&IRW|m@3z^z/&IRG1@4hu=wc$ŚyU~,m=9$Muy P͜_sBz5&IRޡ/chb$Ey P͜^LhKchTw_M$I6<([ɁfU;ݘ$IuY}|@3&7ލIsl96C齘$Il968b$E}q<([fyaz/&IR7όch.0$)Vս'?͜}mz7&IR->rsދIe 9̹b$Ek|-@3Yz/&IR ch\wϧb$E;>rYN$Iy P|^Lh^e 8,/G$ 9>pYO_齘$I&_;->pY}=$)1@4 ޓލI1@L4 br齘$IǾ*>frY>ދImxl&18{1I<(ɁfA?{1IUe39,UnLh=KvIz/&IR1e38,eb$E<(f N}[z/&IRu'1@ 4 wH$IV}<(fغ ӻ1IrUU) hΫӫ1I<(͂_yTz/&IR1@hs3$)O1@hLȗb$E<(͂ĺݘ$Iyr|&G@ܐ^I1@y4 hgK_<(f ׽7$)<?齘$IѪnchPw͎^,IR P͂nXދI+< 5vmz/&IR9Ky P͂{_z/&IRNc0hTWb$E=>pYP5;uUwc$EL(fM7O$I?uy P_6$)y P{_z/&IR chXWb$Ew<]c]WUz7&IRόd3ht^Lh">pYpkצb$E}q<(?Áf ׽/$)d ?{1IU uY]|&@kvJ$Iг3nXދImy P~M ]ދImt{_z/&IR1@ 4-?{1IUjL(?@5;uUwc$E3MKL7O$I68oMKTz/&IRѥ1@!齘$I&]hZ?J$I6eg2@qiݞPIz5&IRaK42齘$I<(42^Lh+c@.ߙދImzy Phڥb$euw'g2ԁEVPAz5&IRs~&7ui_N$I6\<:д{1It|Lhep{1IUSv^Lxݽ@9дΏaI$I? m@B.N$I6:o<́FދImchZhpߤb$EzjL:@BދIs3贖Mڮb$E|g2PMKMn:'$)1i-]Wz/&IRɭ1i-|/{1Iu tZɁzz-&IRޡ/dJ4-V=xWz/&IRiocJ4-6s齘$I_:2>N+9дܝ{1IMJ|VriL$I6e'g2i񔺮jLhA|&qi齘$IцgC|qi5L$I6vm|qiN$IVwK|qi/K$I tZŁV?'^Lh_@&4;ދIm=贊 {1IMn:'>N8P>?{1IUjL:@Cob$83贆 p5?$)dn 6tnz/&IRc4l2`^Lh;c4l28/{1IM'uw'g2i6~k1I?G tZ=$)p贂 ?2)齘$Iן@hYދIy tZ'齘$Iw t ?Iu]M{1IOL: ρ2{1I.;>s᧌xz/&IR1Yx4L$I6,u t ?wb$L: ́czK$I68 ԋ́3ֿb$Ecy t ?gtA齘$IѦw_@g9s'9$)[5R|&@ZLx^@ga9VmWW{{1I LE@C_ދIm,,{1IU@ga9ǿ.$)^w߈dhxHݽމIop_g2YH4<[{1I.=(>Bra;1$)+,$p{{1IMFu t ?J$Ig2Y84<]_qz/&IR4>z8w]ދIm1Y84Bq}Qz'&IR*>Bq^LhKd^$4B[/L$I6y t b$e q t `k1IO t PwH$I7<= t z^LhOc0h,ދIz<: Á2<齘$I>3>BpaNLxodh,5;u5M$I6dL: 6{1IMoy t m|{1IuYL:sρ6<鵘$IzG,>saNLx3!>sa{1I;1?z9аE&]ދIz<:sρ-2^Lx}@g9аEo靘$IL:ś-г;1I.=(>\saU;齘$IѦw|9>\saMn|z/&IRL:sˁ-6>\raDz/&IRއL:sɁ2L$I78 t [w;1I⍯:&>\raغ{1IMf~&qa.=($)^5>qa N|Sz'&IRхg2Й;4lM$I7L:sǁjޓދIm<s dM$I;e t dx.靘$Ig'>\qa}Uz'&IRW?@g8аM{<*$)Z t la}z/&IRωd37hfމIop[3 wwb$_qx|&@6}?wb$ś}m|&@ö[C]O齘$I٪i]c~.\paY|~z'&IR`ӻs4 cvuս7$)^@t4,u靘$I_L:@òkz'&IROdx4,qI$IWWU2i4Mw_N$IjD;>N9аݔމIoٿdh4,5'wb$L:@òNLx}g2i4Uwb$5όeX4,;xމIop_2P7 nz;1I.?4>Nc9аFމIoz5 tˁe78-靘$Ii) tɁe;镘$IW2i$ߪ{oz'&IR{2P7 +b~]z'&IRɭg2i$V];1IuY\:@ÊJLF? tǁsNLxó@qhX1nJ$I7s tǁ3NLxU>>N8аbg;$ya|.Fqaxiz&IR#\:@YC]靘$Iן@$4Wwb$ūwj\:@Ê]vHz'&IR# tÁ58-}$Ihٿe4ށO$IjDk>@1hXY靘$Ioen VdNLFгs4 +ntޮ}$Ih@hXq^އIԈW@hXq=wJ$I7pc|.Fpa&ݔމIԈ>3>N 31>LF48s903ޝއIԈW@'΁>LF\:q4z?{TZUUFF4lh{c6l|o_}+-@CdFfTUuwg3<7c[?eӻ,-@C]ISޘiGhz7K@CLN?k$IjLfyoL?cV}wi b{#]$IRo{g3@xoL|75PZI]c?OROvZ]=pGW ]p!j|'I``7/1Mm<, Q3ޝ~HԘFQeoޘyk:픖p!wKӏI_feyoLXڪ*TZՏ0ȑ$1m&>Aw_Gq=<䫧2WVm:+-@C+I7g3C7fGMƴ񯽥@C貃Iʣh{ǫ1I_hFT}lޘ{?!],-@C\祟7$5ύg`tw{b?w㫏߹>\w'ſfK 8Аjޛ~HԘ|1IGQ5O/->a~]#IRc_wb|6Qe -K=w]pF~HԘ6Ҳj|gl?~oLnG-`ݽZ/-@C#?3GF;E oLU\Q @C#l's$I?nx{Ƚ7fGMMҺ>3gbi9 7;$575>o̦*u?H?op1|2ܑ$9 K]vyl|>ۮf|TN'44w;$5G >-1Zz>?gii9#^~HԨ6~Az>`GyoAhh;x~HԘ&^xoRߎy+-@CLo"$9Muw'3ƨya`ietg$I+.{H?w\.->epқI1z#Wt_jT$gui9(~HԨw^0Qe勵͗_ߏ--@CڮzIS5{>5?`tiݹ92q֙ gM?$IjTogh{c>[wxoyasq6 IW|$> ޘz|> {cw/->̟?$5[f{cluZ9PZK>o_$ύhX]Pȗ3U;+z 3C%Iҏ|yo+5?/ 4 Ik3l]N~K=zrEu=m~~p?g$Iܿog4l{c6u{VRZFg$Ikrg4lI?~onN,is ʹjߗ~IԨFhgG1'ZPw_?{ 5sHF5֥ @;>l #O?J 8XwK?$IjVI) 7{o^I /ǟOhh'^~IԸ'E|F()/vf*,$Q8<>#iyr9hh=H?$IjT}3sޘQ/9n㿸K?J 8h>~IԸz?7>h{cI*i*>>+-@C >g$Ikx;3ğzo̦*~\WZFH5ک ʾ7fGMHTvyLhhUW#IU5x7 Qe I>,-@CMn>?<$q? +uգw'PW勵js 7`#I5:ou|Fм7F\7ş%hhO?$Ij\o]<{cm~gR;8xݽ~&IԼSsmz?Mǘmxoz}G[v?$T(EEADQ}@PQ,3wL2iRI iB {d2{~#!d9/~?ٟ{YШ }.@t-IT%[ANs፧"{8 0qb߬!YШ 9<\\yP$IMx{c"0릗gfdAJƿGKP:ŪR65'|NK$Uy>1;/Ni؋+ȂFoGKPJ~3|NK$|Sn=;~}(]YCQ5<7o$I*Q-Uegm<}em焟YCQe14;/ ђ$Ia8~oğs*S&( K Ӓ$I{cfcȂF{䇢&(=%I&ޘ*묈v4g@֐,hTDMPJ>%IޘUF_kB֐,hT'>t'OԜ9-IFyo @{ی,hT}>@)|c$IZ W'Vcn3Q JwiIg7x5 ?Q<*U{߷FOPJӒ$Y_LUuxo @MrՂM}Ͱ?rY-Iޘ*;_7zg|1~mF4\}F@)u9-IQk7z|&|e ɂFDQPJ Ӓ$y,Z@ MYCQ3 Jx9-I]d9=w4Tz @ty5$ U|ǟ>ڻZ$I%iiKKGn*gfdAJ636|NK7}5:=|e ɂFlp΋$I|95$ Uީ>FÔ/{I$I+_m?IG8|WϾ!YШzS9=cZ$c6J_?UeMOE_/h|pn3Q5a*+*(5GjI_U=@id7YCQezvYTtp$ 6y5( Uy +( Ւ$5| ޘ*+V=>CeA9=Vg$IM|oWPIGns*[)gg$Iu{'RtG?k֠,hTF\}f@iZ:7qc55( Uw>z>|VKT?8#zX ||*]>>%Is=`W>_eAJ3 kO-$IumEP'Kw YQ+V}n@iuY-IR]+V==`/YQ\wt$M4Fzޙ_ YQs JNZڵp1c=3vnsQkZ{ ג$խ|Ex1>ceA7oTVE]PZ kIjV{ExΡ>ceAZ4 Jk=%I[~?zu5( բ.( ג$թ=`ڻjjQ?>zg~)|^KT'sx˗4|f ʂF(_F Jkx%Z:;k4Lټ gl֠,hTF^}@yoy-IR]+ƪYòQm|w3 J{$Iuipѣj 5kX4Mc. Rtj$. ofhyQ|jS0(A7_>%IC0V>_eAZU7Ry-IROfp5kX4U돍>W>%ICӟL:_,|f ˂Fw1("e7ْ$U|#njjU}@u|W̖$ʵqc=36kX4W7NGePjo?%IpC$zu5, ծDePjwljN̖$uOqc-36kX4] FePz+|fKTz΋0vN YòQgg^E3[6>ѣ._5, ծ|V) JmM3[6Q5׬YШ>Hk-IRe*V>_fAZ6|3 Jog$IUX`U|jY>F\>%I\7ֳgeAZ3 *k$IU/Eo5GجYШO}@r̖$Ju c׿x50 նGFkPzْ$UI=`z!|f ̂FwʿFkP ]~1|nKT.0vݣ?>cfA TB/mIw@t50 շ9>F\?%IH=`_>cfAZ7 ʯ(R+$IUX`n>cfAZ;DmP ?>%I*} 7o! sj]}@% 8|nKTڻ.zd؍6|f ͂FnF譊>Qʗo?%I*q=`솷>cfA73*wg$IehPG+ YCQ;/J5g$0vجYШuGgTCQ|WnI/3@NLS9ޙ_ݒ$"{8zTugl,hԈw}+J-IR˗n=`"vQ9 ݒ$~=`"ۄ٬YШu{_9;g*|vKT'|2zD)aQd˙x~o ݒ$-@+ YQcUyg$IejxInt36kp4jLKw>2, ݒ$ۢ3/ DجYШ1u`y1*>%I*CTƮns6kp4jLҭS*FgTF{oIPgEe_YQ=xmѿd-IR 9/l,hԨ=(/eSoI|w 7l,hԨGe9[w]=`"%[٬YШQ^Ŏ>%I mjN*+G2]~<~6>Dn>%I*5&bts,hԴ}@t-IRT#>=`">gȂFM{ԇ>'oIꟿ(zD/)|6VO{ a=n3\=`"z~6|6X3S-|~K4MIEhYF4jb}@,|~K4۵#&gmYШu*믄pIf=~`bE[ڦ7!} IDATQ˷4.Ilֿt QdY,hF}@+..Il5&XJDP9>%IoR=z`"?k,hغG4\_ $i6jc&vV- 5|y "e 6 $Mީ=v`b':|֪eAf=4?=%It_u9V- 5e{FP9[>%ItœE\|WZ,hG~(,)9.IҤji 3lކV- 5|)#*w9.IҤQ 3zYL4j|>r'W6Q 3YL4j|Kv>:q$i+01 ZfQ3*ips\q =V,h/Ji؏>z/{i,$iu [f4\J9.I8\_xʗl>o՚ɂF~KEׄqIY&X@U,h*כg$I㨽*L ZOeA#M`*\1;c&jݯ[ʂFQϋ>)[Y.I6c&wZOeA#9S#TVOrI 9ggA#~o>F|'|K>u~o8k3Wyd \u]G)Lְ7 4zT4ҏ5c*kp~\}@u5zyֳ?,hМI^%[sIֶ|_0q>szZ4ҏ5,y.I6=. j=- Ǜ g%TKsG(L\O\ ;&Jy.IҚ/{IJAkӲ~I}V@ 9<|Ku 7lfsWeA#DN>.چo33]5ixѓ&nz=szF4ҳ4z3* $=oHߎ0q뎎J?, O V%IZ]#?=2`VsWgdA#=K#2W3]5fE>wzF4ҳ/*0JyqL$9I*ڏGKίJ?,k.Iҳ9cfE]9WgdA#=GGPy $=[뎉0+w]>wz,hs;Na/ۿ,|K_R=%`VwUYV}ĽU'T^s]{?FG5S>>{z,h4*Nق$Is#̚~o j=k4jj{'$I˷Ii40;"K j=k4jjkG(+$IRXYS#|YHkjN*/Z.Ij|0k7>{z{W}@-L-zK]{7FCU _3 ysjovIRs_g(Y=#ŴFz/yW>%I m RY= `Vw} Vz,h5w )g$yuOdS6osfA#A>N6>%Ikte#fKZXH_k}@}/{i|$5o~0J VkYHkS]}@mΙѣf]؏`V o8)L(GSh.Ij@ w4R{_J˂FZz|&LZo]T'~*z+:Olj9jְ|WGP+|h$ջWF<uj==łFZF}@tOd|$շAu9fA#EKw>[VFݚyxIR=Q!G}8|YHkQ?>[v"|KW{7TcBL!zYHkS귣W$MF8QKԜYfA#e[Ί>cv}<|KSϦ4D71ѳX5ʂFZzg|1=vOHVѣ _>Z,hEPKc?>%I5h R?= Lc5ɂFZ'>gvFߘyyIR}ߣGwxE%IլwgGxr%Ilf>=@ΙJk 0~$^Tz}.z@ jq4:;?[_}zQʗl?4 ikkG.Vy"^>%IըwG=puLVk֣cFP[zIRE>=}c /3~.+M4z4}2|ǟr; J{߄e* i=.$KJEHRw٬ZeA#O 6KGP_{g$/!zR@)+ ju4z6jmx9^T_Ҡ=>Z,h{_a r5;Y΂FZۤTg0葛R6/I*G}ac{)|>YHchg0^υ|IR w}+z,@iU)QVZ,h1Կ`I9 WO}IRlc?=T~3|>NYHx=0qKw lwF#(޹gҺdA#y"$,S{~IRH3ZuʂFS>w\0/I_12|Z4G$8/IŦmD(}Wiu͂FS-gvb)_U$N!z@){VkW?D$KNEpRVY:gA#ޙ_>9F_4W=qۄj9 iw3et)a@4:#7PJojW4Ҙ=|c ;3_4o2 xvJ4m}6@>/I5=/Z45l;$i|u{̻PR3[ʂFwSbG44N؏$Iߢ-[ l͂F@}F@)gkpעG ^gZ4:?Fxr=@u@(J's[΂FD 6MEs{ԇ.S17| gZ4?!F*GRτ$IkSGT΋ZcɂFP?}V@c ?6. IZ'K蟷0|v5,h /: $kƔyX& kh^ڻ6> Iz/JGnP|3\dA#M_>F^ $IԜ4ѣ*exY3\i\YH,Ug64^EwI3띵mʙ3\eA#MуEl(uwI4}.{g'>o j- i/X}n@+Lҟ HZ)_Tz z4@)a,WklYHnz xmw^=7?˕ƙ4b7%)Eɟj5 i_g L Sw $uO)yXf(~XԤ:iJA=x]7W7 Iukj4Sjag$fEO|6IS>6'~*|5,hYssYbx T,>>bn]dA#f 6H|W9Ip>VF\>՚X4,7sx$NcjIJf};3IZ>R1>v:=|Ϋ5,hn Reg;\9wIH#>h}z@'R6YIJ\lF}2zSA^4FPKjM4 )>Q>՚h4R@ T[RT:Ͽi`"˷ jM4 )'GUʗl~w=ofL+gZςF {GOF$ e޹ZςF j7qӰ}khx7S`;$E;?fno jM< )M߈>0)QBfy `hc~f% )q>4XKIijN_S ҿx;ldA#/~qJvuG[H7I+>rq~=@i6\\T?}@Lwf% )Q>udI#w4z#jZ4Rt _ުXGI4:#G+4VԚ,h4XÛOK>uHJN UtV̼.N֬eA#w|MIsTG)4JTl:!mte3/[HҚp4H)uP@i6Jg0I/ [H3gPvm~?PkVJRD`Lwn~s|JdxÉf= ,(Cѳx;$x6J(qOP,hѳA7uHCwxEIAʗ4֬gA#E{f9bՃ'",~WP+$ LMmF`-OԜf5o?QJ(C"JV[D`B7$5|WD}/&ޠVH4Rjw0AK]*ֳ jeA#9xLkg^~T~. o93PO ˂F*a D`Š'lCR}TFoRt;ZaYH%_ltS{Hv_8 XKOGTF~7zFN)aCR|Sc Xc6.Vh4RI}ߣg0~3tDR5~㢏.`]/zaB,h6& ѣE{SgC$yiKE# XkW(EgA#M߈l RmS65'."\u4zS [TG$zVA?!^~TO80>1(:+R`;ZYHenf36LŪS?HijNTDG Z=C YH%ogEۧlIW{O{.> ZȂF*yaJ`t婽&&[{_C졔(ΡV)ԜT#zve0޹S6o;/{i_kJAILP=j& /\=;ڣn HCHMEwê~o(% M ۩n8N9x⮙o (% "^ Jh൩[*ְ R菤ѣ?>>Yֿhy]DLYHwgPVEWe/ HZb7D@_S'*Rza(ZŪRy}wl'XqG{Rٲ*ӣg P_.R[ET'HJ{'Je˂FPݣ?=K*}ٕ|0RʗlzgTD@Y)_U=EeA#UxHREw;\_4'\sx]ERfA#Ue{F;kۙaDg:ip!) ?@IuzwERfA#U޿=S ==oS6AFl 7O)*G(≻ܽ+  Fߐ}鹚:+ o810GH]~1>T,h /:A'z52H:Rw;iM?@E 0NV*ڣg PCŪf)_4-,upxJJA#Pq!~T,h9=3wl/X2΍{4Ѧ6Ha\yp*OF5QV| :Je΂FjSbŝѳpX/YۦcF54ZςFpFAF\}@ߞ9 JT񆷝=s=)_{ߵzSꟿ̦9sCjU" uXHiIIޟyߑԼڻ>ΝF4h~.nV%S~VjRAfO;.LsWקkSYM@e)_;Rjo6=өۯ߳4 u3ͧD_5\yp}KjYH5jp~ѳ`UǥiK~'lԜSNoF\6I)j;RղjT{ߊEWtWmۥyoI=0w{]Կd4|etUw2*fA#լѽߍIx4?QW_yIݬn;B'wʃS IDATj{ẐFY1z&C/j鯁sR{_Jټle._M3_O;?\mxOw^~SYHuk RY=k؛'|%W:_gM/w}=g>u44+~T,hֿtPYE4z44ԿpYOtxGj/&e 6 w-Sӫf>2x9wSC3g*G_ U,h6̂~;+MMû.I[NKkONSwֶ'SMiM Eg 80 ;& owufQ 4jU:  0zF@muX3@*TӺMZ*S`gjU: $Cѳ jJUςFqwѠ_OgA#ո|xi,ʃŸU,h77ßU,h93 jax9ԪM4RݛQ*V=:/yR]P6zMmOdA#5|NiЉaPYS>OZeA#5G0xmOZeA#5^ocPI ?SvYH jxѳ eOVTG3Շ?SYHMjކXqGLhzJûFjXoWLJqA5|ßש՘,h$ßөը,h$>og4L]~)9ZʂFL;/bpաj\4f|ϣ ̾H=|NeA#MI07lNYHz =`V}ks9ixbx9䔚;ks;Ÿǩ,h$=|Sy"z6D o93YgԿdŸéYHzF?Ұ=#`"7 NYHzW='`"yK7idA#jau2ޤ̂F|z)Fo?w2 I?06k &e?ʂFj o4L~5y( IsG'U?k˂FꛚF^=?`>=?kO4; D4y#7EQX{~w~u36iӳFuQ kßIٳdA#i͚Q=vk<57|W?[>3 Ik\OETXc?SȂFҚ7T#z*ڏ|ԤϞwʿFVx^3#Y& IkׂMS i[`c?K>w4ֺ_~,=O4־/HEPg=puʦ6&]}4֩YFZxAv&ekukͧ?7Y4ֹ9S3~^o f&eku._e*:+G/?/ȂFz?oaʤl-i?=hۅ?'̂Fz4T~4w4z}.z0㷥lƤl4owDds⟋Is- Ic{?Gdbx9äl=4mF= xC0igA#iuXx%9g4i3*Rd`˂F9 @MuO_R6,h$M=Ejjft3KƐ9:)ϽlLYHXϏCßwI4:-znPEoUʗoKƘ6 @699 Ig[R`\R6,h$M5GDq*sßoI4^Ҡ= %eʂFҬԿxy@ ۯ?ג eA#iVʗl@EΝLK&Yw:0z-,yM0 IMDwʬ(R,K;,h$jݣ>=(?ÒYȂFҬ79@ Rτ?YȂFҬf> ?{'ß]I,eA#)E{JdxE)Jf) I!w@ {ßYI,6z4fE~JgUR66MmԬe/MEgE [SpgUR6+hIFRwugTRP=<30#䩏,k>%͍讜9heK_̺~,.,|?Ҡ3ʖoЦ]D E?\JMR*Vӫ@[{Ji40 5KϤ,|˟yh{FHR|&o,JkƧ~&Z["$duOPR\kDsG@ۻ`㻀$jcGÌM'$jM' SI]_o1 (  ~-"Y~ =yw( ssι3s~b]%|˧wLZ*Z_Ū/$ZcTA7h=.Űu/H5?K?-~$UcRß6V3_$=W/}``j3iՋrǪ.*$~<>8U4٫yTQY{/H^Xk_ߊ3I՘5{Y?14^9QuET3;?g֌OA{uj {ašJFѩq;/I՘8_:'SI׻R,Rk?W1uy@?.$J=K@fҚsͱ/hXI!'XA{6IR5KWa[ s:ʟ%IkƷAK~x&I۫yK=W0[)~$Uc\}_r 4Co)%i{ G3x恨}S#Z U1h>|+ _+~v$Uc^?дyd(ITg?b :W]H&Cl/P^wﷲ3xojό5]}c]PIzǽ7I~EsgER55^F-B%\!QѾψjB\e3_$jw[7xK羊f25OP`@D OF}ۊ IՄ8g{=h~/CXK|~猄:뷋 I5: 4F~yjBk~ζ;Dաv>,]<Қɬh]oDZ6`P\G&+4C-$iq_uvݨ%+F^LGZ31o]sߔ$-q?ml0zHkFu\uM{Qߘ$-&o}Q8R5a?mֱߘ$-ξbOVߝg8Қɮo^M޽8FtxBnizw^LB_ڗ|r7Hiֽg6R55OwQ~hTE5CnӦmKTw-f#zw_PSJbkl|wD%ԏE}ۋH<7}-.h77Òڛ_ ` .گ'I#ݼH%3xf[GdiZݙeh׉I%i {/m`dF4Nܧ4mu<4^lmQ?HIg?87: Z_Xij}]_= v̮۹*I޼r*}L3ijl;ٴxY'P%ifVG[%toyE3i~G fJ}j]WF>u[&v>?ZDCX/e~?g~,I@ ǷFag$Tu.ѻ"t@3mGUÖjiM G]FjkwŮU oX.I#Խ['ҵhg"TvznK;u?PԟJ%ܘ}V~/_!45Ctsz;?qOTGAYwƠT[('Agn89Af֨? IZd3~3b0(u\u?Z-Ƹ(6 =\"Is%o jfuijZkwas_wVW$-;EJJ)һksg=iݢ7D}{$iG%åoariZmq4Pz4M{aIbj~#ҷR`=sHRy ? 4sZU4NH$-,}&Ԡ~4U|Cj ZO8fߋEQ'I3JEIӮqkHR{m77a?|IWv=,}Dc˟WHD"t7u}冘]S_IzCǷsuo:-UH_=d4wmǾ/$Z3o@!8/;?&?n|`d9vn}̮$J5TK`azs_^lBfv9#1&yߦi|H+Yv $|m3 ij3ͦf3Dg:y$i{uZn $oo(~!MRcJ`紪h]6ZI^?{.},!MHo'FڱRL@SߏٿkV咤Vo#o-}篏xki\iE 3+byN[y0HoۊjE 4/j=CyҾ+` 7QA皟`to9;ߋnE 4m9A̮}M_FIjA[#0wG}O?gƲwyn(}9JZͬM 4x򞨏z{iL~_OF<Ǟn.޽/ֺwo<3sו,'f{:rN4]%n)}^|Vnv)UE'f>ƚ3?K#_looW3);E_A{e8 4 mGwѺQqŠd;;HY}OEG+UKo*hFlB4_?5_<ɿm<}4>3 %]pgf0}77݋s8gHjPS?b>5FJߗ~#I/N?݋M÷M)WdU)+Y∟yuzTu7D{ٻx$IN{& L^/ޥ } Hz|:OVuEN$=EYN{.`2*YM)"tSs> 0bjn>w(~'"~ wAt(/f;#OSF7H7DO`E u e0w^1n-yYI3ܼgSO|'$I=s`70 X` W}^@91 ث6֒4~bxߵٯ`;(;(= YXG Z01Dq$I3SwQdbm` 7NC^W(\}LUQ!I 9/|,DpoޝbT[>/򁛲O U>|[2H4;ҿ u<h?t_QN10ʇnbIf^7煢~?Ā`^/ZGK[RmգwdEEFYlG҅Qv6dv`ɿһ|IzAKZRJCՆ?\s}L?$rs Y X CwO4,)g~"eHA%ISqog`lL굢ܝ_S{|`<;'IRR975`f (Z6)Qu>+vL*=wOϾ%]Fb;jЋ5SRR+j؋~%IJ5Ng;`veKߞrԸ: >=wQڟ{~+3`Կh-|n QRC+N1@ h;)IRr_˳_K0 X` 9w_Y[Ġ}TPj=Q#wSD1d`$6>xkdOR#7 d*^,J_蟏rٯ&9,b>?'uN_^pD{dI3k_M0R X^OWNR#k+L~q~g%Ij@k?ja[oG$5赲O+dry~w%IjF>1[fOl=#ߓBG'ަ \_$=^OS3`'1\h/2Iͭ}Eݘ}\`Jǒ$51e4 Fk/0Iͭ};>~%IjNg庻_OH,}$5a?Upq(okI~C~CA\濰$5!?զ+FM='$I jbxMo(h7俨$5oj UE7sIS1\s}+ À׿zYvJAIjnՆ{+F\ȪY}%IjNŢ=bW4 ʜV#Q;`L\I$5b  0_^Ŋ%/[+sY{IpW2`a"o>?HzڵsycϦ߁I庻_Qƀ3+њk HR[ 1߅IUqܸ&) X(;/ւ_<gK+&A9Ή=NLԨegC[ jg>h71 IoG{ߍIU_RP+&Bz(ސv'eWLj(;2IRWʀoGqϥ`$591zYi+~;E/ȿ+$57>0?MHjv}Z@ or~_&IjPsw-f,%_*] 7;3IR*=ޚYgڼDlMBzMQO;Swgf["zW*Rh-3E"u[f *s$Iͪsf`V0~zEKߞ:Ǿ?b>)Uݍ>'$IͪWN?JqHjn#9t÷Ewj5:€ҿ> Qmz 6\uQ~&IjN^X1d(YOaHjfžjݝGl7>~&IjVݳ:3΀0G/ IͬX(!=$I jjN n9'3ʀнx*%!--w}-3Gs&IjLŒF7FயGk/I l.1c fDz0~4MԘ:'N f ߉O1HjO]|)3|(>/MԘb f #{ѿ$5K(Õˣ5S$"0F5Y/IͫG̪WISOf`0aޝ"Լ:'|0dR0*Q}$!MûvbH}>"z>rf>##_F #@= Yz}TGԪڸ&^~?'IjF~5v3`atfU(-x}Fks$IK^eg}  #eKN9QsU79uKk  }{|I j.1 w?I[[~-63`ado<)Ԩ+fMU=N_?~+63`a4 z:GzIͩwTSG>]4S )Ā_qx!/1uO?+`|Z>w~.M[dB#\R^Ł`Qc|pe ~(Iao~ 8oԜ\RN^GGM'Jr<%H?%%5S o9';o%I]W<%eЍ/I?%٧La?:G7NPT/G'eBo:%ЖS?>`TbT&'eI(c9TKͿk w$:j Q>ʗdi+xmTGLSs~K֒jX(!V 4Q<8O`BcysA-ƦS`eQ{CIR-uW< 0\2To.>z3?+}w(I;GZ`B#t/CZRmuOHDUe=]z|8MzjΈ~;L9ٯsoduYR=K^{` F%YnQu7fvq,]0p4%w\}[ax%њs$iVz^+gBI?%~>nmл%I[Oenq,*G!`4uV GP%ikSox 7~(KKog7v=%IԜ6=i,gYeQmX};`3%IS_50̀i=cwY/_30̀4oI?%^g3LO;Jfgߒi,X=ϲ`?Jf;G۔tha,ik/وA7fAM$|û~ŀ yߔ~Kي{F-U/|(.R4~` XQԜX 6w0xfYU<~ʿ$XS ,<;4(hj2\uPUƨA~ 9K?%\>QG P~7)Ivٯ& )_CXҌT &̠Ͼ%R43ߐfa8`I3gGyߵG \s}=+R n>5„3`~M?A}K}/I$xfRp,nx釯 Ub$io& 8"c->N^]J~0 X]˟J?|%m=zhuO$m/~0 X] ~JΦpch))I? X]q^IWOg!@UCQLIWdBZH?x%m{eᆫ.5;MIҶ7ٯ& *]I^Q+FD~)I7 aP}ץ91\<FɠC2~SMqH fB+N?t%m[ )FPy5њ;NI׻__L0j1釮]~e 9%I[_K~u0 XU}]I[WQ+FYUF_H$m]3?`PWCWV45'+g=)Izں|$3`V3?~JzzSq5G{J~e0 XU\D 0f:'|0S:G/u3`Vޗ~JzE{DCX{PIS^̀ZK:Е n<)A%IO]f*`,Ԫ8J?t%=y}D{߇Jҷe&`,Ԫ8M釮'>Q6e6=E%IO̟" jCW5(\}<dpÉw'>_L0j釮d $yɀZ(Е_u@DUe ZF};_L0j釮*}eTC07~W*IG33`V,RC)_}$Dο3$MgB&je"5E}L6=M%I,2`V,R~e ;.TdB.je"%Q> :z$Mx,d2`V,Rnk>T(z~=$Mr,d2`V,R^?QUSw4ɀZH9K^զ-w4ɀZH9 o9'*CߍւU%i3`! 2`{_g?ۤw4ɀZH>Q6e?ۦDw߱JҤeB&je"]\".9Z%i2`! 2`G`w4IɀZH>g"G`(|]$MJ,d2`V,R -|n|/q[ɿw ɀL,ʀE+f?3so߽J$dB&je"ncQUُ:6b I X4{{sY!4ɀZHcqS^XI XdB X٩sod?[њs$k,d2`V,W,# oZ{YI XdB XopIُ6@m({uݬ$c,d2`V,‡k YI XdB XQmz H9JҸeB&je"\oHJ8eB&je"L(qH4NɀZH3Zkg| Kߞ~o+I X n>-Qhޫ5w[I XdB Xsof?;J8dB&je"mŢDq({U=$z,d2`V,7G7~+I X}u~sܯJ(gB&je"mG գg?W>|[+I# XWNוQ̀L,ʀEڶG'*]/84ɀZHЂݦm3;^I XdB XY94jɀZH[WF ُ,*~'Z~+I X%~\F^;WF(2P+]G`,TݍQ{_I XdB X-W^+QNHQɀL,ʀEBSsbx%ُ)x;`I XdB X{_d?c\s]~,IMπL,ʀEz}^UG`luX]$5=2P+鯩g IDAT|Z 0֪(~,IM΀L,ʀEzboُ&D;aIjr,d2`V,V{T~4&ðC~ђ4ɀZh_ ` nB}$v,d2`V,_og?Z̶gߒ~/-I Xƭg?Vdry$f,d2`V,ڇuzqhiI XdB X4N W]HP᪋%i2`! 2`Ѹ9׳'t}=$F,d2`V,vruُI+55'Zf82P+C3?(s%i3`! 2`ȷ`ߓ(|_ǸL,ʀE^~h~o-I3 XFbKn~hۢ5wkI XdB X4W,~hY~-I3 XF!o!Zw~-I3 XFwP/}2[f"2P+싺j=^Oϖ̀L,ʀEpՅُ ׻%iG3`! 2`Ѩ9F@Y=%iG2`! 2`Ѩ5{mIڑ XdB X4JuNGQkE%i{3`! 2`45'5g?2qKvfB&jeQ{d?.A'_~-Iۓ XFDwF%i;2`! 2`(=cُ l؏ץwKҶfB&je7YQ=zG+,F12P+50 ̀L,ʀEMX6=0& QˀL,ʀEMwƉ_a4bɀZ-|nTُcfp;pI XdB Xz_q~4\&2P+5ώj}ُcjpwᒴɀZT8+,F$2P+5W6ܛh0+ϿɀL,ʀEMw' &I-eB&jeF5ר6~,Ϳ-dB&je&;o &ɠžHʀL,ʀEi3ZwW#_o$=E,d2`V,jJݳ:q`ZQ{rIz XdB XԘ__y տtA]$=I,d2`V,jB3?(0Q{}$p,d2`V,Joj(\(0zs$P,d2`V,ʮ{f?Up ~o.Iߟ X+*1i>\?2P+e9x\qM?;\32P+e6Wݳ:\32P+e>U#ZswIGɀZ(ͧfIuO{tIڜ X2*r'UcߧK X2\,[9dB&je+yYD-;uI2`! 2`Q/_>=&;2P+YQug` W~.i3`! 2`QTG^UEПL_4ɀZգwdن6+(+ওcp͑]Ew?)r{}s6ٿ;7[ϋFy߷%E&߱K XdB XTWݓ~'Q=z{ !ˢ7ߑ;hSQh-|n-6w($ڇx|wtNWѻdoFވ<̜a%Md,d2`V,]_*Q3w\돟>(eӚh|Kbxףj=sW=[DfB&je:b`d(\o+őezњڣZhh/?{Կl|ˇn(?Omb ӿKK{62P+?EՆ1X>1=R)xmo+ j?i 9;ˀL,ʀE]߫>(4AY7-Wsgt_ެ_ݓ?˗<6jn(0kGߏ%MV,d2`V,1`BUwΌ~#$fٷLIuEw?nL>,i2`! 2`Ѭ9QgգwSw?{(jX{_qxޒ`LkOJ52P+fkHq"w^+>>/OU1ب6ޗ`lﻒ&'2P+ZSsẄjpbhh%Fao/?49ɀZh7#ZO >m5~ ݓwsV0 n+i3`! 2`l5oFD+g~`E7w|CZwWtrwYI Xf!2 @S1\uQ.cԜ>ѻd^~RhrŁ?UgB&je٨?4L;jUzڦDFCj~hͿUgB&jeon<^ wA_QҎ>Ot.mbW%u,d2`V,gy$̃N)bӿJA=\"z_Q%w,d2`V,{XPj|"Tgo/ET;74ɀZh&k/{WG:G+G7ZS;C򁛲Ot裸72P+dH0KVmUl4g?dxǥC%o,d2`V,_1dAUgG F+6V]<5=`32P+T >q`&(gi>7{4{TN ,|22P+HS;Egv@zEDK^RǦvIWg?̆~{ӿwJ XdB X4uN`GAoKN)MR[>a 9ˀL,ʀE3?lE?g&ʳ"2d`TVO +2P+h(eFZ+oL)k\ ` tO+2P+hKf؂kZ[wGI[ͧMRix+%W,d2`V,ڡDȪ1?l؛?%mseS_*2;ɀL,ʀE;RTLB^ӿ+J:'fܜ}7]RdB&jeipa6oޗ>IN=#Q=z{QU%%E,d2`V,ފ_1f&?197cCI]w*>z K4ɀZh{|q @-Dw'TŢ=C"aiTњF?2P+moog|&˰o^]PR~ofLlA?K(i3`! 2`>?c؋G7԰D?{hru%|,d2`V,ڞ60\({u?IͮXBV:G/΀L,ʀEZyQ6etנ+b4z٧gpi%v,d2`V,ֺg},c 0A ut&;nj.˨:O56+9OeB&jemmx[R1hzƧbW_>?4ɀZh[j􆈪E{ҿIߺ_~ YU<74ɀZh[_:?# 0~1ɨ1\<h3,{̀L,ʀE[Ԝ(Yiњs;IWD~$(HûL>(i43`! 2`9}W/yӿI @BVdB&jemp+詪\(}e9IgyTݍ٧$DX=PeB&jej޳*ru>=$)*(*~SҶfB&je{?#j?/}2ZswN'IO]wɼ>>&Bw_{ow]~EG촣cuqZ5iNm;Ctb{ZO۝!C4\B0*B (ɺZ<ЇVAw|=%,̀EY3`n4n8 +aOXImpw02 XfRkT$Ȇw_:~6^ sߐGV$iEfX:ye$I*Ru|ujvcY$ill("3`Q Xx,/<%IBkSwe%~9G$Ix4I(2èR?xG$I kxU~ cYtXp^jIE3`Qd,ʚ ?LOS$)zө5uPMPRܒ$I#]7Skj^mˀE(k,0N~$Ik+uV6%8k$Izu("3`Q XSR)IU}3o19}orImpE7P.EfcII=zA 0w޵5Ǻ$Ih6R{ o:L,̀EY3`_o:-YJ$euk,?*w]]$i$>{("3`Q X>SoG?KI,_Z|D0n7]c^$ijkчs@q Xf')I4;]cmj^OGė$I~+c X5W+~$IsVm2 jR?%IiM,$7[_Izk CU,̀EY3`a}c3$IzR5{K2iR]+$iĿ hp%ZwlꮜZqEfLT$I~7;{ }ʋSI4"cᶵZ??~%EfLe%I[_M~Kp`jf3$4≩{~`"3`Q X&+$I~5.?3`nH4ՃTښ[VeHGA @4EfLOOߎ~$IO_ZtX|?Iᫀ\uǦ:("3`Q X&WS$Iz nxj-<$ JMItj7өz,̀EY3`\|$I$=ןFLΊצT?$I~]_H KSc`e IDAT(2èer5$I~di01aq$Iz][`˪ٯj3`Qd,ʚd OO$Gpr@ޚRD,IIMUV&~+;EfL~z$I[K(Gu?$IixUZ? &"3`Q X&p'I7~/PuFDI45nߴ,:ˏ `EfL~/$IR ?;Lhj^lYQ%IWRkWZxpg=?"3`Q X&O?~v$I? A>4 ,IFfώ4ܶ6UW]ꮜZL 3`Qd,ʚtA$If ODgz]$Yڕ]RwoFnEfLg'I} ]Z /LwDI[Jû?zڧ83πE(k,eCJ$kSkwsS}8L<ՃT߷% 6HO9`1g X5''I/sj =RVi$=;pTNߔZ "3`Q X&K}$Ilߜ7%I4ܾ17,M RPEfL?ݜa$IJSGeo$=־uoIS_9 @ Xf29zM$)~'uV&6`,I oݣo"&CgRt?$I԰קeY~TjM `2(2èe2Tk"I nWh O?IҨVS4ԻsƫRk!mL.EfL?$I҄Vg[j Wψ$@͞jZ0^,̀EY3` >VI5g0`2M7DJ =7*N/E(k,㯻r~3$IX=H~ 0K lOiyE9&uZS?`(2èe(I / =S4}cKiI1{·_6$i\kH[.IպcSwZc X54>%Izͩ{'$cVH͞뗥H#OxvX3`Qd,ʚZtXJ^Ӓ$IAg:92O[IگjfoZzkU@<Efg$IcZuTsi4ȕ^=HieW͎˧ -EfE?+I4mI:0׺)5MGIiRip*+^Z g X53ܶ6YIqSgkȥџ&pqUO}e0`Qd,ʚ˘w$I_P9-:<;o454ܾ17-K5Ǥf^>H,̀EY3`/^$IҘ'{FuŔUGQz4زj+?a X5F?)I4fu/oR]ŒFfώٯ}cG,F"3`Q Xs$I\~@=E$K*+ o"UJ%ύEf;ۢ$IVj>S,)w1;%.>?` X5>y)5M$IcW&D7Phz][`˪T;vWM?-g0 Xf2>Ns$IcR15/ yeG9ٳ# M=M;"3`Q XG$IƤm4S^⫄1NgYZw>?_"3`Q Xp$IƠ(UuŻ?%OuoMS_s`(2èeL,<8$IҨWSg6Pk?%awmM-R]9?s)2`Qd,ʚx|OI$A+(ophّ֦j:?"3`Q XC?~J$iěq_~(>7DU@,}a\ Xf2WF?%I4F꫄oƳa?;OMRo1Ԛ=@Ef$Iᚽqi`tN{yJnǸ4T9 n87.gZxH%1`Qd,ʚX?"Id>qijޞ\Ͻ7uU#j'E(k,uH$p͞FCR}MR5Gfjk.::,2`Qd,ʚֽ'IZ YRSGK ޵5 6H5ǤRkj^ߟE(k,opH$h{Rka ΊX)ԩukT}F"3`Q XF$I WJٳ# M] <7 Efۣ$Ijojw CS|MPMwwqU_$u/|sjp(2èet{$Iڟ_P㮻r~JMqz4ز*.{G,?* EfE?I4j c` n _^S;f*N~9ˀE(k,/$IfEZ ٯvh͞pTN |# Xf2WF?I4b6_T{pߴ,變 xǀE(k,#IF Lzg޵uW;6u|ujM> ,̀EY3`Q IiЍ~>$i~o@}(s͞ip%ce X59$IN00[/>4G5{KmkS~:uW/H/,̀EY3`MK8HZ&Y?RՊ> ki}coZzkIG-Ɵ"3`Q XFS$Iޞ>Y L> ? q}ğOǀE(k,ixUOG$H3%vMj-:,}47 RYZtxg#IF]}z@3{;pT]L% X Xf2z' Hixo :DVnߘޚcRgQ55/e X5=ף$Iz5v_WgxVRkklY5U@ݕSkiSa X5S]g#IFf jpyѧXٱ變OoJGo "3`Q XFk3Hw õ05GυN;7VY Oz~"3`Q XFpg#IJS-c苡ܪ?_wJ]&"3`Q XFOy0HyuG Tښ[VjݱrAa X5>EOF$@K~?Z?JVgGn[變Sj->"("3`Q XF?ؑ$Izn"FԼ44wp߰4uW/H^F"3`Q XFK=OF$`x:+_Ƣ~{XSSⷦ?Ɓ"3`Q XF`'#I s֯,4RTښ[Vjݱr~j-:,##Ef=_~2$n WY)ՃTj͞immO* &"3`Q XFK}8H>{xrfwϤN^&"3`Q XFG䟈~.$&O}i<9_R{?;ixu%:3`Qd,ʚE$\}{xj?0ջUZwlꮜZ <>Ef~.$fET<5㟙;mّ֦jt^K,̀EY3`N~.$Ԛzਜ਼){$ oLMRS{=ÀE(k,cxۧ$I*W*2}h|}Y~TjM,̀EY3`w\$IR>[8pz|7ݙ[Vf|@>,̀EY3`ӇT$I*z'x8SR_Me X5YsOE$ 07 Xf2NS$I6uѷ 07 Xf2Ͻ7HBk[,̀EY3` +$I*`(2èe4 6HaqEffOE$XW)1`Qd,ʚK=#HkVjM Uc X5uNE3$I6ؼ2N"3`Q X׽D$X`n(2è|g:HҪw 0 XfRӢ$I*[_ Qg X5 o"H_{B=Efuk3$I=o`(2èpSR귣$I*ZS9g X5D$IRa ota X5uV.Hª>ÀE(k,e]'"I 57 "3`Q XV]=D$IRI;5ÀE(k,ep^$I5ǀE(k,e'"I ǀE(k,ef$I~(2è`SRw$I*I%ύQl XfRIϏ~$7'@^,̀EY3`)W_~$W'@^,̀EY3`)W7G?ITP~y(2è\~$:g:>2`Qd,ʚKF?ITJ*~y(2è\0yHB163`Qd,ʚK7D?ITHM XfRợ$I*j_&@~,̀EY3`)A) !I s/'@v,̀EY3`)S{OC$R=HOO XfRΙ~$]&@ EfzAӐ$I4zim0`Qd,ʚKzYӐ$IԿa X52UWOE? ITHK06b(2èL4$IR!u>a X52 nDӐ$I%ԩ ÀE(k,e!I ~c X5254$IR o".(2èLߎ~$?~q XfRϊ~$zc X5tN{y$I= ǀE(k,U$I3Oyqm1`Qd,ʚKyz5YHc X5T,$IR5~ XfR5E? IT@;ׇ%@,Ef3$I*%@,Efgg!I  "3`Q X3g!I w "3`Q XS%YH|]]2`Qd,ʚKy=E? IT@e X5LKi؏~$)N&@(Ef9OB$Pwg]3`Qd,ʚKY:~Y$ITS]3`Qd,ʚKY:+^$$IR g X5t/'!I hpw πE(k,e}O$I*O Kx,̀EY3`)KF? IT@պ%@<EfOB$Pⷄ%@<Efӣ$I*9~- IDAT XfRM$I*β Kx,̀EY3`)p'!I 9w πE(k,en$$IRtMZ Kx,̀EY3`)K'!Ik$@ XfRfOB$.` X5rxbs$I9w PEfA$PgQw PEfcpyA$P%@ XfR-D?IT@/ K2(2è?$IRf]E(k,n$IR~e0`Qd,ʚK9n~$)a~0`Qd,ʚK9n~$);&a X5r4o~$)f("3`Q X1/$Id~0`Qd,ʚK9f2@$Mv{o,̀EY3`)G$I y("3`Q X 15/~$);,̀EY3`)Ģã$I*,̀EY3`)CgG?IT@w~0`Qd,ʚKK~ $ꝷ%@9 XfR)/~ $o Kr(2è e?$IR;nKr(2è 2)H("3`Q X9W$I*/%@9 XfRٯ~ $|).a X52t$I* {(2è ݏfS$IT+w PEf$I*ۛ,̀EY3`)C7G?IT@}7%@9 XfRsS$ITw PEfw[$I*z("3`Q XлmOA$Pmw PEf?~ $~0`Qd,ʚKzz{S$IE?ITH o ,̀EY3`)"Iw PEf}OA$Ro1 PEf~ $z#6` X52T I ߄&@ XfR$IR!Uo ,̀EY3`)C]OA$RSo ,̀EY3`)CwF?ITH+o ,̀EY3`)CSo~ $7_~e0`Qd,ʚKz$I* M2(2è 55)HBs]mE(k,e] I ysmE(k,e] I y("3`Q X~ $΃ PEfߋ~ $AmE(k,e^$IRA~ XfRGcS$I^zd}3`Qd,ʚKZS$IY πE(k,exMS$I5J "3`Q X9$I*yo Ox,̀EY3`)CgG?ITPOx,̀EY3`)C/~ $z3>(2è  I  "3`Q X^ I ) πE(k,eh/yNS$I5g X5B,>")Hn<>(2è ~ $\ XfRT$I*;o "3`Q XʑVs$IԴv&@<Efi?$IR)ՃԚ~ XfRf=A$TwL:Ef~ I }K "3`Q XQwcs$I5L "3`Q X1 I OX,̀EY3`)G?ITPK0>b(2èï_$IRAUW;>b(2è?$IRA8>b(2è΍~$_;+>b(2è|$9H~S ˀE(k,o@s$IU߻)>b(2è/,~$ OX,̀EY3`)Gu$I*~ XfRj$I*q?~q XfRޚc$I*·~&F(2è 79H|]1`Qd,ʚK919H~o "3`Q X9뗣$I*~q XfRi{s$IUQ8,̀EY3`)G?$IRazf1`Qd,ʚK9'oA$O(@Efd)5M$I5c X5$$IRA~3>(2è,$I*'>(2è,w$$IRa~1 XfRz OB$V/ Q,̀EY3`)OB$V7(@ Efep'$I*ޥo Q,ٻsᢕffemjS͘t;6ZyXe5;MYmyQ@夐ȡo@DośC"7A>\~?\sgkd,*K]&W~$FMF2 X̀EE3`CoL? ITYˏ(@h,u}`$I5ٶ%~,Jfe?O? ITY[.(@h,u$I5d(fR祟$I[]S X̀EE3`g$Iޡ?S X̀EE3`K?~$|N3`Q2̀.xIH l~nN3`Q2̀.~$†g2~(fR ]7$I8%3`Q X3ߕ~$&WQ X̀EE3`˟I? ITY/(@y,JfgvˇB$UOo<%3`Q X3$I5(@y,Jfgr)g!I*ww Ph,o=",$IRyZN2`Q2̀> !,$IR NyNN2`Q2̀>ó$,$IR#,%3`Q X3zByH Օ[X,Jfk|A!I*'o`(fRѹN?ITiSV֟h,$I6<[X,JfkpC$U X̀EE3`WN?ITio*3`Q2̀^~$f\Ugd,*Kݺ0D$IRͿrGN֟h,usKHJ[X_,JfmvU'"I**2`Q2̀nM?ITiϋ*2`Q2̀nOJ?ITi"~ˀE XT4/98D$IR?|LV֗h,u$I6=[X_,Jfmy'"I*mOo`}(fROO?ITk~!~ǀE XT4^'"I*w ~ X̀EE3`ʆ D$Ug`(fR]M?ITiwqV֏h,tqHJ_zhV֏h,|g"I*mwo`(fR_~&$fw|"~ǀE XT4gg"IjmVW6`}(fRO?ITq?)~ÀE XT4{FH{X,JfԯJ?ITqó$~ÀE XT4l0T$IR? %3`Q X0S$I6%3`Q X0OE$UK*0`Q2̀ oN?ITkaw`(f҆񥇦$I~"~kπE XT46}uH+3`Q2̀ S_~*$F*~kπE XT46$I# |'T2̀ C~*$ןWgd,*K#V6td~.$fwސW5gd,*K;;nJ?ITkq# X̀EE3`it"I*ē X̀EE3`iw$I)ω+2`Q2̀KK?ITq"~kˀE XT4vyUH| X̀EE3`i@$tq^֖h,OHw{^֖h, ȮOF$U\o`(fҖZ$ v X̀EE3`iOF$U̗`(fҖɵ$I%`(fҖ%$IɧWcd,*K[$I7%3`Q X287OF$tԭWfֆh,m'OF$U^ȧo`m(fҘ}$l$IR X,Jfg~F$U+0`Q2̀=ӛ.N?ITqWad,*K{&W~6$/+0`Q2̀=$I 6 X̀EE3`ip$I!?Y=gd,*K{o$IwY=gd,*K{z=1l$IR 9%3`Q X&ӑ$I71%3`Q X4ӑ$I79%3`Q X4ӑ$I79%3`Q X4?$I٤[ݴwfh,m]7#I*,1`Q2̀M_~:$g4~{ƀE XT46E%IEo`.d,*Kz@Hʛl;3~{ƀE XT4v;G$U싟+1`Q2̀]>~>$nuYgd,*K&מ~>$<-~πE XT4v/ڔ~>$򆧿8~πE XT4v ,|$IR>_fvh,G$Ugo`(fҮߟ~>$fw|2~πE XT4{_N?!ITsQ^=,Jfmv'$I*>=,Jfmr)'$I*oo`(fҶ_~B$F_,1`Q2̀m3^~B$&׾#~ǀE XT4$I7µ=,JfwOH$dحWnvh,3$I?u,Jfo3$I78u,JforIg$I*oto`(fҾѿ]Iʛ||sfvh,{g$I*ov7 X̀EE3`i_?~F$nu-1`Q2̀e IDAT]7$IO-.1`Q2̀e1-$IR %3`Q XOI$Uo`(f&W5$IRMm,1`Q2̀e1M)Iʛ}%3`Q X租$Iٴ[Qy,Jf,1OK?%I@c[gd,*˂شWZ$4%3`Q XI$U7 X̀EE3`YI?'ITy΋,3`Q2̀eq/=,$IR5~;πE XT41<$Iww s X̀EE3`Y)$IR Nxfnvh,wcI$5?-1`Q2̀e=$IR卯<.~;ǀE XT42OJ$Ut9,Jf,Ǧ$InueCnh,e~R$zXnh,epo$Ij)ώ-3`Q2̀e{bII<<%3`Q X|pOYIʛ\sJfh,gvg%I*ov7 X̀EE3`Y%~,f,=7$Ij/-h,ez{ON$5E XT42$I 4w `l,*r$I 4_bn X̀EE3`Y.~r$z>!~3`Q2̀eɬljIK΀E XT43$I 4w ,;%3`Q X䪷$Ij'[`(f|F$I 4΀E XT438WN$|r+@h,˧wcAJ$̀E XT44qSIw ,3%3`Q X~z$&W[`(f~z$f_[`(fxaIM{oXV,Jf,ON?=IHc]`Y(fV6t'Ihx+ ,)%3`Q X'Ihcw ,+%3`Q XO$5teh,kx+O$5|x_1~22`Q2̀ey$I?)h,K,%IR OIv%dd,*ruc J_zhnedd,*rl;3%IRM?{anedd,*r}`$I 4VW6oX6,Jf,O?AIH7Dvecd,*rC$I4< ,%3`Q Xʆn>; %IR/981`Q2̀?~$7[`(fxg(Ih޻3~1`Q2̀/O?CIH?)~21`Q2̀~6 %IR# N}Avebd,* uA)J_|@v%bd,* S$I 4ĀE XT47S$I 4h,ox+OQ$5R'oX,Jfp[~1%IR# h,|$%IR>_v%ad,* _7s$I 4€E XT4nrQ$5w , %3`Q Xy~$z>!~20`Q2̀k(Iips ,%3`Q XAuyIJh,|ϥ$IjΊ- X̀EE3`M~$wo- X̀EE3`ᛍ.$I{oXt,Jfo$I4ߊ. X̀EE3`$I4׿. X̀EE3`Ϳ$I 4ٶ%~3`Q2̀o7g)Ihsh,|%$Ij̀E XT4K?KIH3~"3`Q2̀o{O$Ij]`(fwX;OS$5. X̀EE3`Lo84%IRw[`(fo="4%IR#y|vEed,* de)Iipʳ ,*%3`Q Xx I?MIH6~2`Q2̀K?OI@O;2`Q2̀3~iyJ{knEed,* f$I;G ,"%3`Q Xx0-/K?OIHύ. X̀EE3`'<%IR#/]`(fƒZ͇$IjoX@,JfP/M?QI@/XD,JfP[H?QIH?)~1`Q2̀2$I4x.h X̀EE3`'D%IR#/98~1`Q2̀K?SI@/.` X̀EE3`L_~$Օ h,<#T$5R?]`(fnyYJFĀE XT4N}T$5 ,%3`Q XxX+S$I 4 ĀE XT4vt*Ih>€E XT4vx*IOoX,Jf3[^~$ҷ , %3`Q XI?UIHGoX,JfSV6v}*Ih €E XT4vt*IZhV+~"0`Q2̀5zDJFg ,%3`Q XY-/K?WIHwE XT4vV}U$57oX,JfV6v}'+Ihvh,?~$&nuZgd,* b7$Ijqψ.:%3`Q X3^~$Fiv(f®$I43`Q2̀]~$f_ܖ]q,Jf7^~$泮wc ̀E XT4vV$5_.2%3`Q XUS_~$FMv(f®g+IimKv(fo+Ih~Zfd,* cz+Iw؏ohh,WOW$5`s ʀE XT4vg$Ijohh,<|%IRMo=~@k X̀EE3`aO}u KF'Zcd,* {/$IjGO.%3`Q X#uqK}1`Q2̀=53$I-4v7~@K X̀EE3`aOMzkKF-1`Q2̀=5~ƒ$F?Zbd,* {X$5ohh,u~)K)@C X̀EE3`a-Loޚ~ʒ$z0`Q2̀0zd)KFw €E XT4𝿟~ʒ$m. %3`Q XX #~ʒ$77~@+ X̀EE3`aMl;Y$5м`d,* kezy,IƟ.%3`Q XX+6$Ij;?~@ X̀EE3`a ,Ii|QZ`d,* kwY$5ohh,ϥ$Ijɰ[ݴwv(fZ|$I]v,JfF$I4:jgd,* kip¯$Ij7oh,uqYKucv(fZ~MYKϻ!.P3%3`Q XXk%%IR# NyNv(fZZ$5Mjfd,* kM?kIHϼ/~@ X̀EE3`aͭlO[$5|pw!@ X̀EE3`a=L?IiKF2`Q2̀0Ӗ$I4K?qI@?]F,Jffw^~$zpv(fz\$I41`Q2̀4:'.Ii|Ajcd,* _L?qIH^]6,Jf6uaKVW6h,mI?sIHc]&,JfW)%IR# zEv(fz3$I4[ ĀE XT4[}\$5k ĀE XT4ʆn>;%IR ͦߓ_,JfP$Ij ό.P %3`Q X(a|.Iitk €E XT4JS$I4Yjad,* %}BKF0`Q2̀Rܒ~$zoj`d,* L~$g50`Q2̀RFmKF_~Tv(fB)~=%IR#n2~@ X̀EE3`ށ4%IR M/fd,* %dKFW (fBIOJ?yIH:~@h,4<'/Iii,JfPRO?yIH-~@h,#nO?{IHx~ %3`Q X(mz$I4< X̀EE3`#^$5wCv$%3`Q X(mO?{IH[.dd,* xrKV M/bd,* ŭl;O_$5R_/bd,* ޛ~$F),Jf0~/IimKv%3`Q XHӗ$I4 (fBBu|~$zX~%3`Q XH}3/Iix $(fB_$5Co.`d,* )s_~$f\] E XT4Ro$I4v/Ph,l$Iv񿔿_0%3`Q XHzeG@$5輿.;d IDAT<6zhhD A{™L@&!"pMOw t3ә3=iUY9^l-Yv"Wy%,7xF>9UR{_շu' 3Efs' I*Rwe f X5"' I*Rc f X5"5|[$I8ɀE(k,ZvX*碟$IH/a(2èh_ $IREzZ9(2èho.~$"-v XfBE~$*:ibŀE(k,D+NzCJe$IREjr1`Qd,ʚ àPS$I}ݧoŀE(k, w6)HԻr1`Qd,ʚ àD?IT4r0`Qd,ʚ àq޻$IP5,~ XfP8U)A$UW8~ Xf°?=9Hݾ.v Xf°~vs$I ` X5EkǢ$IJe"3`Q X5<9H ռ 7Ef04ƾ'!I*RU 3Ef0Lz^$$IRE="3`Q X&WF? ITib"3`Q X& $IP?G/0 Xf0)N~c$IyiɀE(k, G$IH{/ ]`>(2èa3DI$MoO,̀EY3`aشd$I~|1`Qd,ʚ ænQ$Iuٿ _`(2ès«Ru$IH/0O Xf0?qwӐ$I] Ef0:w4$IRUwS5 Ef0Z_!I*T~|0`Qd,ʚ èG? ITo Ef0 C$UW/0 Xf°=!I*ub 5Ef0:7<$IRj"3`Q XV͋ yH պ"3`Q XVo~$Bu"3`Q Xf勏F?IT}.0 Xf09H {fˀE(k,TMD?IT4q«o EfP5F$UE7 ̆"3`Q XǢ$IP?~l(2è*"H ջfÀE(k,TQOE?ITKibfʀE(k,TQF?IT+2`Qd,ʚ #I*TO00C,̀EY3`O|$IRfʀE(k,TUwyG$U|Xvx 3a X5u'$IX~L(2èj}G$I? a`& XfBe-;<$IP{/a` XfB$IR*?~L(2è*|R$I柅00],̀EY3`ʚ|$ I a` XfBD?!IT;. a` XfBՕ/>$IR.EfPu]WD?#ITi a X5}$IXKoEfPu$IRu~ a X5*o)OI$U00 ,̀EY3`O~J$b~(2è:ynS$IuGo8EfP+?$IR~v c X5꠱OI$U;o8EfP Oe$ITYDYqLʀE(k,E-I$U% a;25.LKRwywW*_|,?e X5sII$UηaCzAj]z\l[z{iߍsrp,̀EY3`.|89I`.* S{xޔH(2è:g$I3K*0PcS󋿝6{e*_n짉ewb0EfP'勏F?)IT&ek%S4d'G's @,̀EY3`N~R$bun==Թ۳5Ncno~,̀EY3`N~*II=)oM, ,̀E(k,IF?)IT~*NzCW5nQjo^;֧]iX*N> f X5je)J$U%cz;25.LKRgۚ⮔45>f d X5g%I*V[g0@5L}PSRo֔:TZ?C3`Qd,ʚ uӽg%I*V{o`^?Mx&Uƺ `,̀EY3`nZW~ RiTk}`0EfPGD?-ITO aWz݁3{S*'F5Pպ7b0EfPGO~Z$je*N~Sl^;֧]S?g׺ߍ XfB5/pӒ$I̯ ;"5.LKRgۚ۳5^;*W,K2`Qd,ʚ uT%I*Xχ1+V/H S{x=xCJJE>-(2è*_|4yIxE*VG]۽){ڠ`,̀EY3`;/~^$jorc`+7/MSﮩѕ'` EfPWk?$IRk];jkX06.ImkRo֔::3(2èj%I*X/1Paqjo?Q@}?'yn3`Qd,ʚ '&I*V1PAcSsݢT:|Mg XfB$IR+V%6~ԁݱ>J,,,(2è:w$I3uc`hg3GvJNzg XfBMӒ$I3}]Q Rs2z7/Guc7c0EfPgP$i~9+MuR{yy*?c2{? f X5jml$IR+20Ə?[W;֧])\l2"3`Q XC߈~f$6. c`֖~`?N;I'J׉q[CXoye EfPwO~f$u *V/H S{xޔ?Z"9/(2èk^g&I*Xw bkSsݢ޼tꣀ}G {? f X58L$U~0Ǝ$IREzZ-0 RsԹ唩{M"E6(2èQR''I*Z ()V>5/|joOݛR9LR-+[?  f X5FMN$ULo eji1nQjo^;֧]S?IP5 Xf¨ Bc橲?k(2èQ4o H$ͦrSiba \)NzCjc]*'KRK_̀E(k,ƙo~z$5{`VƏJsޕڛwWJecƾM d X5FҲ[$iֵT=p0cGڅSmMٚR#!,z@,̀EY3`aT'I*ZoT^(ݛ~$rbo/3`Qd,ʚ }_E??ITպ4 0ǦE> htOJ*Z'ÿ1"3`Q XU $IRk^{G(OSﮔ2"I5|s d X5FU){OP$USߚZζ5gkJV@j\_̀E(k,F?AITO~W^۽)ܑ4bZ`,̀EY3`au%IRU+˩hg(VSTHO6? Xf(k]'(I*g!5~Tj]ZW?5VݕRُ1F~d Ef0{{$I{owI=[S6di f X5FڲR %IRE+?=uO4@V'ܰ8Ml<$ͺu Xf¨=pm3$Iq3)V65-JK> p!4NZ3`Qd,ʚ nߒ$Imk?~sdXpꣀϛG!IZ_ȀE(k,g(I*\`Ժٶ&lMیC f X5F]- I447 pJs۽)s?MHP_̀E(k,(I*\3+^楩c$ln `,̀EY3`WD?EIT:[O g`dk%S4Q~$Mޣ-g Ef+R㣟$Ip g`> uqScޞ)u?HR=rsv3`Qd,ʚ "5OQ$UL)oic:7JOe_jWÿ3"3`Q Xibl%IRu7 TX5nQjo^;֧]g$D `,̀EY3`z}#9J qQ=1vdj]85(wTzIz]} XfLRIV:M,;,( SSRo֔:^ս f X58`hIC~@(un\z\ƾS]4 Xf'!~$µlMY8&5-JKSw߻߱IR' d X5sߏ~$)y3vdj]Zζ5> ׎>%IX[ga Eftw\$%IRwS} @LU IDAT=L}v{x=xCJ"$CO`,̀EY3`ioOR$Ufjrݼ*7rZɯ߇̀E(k,#s~-IJݾ.V楩c}ݕRYFҒ}&{(2è#S,%IR+_AXvX]ƎH Skٶ&lM׎>%IC1(2è~\$Ix~0 Rs )uX4䵮:>(2è~\S$Ixk2U;Q@}&voJSXTZ?= Xf?yG$Ix4Qqλ>桻c}ݕRYFԺs d X5qo~$کX;"5.LKRgۚ۳5n+ʕ$մ@,̀EY3`VHӔ$IyɇoX 57,N-> B9+I~ {!(2è~Z;4%IRS<65-:Q@;/OOWI҈<=̀E(k,ڛKӔ$I|`G9:0Vٱ>J,OUI~qDL2`Qd,ʚ ƹ4%IR j|w k%mMٚR}Jtg3((2è^Q)uS$U5kaqjoOݛR}~J4grU3`Qd,ʚ ޣߊ~$>+Mu|SSS98ÿ2"3`Q Xun=-yJmbkf`tc}ݕRُ,%I Xf/uqS$ՠ_+}56.ImkRo֔RM,?:1(2è^^-S$ՠk8X`j`2z7|(IRxcGf0EfV'*I*^`^~ oTP(2è~ˢ$IA5<^Fjݟ=RTg$IC_Y<}2`Qd,ʚ lK$IAk"%mMٚR}IT}_ Xf?[wE?QITz3bܰ8M,>$IM'3`Qd,ʚ 0vd*$Izn*V>rצEScԿ.I#7 XfL%IR j]`kN}PwywWJe?l$if7e X5sg*IjPwEw @G.=.uI=[S4O4IF="3`Q X`ߍ~$ @Js2>ovs$Iz:w|>n Xf+Mߋ~$5- mZ5SwN{ݱGIJԹ[3`Qd,ʚ \{$IAO kؑvajm\2Q@'JGY$ie X58_~$~检:z{iDT$ikO ΀E(k,pp+(JT )N~cj^s{T6_>$I<7[բo΀E(k,ppT%IRMj m^N/GJ$)s3`Qd,ʚ LOU$ՠ k^"IF+ XfuEs$IuJ׆6?ۣ/%I9~pp,̀EY3`i_U$դ% m~REI$)s3~% Xf\%IRMu~mOGI$)so A88Ef4R~$?|2M,;,{&?P$V'2 Xf{'+Ij_$IRi1`Qd,ʚ L_$II- W^}I̕τ L"3`Q X`}0J|{m5.>$IR?~0[̀E(k,0}ʼn l%IR*T~K}0q޻#Iw LV3`Q`,ʚ Lg+IjRk~L[g%Iz~0=,̀EY3`n?/JԻ`R}Iv-az Xf3g+IRdž7<2$I}A (2èfq/G?[ITZsӉg$I\7c X5OF?]IT߹$n_}I̵t (2èfݯD?]ITib`jY$I2׺7c X55~$F5/@}ޣFD$)s͋?~0=,̀EY3`kOW$ըg7h?{I$I287c X5RW$դIJo`dO"Iƙo AEf|%IRQ,!IbŀE(k,0;O~$Fun\~X $Iw6 1`Qd,ʚ Ns+IjT 0gj)$I2W*a3`Q X`vJ9q/8i^3H$ewW (2èf}OX$ը5~cg$I\oπE(k,0{ݻΏ~’$F~}>$IR;/A>Ef쵾OX$թSQgE_A$)s; A>Ef5|[$I5u'o`{e $I2׹qE (2èMg,IjTo`pG $I2޼4a XfwW$ISFXqLǢ/ I!a Xf}_F?cITZ_cGF?$)s/N´(2èMcoF?cIT~9FC-ѧ$I 1a XfWmF?eIT4wP{IFqMȀEY3`C{,IjV󒏄8@5/p#I/T"3`Q XunY%IR޳!꯽>{$IR:E (2è]s,IjV|1M\[SI=73c X58tʼn %IRjn;ˢOIc ̌"3`Q X`n79KսwF<$)s]ofƀE(k,07:%IR*|0ʉgOImkofƀE(k,07Z}49K9@M8&ԑ$IlŒ(2èFzAs$I5;Y>u$IR@ Cf X5;~Ғ$fųib;ѧ$I yfƀE(k,0w߾0IKo9@ϢIPsoCEfi]'-IjX~:}Hdž!̌"3`Q X`4'-IjX41vDKWF9$)w3`Qd,ʚ ̭OD?kITÚ'䷣OIsA9Ef,YK֙wP#KeG$ew3f X5[i$I5|)8IP;!̜"3`Q X`n5g-IjJ}H:[O C9Ef[vx*G?mIT:OIP?C9Ef}O[$հr41vdT_gOIPf΀E(k,0}:iKּP}>k$IR@uf΀E(k,0;iKֽooD5$)_ C9Ef<?*N%IR +/^յ)F$, E1Ef=%yKּCP]e9#I*gfy(0èG'D?oITӺ\~պ$I wfǀE(k,0?/yK֞H+ wjjof$IR@CEfe$IR@ݻ~0;,̀EY3`{'.IjZ_ uj?s_)#I|sy(2èO$Ikf*VZKF$Ժb X5?/N$I5cP-IF+ e}H~ph Xfy;K{70O$IRT4{Cc X5ȫs^$@s#WmE&$)]̀E(k,WsG?{I4u<75[g$I #:Ef@^צD?}ITibe<,$IMV{Cg X5ȯmO_$@K VoD$$)ULJ#:Ef@~N~$i=|c?*DI"Ikp Xf5/|ӗ$IPY~1~3$I9&a:f@^R%IԹiUh_SD$V6_ G,̀EY3`_$i+_zDM4&ӭI5ܪ (Fd'Ayd ϼYq`w_JzeQ{1`kO2ӿ~Imxѵ% XdBV,R=-RG~$IV'Ps% XdBV,R=]_sL? $I-ѧP"6,z,2`!+h Dž@$ivѧP]7 M4ɀ XzTl󒔪2IڤbWA$i+Ae: M4ɀ XTwuߋ-IR>+(26gB$2`eNA$iU& XdBV,R}'h$IҚ7^rf9 M4ɀ XpO xw$IZE4F@MD XʀEWa;H$~6jef?"T5YZhtw$IZ7}F5Qx 6dB$2`UwͣFT,~y-$IVbU{}ɀH,de"լy<4-48{*$I\E@ /1>dB$2`#GB$i~^H;~hn2`! YHg~*$I+)UeHwoM,D2`!+~ۿ&iZ[H$_>:)GpEs XʀEg[[H$={E @~h2`! YHlxR$I3㷢fF~h?Tz,yڪbׅC$^]o( XdBV,R=+z<0pq=$IuR]ѧP3>h2`! YHm|ORUoy*z~=$I~>*v|CˀH,de"շ %$ICOfޣ35/NeB$2`[oD?@Uݓ: 6$I6IiXD@͌(NfB$2`jR,Zgo"I4> ];Es XʀEw~&+ݒ:SD$9y IDAT|~hn3`! YH~&HO{v̀H,de"ջbF?@˕w &$퍮9,$hK* XdBV,R+)Z~I֊m^<~Yyo},D2`!+ /9Zn|7$ImmpڿF@M [πH,de"տA~*mw$Im|Kw.VgB$2`Rr$IjY}5m{Es XʀEjF[O~.S"I/ԙnπH,de"5\{E$b7T?/ ^Q XdBV,R3is? ᷑$Imhxџ@ /1^Q XdBV,Rs-H~I4[h<~(O,D2`!+9.Vx_~I4 O|;9fQ XdBV,RsO_i}I4-0UqX{4u-ʒ XʀEjNVOi<~6RSk#I& IxY7eB$2`xw $I?^Mݢlɀ Xf58FTlHIwG?E2`! YHͪ~I4Io?7hbׅ-ʗ XʀEjXSR}O~ v$In';UEDԼFWt)QL,D2`!+ٍ|z3գw $IeK7F\ 38dB$2`{;xZ~+IT<&z'QL,D2`!+;1xZ`E*{U$IR*mbY44~,(QL,D2`!+"4YpJK{%IԼ4Y`TGSg3`! YH Sɀ Xɭ'`T˗b_ $IZ{#0_}^ɀ XmxޖO j^k%IJ[Q*!c@uT XdBV,O R$=[v&Tؿ uT XdBV,75/UٯZU$IwTU*{UzeB$2`&~fCo)I~bץX1 L/"4`3|2$n{.x&) yT XdBV,҄`TG?5k=SIIh&\? yT XdBV,7`(u~SIOSU_~~ɀ Xɯ_E?5kep7o*IR{E!0{ {T XdBV,W,Քƃ`͍*IR*zA*Io3"ԎKΌ~nJTlJԢ F-;Cj XʀEjGM'JԎ>-FrG̀H,de"bצTUOZJ4@J(ch韢}ɀ XTsyQᷕ$ir-Zdp T XdBV,R{'`VT+Hv $IWKR:ezfB$2`SY3ԙn%Inʻ.Zz;H΀H,de"kY31$elFi|w?~|[IʀH,de"=fpK-7N/Qɀ X7Tu~7$i*mʻ.xF?~3Yɀ X$7)ȧRυ`ٯeџ4Ϩ-OMjV,D2`!+I>US7$^IC7G< Լ XdBV,U `f~IֺοK?YVwğNj^,D2`!+IӍ'9oOC?~IּDXa:[n~?yɀ X$MG?G1;$i.?QhLJOjf,D2`!+I3M~bHR5pUOU?S7 XʀEO^kLjESϥT?9Vx_~Gɀ X$5Ie"Inj^ `Kɀ X$=ԼT-#YG$yitñџkdp)56"oxv@ Dm&IzbWˣ?LUbׄTjn,D2`!+I?_wwD?KPSφg{nGTXc] XdBV,~r٭O@=TU/$QҰ4X+3-R3`! YHm4hԪ毛.4]wWjt,D2`!+I\wF?M3R;So5Im_Ʒ̊+5?"| vF?<$u~IҤZ45?41ɀ X$=[bV躣RgFw$ե~ߑ:S0MN,D2`!+I+kӣ*F)*;6毗g|-Q?Yjx&*"?SO@Tߛ{?ᷜ$E Dwc XdBV,Vږj"hQ?$O]Z|L XʀEҪ4@c /a?Ft4u<\3?.eB$2`* K/Hv $iyixQS [3M\,D2`!+I:z' ѪC3NfޡI;WZ(2>dfB$2`M{R9N3:S;IZӊ_F7i XdBV,VdL񭧤bۗxZ-pfg^2;6^DfB$2`:_lL̯߈$iUT>xc PKk XdBV,V,4d癟j}IU4'}!nfB$2`:۽*rtLkRw=IiŢMRHz+G~E4"m `2zipRg7`?3 N XʀE?OD+4uwORT.%hw>dgB$2`mq+/槱HXww_>RkfB$2`&94hno $Mf=7O[O~k|7&?"5wЇ/Es@IQ%;2~ԟv XdBV,֨uR=O@T63$%5b7T4ƫo'"ipW1RJ[OI]7 %65/4^zA0kdB$2`6_R9~Vgn;QRl~*_ x/՚ XdBV,ֶߍ~y" /\E}ONr+hM'߂jW,D2`!+Ik[E?eKJ֪:w+eπH,de"i6^}s* Y>?£GIVipfox7ڗ XʀElu UT>[R]zAp\Ja[Z XʀEl5' 0k ,HV/%%='۽j槭L+oF3"٪碟4@U,{bȲ͋oJu-04QsQ̀H,de"i*z~+5Ԡ;9&>푪Xѿ2`! YHFW25S!:SoLiR*v|"h٭XM?1/T{3`! YHzo|?SgߚR+< SyeX C>~[ɀ X$vC7G?m̲h]O{S{?ZܧR*G|XKՊSgzwڛ XʀEl78Os?ᷧTV&ڝ XʀElWl*_@[푺{+"48+i|E)?̅J]7 = XdBV,-'G?odT.% Y~JsYwfYIDLߠ XʀE\;Ϣ7"T?_~Jk[ RѕNF  ~J,D2`!+IsR'HxW Nr*}i*b?IhR$d;΂ SɀH,de"i^c@]i|)O/ UX?itz?-oUi:"OuTSyip΂mU-lށH *OuS dB02`4w}?eE;~U7&b47hw^x=57;Vi,D2`!+IsYD?s4ɠKJ3{3uߴj^V/x'hWXVi,D2`!+IsMU+?Tl| IDATVkjmRM~%kZt ùH,de"i^KS(^FW8;9Um^į:waT 38 {πH,de"i$sz448+b_ 5{۽*48g~tb39&x/πH,de")Gϋ~hr}|YQ=`3*jx6i|)Zq?M#c2`! YHQ迌~h塛躣̯ޡI [;T7RO9 cS)J`Fo/eB$2``OzSyQEwLMnz|8 N4l4z䶙135/~)"\ /6T=r{vN]u@3?t}- Crm;Rϧy[IOS|9ޖ&"\;q?@zT}Y4|_?aM}~7uwyK*yILӌ[}b7~gW,O^K]{8|Tu>̍A'6 ͥˀH,de")g[O~ O&)"F3KFW쓆m?Lg|- NO47ԟ?Yށxj?tܧgg Nי?qx3Udg4kFW~;s2`! YHP'ݽLɀ X$emZ~G3{.\z XdBV,r78g~3ͥgˀH,de")wvLi<~hjpͥgˀH,de")э߉~hY\ZY,D2`!+I`@ %ߗK+ˀH,de")yɏ@Zjt>ߕK XʀERTӿFUm=*ɀ X$EUlFgzjwҪfB$2`âAZwÿV5"]T>xCL ~\Z"ʻ/~ h :ɀ X$E?O!-PuJ/.N,D2`!+I-X?U0.N\Z XdBV,I6b+¿V7":TlҔF' 5j¥5ɀH,de".>0I`Bux{ҚdB$2`T{n$0K \Z XdBV, E&L-i,D2`!+Iu'E&HԙZ'oiM3`! YHUKգwF?Lw)oi-2`! YH[340 [Z XdBV,V StGnpW¿6":6bb-m,D2`!+Iu[S'0ni62`! YHkΎ~"hA'ۼ${ni62`! YHk>D@Ëw [ XdBV,j:|xI3 @qK XʀERIdt>mK XʀER+jG?4A9Nݝݶ4ɀ X$ս;E?4ÿӖf;"Wlƃ:sﴥ΀H,de" ~xHs @o>)li.2`! YHjBsf=O{¿˖""4iO&54ﰥʀH,de")x @ ﰥʀH,de"Iw_lP#}WԼﯥʀH,de"Igﮥ̀H,de"Q_7UtP7:]Ks XʀERﬥ΀H,de"qmTˢO\积ɀ X$5[D?瘟ɀ X$5b4D?(2uW-ȀH,de" W @+"Vq3 @F]?-̀H,de"ɍn86 ݴ3"&D?d2便ɀ X$5R2拉ɀ X$5ޡ~Jc%g-EdB$2`kSPww-dB$2`4 92 XdBV,&uRO*s⿇2`! YH~*I`o:!g)2"i\vk l?Kɀ X$MR?0KF XʀED`T-_qYRp,D2`!+IV3i`-: fɀ X$M\ 6HգwF?Q/;.fɀ X$MbSl=T XdBV,&{XVS}$[0{f&ɀ X$MjӿsR2`! YHض8UYVQpeB$2`4 F3 *+KuˀH,de"i+zK{.Oy+KuˀH,de"iES JxR3`! YHEhs 3|RwR]3`! YHjC ~nx:8uw{kR]3`! YHjC6/N`E /]:gB$2`ԖE*uR3`! YHjK6/IUg4o7,5-"6T.%h`*mݰ԰ XdBV,\OF?0S XʀERZ'_Lg NXj`,D2`!+ImwF?Rۿ] XdBV,T}Ys 0F XdBV,;1ĩ+Rÿ XʀEh|yO2DJMπH,de"IO=O2(^: 7 Wjz,D2`!+IY,La#;_i2`! YHΔ*ih¿&%"$b돉~kD4JO+MZ,D2`!+Iz%hSgj^wҤeB$2`gh|xI3 P~ifB$2`g_G?78g~ҤfB$2`gij^*4r٭ps ̀H,de"I^wwTU5@TUqI΀H,de"I+o| 5@팮>([i3`! YH'6éeJ XʀEVe{D??JmȀH,de"IVKS,7^zAL VjC,D2`!+IZg~=5n_+>SO$F[<7Ut(ZE{o{Z̀:[(ѕ&?on?~Jmwb,dYGW: !VjYG}Z̀:;>ѕ}7@VknVjc#?ǟ3`!o t%o=% Ȣ-OW/+1~h1*v{[+IM)8d?sO-fBVŞt% /!SIyJmmpףZ̀'ѕVlT=~_S0'Tb6/ɀ}4ѕ&?O9¿Z̀z6ѕF75/^̪AR rrs@U?{nR9~fǠ;Zwʻ"b,d5`q+I򽣟tY18K߹Jz'?~h1^_+IPRU$YX+;/Nu¿s_Fg3`!M'?4! NB憅_$ըbWE  Y*ᕤi` Nr{Z΀#$M1YU;jy_$լ~h9lᏯ$MRk~ۻ +Tg:9n´:N[SKgN=v8%a M0,`,%- $o:ȖyA9`aε/+Iׂ]|zhO{75?)A9`au,IXOexչQ%pҷep?*}KҤ%cyৃu~c݈aIĚG^+{N#Ǽ#Tҋ׹fA,TCX&ugyg/|w٣y~CX&Edz7SI/[}tIu'G=PsǢX勒^7e 倅bIz=hN*kf9`!Ex2SӇ$Mratj{1og 倅4ŲwcI:Ej\{W42}TҖU>~k؀YXHӺX&|#^;'7mTU=9`t,Iu'0':R-uog x7} KR]Z= `BgJ7=:YXSU8 CYPqzLTGR[Zg9`!U?IʒTZg~*{}Jںޕ=:9wYT٣0[Hu.bpB!fwJΒT^Us}&DQOI[_'Wex,k,Iu}G?0 ~N7SW{D=E9%Zj;%mS ${8`!];$խ16W06'o#<X űiI[=1T5Fq8%m[E٣ #+$i)n^8hMI\=I9`a$7}PKRk􁈲1ѽwMIWkG ,kIcݕW0oȷDq/ #-Il+\{gFXXoϔ]m%UX3C[X^XUF)i;) fOxQX)ͳ~'pKRM~5wIq/ #-I)uW0B^? =R%9`ah%)֩~(@Xn#MBőo[,2,\\wձ٫VU:w+% fOxYX9C\jAjH]$R@*=/ #u\\SBPS)% Ε_+E00}KRpt:X|*ޚ>)i@-|ET-E0z@:Q[R:SoVeObXY_>%5O`D^ \ MR1'-0*cT!hL)ipƍFZ]j߂| I=Q oׂ]Z[ G$ռ汿keo`L4{wֹ F^s$i^t RUE(i-5 dOjX}eTwC t?*{5@ߒF(ihu.Bqh_r@$mXWJ6(ix5'[d,Ln;ߓ8$Ikf\&(ix:ʵwe*,L;bf Dͧgx.fs޼<H6wЫ\:%\D IDAT{5*y.-P\}`9စԾ$is79`Gq% ODqs ߍN_(͵/\f-y$ wF\=m`8`aboL_,n9#{5dhtU,~]?7{rD?*f쒾`$If\{gj׹>IknQ>rc9瀅׽9p~$mcwNJhL4M.5 Yyx$eK]$ 5 Ѿ Gͧe+ڻ8o{צ:sB}h;GٛB(|K֗G sBth$IeLfV7DI^K< sB픭 QE$Iχrx1n"Oj_U=m`$8`(\+KHԽ3wW5gOXd$M^ 0R:WU۝վ| ,ZqMޕ$Kj#kFBwձovW窯dIXx*>$5#z?8;INkfYX`Kh%Ius+> wM4wO30)Kj^\(}mWϢcFhH_bTfo3ՆG8-os^q䛣\s[~^UEe&Iu8Q5eo!'/MNkި6<=f`l8`ѽ餘1}IR]k񈲗`xw8I}F^B+qk$յ `82+>'iM-`8`_sG4;IRMW VUE?K{4؊VfO[X` rS*\w7IuGxxTUEE13CUfݺ+I`;F'e{X`+.K_T|8^ͺ7&ipGO9`mP>P4O7})JR\ۤw-Ծjo-0Q*Β9}AJRxB_hL&i+;/+0v꯹=5}YJRm1\=`& wWݵ?ƺ BKXTC{?U8Uio=F PFӗ$աwF\=k~!Iڎon3{@-8`AwrI,%J҄Z[e/{sOaO?}; ԊiO_4u.= { Dq?O7m5sY(ZrTUѽhe+I\fO|jh2I[_dke?{@m9`)s͂Y[򕤉lzuƪh2I[Uuѽ:3cj ̡Gugcf$MZ!Gnuh72I[^qkCjo!?p ͳ!$ bQ5fyjd|8mLҖU,34{x,hHkn=N#Z_XyۣjcaX`A4CIPscDUfw&Xՙ֩IzZfԛ1,0BO>3 vI_4uc>^h8trm X`3krI4{Cq{Ӊ#I-f!K55?Z|$z?<rӌߟ&K86S"{0):h}c^yܻ{¨ߟ=!DѾ⯣x4N:5?L7.IV5 \{Wd ^'w\ͳ?f"$CՆG'8I-9ZFtW.q NG̢?3S;}U=OgIׂyF{ŧgoGޘ/X6dƦj_hјYkIJs^+Zg|2KۦGquG}Fﶿ#run-֊Dq{bfz34u{D4`hQ%{Emm֔WmM^As_D]ul~tvrUOkgKƐZ3s}'?GfIJSgKHg]`nIENDB`PNG  IHDR E? pHYs{Rk IDATx[mwART@P xI`Q!B|PI'bbb 1&H{ RLLiQkKĢRPlh^zzofD}笙3O{m^ZJ @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b @Fl #6ȈMd&2b ̡M[oltXUcvŋyO_1{; cWN}:6֮}f'𴽮vMo[w,8GlZ,ݟd]ʱzs?[zg7|gv˦6;ly{opٸ}-{}08icbؼvkϞkG4naձ?3aޅkc3׏CdurŦձ~us';紱ٿl%NMmfcr'46?uX=i1p'vwԱ[0f6{Ħ_7C0nfkԶ7/Q'nkco{G6>tXޝGYV 8o|\h41&f7rsc&^M̍In t Ṃ 3Ȭ $2u3}wUAl<'+e׳y95ZOuhα#ܔ$I 4Ҕ/2|Y믾`nM/~R>);s\$ITg٬Z~ Zu*[ky&I$Bu|dֿM;6 (?*vze*׮$Ik-|Yivlj4KQ&I$bMr%flrAwݚm7y< n8a>e$I*01^:;6uN/f]|<$I$UY  힓xGSsx{&I$Glƺ9cSP}{St&I$M} u { Hkߜݱ_4RTK$IRse=+|?ڙ^z{(]$I*^ҽw D4Կ[xfI$I:lgvlYFiS'$I$ɕX}Ȟk6|lyIIsO$Iu}YnV-sڿ4CkϷ(U$IƬ;.@6OcS;¿HX4|ǣ^* IDAT|FI$I2ddOmӰxhǦ#LYsIm4ǔ$I1ONeTcS¿8wʈ$I1np۪ߞgl'lQoesI$IR 9z~M7qWkw4F<$I$ա ~-R~4|/Z!xvucI$IR *;K_y)&7K?y$I$F n8>~ҺzǦ׾2Og-|I$Ia>ş=6/iUK$IҜSk7<@ڇ|gMb+RؽI$I5npDž)vȦ?>p> F}F>?#I$uH&-6OF?s$I$5a?Ȧ eG3xRC}DJeȑ$IԐߐ߅, V7su/3]_CI$I w:}-=+ 2#I$ejwɬ}ÿ_/$I\=X띻t1k_ F?W$I$) ?.|?>!r{ÿWkͣ)$I4]瘿ߓ o_9̊obSLß\,$I,LŲK0<v0+vSx]<9"I$I?K7P/L f. b?C>R9~H$Izg{ MeW1bK?A$IZY<_?A ?Y¿ԯJ$IR &$Iqsԧ(±YkzEB$If\ؽX} plbvm?AsB$If]oT0QMJ]$IѵT^y961cC>R9~6H$IF7ŒWטc325ˇ~.H$I&׿ slbF7<$I,SYהcOݿ~H$IҜ6|G)_} rlbOe$I$yUw.kȱ6Y~N$IiM={D86')zK$IҼ6ܔO.߿ &֫u^>'I$u;5ϛ\=%I$i$ŃN qltOb$Iֿ] pl_>y4zK$Ih+>;59I$I n)_enͱ=g$I$=s"|7|961$I$i͛:-;c̱_>w#]$I*ǧi01H>zK$IRj] 1pŮ9I$IZ;Rx 14O;#zK$IR%략mDZ:}>zvK$IRu뵦?L)zw|865Tl==%I$Vqlj)I$Iz} ||865PՒ$I46 > A>&|Y-I$IcU/s Ǧ]-I$IcWZ͐πcS{WJ0zFK$IXֿ|1 ]=%I$i|+;;6Ǧ/cY$Iƾ|rAy965@kR},z&K$IR-|<+̱=%I$6koO-w=+ʱڇ^$I?{WcS-~v*=%I$vX&DZzgo=%I$.=|jRwg$I$շA7v{cy86ওǮ$I$վ Ǧjy+I$I{@+ın>3 )zJ$IRcuI'0Q M5=$I$5џ !Ǧ)v|oJ$IF[涔/2|/jU$I[{^y86D뿖R9$IT,yQ~y0Ǧ~n\$I;gI~y0ǦhGT$I4U7OŲrlwn]=N%I$IOԻhEq\Ŀ$I'7bEȃ86b{Ǩ$I$i>-BMcfp$I$iP> 86$Ihx%;%#4F=%I$IYcӘhsQ$I 8||4(I$Iڇ|$~DŽ4G|2zJ$I3Ǧ10y(I$In =%I$IsֳwMcS zJ$I 7!'M>O$I4 ~yTaE?I$I|7|86UDE5IF۰֚ǭ-knß0 " zG2%璤VJv O!DMU|&IkCSGޅ9u柤!N}~#V,jϛbSkwH=__޿4U!IfT0i*F3I6\=}\\ꝷS7}GRkL|31uj۩sR0퇣$g)M7cS 4zI4on:9%uNBjTO.^ΧbR?NU_'IRTc"&pl =sL4O}R%*)vxaj;{4 J4uZsl ֿ9&I{e]?JZn ; G6^P>EV4gLlǦ@Ů$IaSzH?=ŶOz->I4 n=3YDZ)aH'/~v3Z+ޒ~5 n[$IsRkw? MQ?;g$iL+ܚڇ"勶3%/NcI[Θ~$ISG? MQ*znIƩ~; ~=Kßc\ӿuvY7L?GeϒcSݗG-IR+'/^ZUM7K⒤׻`y Yrl G+IRE+[kR?0mgys'WE$UH*~ Ypl JT~˥}|3ßSV5GDQ$UI_ ^A> M#V,}nH^78&v >X=ka*G$U?Jf*gȱiĺK$6=˩$XǏNŃ\%I}ŸQϐc(M.HÇnQQ7J~wYl|Mr#I@ekMO~f;b~n$i_q`su86͓޹;FI*ԿT,}iBm;oτ$i/MarA*=r$IT>voj $i O4Z+zH֩1XgTQk_MۢL%I!yAݣg$#>f`;YIF>ȟ4&7K#wEI'ݶ*R}.+GW>"9slc=c$IN54iS9I$ͦ~';*i@I|Ÿ0:G}:^+GZ4~5c<{$5es;,y5ݩ,і$ͰCxpR86͡A-2`x[*S.IPVqa]";0Ǧӻd#IQ :+" zm$5UM^{|і ȟıiL.~I{ujg4KT?*^[ n<1uZڇ"K^Li86͑7$uǤ|VdjuI$ն& ~|ZꝽ}j,oǦ9;oY\4~ޟ l41 Iߠ]:nZ+R]86͑7E*I0u3o]4aw}=RkHgsMsWG$տ~'u3xֳ'$,8~n86́ѳLj'|XU~N􈐤ΣiOX ˣ$նr[g=~ᒚS3=z,MerA,b6ԧyTCSg=a/ojrNS'勞>s!M C!ǦMp!%Iܔ^?き2G$Wo^:,uN㇥%5ش ڇ|$zlJRrhzh[)u",-~v\a6Aݢ$զ7bg;07G|r $i>+IpB6ԛJ 9]~)|ssDIu{VyRO .Ǧ헣g$բHj̏DIc>KS/kNñi#uO+Iߠڇ|8|hr闸HӽSy%MipqXƻr:G&|#x4#"ip{>. y86mm3Zƺ)_L}d]ѣG҈+Ss6rO.I@66Bkߎْ4Mg,FokE Iՠ?A_O)vd#شzEqI/`c"z IY*|Y%86mFuIʵbK8wףǑY66"g gȱi^01ٿgW`n*sS]S?KŮ@'M>G$_e9TG/p]W|-"|FXslˣ4v1|~) #Jj,M{% ǦYsEAƪwS1%ն2? n>7>/ Fpl5 46ip J]"u&Vn=3&rl~HX93bɋRvuȒ'LTc,L}$if<(|n}|4Y:?86͂kU-??|n{D+;SeE4>|fթl==ʤѼҢ-y4CS˓$i _M9LYZ-|Dfhp۪$UL?>z_}DTf>K$b+@M33R},&IneekWG69αۤʭo,g Ǧhя4ItekM*v|Y}|@+}&fDZi')'Ina=z.iTߙKjy?rlߊ~IRe}gViGjXygmRLԃc L $i=s7F+Sϥ֊|rAmF+T>f]葧~gıig$Ua`CDO>U{S}'R^شasv~~JR%_O}S**ׇ 9MOcpTI^v*v 4ODO@a? npZ+iC&x01+Iw޲ 4R%YM헣TZ|/G}n8>u>Ccӆ9ÒT.z> 7 n=3zj~}_g46wg$U~'^>> sj&b zixewק,dشVE?%R80|6W`eܔW'){Wm,cӆ&.Iթ,E[7GOT>4#_ObK ȱ).y.Ijpwg3ڇ^xeg |86=~KRj >Nݰ]W|9~gʷ<WzE?%2Mk\x*ޘR=*Ǧ{9i_KߓV I? ;{QY4zl96=rHR%*)[U6>Kz2. ֣ӟ$IJjq\η?>K?A_oaTM1uI?Sk2L.H;.L~ ~96r>!Ihp)3`6Z{Cl?,, ,86G=!I}g2l n8>M< VzHcI[OVMش[όk$W>vo>3|&VkśSRRR/OuCps̱i=,Ijzscջa IDATd1}HMشbɋ^"Iej3`cK_:G#}Ý,xǦ>#K$U7{ϐ.-uXV+ıio ;?)1>6٢g;6}&8pޑmشy;ͦ&IZ^>Bm,Mn7@>fѿ;Ix4Y 0g&ݗwޕG9E+RϤb^M5iIjrS W,KߟҠ\amRkӇ rlz)u=ORs1\>KFűI^IRh>l96=I߉$)>l96=ql96=IoEzV9 dcϱI\IRX>l96=I~8zדڔoyb_$)udža Ǧ'{w'IaM= 0Ղc|#&zדZ{-|Y-86=jQ'I!R>YZplzBâ=I ipI3jñ [ϊ$)i_ @VMOC'I!x_ plzBy4zߓ7|V3jñi"Kϋ^$)O @V+MYj}OB d4$))_@V+MS߄c$) @V+M~KR*@V+MY]2z哤W>|GqlRD|4?:5|Y86Mdix;$ޅ_ Ǧ,IjDZirOF^` MMŲG{@V;?6}OF_7O OM>Iw]Zjs6;$M'_ |%z瓤׻d dcSoբOF^ԯ_ %ǦWF|4:G&|Y-5ԿOF^{_ ?:5z瓤jǦ]F|4>q'I#<>{l*[E}4҆>{}l, z6X}^R]5T,yq'I#opqjǦo$i<8|Ym5ش$i.X>}ljOF^̉ dcS瘿$iuObj{?D|4jǦs'I#}_ fZIk dcSe;$־>}lxe'I#/VM+$i>}lOF^+/VM$i; |Ym5Ӣw>Iy-/VMϋ$ieZkixϕk$ |Y5t k$~'|Y5T]IhjǦOFZy4|Y5ؔy'I#l @Vk=6M.HF}4 :kiі;$2/~Κ{l9;$ @I+[_ vxA'I#l?>֚{lZOF^},|Y5ش;$~;|Y5شˢW>I}^Zki+W>I}0|Y5شW>I )\>|l}OBn>{l$Tl dcG{$D` Zr'I!Mfg jiś=I -3jǦ=IRH?3jǦ[G{Rkw` |{'I!@ jo6Ijh>>{lM$柆` ]_IRH*|Ym5ش=I {Wg0VsM;,zߓgN` (zߓz>{l$Կl dcSh}OB_sT R]54Y'I! n:9~{lR*;$/VMN'I#oxjǦnI+3|Ym5TF|4yj)?z哤E @VK>6=zO'I!;*|Y-5شvu'I!o3jǦ7E{R` f2zߓ:G}:|Y-54X}^'I!u dcӏN$)i_ @VK>6;&zߓz>}l$!3jǦޥ_$) @VK>6s'I!M}g Zj{}OB*;|Y-5tW=IiK9 dcKR+$|Y4t6ѻ$Zui}GzVa fh'IausjǦIRXS>v}lj]OꝻ4|Y4شw=I asjǦbɋw=I kpsjǦ|S*$49 ii"Ke{m'I!Gg0ՎcӚ[=I ysjǦ=WDzVk[0JM[N$) @V+?6V'Iau&|Y86]O'IauO9 dcSܥѻ$ջxeZiIRX>Vlѻ$59 dcS?$)򱟆a Ǧ~7zד2募>6ljѫ$MjǦbDyZb IRhS>TMYJV'IaV-@VMY*׮$) @VMYui'Ia n[>6&4]O*>6&Կ]OtS>Y,ZplRW=I Uji"KݓIRh> G&zϓ:|.|Y-86Md}DyZmg1ՂcDZ+IRh>&T=OB~n,ZplzB귣w=I |9 d;w=I,SYƞcw_IRh=>l96=apI{$g1=Ǧ'80zϓк'Y dcϱ sDyZg1=Ǧ'tO=OBp|,IRh{ @6ף3|XrlZGl86GOy dcDZi}ߔc>IRx @6v֣}{wll86m@ODxߠ[d  MZO*Qkd  MpO q45Fx^>l,86=N$)5Gc  MOwɞ;$71Ǧ=;$qlz>IR%j3*ϱiv{c~'Isg2Uc);;$;o sl}Exc <Ǧ_wL'Iᕏ>fwv;$UbKg2UcLIl~'I}d 4Ǧh}ע;IDS>fbV)O_q@LR96POui<Jsl+R>YLrlˣWf:o;IDoILrl$V- @VYM3T,}I~'Ihpq3*˱iO>y d4 ύ$)r>fپ+$U~ @VIM=+$U >f}G;IDWd $ǦY(vze~'Ihp93*ɱiO+[k1Uc,Mk$)b_ @V9MԻdN*Q@V9M=;ID5|&Y86REwT>rf$UO @V9M|OSh dش?:5zœJ3*űi#%zJ9v dش1ߴe~'Iw3*űi#N*g2UcX씆O+g2ıi# q'Ig2UcFp|~'I}g2UcFꝽ}~'IjqLploџ$ n:)|&Ye86m֊7GwTG@VMkrTv$^?TM`x%$Ua>6A;ID3=|&Y%86mI_$;&|&Y%86m$kn @V M)e'Ie*(|.Y8ǦMT-zœJ>396m GwTSLpMjQ~'I396m7OGwT]>,c&jNp>,cӦ\#+$U~@4w\IR% d@ҽ;ID+ @ʱiNIR%seLPMs߻;IFnn>,c\X씆O*Q?űi >zJ9g2ql#$.+|&YǦ9=$Ud 4G} zj+RsB86͑bT+$Uo @±ikn$u d!PDwTz>,c9IR%ܶ*|&YǦ9>;IDe{m'e 9Ǧ9TN*S sFαiIR%|Og2cN*Qg2c띻4zJ4{3FαiN*QY<>lXk7FwT]_>lT$uL\(96̓gEwTz>lA=;ID@6RMM=Ϣ;IDeєOn>ldA $Uo @62M&Ń$Uα#~.iTǧEwTz>ldI%$U]d ǦNQ[e  ǦyRK$U޿>l$Qؽ$Uw.|&H86ͣͧDwTW>l$QoN*kg2cҵnU}=βi+y0|P 31|&K$IjyMsSwп,I$1Y6qsGJ!,I$1Y6qo~<|PEۿ&|.K$IjiMs\s룏w>sY$IRcNlCSFJ{dI$I9Ͳi o9!|P [N ɒ$Ise;R(?|&K$IjiMc}Ǣw\,I$ilC_;&Rj,I$1gY6GJw3Y$IRcβlS>3g$IƜe4g}=|P E뉔M ˒$IseӘj;h.}k\$IԘ,TsWT;RgsY$IRcNlccwDJw3Y$IRcNlc> g$IƜd4ƺg~-|P Ewuo>%I$5f=˦1>;h,I$1Y6/O)DJssY$IRcֳlsʛwлb,I$1Y6߈>B~3Y$IRcֳl xN4|.K$IjjMcwW$IƬf4oR7>B/eI$Ii6l hp%;R_,I$1Y6Իdi ɒ$IeS_1}(H^>%I$5f-˦K}(7?>%I$5f-˦lezm>%I$5f-˦;|P ɒ$IeSPsGJh?M$IƬdTߏ>FkeI$IYɲ)} )uN,I$1+Y6?~gW>%I$5f%˦}(g$IƬdXDʡSs+$IFgXk߈>F-|.K$IjltM-|iJNg[\$I66˦>֓g$IFg\=wPd+g$IFgpV;h.}k\$Iب,k-{W4:~6|.K$IjlTMMKE@).[?%I$ɲ :+|P WdI$Iʲ_}(A7e ˒$IeS j@i,I$Y67DJ{?eI$I6_ IDAT β$VDJQ3Y$IRcl*I>B,I$Y6}(7eI$I ʲ$P4GQ\$Iؠ,6[wлpq\$I6$˦?|}w>%I$56(˦տz@9t,|.K$Ij8˦9s;hKsY$IRcY6֞>F甿 ˒$I3βLMo;R_{p\$IfeS>Go ɒ$I3βd.Z}(H_>%I$5feS@i,I$1,JVsDJ{,I$1,JX̃;RqFL$IԘQM%lpI;R(ګR6=/|.K$IjwM%{EJ]sY$IRcl*a?}(Ή;|.K$IjwM%)y>%I$5;˦%|P cdI$IβwH"5GI$IYEl*iS>xP#?>%I$5+˦Wvѻx,I$^Y6kEJapsY$IRZ,Jp#:)[E\$IXgM%wn;hsY$IRcY6α>F ˒$I̲ĵv}{4>%I$5֙eS+;R(ZOlz,I$,JӣwsY$IRcY6 v9 sY$IRcY6a=lP>%I$5֚eSknڔ"|P $IZl@wEJsY$IRcY6U GFJsԧ$Il@!lPKw ˒$Ik̲@i_>%I$5֘eSZEJnmel$I^,˦?pu4sY$IRElH+>FSsY$IRElH>3$IƋfTZ;lPE4|6K$Ij ˦4I*OEJ/fI$IdzlPDJ{߇eI$IdTzl}(GeI$IdTG|2lPŪsY$IRY6U7DJӛg$IlXŪ{v9$IlX>F=$IlX3}(k$IlX>}(|^>%I$5˲j-"A/xPC>?%I$eSmgu]>%I$5˲'lP7|.K$Ij>%I$5FY6Uyh>F͒$I0˦6X~N4w>%I$5FY6UEJNقg$IeSUk@,I$aT՚}(>%I$5,\@i <3|.K$IjX6UGGܦfI$iX6U_>Jk_͒$IҤױln>}(w9|6K$I^Dz-"A/lPۿ?%I cT>Fy:e7 ͒$IR6Y6UޕDJ﯆fI$),*^焭u=g$I&?ڇ=w+kʂlx}(mfI$մ>%;,+oN(huNfT祢*HP>E)m$I7㽩sVwٲ4XqqJ:}*6˦4X~oY$Iժ䍩}'Rߖ/ZOn2ϒgTzl74j,I\>ϾcSY^s|YpM5}'g'fI$9K÷Ý?|ξ~blAo)$|>K$i5ǞݳwgTU(^>%I4,=mh;?% β&o<:z(>%I4{5YTK$p?,Zளm,jTkD_S$IRk.ySjԻ`4X~N*OEWZ{. ʂlSRz2(_ϒ$I˟Xo{/ 7̂lYgG_Wҿ,IT, ?xD>gi6]:eS]]uP*Es$IMKeL2.cINk?puTlM5}'+i Y$i5w>{4T4l"}/> βf5!(_ ϒ$Is,G ᯇ,8˦V'(͒$Is|-?0\FblaJ<gI 䍣.1 V\Rk?z[k& β .@|$IZW^ڇ|Y63ugTÆ*,I} T6'ښͲ-"A/(=gI4yYnЍ9PZzͲ^}}ˠ;a|$Iᖟ9Kx_eSM]OP:C?>%IRjngwֿ9K+!PC,8˦9a tz- ϒ$y0\6Nbli}}N5Y$U(Yb_SY6յMR^}K??%IR)k.}kwgK(ZO,j`@tt|$I5wx]j>S=m 57Muw@ ?@!z>K1`W%IzK4Yʣo0V}8eԻpk |~jn-IRk.}ۏ=g}p#7_YpMP?J}g$I}ѷr(¯,8˦ @)+|FKTƚ^,]wX*; ?xM5g4!O~?z(;$I,U_,F*ͲiBpdPJͥo ђ$MRk5 8 ѷc,&OPJOˉђ$9KǣoP{~gY6MH}5z(-'hIf᧬HoipIx,Lσ,8˦Ii)@G32|NK4%IYsۗLӿJ]glɂlK}SQfd$ռypxPTlMVԽ@)uN3ZTϷ.s`_>,&MD_w43ZTݚ۽:,{Ϥ,8˦ {W;R*ZO=%IsOs* βij[@i sZT,7E߲5eӤ);@)y$YjFߞ7, βi<(EhIRsGoE@ tg4.-("O*|NKm_}x,BVDu|OgTlMXD_{9$i/GnL)Db >csp*6˦ M@i =%Iᖟ9K@~>,&b=@)S%sZ5{Cg2<>+,&GD_>#sZHقSk_Iӿ7Tѷ (|~Nf4uObPZKw Ӓ4q4xoU], V\Ҡ}K/SY6Mh~1(sZ&9K÷õWER6=/|fY6Mj7=ZY-I5}=X۩sb8Y lw}V ӒT|B0 U+mV,&C}^ڴp0#7ܩ,&-y?5{u:?EOu~AJe$F)^\?ՒTZ{BHܬY6MxF_տ9-Iu=ƢQ37+AM^=E*>3zVKR|OG:X?|f%ȲiE5kY-IUsFs]SJeӄ-"@.Y>%uq0s=|f%ȲIxUiIzwc9 37+AM= 5kY-IU7G9X37+AMJӾ}=ZZ֓G9XPJeRkG_?xM*7Xqq(Y lc$@y$U|-ѓ`,;.|f%ȲIω&J{ڗg$Ubc`9gnV,4wԆKY-Il)10c3wY6iTߋ.mK_>%j5wzsgnV,4~Wף7X V\>sd٤.(MdžjIZ#(z|֓gnV,\+6ʭLٶ/ גT}9zzEgnV,ñ}m^[>%J.!ztEgnV,\]~&( GkIR=Ƣ{?ܬ$Y6yO}}Zy:e _>%* ztEgnV,}}^OkIJ~ L>sd٤9 '@ =%-<|=Ƣ]swY6y3(*e ^>%v}{Wݬ$Y6<}^?גT$z\E]>se٤Կ>%uN|gnV,􂺧~1:(Xo>%.>z\gnV,Z{|u P C>>%o>.zTE#gnV,¦~b> ~fKR)zTEgnV, n=)Z(O55IJv_SɲI/ZF_>3[XsۢG4t𹛕(&h}~9ZlI*co~we٤6X~vu P ElI*K>=Ʀwюs7+YMZkNG_ՐSsǟ ےTzm=Ʀs߅ݬdY6ipu Po-Iehp#`lڇ~,|f%˲IkonWmI*AŪ#`lZ>we٤u6k2Z;|nKRdoS_҈Yɲl:띿m P ےY?cS<@JeYF_1|H6I얤z/c3XqqJe6[4F_>wg$51 06Y lzwy5 Pk ےT4c3|L*_MZz} TF~*eD얤q#`:'MJe֫a} TJ>%iuN 0V7|f%̲Iܦ~':g$G_jٛ0&wE_Q䩹τnIgˣ/tѳgoV,u]})TpnFnIW%oc?ٛ4&w>}-TJ})iq9c`7>{f٤of<}=TJoIC+c;oaJefoG_'^&|-#`:EJefTF_ ߒ45wzs>>f٤}3@tOrsG-xEjn4&ͬyXHe P)7oI7=jƪxٛ8&͸ ߊ*ooIoc`n*oMq>}]TNooI|0z]ʽoV,4㚻Lu P/vTzo=aƮ{WoV,AO}mTN;7|~Kl? 0vC?|f%βITm.=%ijOd4wDY6ig6@%h ٪{W*qjY6ij)y5P9[N4[ 0z`E7+yM?`3\6|=UƮw>38+yMz}TRg$ml>=NB )38+yMO`)'$mLۿ=NB` Je6mL߉*s$m[Q 0~E^>g٤C!6Lfb"uORQPo= d٤E_;oY.ISãG&@kpV,4+O}TVz"5}y,'G?TYElҬԿҺC,=ѣ T/"Y6iVҊOقsIZS[G%@YElҬ)k:o>%j;# 6YElҬ57lzy.I?^cG$@+gqV,4ku;}T^? 55|=B3|gʲIVk_*o7I*[뜰u<*efMR֟tIVIEwuXgrV,4o82zT^u)>%{DDpå{6Ӎ?ej IDATU(&j*zBOtI—♇!@gTlҬR*YPy&IuNB((ޥbY6i^,L')ɻ @)tl\VMz= j!,|K:](ֲwbY6ikYP>>%Mo5'zB|̣ fefxLS͖]=G@i n=9|.g̲IsR#g@mt纤 iKRjE(w9~6OU/&I0;-U]R#TYlҜ5)PvIͣ~D/ YlҜ5XqQhA7v{GlTz=JexYElҜ=_g@o9!|Kg]> >?Իpq|*e֞?=j}G绤5P:?>f٤9XuO|R6.>P>E;d*e{E.&-<=J'=U,4P;Oj/uzH(Y6in[EJfIؚ;TtWG3Rꜰu*emF ):3^Ruqz$(֮%|NgβIs^/D Zq9/zuL(tV,45qxf_̯yIժݫR̃ ;4|VgϲIc)yPO_4=Js_Y6i,uyP[OY/# ;9|^gϲIc{@uNY/5)ǣ@>d٤?vGnK>%yipѓ zW?eV❣@ IzѺ}9zDTB? Y ljs})|K*W=70֡SsׅY6i|MoGzG/5"=*!{s;IMkk=?j/䦔-"|K nz^|\H%zd٤>D͒wo(7?>d٤͖0Eڇ~ܗR'@u zG&Y6i n=9zLXj/i51<=*e(& [GwYl>%mLWGo3|>Y6i5{uJn,Kw &ipˉ#Z{bOM ipwg Dg_ֻdiG=dze٤:'!zL^+/in)PYk YͲlRHůO)DRZ~4<:G}:|g5˲Ia >/zLlKfP]^jny,&=Kc`"Uq~*ګG @ >?|g5̲Ia5w锊u.[=&L6[Y6)ҷy+@ OܕK~_Z| Uv>g٤Rt%Z8Fj{)uPK YlR)YV֮o7H\Ŀ}b$s`K_>g٤R4|F*|pk~&y{Pkgzg٤4(V?Z{\An7|+?eJS/F~Z{/!ս?(Rs7Y645!=z1Ehj T)+ 1?~&0&=F(f3Ssɛ-Lk4X~v% 8#MhM*}>=EE=+)i=FZW]~6?|YsVlBlRkn/Sgw2:5}y$,T7= E~kriTWoS βI}F*PzOq֓}0 @MP%,TlG+X>R6=/ޣ7IjipY/}fQͲIwN3 12DGsߦ|-/u@Lz&Uֲwv 3> գnHvLE{UKR䩹[9^DzIUjpѣ g }R[譙5:ޣd٤J9ѳ @џIMI*w=o1~$e u 5,T۾< `Sl-M*O%o. @~*eDH &UG0JM?~RþlyfJ % @Uߗe٤>C3 gb`{IJME(~~Rce?vG;gijӣo\G/3J&{e٤J=_gwY.Ͱy/wy`GYtOrKe٤tO5V\7o82]ՏDUs\ o*XM|C?=`ͺYaÑ{S/ޖ>ãߌj.~}ʦݫSkw9zHw焭S̯ޅ;sRr1 @5O*oM~ӛ<1TY~sx)\8Z 8=o:6o:fu?oFwgt0ҚlR-Y C8lR-jy+V=c0lRm>zOO5֚ej!`z}TcY6V=#v?w,T}9z0>zF0 v{GyR ʲI}Ї$3пe&ˣg%(Rk#,4uL`= n;% Ɲ-44O=3X?C*mLM~1zf ?;Y6irfTdFN֠}ş66&MTsDN^D~gF5f%&MT_R7ԨMMzW=C{/ ?+1kY6ij.}kJy?zoe&MDRsψjjMZj<`[M}8Ƭf٤mpy3` <3lƬg٤}G*DkgC5f=&MtO<`~&TcNlDǣ+)τjIMqgA5,&M|#(zLZ',Ɯe$MK7D[пjs\f$ /c5sl~bՊ9 P+oIyOc˲IvAe$ʹ/Iˣg:@ FS*[M9/g:@R6=/|Fl6y)cM=6S*cM6I;QL=I#[/FZNc?qWn~SuȖ/FZeJiЋcbj:z4KHUw>ѳ`,7~Suϝ?z4HUh==T|<5w3wNL/1RU0:EKJԿk:#_To򇯏sbp۩.4| 5GY#URQDfU^;P15ֻFF/1RxT}`Vuxk=wa#UNoNE f)i7K)^?޵AR V@=Fj.}sFÿ -|iʟ+:'lRZP#_uo$ե)l?WQɺ}Q#僴z_Tj|վϽh+_TZ#~'0c ?OQ^eSEIuw{o<:Fu$gl^[&ayX/?G)U֞{kjl꯸8 j$_[.'5*]˦ ^IuaAw u]sI׿Y6Z VsץX=`=$ܤF+VxeS;Ius 5Sk ?/QZ/M 6X~θok=+$5jQ̯yٔݔm/Rc1@S6=/Fm˦sd)յwyx3eK~>R5{uJڗM Bڶ%)_y8#?T}?)ե /-챴zz/Vk~#"׭9w ?QweP됏R]8#,e 6?Q_R_eS¿`m?q8'h=lYHBeS~*f/Zso9MG005f[4>ÿhs.o)w.g5jWu˦dn\S 4)E5ePs_⥺>>uӤlj3k|0:M&ޥŽ4}:jԲe%eSwSMmes.]4Tǚۿ6lJ)u/Z&R> 0wqԨe p˦:e;>#MBOPSbgx5k<˦!$/MʛgL~;sR]׹lJfv?4 s߄gTZ=~gMÇ]oLc ӿʙ]9mp3zMײi枿&Mnm$}~Qmk.)@iRjT LbéM6w˦QJR? LA/s޽vtN+`@Ac"Qb"AА5FC&`-`o_i(%*D , VE Xn^9|欙=ϓ|fY椭9~Z)Ŧw/{XxZXo[Wp[_Vvm_fGfX~u/Mb8_w)ǦZ}uOcuڇX/|d<?zoڋ>=شuo'_Ó͎ʶ>3:p[mX.~lڵs_#c?vF8VK~jg[^3_O;6x'fGet?0$;ck[b[/ƛ|g+7?}ivϞYl{ 9E1;*Ǘ58?ɟAlgǦ];_v8_#Xt['7\lڵٷ".|X{{u|fyǿ{>a6,6ںl 2r<W{KobHcӮ+:_Ta`B]cW?3fX}ylx׳&pfGbȏ108JIDAT7&ΰ˻n[Mq3&fGaoݼ/G8KV˱ߙ{ibӮۧO~!͎h [_ر綳r?_lNWMlڳZOzT}?b#|սw%9o 97_5b}wǘq`r|1gFV7A2ylڳ16~VgO/[~ƩO9Y{ag[.~X|At0b}_7f?0uGuwO pl7=ig[ccĻElڳ[8O@xXL}Xl=mg[[Awb}'16|֙O}hX-xSόƦ-ܘiᚭö?SkXgO;gl)cOǦ-~lwE'3ݱs HzZ^0vxw滟5_~V&6oqg;9Noú>x,3'xۡ?99>V'ݡM[}ЋWH45\Of~{&Jr(E }lR c+hUoſ(bw%9g37?AN^12ꢎGϡ+z~-ȁ7p HۆZ rlVT7 0iXIJH H[8+my(%PN.={Q~MP@@@hxl7;<qз5 yX 9n$e "IUjhW~(EIg0Mx@d,s3¹0]ЮV @lK ӹ@uH[^֕R-_ tCYbް+}]Nyg\v,hcn!WL ǵXyL9`$/}[=c=R8n `c$Z")KL^/*ȱsdxsn8Ӻ~nֹ0/V+0q5rb3ipRf A[wl[x(glxn\yc `mI: g1uuA 5K Jom2k9aeć|B=UImM@!%D+ys&9"3)ZxRN ?n:1;CZM D*ng##ޔ&Jٚ<b|ߡu'IENDB`PNG  IHDR6Tפ pHYs{RkIDATxyp!֪h[[TZUd,ںtQk*nU $PYAYEPPVYbr}y;c{~y~3Ͽ <-giz+=֨kw' 9(-1zB Ck9NL8շm`۞yjq3(ȱg[{AlJ=J|{}j,rpL X4 >{7Nɼ&rшN4 w/`ha1W3&5uY+Kh̡i٨b#c49r3Q}6f~8oßSCboOq%ƌSD3`F3X Nt[7ƒɞq_5#L4%gc:5K<>Cl@؜=(Vx69˜о]Β KΜGy6Bl b&Lqdx!{96L6xL&'*:EI2;yUMΥ.Kdm!6$T@RDu5ȯXF{%dO+%?t[XIEXe\,9bfw{&{)S~Ʊ狩[S/6kLgy.{!S^s1 h+6I*D 6E$x `v"It ؀~bSs$Ta/#M[OMc/#MMq{t}$.^Fb:-7GP2"QlN 8 rˈ@lX-Ç *-I*jYw h)I*ˈ@l@G7'dtrbbߊ$,2"uSCQKˈ@l@ە{H" eD 6ZH؀bIs:{! mѦY$sD 6F+GTɷ؀bS#Iř4{! d^Hb:7+I{! h(6I*aNB"PlBUQp2{) &6b^JbͯXFRg^Jbh IU#H؜MRc/% fM^Jb,$cf/&$b"MljI*D 6ؼգI*.w1 h(6g#$`:b"Pl+I,j]Nb-Z3$kUD 6 }I*ΜGˉ@l@Cե}<43 .' f=% (84ڴQ B*VE 6T>#8sc/( 歝HRL`/( Ŧz^Pb;L"LlDMR&vc/)Ħ^ YIRq^Rbes){I h(6$פd{Q h&6sH2ً@l@3%sShUT0QW^ 6y'xLf/* ., ջ؋@l@CY㻒d~?d/+f! C=."Ll*-$ou{YyZt R7$9 U:Q];@l@9&=;]~7F+>*bMJƞbㅳJ; 7zt9$t&_|}澛O &r q=M7͆؀bS,c#uDAl@_%GgvJFT]|$bM=g5} RQ:z($bZYKұ_{]Tƞ79V$ruH$]`[2ьmtvUJBkk9!6'6u~:I'ص]XS$oU)d͞~/kuoΜ،>>I'ؽB ϒd̗~ bS+QP2r? <34j;:(8I2cwyQ!6.6u H\+ދekq"دbĦcXdnjG1 yb~,߷q-1PHe9RѼ+7j~b"Ŧ@q2>gdMjnV8QC!6؜=(I;2zk-Qs!6IRө+kM)dݸ:؀hR n'waS|n˜7ugQy!ċ͚t 5$B:ZyzD"Gνez?}ߐL8؀VbK&Rxx/w~ MDM^m#:5T.;7}XlHq?̞:7=:M ٺSy!4u}T&BT|'eJͫߍn^7ZZDfLug%`ܗcޜHMGӤN.M~=3{^T?}wVv=oйk):iV7_J[O,ٿ9l}ܷL4c4a֯[8ˡ.KL7F^QoH 7E`*5U+ qTO}wu*W)^fG6{c47 im'rvcSwS`*Y;.Vڷ}~lۢں֦ +طȧU\Wb(U'u_E;[O/V/ߞ-r.j;+AR1Ԛ/oJ:u֝=]_;Mk #El:y~T#Nc޳fbHsZ~ 0Fj~ײ%$#/zc9X_b_i.UǼ9ܗvz)5@3b4:(u7S/ͱꘃRޑ*@SC-$iީ):Լw¥9VT?}Ho ^\}ƐT~k"55UFuCVo\OISVM۞+͵R=ꭿfkeGFCmReJndҽIHkS6C[T ?\V1?a"оS8ߤԮshRu/f$Jsn>ab淪7듦ƚo9VC[x!Ug|0'OsKJ/,Vfj~#(k~?֮RuοI{ͩq?.FY/ mu_="'KOO hVl"i[OYC[?IS%0RyQ$kf}9ubO4Z_o`t|p}VTjkh=.ɑZ%~L~^TT?)\kξoru~nTE@ޡSca?\}ԩv&XjbC[8غ7 0/oJ ~Tަ mgw465N>t黽4eUg| ^{C[~1/ͥ|ӫ{ߥ#FR1Z7-4H3/h ,MUIg0-eKG.xEZN34_W z mu7UgJVe3{_ =˩#)wh;;)ͥηfؙ ?Lꃳw$#Zn0noAJu{T.}sb$npIyJwY>Ѵ|To}x·]k_4hf[Q>bf%9KRlw:5/)ޱ| UN]*'ɇdh\3/Rj]rxJ{~ޒTVo}lC[d8qST9yCo'Bs"]mhkgetWG9w#Q?ug*>KRRָෳ_eK'nO"j muʣ~q:?-#`~T~KJk30ML~|1Inͯ:w~Qfhb@G֦rf2In]wku4-7OߝU;LRڝm#Eiu~@~fj3Iłk^ۯg(MW+?QhOݙe~NT,wr?u)|NAtg5IZwJzp/{_j~or?~_g6IłV.^b4=u( `Qo},U+ߘ&w?~Ǣ}/FQu<7MR1zE#_&ٿR.9<NR1|yp+>b4UL js}kbun?sp>b4z]90Vzn$Թ[4ɭOcud?I*T}[T?h.[' `,/g?I*vYOۢ:/F؊R%{;IiWo-ޙb4yu:?`"x3b~-c~1Z,s`~mz](SMsίOjϑR9e4(X||d2iNotgQwSd?OJeh.k:܏޸nJϕR9%ڴ}?j}-%ӑM;}Ñ ~ck4 ma~e`2tn?#S* Cv.?9u/5gMidghvk_r?{T)M?Uu;SrgZ)M?Uo7r06jϝR9Z^}W=rB3镪cJܯ S;T*'0C^{E_|=T*'0C5/ܯP~ ЦxxF޼>~& ЦԹܯdоgR mS^~m ~k[;$T*'$C47G=ܯdԽSiddhZW|<9ս8ϨR9ڦRӹ_Xz_*mJ~fqmTy)q? ?VoA**cmښ3 "ԺϭҒ6eܯ,RmOr~ϮR9ڦjRM_X7-~~16Eun=95\r}k3Ta)q{Sur^0~16%.4~)YV*,CԼ~`#yV*,CۤlTo^1\ϵҒ6ᵯTeTTl+cmV-_c?|+cm|ܯ?GT.ww]3!!z)"EU (WQD"*vAL&LzOH! !3B*!T镄4HL|:'8唽g?~z.=BqmԽ+I$IX{s;/V1E$I$U֙_ {!0*Y̧H$I4Cs_Qm<3W$ITZ. !(X\<~w$I$UD=&GC[EB$I$I w ߃! xV.sV$I4.uaH#ơZ.$I1}~0Vr^U$I4nu[+bH#ġ/^$ITL s9ksU$I4yWu9XҽG$I$i̛McH#¡j;OI$IFvyY i8TѣT$I'Cm%TD$I$Z)vzq )C[ /5zJ$I3/1|_̡dj;0͵S$Ii7+zoȡd=;%I$I` ߛ!rh+?&I$IcgHAJ})I$I&k3?C V+CR$IMVɵG9D=+%I$ISo}9| m$I$ͩ"=ӶψߧarJyEHI$IUOӐ̡mM-ɽ$I$ͫsZe^ 6yl$I$iA5@^ iF\K$I$I w3[C83Q$IE8]5!qhaWGCIFN39SN̝[.ͭ3>'Cn3|Ssm{.?7?Ss7W9O5֙_ wΝ7{wg}4*$L[ ߯! Cۈʜ{y(IRlN=r[ܾ|:gjӸGgUEZ̙ٓ-9w[_YIZ}ߌ69$i,ug~ l_gig|>7'/lg@Lm1j3Gs 'sQDא$i u96 6]h<=%I{Ϸ{Jc[?{GEm̼u?ΕG B3VA{:wY/{ܮEѕ$Agm#sqMT߽o?(N/9G8K\k;0FmE7IR~ AyVjmܙo@oIREk}_ßwȡ-?_k2iurw?Ө̭%I}xnph {&I*aGn`ʰn~_ǚU3R8jy&I*ᯇ6l_~ Uf{ Խg>qh LTw|;7|w U7f#I[}\mAj+ѳL4EtJ;-ؔO~7FT:W<mA'"zIF7?`^p2o$-N3v~I &ǡ-HGG1IҨUrcsmßSP^I%I uTs "9kK4buowPSKr IҼ*ޓӲ?`r/%z~IF޽WlA|Uf</H6lS[xY$)=δ)&%3֋vԽgL.Cې5xWܒ$Vέ3>ßI0L~M4"rhU_["w:*vzQBvg}2$i/# 6L+4%7oţ?)Iъc9mphm$iku2P9sףJF暿 VAZ!Y%IRݛO͵_RCdWV4bu$iچF*I>Mq쟅?wLV.+$iĪgyrhE(IҀ\*vxA3ʨ }*$gj_ <9 IKg$i/mHJo閹}%I#R\k=;s6~!碈QԽ\ß5P%ӇܮG$@͓1iچED&IRks4$9UT?x钤z|?iچwѳIz_0ʽo+/I ~ŸIȡm{&z&IXҽrZUC$$)? ͑C۠g{L$v=7O [εEOIRTZLnCۀ:z$IYL6OJƬȽn΍3Y6@~mT_Ɠsm?S'RX$ b38sm?{ ̓C %IZhEXWx,wo;;]G/vzQRY'IG[ȵ ~8s4Lj${vn_kn׹+ŸFCL*_cԹ򈜖mαMP{\;W[_=MqhOK$ȭs?7ɊPzܚ;[g|>Ushu$isy??3jO#9TrSgqk;0|C~[U.GLIlk6 DwIZV;/K >ijITAm}8G$iS: `Z~:zHR{*wwpn\9-}J\4&}*IOp:4Mֹrw3/1gnV}(9 Ԓܹ#I}k5E3zιqrmZ ˡj+_=w%Iͯes)s SH_{\j0Y.mbQ,IZ^'7ghg]DO#IxnwM\qhnot rhgEgIҺEn ^mރ7EO%Ixܹ:q;rZ9 LC[l;y-IZ9`d\MƬӽ>o8ޫ'=%IA`4}4W ^ˡ?ڗ=%IM У hj1%*U{ܹ:qrZu&B9$׻;3\F[]ǕUgZ.ˍߗk;&yO}X4ĊG{՞>ph[%xg$uo}9yj/9D9-R}߈~vHX׹~?zD?r~r7ө۾>7ys;m$moʵ,*7=$͵^]uTn Uph[$V%Iqj=nPӟZ<&I#V˽o̝+̭S>)e[ m1E.jG?v$i,P9 |G4?4Lqu C"x?$Zg~!zIcS\w^ۗkɵi;s%Izܖk+ *ljIxrж&IC>1y_cwFO=kɝV͍CޖӶO ̡mPKƪ9Sߒs=RT7wo:%]G/v|aamzLƪݗt9OOrrrkk|U4";S7IZ)|m{Ƿ4Uo^5ɍsh[D?$ilW|24.Uгjж@cwD?%i,_5OX8^}WNɡmj,(IQ>u_=W;/K5> ;*ȡm_II:=(|OLT-}J!4}ɞяNI|Ez vx~XW?rcgiZ?wrZ+iL9-@ߍ~JRky!c{^^wC|m$U4$~l@mR jw\6Mrhơ~JR+\?-`S ^3Uk򶜖=5:6/ؙ_~KR\&|EگGLb={)O ͙?L,C)GONxyQn_{^ph#F?%ux=:5jRyan_rGm014m|$Iȵ^>{TQy?ˡmGq\*[=aMYSreqrm74ms♾Q><;u84zԖj/ oiQ풤U+?@vo?=rGN#Nn_wnHޫ@9h~ߒHRj_{lc[˽nȝ+ȭS>1e[74@msоloS$R0˶ʽ!U ~~-Tw|;| SUh&V* i8A^F*Ss:MJ[{\;W'"yO shKl%Ih<ӶOV?9E.˯v[[67y[N˟Tm;בԾdsy*U_'H%ж/Щ$U>#|D~Y4Gj3:_HжfHTg:@+^_UshیOǓ$-Ij; G;`"9wjn[ i 9mF7B4u[3eL3>҈phۄӆ)I]ot쩹ȭsE UphۄA=SƣyajΡm?2mTV+ڊgt2$w_;WQi{y16}v$ 's4mйTJ_s߆s4mлT]<.6fj{$I {Ƿ9p8mDmחG戮TZg~1|!qhۈơO%yġm#'|4z?RW CF[JR|Yȡm#:WJRk`,HCж;/Q%EYȡm#-$IZ ; IDATX i6dr.z{$rrhۀ^JRk&|!shۀJRY̡mk6zGV'|m|9zOֹ~uH6}پ{$Y_ )Cto81zO8]s phۀޏ.S%E98m@ETʊGo)Cȹ׉U%  1v~i*IuTHAS? {$q>R4y*I8@ жS%:9-:| mi]*IM3 rh[OG朗Tʺ7>R tpf*I}3 rh[OwUI*e͓?>R wUI*e#(|@m"JR)90ǡm_JR9+z9-:|@mi I+~9~oG朗Tʺw^>R0u4zO*Isq3 sh[GswUI*eK )Cۺ_>JR)k98wY*IyGg8@ ж{G朗TG;|`m\}t*Ig8@ жͧE朗Tj;4|`m]UJYZ9-ѻ$DH#mE}UJW ZsJRm 6wUI*e;.i8ͪ]UJYop4fѻ$ΕGp4f|S*I}پ3 Y~/zWR־p6q{wUI*ep4f5]UJY/p4f5W$zWR:33 Y͓?JR)kFCOg|>zWR\FCz_Ij|/g8@moJR)kFC۬+wUI*e8|6}ѻ$>phչ]UJYi8\*zWR8g8@m7JR)kFC۬E朗T5|6wѻ$Aoi8ѻ$26mz\JR);3 Y{U%5}G H#mVkwUI*eFC۬E朗TG+|6 ѻ$Ƒi8=xS*Iq{g8@mz zWR83 YGnU%53 YţG朗Tʚ |6x]UJYĿi8*~]UJYOp4fkU%B H#mV}ѻ$>phUwUI*e i8*jG朗T>phUU%/?|6=JR)|+3 Y>uTVگp4fJR)rz H#mVۢwUI*e;/ i8=xS*Iw53 YU%>phջ]UJYQ{8|6ˣwUI*gv H#mVWUI*miۧq̡mVTI*m_>R0Y۾JRi99rz*I~8@ 6{{$Ƒ)C۬kTI*mU )C۬εE禍TZ~:|`m:W}5zO:wYHfu8,zO־t99j__*Iss shվp=UJ[38@ /ĹKTI*m]>R0~!B*Iȭs sh<{$HHf5W$zOV9-*|@my*Ig9@ 6qF晴TY9ͪUJ]?)C۬~Q%5Oh,HfxM*IuֿrHmj;$zGR׾xe,HfV<+zGR׹Y99E*I{`2C:rJRimHQTI*m34z@m(a*ItY8wk$n>Ruto??zGRW? qh[GwTI*uͯe,HAѹUJ]τrġmvQ%Ե/9| mbHVg9@ ж7>JR~^,HAQ%%| mh;$V )C:!zEW ph[Gm嫣SI*}5|mmTJ_? )Cۺȹ׍Q%5Ox<>GwTI*uWrm=GnQ%u:*|m;$rm=[JR+=|m\U]ҧs4dmi_W*Iχs4dmH^㐷s4dmi$s4dmiTJ_[_iS?$s4dm $-s4dm[uEJR=xc<. (F晴T:s4Dm{UJ_msarhۀߎO%5}{<HCж뎏O%5l>9m@;D戮TZ. i6E9?SI*}+ i6yǢSI*};/ i6qSI*}O~>9m@7E戮T"m>Ґ8m@mWDT{jLHCж!˷I Ij09mQ8mD}D漣TZ~:|!phۘ[\${tshۄ"=JRrF<HCж {JR=rk<HCж ݛJRurZULHж ^O%|mLH6/$iq5'3 C&4lJR%j̡m_ygn*I}~3 C&T*Qg:@0MYԜ^~*Ix09XmQG$ȵ i6{$U>9mF窯F漣T>>9mFmwSIDt4@m9mFߋM%:|rhیnM%9Mm>Ҁ8mҧmETj2~LC-z7J8g:@9vvn*Iug:@9\qhn*I}3 C\Hg{n*I{y3 C4W}0z7JT7|qhoM%2ն^\H6_JRem.ܮE漣T'}<~LC>z7JԾdm7JR%mJR%*;|phɟM%Em̡m__ѫ$UAo樶G勒T'}\H}6WSKrnT*{/:d9CkwSID[NsT*Q3 CrhơK%25Oh\H}6_JRej_K\H}6OEsmn*I{i3 C<2z7JT<~wLH}6O뎏M%2vx~\H}6OooJRejs C"9-P#RIL͓>>"9- w֗RILK iqRIL>"9-P}F勒Ts -CB-}JΝfn*Ig;9-BRIL#>"8-B{$U75|Eph[+RIL>"8-BD勒Tz]>"8-B}_K%:u[9-{jlH ж˶Y %Ii0g;8-RRILU isq{$U;u@m{$Uͧu@m8ϢRILwu@mT5{$Uڎ/ ikj[)z/8wg;9AߍK%2Nt\H JRe|_3JReGQ^*Ih=1ɡj<9IRIL><9 yʧRILEќv4m}8{$U isr.T*Sk><8Q{$U+:@>xR^*I{is ̓C[[JRe*><8$IKg;@#>|uN*Iq{g;@#~ZORIL#~L΍C[u$z/Թ~M\HsgK%2>9Y_^*Iթ(rmv4m}V?-k$U>8ۊg\RIL3?&7ϡmz z/Թm:ׯK%21|9phTS˵ i3qRITC~'|phJRj mC L-ET*Sg;9 HF勒Tz^>f8 HݣRINVN˷ik$U>&8 H}E裸T'}<|MphOɹRIL6@JRe}i\H6@K%:k3?-=F8 P^K%RM2zphoI%R5W$|phG勒T6`K%2uo?/|phΕGF勒T9M- i>s{$UWvm8;$Uq>8 Xm\{$U;vmC{T*S:@!\w|^*I"iD9 |֗RIT=_>zچqĻwRITU i=mCP>AX=g;@ZCې@I_ݻ.i=mCҹTS-g;@ZC۰T*U}ׇv!i|;$UI imCR9T*Sv!=xS^*Iw:@ZCu>:z/mg;@6/^K%RzslHچqۣwRITS?>,a9:{$UUGv'9 YRILo iCېu<"z/Trmv?k$UW>C~KN*I ɡ-mG勒T:׭m!z^JRe*#|$+K%Rvzqlh9 _I%R5zOlh9 _7F裸TZ. -˞sJRe|jl^ˡ-FߋK%2rh{$Un>yǣwRITͯelƛC[JRj_SlƛC[[ܮG勒T?<'~y9T*Sx<-g;01/7z/JUg;015OT*Usg;01T*Uҽg;01"Mm{$U]v +`;/K%:9-*|cɡ-X=RIT~#|cɡ-XsGwRIT͓>>D裸T:;8|cɡ-Ԓ\K%22~y9mߊK%:u9mLk$Uo qhcJRjLP;$U5džv`b8RILGn qhVE勒Tj;$|cšmD/;$U1>6"nN*Ijg;01VFŶȹ׉K%2uxNl8qh!K%2͵9-}Jl&ƆC|T*U}_ph!͓>JRjm#wRIT+ ph%K{$Uv ӽ{$Uȵ>6bJRjL<wRITs&g;01FLmWD裸T7>6D勒T9M- D9'G勒T{Rl&*ϡmT*UsGg;0Qym#h$I}پ<T9T*S D9ރ7F勒T휶}Fl&*͡mDu<2z-J84:S;$U7%|61z'Jչ~ul&*͡mT-*v=z/T<~wlr9ݗF勒Tj<|6ڗJRjW,\T*U]g;0QYm#kwRIT;/ De9%=JRujg>l&|F\3RIT>JrhqG裸TZsl&*ɡm5';$UU_ D%?<ڲ, AB IDATF1Ҩ QlvDDDlih@e[UIU$dN@HȜLd ̩ϼ p}#|K$I4.:)QKF]$IRjRm5RF.I$Ө,j𒽣I?vI$IFeV_{RF]_l$IiTm5/Fߓ4Jq]$IRQYեE=}_ e[wI$I)YըgEߖ4JwvI$IdVm}O (svI$IdVz7QƷ>%I$uE[wxU=)@ )[#]$IRYլ򱻢oKϯvI$IFdVF}O (>>%I$uE[{RFFl$IiDm5wDߓ4J.I$ӈ,/NEߗ4Jwן$IRݳhaDߓ4Jؿ $I:Ϣ.? QF>%I$ujE[ {RF)V\>%I$ujE[ {Rf)˔o]$IRYձ4ȢoKwwI$IYմGߓ4[ۆvI$IZgVӆ}O ($I:΢z=)@)[Y|$Iԩmm5-goI$INmhqEߓ4 $I:͢ƍo8)Q>%I$ujE[5}O (e`fwI$IZfVzA=)@tw{}|$Iԩem5._Ҕ"Q}4|K$I2W}K 8~+|K$I*e(@ ]$IRVY52[}O (O$I:ʢ!o<%Q#)(|K$I&48{q=)@txC|$IԩMm wȻG?wI$Id֐[T2!]$IR6Y5Ix.I$S,ʯDߓ4Nk$IN-hkP?}? 8}(|K$I"-3l.I$S,ښԒMSvIx.I$)!Uuq=)@;d|$Iԩ|m kxn?]$IRY5 5t.I$S,V˖S!|K$IT>Vf+Is$I$eϓE[xJ(@@|$Iԩtm lpl(@ /;|K$IT:;GX.I$S,X|2Y2ۿ2|K$IT6Vohsڶ{E$IoHc?w\Ҩm3ʢ-4a7.GE$IXëR?I 'Z7.8g*E[ŻwI$i}˗mzɏ^{L*Wݿ dˢ /o-(*|K$Ik\G@OSUKe1+o3T+?Sxxsڶ}Y$I~|-jS}kbY5`z7|K$ݭ\}q𿇬bY52[@M>=%IԞe/sծ<4ޞ?wU,7q>%IjS5}T+78k6hH6?>%IRd7;*E[@#g3^$I5ZPlfʢ˷]g$Ij\GnKMoBY;)<|K$"-4lj?Wm*:Yѕ_p$IRG@GU U(48S@#/IU~9QV,ZPwD_w4`/I/<4濧wKD嬼-Pmmhɦ) @\?%IU|t ޶%I=WG_3ɢeuyK5X7s^$i}\5Wfʢm-4a7:h)$Iϓ1M15U(VuquHN $Ih}.92_3ɢ /buHeﱹDyI\Q?- ?ſgE[ !@cu}k$I(_;4Ȣ B>:yFm-̏>%IRʷ}Y48{qxQ ,ZZĽ"@#o;7|Kd'?zCS⺔2mQffE[Kkƃos^$$U&h:YwyIT^zI$o8)Gߺ7UV,ZZwD_59/I˗mz= NL]{L*W6¯BY^x}=4R9/I*\"m ̻QfE[+"zh|ׄyI4lCUE#"z*E[~{9/IjGՀk4Pm-n/̏5GyI^]yh*-mTZ~fʢuw}]XePf7 $9ZɓU;it~?gE[]le5 X}?%I3>:yp}wU(7kgG$\H z*E[Ivn$U5mF Yhky~?h [h$Q-7O-Պ{;sa:Yɿb}]4#+ѳ^F=Wm؍>ށ9U(6Ks^w{m3S{,(Gw7ώBYikC $U\bu6>|dʢMGKFs^o{!G@{/\5h|ϘdѦKF<9zKU*<1zeˢMOU>h|-g$m՟V"wϸjeѦ]qP5 h?>%I oxG@ǃ#hϽjeѦk7>%I|G@o9sՀUr[˙jeѦg4)@ /9|K*MRw7 FNEYk|ө3tZY Y}4Z^T `>"|fˢMϨwD_ 窭z ѥ٬bY[_Sg>>%IВMSw7I+MŊR*c` !~T+6Vqߕ*@o=+|K6oHc?w\Ҩ},Y3xZYi3Zh0˷|#GOpS>>eѦkG?|K\l'6x#3;XmZ|D_7yvO$䣠>eѦ5V>vW her>^[P~/|ngˢMkltQ+@uy/Izf>j[vV,ڴ&4`~Mn$ /+xnYŲhk+@_>%Ilt@mۿ2|ngˢMknƩ?}4^kg$7}4F vV,o=+hI 4U06=kslo|^ߍ>j Yhӳ;]-@)_E̗$=Y?}2BM3;`mzeT]/Iz9GLhs6F<蚣$^}$vV, /;hr*eK7 {1HY9C.@+}w̗>jcxs;`mz_}}g$Q>jcpYy+'h{S6Q̗678G?s;`mzF}Bw߷|IjssE;OvV, Nl om>%͍8((~_*E>o~ZXy}̗676.|ng̢MMRd0@+tw/I-xc6m~,|ng̢MksaV3_Z{40evV,ڴVy0,(<|KR+EG@m3̢MkUwG_eܗQqo>fѦujx^3@k NdܗVt3X.[jfѦuj,m}IjC~>zJ gwV,ڴN;*zhb^>%g6s;pmZ犇}]O}Ijz3>=jxU86sZ÷J767> gѦu쇣k(˔3_΋=@mLq"zng΢M\OG_2ƿ~IjrePvV,ڴ^}mFqϥs_ZODyZgwV,ڴ^<4h?>%P+> gѦZep &ٝU86W/kU|$OKoٝU86wF__Vq6s;xmZF}ܭg$5E?=jç,:ϛE;ϳXX÷FIjJ.[FvZpR*EֻGXX3|KRScV>gѦ Uleu*KԐg/28s;xmڠFzu*e-,|KRxJX Yųh589@/IMVDtZٝU<6mPݽ~5:hw T]~6zN;xmڰf7Jek]ƃo3@j\DOs=¤;xm7}NOIs wR{EjE6}΋$չGrZ]wljE6}OY ?$-$A=je{Yi[I*G_3S,4f7Je`>AʝᒴuѓvYMhԚ|/ opgIK?=jgt1;ImZ>}aotQcv. YMh>@ku~s9 IxI2zdNk?gEZ=?@+ /+ 75@-uyK jE誯F_TMV/ ?$ Κ/<|g5ɢMSǢs@ G5@O>eѦe hKIj-R*FѣvƷ>óeѦW>z{h-_ IkG4@-.'|g5ʢMSotŗ@k.? *6i YhCsYʗ4,J5Q*W==j?3ɢMS/)e,h)? $J P[ί YhӼTu,hb)]~HRU^kh3EᅻDV@Rȭcw\>óeѦyw軣@=:,*M#>dzeѦi4G*F)I nxV'~"|g5ˢMֳg@ ]Y I\=jke2svW 'eѦymtעg@~gy I ]˿=~jmxY06k>=Zo|$-t?gyV,4ll,Rwׇ `-}A*{FO_Z|~Yi+9z>IZGuQ/e7 Y hӼ7d^~&HB4 PkŽWYi䁶o~&H|S* Pk+>ϳfѦy/_9ze! IDAT/"\lx.'~"|g5͢M )?$iZ#VFZ>S,ڴ/4b6sA1=fo=JcxzV,ڴu+OIZ =JãE:Epi_H IDPF=ymZF=;xStAٞ7z4FH48s#qz~|EB5=CXs9r$U|MG&@/{IEBkc5^{!IܭG%@^>߳dѦfy@$|W4̣'%@ԲhSX%SIZS?g|֐,VDEw{o'?>糆dѦ~qJ^<` קl&g$}GFF*=|g ʢMo>=z,'}2I#=kts>kPm mpʧg ϢL/ ?+$|KR#jgY)|)<ݢG!@uY5(67yUoYw7T'!@cSxy5(67`s(#HZo{/6y?Ӭ,^ߎ-<79ԮSh>ﳆeѦole|9U) Ih2oѣ{ZE*芃 c|ө煤4Qzvh 3ʢMw{g k߅̿udžYm”yyR IRvG@+ NdE* ka|gGRqU#5Bo`mL!z|0ܐԬo=Z|546U|WT k\!4z_,UYR0zƷ盪$mp N>fѦJ58ߢ `pjMoE2w3`YRuw}]`]ׯ@>gѦU>z&s;E燤z?/R*: ?gѦgCISzGƷ+lZE*]?GLsStsEoTeIk}Sls#kYmM8e۩ ?k$=G7Io=-XKN?;fڗEӒM=gGy#ie/a>,ZEjgl?o$|-S(o3$kamU~/z\, ?s$=(!YKhS(O=X+{&T#K|@M N\Y2,T=X Ϙ{6T#|-ߌG'YKhS3 Tsiʷ{E#5Wwey86կE|*9uw}]$5ٍ澈$ 48{q,Tˆ=X`egԴ_Ʒ}0%^~d-΢ME." ꟆCR#]'|#W" G Im}iL7_~NI 좹o-%`)_EY4ɢMo&VD6*=_PY%c~?^}d"uʢMh/E6*ltQ)'+iu|3yh?y*65omT\bUTuS* `eﱔmIhSc*1zPw;-i}~mt)|t3hSc5=[Xۿ2oON{u{[93hScw~P_0qҥ/?ǤwE_&TTJղhSzVN>mofSqUї78 gѦF?og5V>znijWN202qwKղhSZTvy\?ZѵǤT_S0u֘E𒽢g 1;=)(|Ssʷ{ET>%@MNehS@Ôܚ~&e[(SM[Y'OxsJ٦,Ȋ}4Y{VYz s2[!GγfѦF67^]~}֩Y۾,Q?zŽ>k3w\ ?y,F=ha7:,)]~j]B%&_~*=WmjlC=h'5&<s/~6nʷP鹲hSs(= hbuipSi.[ ON{6D]qPfѦF73Y,FLV>b:-oSYS7vGAGW:Pg96YOLuS΋w;-ٍ֧Rwץ{S<,Xʶ~q٪6Y-ؗ"P{= $ۿ2H}D=o|OS1=Zu:6M 4aO;G uyKsm)gR=T>rkJefѦV깏@C4Mo:w-,\^cK6M[48 iti|7S)ƷF+KmjMR*O-.8/᷶K>79lI}:oL.[|צ|{f;={_2EOIߞ9<; ֬_KNY5yWRf+JϖEFxY kx6JEZGJxnV}:whSʷF jtaWmj]o`Wmj]=3`Ʒ~߬zgѦVVXg&=ߊ4\؝)[i=:SϢMzZ$zp>~μd&=EXq]Ul*Gm?s^u-6[i*+z0eﱔ/i}|e&ɿ04 ^~,ڤ˗m>/ 0 eє/"~Wy͢Mz=h&>WyϢMz_x=20^~μg&=G=7%VɢMzBJe=r)E,Hm4 @M Nt}: E=%{߫E>-xJ%^U):6i=g90^Te&MgGz[ۅ߃S,ڤ)7R*y<*Wݟe߃S,ڤ)6<o=թlm~S*<|^6(Sf&MѵD~,}ϩNh\w_HGL7թ|m<4l3))|~Nh|Wr*,` S}:ȢMg/> @Wlɦ"6iꅩ|3 T,ڤyǢ{WS,ڤlƩxuT?˷TSm<;DQTvYI 3#թemMsݔe}:lp˨mFjr}\<GujesNë;:a}f,ץlɦԶ;ͽ:~-R->7XL~ߨN^˩ ?e/IFѥ3SF8z{FjC}(iGňEuj^S7Z4sCԄw^8|#~)b}}iL^Wa65dLiLeVL#|OePN>26Y?@Rۚ&) ot4oz|F$ٍRqϥ @۔ߓ[*5}5?Hjc>+,ޡ#^P5ƿ< (B]qP=:lCzu&#(;*'"QeXq\|_%y4[F~g:l&)z\ :ڒMS5@c /%OuKx-FןImR*s&Ԑ-,O?h+x 𒽣Sw_ Sэꋶ| 6/|li SܶE[ؿ ᤶ?}@o93eitN?kE@I4>>_~oNϾh++4و&U }4Bשӊ=mnCJ7y!!F}9uђMS{m9+<C'_2~?Ԇzsg,FJzoN/ԙP_A8uZ6϶{E+Ɇ}qN%7FŢm?K+GS q.S6(Mw?qE`I?wT}6N])emjWk^E[*Z^<O53~_U GϚ %=_o# V{55.ڊGJf7 %ޗGHv)-xRMh~_3 fe3Wy_Ϻh?5}iS5z.ƷG=~)!|GJe1 &NJ'S;ֵz>-4?^۴)Z8eSj|hKAvxuFՋRt\T[/{IZYw7v2WHMK4,*OoS{kz}Eo?^YVw{z}^Ͽh6-}A*v},J~Ow#%ͧk|jѻR悑*YlTv]z9}9?p]O/™'۾퍇q˱}&? ~C%?v׸pef?'u<=3loN~hmUNb vCwOީK]wd}G5Rm,7r؏`M-cluv Gzzh7?wظy=_1xg.o9kHB۾>96_h3{ގ#ɷccv'?n׌?жoԿ|/=g^2Q> jy19|6=pm/}}k{Q?d}~lol}g&<[g4`f_;s,7sc?:tW]:v iB۳vx$5[m}[LXӟfvxS!Y<:a|/[{;S_Gą1G[%Vh/^;6o;wؽƱ8c/N}ɮ m/9O|j~}c7͛b̮qKV}.n.WFkD[k{cO{[_<6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m @@h B6m0q SKX7=IENDB`PNG  IHDRrr݅} pHYs{Rk IDATxwEǟ bÖhb5Jػi$أƊ8)(MrJAHSD"lߟy}7o۷f7H27JR(R(RtLs#+Ʉ lvѴD1y+'+;8Y`㮭=0H">{$r}(d@ F/j9=[ -SWά`\?֗/DwKiY UYF]hh S\ Y|O Gx8E#ǯ LgXȘ5"=Yjo Nx^3ކ }o?.nȦ 'sCANz2a!o]SSvQudφ̮lTE 37+U<{ЁVOьT9>k's-Ƀ7/nv6~,Hs|O$m?e@uW'[? wƞta{/=K2x} *d@g~*E!׃\|^RqZaOzFa3w ])x Ț>@"mv^$Be1/;al2\,g&z8qDִGro8t6E@8!g~_ƃ=u0 F#ANddrfҜ+0[;os?=OJZhLA sZ>,ixE8E" 9A*mCb3x8*Zb 1B|"+H&S 0]@b/JF10]@R%1Am G`Zs6 w7rcV s!7r `6rcV 0@}GXa ?VM&i:MB`2aڤ"3 I7@3Kax x9"|䨻 ~)=+ R,L&Rw ()k-TRa- +hqYv #n#7Hrd /te7Vl @ZjXD{?^FZ0A+Vn6=WgBӶ:;qWUdV#Hkd I"vx*%7)Uh+v%QIlQ,p\_qT'?On@2Ocɍb`Uj. LJ=O&7),=Hש|4(BU }, HbA%obAҘ٪JGP It g 3Q /=G*TV, [ %guD-/bAߛZxu@7ca5sU7ϐɏ(ciTP`9Ph2P!rx K{2Z]ifU_x!2=1;V() i %4{Cתyv$ U̒о[S^YIH^lNB*H"YԞ+wN$ݵ!# S'ZP)y2kCF\d3rJv&ggHq #ĸ%G~/o]mML㇖}32T)/,mTۊ`cyor5_9a`ݎi`?”&w.읓7O60D)HMD)HMD)HM=IENDB`PNG  IHDRLLǗQ+ pHYs{RkIDATxklTEV$  D;/1#~hԘh$5/B -U D [bR Om ܹICݻsmwd/{u̙s&q ) &80.%8MM ho#Ēc_JubD`bPRݿ+X} ġO%mCiWX{() ޠg=z4d.,9dhEF!OMA@-| _}d=:M I`)meQ&*8+ ,}.8 ,z<`f͇Q51΀s5YЯlj`VgHS>5sĉ&Z0*_ڽٛ90) t!0~|+'9=0DAZ <;acv^Ώ@JXJ8[oEaC[q3q|[GA>0)0m=T@ͻ3YMCCfl{ٛf=MheJh iZL]y+>ш80z=t4:0T3*0ڹMr`uHS؁,a \`fݵr~Af%706Pe<--0{J?&y;?F-̟?t`֡Mc&*0{Sb`>'agr:p#.06<,/0sec-"ͅc-؎6J 9-JpX [z{^33k?Vp:0U#/07T`>vLlx`Ksɩ)M; #90ܣ^%{0<:0cIMm]`l}EPV3ŚS{#:0\TCjm<4aJŀqƤ{8YI? i@vlHD~~(;0Κā1G-`عƖWŁiD mdf9"9H]b80og E/b\KfUsdni8&WKSԜ/XȾށƊ_G56ķ1~;|a`,s/kSBM6 VHx:}HnYxw) d _^g>tSp E ?qo|a#tqԧ}T9%AIae \V/\;&v'YbU\ͼfʦZzR&~&80AŁD..1IENDB`PNG  IHDRx pHYs{Rk IDATxyU}bQcՌڌmӘfjbmژ 66I35if.22"(8$EgPgg[X\ݟ~^]+p(ֶ_8gӿ9ӟtޘԴl g|ڤa+[ӫr{mŧ=GEvq[pޏ_O$?p[& *k&լĿ3Yv֊.XW 9!_Y= 6TIk_5+`q[jEw}ʽJtKk(^^1\_~x@pYS/"իR_'Կ}E_p]9\x_9M]rmxN?ozO@nͫk/G?QcZ8\@]oMkOk0-/@0DQ c (k1?ҽ;gp`6BTk֞w~ש?7ruOuw4A~]Z {s"vg[ #Yg[8ۏ> <&>kP8uuj|OxmG![l'cPXڹOzMvw>[k__Wd굟m?S7_ɶWcm'6hEP)pC`gTme_e hH)YMWֺm<|Ï_ 9+POYGIӚ_ǩ ~etoO&+Jްs?_˩qdO vA%a6|zΔS5ioezJ! 7Q}iђ__n"@E(Z[_T Ks`K F?`͟Vtk<^,tc`7g:o6?! ZoOk3VlvRK=f~տ͊}JJ0Z~z_@%4XOfWּo𪯫TJpTъ kf*y?_4ܩ P)EּoU/m5T@rM\PI9sEwԪxh`J /?gL*кM6ݣ^n?ri)W?PM@7 .>M~ޘ=̦;VK@7KZaMsǔ$5 I0Ksǔ$!6d}\"FwSE@β;Sao6! gs[S~svnP]o!xNް_Pa Pи]Z& %+?934oS3@* tn{/z?p![,?93Tƀm~?0FKslxWG7MDK{\6z6ݹQ/?)Xn =mqDvkhqoޠhQo?SI}X3CV@xk k7`ëeoWL>Fl^\pR[INN 㷪ai}e?l?~-pNcc?]5w{.3}|tI`ڙ6~kT'^]YoQFeK ؽ$n~߼I{;G6=8Px~-/Ƒ=9ئsLkk~;_Gr.Hb|s(ݾ`Z^lφ3aM?omح5=b@2:lr(@e)^&^D7vǼGPqɦ{l0_{`78R?e aFK+2@~PQ٥vhǝҼ=+P;/ S9Ѽ98j$|Zldi~6Qq8~V k]ln/KG'yFs$ r8_nPo owCe M)p-u/9|͗86^7OT²;j)hK-[MpX5UZYݓeV76u^{ Okl࢏׾)hZUvPKcF+\,t4aGnjt<% 9^΍#j&^K(.ޚwF󋥍USnr/R mC %?e4+_=K]Qi o/`cQGM7k@t@چ~Nh ."?,q4/Ԧ^T+<\6f)}z9UNCqe>֟kz$_T+&zaIj|# 7t ޠso{) wZo>UV+ϲް7˟[&-#pXv=p&);퟾6V5{W3F-K.ޟ ƽY/v oO>ݚ>ȟ/9vhټ?;iIO{~W۽ꚷ~d>?VP?}GEwoʧ睕R7wFlx׭7-jL:Hȳސ䛇qŶo6ІmQߛjH:4VMUo?8(u|Py.ům}W?Es{#\n|׺$XѢ6zl }m^얢MCzhݸC7#j)Oz5IܼazӐ.{z:[>P!2 h71|Ðh\]}m֯ &|R7 2.nb/yvKoy]:w^"S塐)X}]}Vܞl lW Mo*P=mNtۣ|nO"!wAJS =QYXl`kO4?6P?^"S$@!JX&(TGs7 Ipg R_KF]I퉬3@t@x&(DDdI3H6'$DDI --$DDI4ܩ>W7 )ao1MBDdJX l^- DD>~^}UȔp jE \!"2%-qs' DD>U+p@oo""Sr+g lG9L}HW-p@n|sU䛃Ȕ|Ww^M?7Qu>Wp囃Ȕ\ \9 "2%. cs&*DD;\9G/DD:W\#'7)q3>Wo䛃Ȕ\Q+ps|sp az'DD;K} DD ѭ @DT+pG囃Ȕ|e @DT+|\#j%>W"ZyƊs0o""SP}ހ䛃;5I}囃Ȕ8?]ADdJ > DD+ L|sF8"z|spPGW%DD;2@}o""SQ+pD7)q>Whp "2%.U+pDcT "2%. CG]/DD;\#+囃Ȕ\`ڗ  DD;L>]}/DD:>>VP!"2%-`ߨ86!"*k޹'8$x| tT!"2%-fm#T+pD7)iMs' DD>$<>Wx!"2%- ްT}w7)i8"7)i b"$DD>D8y|P?3 .|7 )a8$Z2XIL }~ƚMBDdJXiim8"yz|мfG]MBDdJdȮt7XF!"*@2U)pGȔ,XyLC«%(DDdIhQDz7 )Y 3is|%˾>SBDdJdǽ_}!MQLɒ ^#g  ~|%R9>),DDD3n#,DDD}W8$[BDdJln>S䛅Ȕ(^]?%,DDD`3!0DD$ܿR'p? CDdJl0zX3 g~[aLI Oܯ>Sh`!"2%I:k8$^;GaLI#g <|$V)pI[!"2%H:S>>R7 )A6yDŽ|OiL ~֍LC7 )A )ƻg ?PiL USg z[囆Ȕ Pw3'8DD@p \CDdO>#NR'pL}/8|h g X5EqO߭>SUCDd@g \i;@yb{c#
Op7qB :Hyb0[3^ O2uKDdp X5Uncn0m68$yf~UM6T)pG-qBG MRnCrgS<_DD-nT 5g  }|*Y_[""@T'pLd|*~P}1w-)x[8&[uKDd ^/8&Z~|WrO-)h R'pLtP%"2͙?}&_DD93D5mѯ]"pm#/|->O떈0U'pLK떈0o[ <|ڬ>S4c떈,x\}AnLrnK}1ђuKDd s@pg j^#}|l}P}1[""S8~ï떈('n@gk-)PN8&Zӫ|-bw.QK1rsȾryDŽ/_DD 9;d]-)Ho8&zO8KDd9=x΀kȈszJ{D}1uKDd9?4>Ox%"2Q'pM\!KDd9??>N`ҧks~0lѢ>KDDgMr}[,_DTZ{Z̻mxl 6ٲ4yupT@|0a6U+oq6,-eY{|Y!W;bo?!_DT>󶾰k$o艹>R {UvȽl j owswb΀ k>Z6&Ws~gr {#"Q]"*[ђܾ+m Ϻ .|&6|>}nߕ >뿿4IDATw{Dw &}6\ml~4׿Ii ?~|Q'- _&f΀贸FzQW~nY)׿[ \9%Bvh7=/G3sj'|XAKT g6VNܾ+e o^ygFإO* M!/Q͆W;p~nߕ˿sP "˺ A5dP]R6{+s--_Hy)-~ݗ.Q)j;N])3>W+ڥO!ݹyO %r_{Oz;;+\ g^ȩ[۶T 1t@VqeoY.QQڬޢ`q)ƽG8(^7Ov$95_?r;[iu큩s{~>]J9d@\7Q Guk@vE1ЮKg?[=ݦ6:\K9[ܙ;Дl}Pv:{ҹ/>Qo!ܿu vn/*y|ҹ|n_jޠcs]SϼUR~yCOl^,Z2nfTo 'uVx4^^ _T~얷\ǤFW#-l]~JFh/sewNs{(5K=4]˾(_TqS+#FA%>,};/p7K<"_' أ4y'_Ӕ\W׭}~V}emwwӿKuU +ybz=D/4WtKcevj~sz=Di4خ^rpL8k7S>+_EwS/58b_=li@$>dMk-CTɝ&=/|]S7իUx\S *,@ɤN 9^^/f|SM?һr/tƽkb{Ϳ5^RڽVvW|M _'F𻂦s /)}@ V ~|}ӾWwz9akk1$o1& A k7[Zկ|4o3#_ߴ=&ϬU/!8?}u?SUq գyv`_67oA/_//򆽹yW7;7?jRsx~eh}I6+K6ޥ^+( _k^.(_9[t|S.ƥ~yv?=]{R_KZ\9kz$ Kkzw1SAA٥ Z]]~zw1.`Y酲j??k{w1?]]Jeka7_%OүvbC!@W7mCro'=M45^U6~nz|^|Q-|KZ^0LO7J,||)W)~BeoIgoMn+'bT@}a|)W)CBE%Oh e*6EE%_{Uo!-CK\F۸2Ӊ IWerdFK@[6 vETL}a~J (PP~͟Ufw_1W#9ĦNzibAWe-)TXЁ:X㮋k xQ=k|[7 QCm}tۣk~TWHwlh޳޴#=? Zoё:Q,PDΧ_:*=ǻ>7kpHcD[@ev.6ںQvSk4y@kcsOps { gem@>3NGcd5 IS&78ՙ:[6>@Fe٥r/f'|zd߄Ǿ}QDlͳb_3`//zIog7'ʾyոf/ 7/ݿ&a .>M~617o=H6|wX}61Tc @xg@e@@ִF~&1\(\~1ʾ- 4|VYxBѭj o3@XvK9j(? P|z-nP'Y&% Av-K^~tE ]T0Ttƽϛ @Pbqd'Ϛ .zyIcs+c'PQ@Wk;ӕ1tq3Ţ%KW %O.WU@Ipl`ʿ+o\xm5 Gb~ϔ .zQ8bKkVXk?Y]1tc79Dϓ@7P7ucȡƚ pF17m6BxRkz JF5`OKwKkzHm`zy-%?+,Z5ūGR^H=V+Wc5oRZ{dj:T࢏ψ^ysRIR/uKD g_tjR`Myυ>I2\S'Z[7uG~wJQ-?V?UV_Z3h??v :uu7ޥ^PIi;@VO2ȷE/IP-c#?d&?qS ?6W*W|#7²Pn>ܟ/\>&Qp^o_[EzgO^mjUl+m0sS'YV( ~U>Ϊ;[:nPklwxh~0sau{>RRKGd9SZ7wUx4W Nռֽ[ǿm#oܤT5=n|!mS+̆&}83PU_BK?no^;&޳Zk{ֺŽO2^V]_PHic-6( 4Z{`+ym͠c7Uk`}G64k)@geo_~նԎpZrsŐ&6MkQmo50}v:9L>ڤv6d#zmD?tYƼ7N[kƦ}L;ld Uw9IENDB`PNG  IHDR X pHYs{Rk IDATxwgu} (bÆ%1bM1Q5Ũ)]ה͵n*i){ 30Ф7A@E2t a0ao?lY@ܟ[zv|ΜQ\>svjWEkN?? VzI^}bpњ[.#PwWGDe߳6},?3h n9;zkF4VQ?;0M4c~k:Xf c;wE}C?%#$?l=&T½k$%)>M;oe }m`¨1|Fkd?ͣdE럷"FҘss"?dpۅ_Fk ?J[QE~0VDIc֪D_>lp/;8_Tچ:)#ٷ0ezgkZ蝿Gԭ*&ZcQi[~;TK4g1 czA?h-*-@~7b;i4;$C~5.O.&OhpéQB=O"âg<=HdT|F3aoJ)-tED-PSGIC~%kd^)?ex5>5[ U0:A{ɪ};c7O0ƌQWFOI)wƇo3` {97ߏ$MXK:ݮ<}0& fY]G#y/-ū4yMhߕ$M^^k>}0 fTZW307VMu}E;G Dw>(cKϾWmQN&ωW>Hb0CDJ_}/4uW#f0#}&Z CT4 FYR&=8<78` ݰ/H~dq[dvM>-Jx蝿GD]gi ޔQ*ܢ\vp-UW߭$Mtuwc@aSjxWJ(7]z`-M~,JWK 9H ?)Կh(_[`A]%i ZzA@!Sw fo9;ߵ$MA==מ}P4C-Xx0:ǽ3K4]3 :'iGDiDOw@9vy}4 0U &ݠޓPU/}]P\Ӻ/T;}@ &٠cN&i<>ݟ.&i:o `KP(wH o=?ZKN&i:ꝷ2X`LgGBiTu{` >!Zs$MG>H0(o跳o;TVI涋U>Jw>tξBԿLO4%-!kdkl? ҿ jy`|ԃ[kj bxM'[`B n(ZKwL(jfٷiz{D]=} &@]Z(xaߘ}摻$MG폿=66}?IZSȾ^}Z8IQ`uO~H1[`b ;9Zs$M~s_> cQ)1[`,4U^볏57K'onQ zd-0&|_};O58>?I}8oG_J4/?4T0CWؓFQٷTh6/Jϓ4U˞dk<?13h-1ÞTi}LEk$M~~3H ۟=u{|w>IQOdi<?1һyR._enSH4U^u`w1{򤒵W< `&2DO*Y ~[ `&4Gϥ Jo{>6c`xњ.Tjٳ^wE0Soj祿J oc0ڇ)ÝT ~o34wCI33?dOI`'lpaٷLYn(ik  S]Gu?I/wMcޖ(i ?\OLP'{»CQ}'%MnC^}`D~;.;3JRQ0 t:D/{o1c%Mn~#yI_NZώg^|S>(ir K?I cxiٷOfЍA4u?O1fs?I ಃo-6SV.)iQWdc3`GEkS?I X]o-p֞N)i}e# `fXe䤅soDԃ[ ?oE{ɫ}/e_3`azY9ij~y4퇲,VDw_Jw_}$?|⤅yQSm6j:GOϔ4YOL2Χޟ!NZoÛ}K@.֒7%ML՞?Q1~;ZwJ'-DKȾX` Lߔ4Y ,9#2अȾ(is;%MN-9#9}m}F {ٷ4Jl0s Fa|5Uh6˾(lxyZ}{ɨ~L1s?I[ Y.*i"|# `@KMږW}0JM#ߒ>*i~eX3`^Mz} y䮨V^*iV8,aPXh-J&mM1gF$y5$=igW3'pj> Y*i\ `f?pO˲o^*il}oO*aPXu/pd:桵QxN}볏)aPR%;p}06wVIc#c `&4m>U*`Lu?wWIYGL0(ڤͭZܨ%`5Ga%_?}D?}6i[>}09.+i_w0 j_?ISϾ] m{>f@A=Qo&I}6V97O&`Pʠۧh_ժG=w kZC+%`P?I߷b[ ?oEGL0(dp٤Wٷ sq%G7eҿl97 l[Zw]I5ߚ}$L=?BzMzU/fٷSdpﻒ&8zt`bxYٷS{{{%VqqQ0 ؤ[)TG%メrfQ0 iؤos[":` lם} L=?BG%U+wfKip' gPH7`[>}K0#ꁨV8}X\#`RlҦz};0c6~߇%>~@!N&eD};0';Xh\{R0 %feόofTQ|AeP@!վ?Mòofߏ%.? 1Sfߛ} qLO4 3(OYU{4ٷk6K_T>? 1SJspٗ?|׎gT-[ҶeP@!Z躟ٗ5;{.[ҶeP@!Z?{_e ^wpI[@yi!Y0њ[.i } jzFNjҿH@ynղgEKfZ#f-? 1}NT{Hwi2(lӟ j/?`CҿH@yf;P Y@&-? 1܆7~>VB 3(o2kKDd_>=B 3(o2\~H,a?뢾4k>+ޚ%?Duy[tzw?)?wƇފ_*OE}Mt6d `+4ӿWH@yM^LOٗ9!]ScpA[x~i>Qzq+= IDAT[-!:Gft?g?wy ~|w^2?(OԿw4!gP;߳/G}nڳcp?EMZ;Zh}c𵣣T%ZOw4 gP߄d$\uȭߏ0.-!2kD~0'3{{@ 3(o~g_201_m#?ݓ8W7fx`jw]ܗ&!? 1uWd_20uC1 [dOV{X3ګV$'g~PY}eD=̾ `jt|K^ 3(or/|MC}-4(9?U??o10l7l=? 1}&rQ$9Zs3]Os؛_}ihg4gPdT26S7cp=]Q|As\d_Z01W 9? 1̾T`l5Gcxé;џNn\}~*zkG} ٗa<5? 1>-KJ]1geZ#_E95? 1~ec^m]~)Zsҟ涋'7ٗ)pT˞0? 1;.ξL u[$LWh3;ӟ8fP@!]d_"0rxl)ږOvA o}+k5ZOJ@y_ye[ibx9MQiQc KJ@y__ɾ,`4u o856)iSw~2ScsdP@!U{Wd_䆽\yLW<)jϗ_0 **egP@!Ud_Ć_TgQߊD&+KJgPdh/ ^MO>?[蟻<dߙuV *%fP@!S}9~h4n?Q{u- [w濤?K 3(o|\wrR.'7(uK3>1e߲E GkR))? 1ݟ1f_#wF>UQHNJYgPx_d_ ̺~؟v[csQȖh6SRRb7w\})0Æ7?<uٷ5ZaM@LJgP@!s۳L-gFr皤mӈiݗ}0cbx);S3@y%|P?v&YDUZ}3MRګ_͆;OT{4]WGD{]ҟ}Ҩ3(x{O}vOxwLR_7g;Lzkcp1;}h5]sNCMrV,αEi 2(6( g0C"vՊ]Mva/^ݓ>vI>I@yA`/;Zsۥ?$W-v or( Qj .;(hh->Y$MSb7`R4M.IU|4`5SwƇs3ҟ9ҴgP@!7`Ѝܒ4w'[<[Ίޚ%9Qg4gPhj5ܒ4U+wk,D{4 j?C$=@y1G kZ룽ϧ?$MF/zuGF\yLN?ͻd煤fҦwxlܷ3ҟ 6?? 1+_|a/G j7\JdV}'Gt6 ߲}Kڶ 3(|ߛc`~?$Mvxy8H~뮈ū{ܢ^fP@!#;O?$MG#~-b>&K=z1蝾cwggP_涛S wIZ|_DSgqcٸ.75Ks[g 3(l_#` _HFI6*"蟳4:Ǿ==^~FK 3(lsv0FC'I]Uh~QOt?_OŒ;? 1+[}e?bŠޔl4m?bӫF}1hh-~J+io% 1+WM#`4utOxOI ӣ`5SfIt}GT?/4gP_|_1;}璤٫F#`5GbxۅѿxutO|oT^~J 3(+0.O&I^+(^~믍DD{]5(ܔ4gP_olpձõ:<6W3;!ZK~>J 3(L/lxZg$mwd 7iz_kQ-v9(Iߞ@yio,`vm-ʝӟGOfj ިV$̓'ma2 QyuyA,.ItD'Y[2:SSC,&ƘEMܒQnvA6i (6i-lMsz}hjj&u>s~#){m_uD}ܪ?גE3b7v*U uͿ9#ȅƫ6į=cskOM+I-?xA EخUKkIZz4c[V?e ߔ$O @2~ɾ7kÅ2Ʋ;Oj5ON'I @4|{O @Bi[#IuO{g0L[·>Wz|zM$I+@e~n??ff _wFPK p セ,\sԖa\WD4;3bWd?#|̯%HRS|fvP泞ռǽ? @ͭ*Ug @soͿ3ԠZTlΦ'~5kK]KkK 1Wf?!?~g$iu|oG4ۓA ᄊ8tO}ǖJV"?xA =O@αoH1v*=cY4* ]gui+e~.?Ӓ2?xA տ'`~_$ɵ~I) k|w|V]_ͻ׏J3g^G#UUG2HR_g'6 Ru-=yOZQI@[zgo˯H_$i{ @ɪ~:ꪪ>%7EVR};GP7^z|t}Cio'I@e~nU{H@$IR~ Wg?5,\["I;\s;WWep%~-cvI 1k~2jDv:Gt?2[Uڇ̯9$I 1K U,so$ n>sw?yX2H @~2&Կ;"I;r_RpaU2pa]tNص}v?$Iھ2goZ{=3}įI[ܛ/(C^ZvJ$Iw ^ӯ~.&4|{wDJk畅,2z&Ie uM#$Ifd /#P{ݫ$I$A IDAT3b77\LϭJ#$Ifd Y\L`ڣo$I$93b7bs;Xs0Ήoɿ#$Id h>7B;"I$IjN V{ݫ nj $I$5+?xA Fg?"I$IjV VTL}įI$IR2go/yLS0@[~C$I$I @~qS0o~?$I$I @Ѫ٘TwJ$Ie yR)AS0C$I$I @m:Φ2?*H$I@pK$I$57?xA og?cXIC$I 1vUg` >vH$I@OZ{X$I$F -]e? 2z!I$I 1[ޚ4lJ$I @`D#O$I @`D{֧ I$Id H0~7$I$I@eC$I4;3b?,UC$I43bց/~$I$i62goq,!I$I 1[\ks13I$I҈3b?,}+$I$i62goq=,sܛ$I$i62gov{J07~H$If"?xA h.+~H$If"?xA TU09N$I @+~0%{I$Ild ҕ~+iC#o$I$i62goΦ` >9vH$If#?xA j=4a!I$I 1[j=O\~;$I$I@+iSI$IR3go/uR0gs$I$5??xA d? c~$I$3bt+~$I$3bt4C$I 1[ޅ4iuC$I 1[~4C$I 1[2iM$Ig uO`L÷I$IR3go:'4J$Ig uy}0OO!$Ifg ҵ`OL $I$5;?xA }K zM $I$5;?xA ~&9m7D$I 1[>?4Lwo$I$3bLk4Lo$I$3b|7<i$I$3b|զ;1 6\~?$I$I @`LoJ$Ifg n$ySٔ~?$I$I @tz0OO!$If V3| $I$57?xA :Ǽ>H$I@!H$I@9H$I@Wo$I$)??xA F@ ݓ H$I3goZ??w?I$IR~ ]J -?>H$I3goMwf?ue$I$g x 6^dLlJ#$I 1g?5D-$I$f x/-so$I$)7?xA ƫ{; g'H$Ir3go:/O@ ?~K$I$I3b7^^d0["I$I @1[s)^0o$I$)5?xA oІg`Rհ["I$I @l0}/I$IR^ M5Ge?5tO["I$I @]@ ΥI$IR^ _?~6jX["I$I @k{UPko$I$)/?xA Ư@2?S=$I$d d=>`v~-$I$d d 1sܛo$I$)'?xA &kݯd?5`-$I$d d<4auD$I@j|D$I3b7y?|PL%$I @߳Z>'H$IV6?xA &ɟ~>j{"I$IZ 1]Jzg/H$IV4?xA 5|'I$If _JPo$I$ie3g^~Bj/H$IV6?xA ;}O@M}~O$I$I+@'ޗ&H$IV.?xA j6N3P5$I$i2g~o~Fjqy-$I$\ o3e~n{"I$IZ 1_ҵ@MOt=$I$L կ{ڟg?#5uND$I23bW~Fj]{"I$IZ 1_k.?1H$IV&?xA SJ%$I @4A̯yr=$I$g t_yXSPSI$IR| Mޗߟ=$I$)>?xA S7d?%5/3H$I3go:wH'$I 1^Uo$I$)>?xA +:|F=$I$f (~O$I$I3b7z49J'$I}z IDAT 1^ߒԿ{"I$I @>粟/M'$I 1bw.ePu6o$I$),?xA Z{"I$I @iY'ΉoI'$I 1nw~Rj}u.H$I2gouO'O=$I$e tk~/H$I2goʭޥnPG5,=S$I$I!3b7^^{"I$I @/ ?1Y{{$I$)&?xA _g?+5:"H$Ib2gouN5Yip7$I$)&?xA _/~VjN7E$I4 1 hnRu~Zjj"I$Iz 4_:'-H$I@5 @]Ai7E$I4 13JO @MuN)$Ie _lÇ6d?15{"I$I^ 6'k?~O$I$I @z~bj{"I$I^ [2I$It2g/ց/~b}I$It2g/Jٔ_I$IT2g/˲W~O$=hVۮ33xi5==,{δ vӮ鬱=I AK`D ox J "(D 8 ?}~{"I$I`B$I$i 1[za @uN)$Ic @f4yyM$I${ -`N(eP"I$I: 1[ܒ0ѝL'$Ic @oޘ0z{"I$I: 1[[$#"H$I-?xA Υ/h@I$Iұe wJ?v&ԿI$I1e 7wG_y_=$I$[ %]0wI$Iұe ׿u;R=%H$I>?xA +cwFM$I$} -|?vOVI$Ig _N{?z&4eD$It3bdLh/I$Ig _NxXxjM$I$] ݼ<K^~S$I$IG@`B}wI$Ie _^OT=.So$I$3g/{e@'7E$It3bWuf4?O)$I# @v`Bߟ~O$I$IG@0Y0M7E$I3b?gݙ~O$I$I@00_Ϳ)$I43b߹-0.4sᯤI$I 1koe?лo$I$R ޕ~>4`ŋo$I$R M~>4`]7E$If)?xA ]7~BLj<*՚o$I$J ўk 7o$I$J M= ЀGߐ~S$I$iV2gu/{y;?~S$I$iV2gUkO)g?#&TK)$I4+3bݙh@濟~S$I$i2g tY3"I$I@Wʰ{D\0q^d ߾:АC{$I:뙥{4=[' }ڒ@АI$i1VÿחўW;:%?xA 4ya3A՛~m$IR[}b\߶ wm*}K2Ǿ׾%3bէe?CE$IZV_:ޖ`2ڻQ̢w?d :H$IGKekS]J]gn- @?`z>GE$IzV_:o}A}ߗ͗w2f sghۂ 1^h?%H$I߫Zwjn^~_8t6,-иoow)8+ 7ւ 1m|糟$ _o$Irnm9 v/;Jv:\2gO $ ݵ-H$i֝Zegk;f%eu.x^;lC ֻ' @C-H$O/ݍJۊC~_?Y:9m!?xA w;o0]E$IٰЯ|i]J="t𝤿d KJ]=,hP"Iռ+_];ח _+i[_~ې@kpצ2޷zuXDU- @?Qgv%?xA tussiu]uIfyyo_]F{hǾ-3b#m -~c$IO/ݍJۊC@ Lז 1ӑֻ @Wޗ~c$IVP:ռÛ/-}KRo)^K2gOGZus+cenwFi禃ewG)nf?ے@Ojx5?C[@(ePe=m @?KK_t2sm$ge//hR=}_-3bcj4i5蔹3k$IiIF&m+pצ2޷Я`auВ 1ӱ6 @__wFH[u|lXZz[N/jQ?tp{sDK2gOSd?_ pQ$-]~O`q[і 1ӱݼ<}en[#IZ\>Q<>fߊd xO 0HWuwy wM3bI?tg HL3E ?Xʿ- @?Mwd?aۙ~g$Igf&q_̾m @?MR?~Dǥ:o$iqT ٗ y|hS i:oy~ P~k$IQY`oLm @?M%ۗ2}u$-<زoE2gO6 u@;F_We%1]鷢M3bI/1y$׻?e$1[Ѧ 1Ӥu6Z3 F_c#$0-V)?xA 4qgH)nS H=̭<.HR0$0(V)?xA Do~&)}k$I |E9`;V)?xA DO~:s>HrsS9`K_~+ڔ@I$ia<oE2gOM}ǯg?i\~o$I dg鷢m3bF;㩥 Hn>=Hg_ѻ[Ѷ 1SӍ~:YwIUd}oߊe n`ϱ{#IZs~2$:Jh[ 麗h̭9)H\֞~/ږ@m^ߜw~}Wbdbu7 ~Ȯ/ s$Iyݰ4`3^~WbdbNdGh}IR+/n،ޭ'@~)G/MG\\2`3W~Wbdb\ Dj,|A#IԂR*{ 9o ??L x0 Α$婹 [>S(f@&׻;G}ͣ>~_bdb\{2[Hn/w$Is_oD2lA[Q ??L ;? @? s$Is_oG_1lNUQ ??L GsIW>x]fTwŨf@&YD~'{<ޑ$mUk} f( 3O9+}]Gi$i*{}>? 3O+Isq#IZ'|"j` z7~_jdbn:&c T{G47u.-\bT3 ?}ƟFι_w$IsSG'G_+lAτ@~)wo0 UW;\s{4`}1gQ~UGAT,~k#Ie OߍU؂bW#@~in9!t.F#I]5:`K:b3 ? w{G)׮w$I}E_'lA(g@&Dw0@ͥ{$I3{ݡW [(g@&TՓE5;W!*` . /F9? 21Ӡݶ,T`G4nR} gpdbAY;:w$i5`N;c3 ? wGɟ}H__W4{o1gļT50(V*xY#IV[NA֞}g@&d;ϊ0@<$Mѻj=~_zdbA9o? P+I+唪*` ʟ~gzdbA<=yRxG4Z'nL;c3 ? yj0@w$IS{բk)~;c3 ? EjԘu#Ir }Q ??L 4:2cG^Rً2 7F=? 21Ӡk=6]Ik)*zE1g"6<`TGu#` ;c2 ?EԻ>9oI_ueU: 3Oo}\s{#Izv{QJvUn:& 3O @s Iҳk;WSԹk8d@&\wOݰ4$=uF_LQ 7!? 21ST0`UTKw$8y;q ??L U?} $IOW,~kT`c2 ?EUꔪ*0`÷A)*q1.g"+#y ISW,sH IDATq ??L Y%G~I~!5nk)^_1&g"k}T$ս։w{1.g"+xiJe/sW!I{ ;%? 21StDVļ{HjSX}0UU_Idb躗} :$յ11`u@~)ѿ} 2٢!Ik} 0 ;)? 21SxIU{CQ BOETêߐ}wSdbabyQ H!I[54~Sdbas_GTw$թF?A?)? 210\SQ Pg_ET&JD?n35oQdba`q Hݛ(w$աֱ)4o?-? 21Ӱ@?~IRtL#i|l1ng韍>}~]$Ic>4u;d2 ? K>IQ*5D>SO{fuGq ??L 4L(HwHƹ]ߍ~0ޯC-? 210սz#@^kO|$i~'I4UC1? 210:cG`+ $i\яxfw8f@&v}aJf P|<R$IļT[`Wadbac@_ $ij}뷣P{.8f@&&G[auj,.NqwiяvfX{d3 ? [%;E @/I4&~' Tu~-{]2gj@rԘ*NQs?F? q ??L 4n<2h0Z;IF[{P=1 ??L 4O(ٯ0Y^G9/ ??L 4$~7x0Z'~2^Q|8Pd\3 ? kUWF@M~ʟ$͠;G?jw8g@&:|3x0$Z/$ZΎ~|0 %@~iXkS$iz51~|0 K'@~ihkCu&Iz7,~l0K~u ;?L 4n9!0$ $i*ymJfcY*~u2g韍>" ։ $i5T_~{dba)Ue1`HknK'IWD?)@~i+>0DڧI$IŹE~{dbascߗ $i*}]Jfc9<ʸg@&/0d:~9~a{3sN/W=? 2171/UVGHx$R%IC0> W@~itLQ`t.f$IR#̑+u ??L 4 NOb׆Q]sN)2su-u ??L 4 8^;0d&U%IW^8`TU*~UR 3OR æ*SQUOD?Cڻd@&:Mq`,o5G?C_j@~iT*}\R~=%IKя_X//u ??L 4J80u+Scv$ bH9<wL]2 ?Rݫ>2 ΅~OIҠ^$ kScb^S 3OT븏DUHo$)wͥOG?uc; c@~iZmZ룏 Cj?څU[򡛣dйe@&z}lb>~WIR:|51 @&#?~)? 21Ө>Ϣ Cz +IEoJUgcc &ۅ5u ??L 4j{"}tbw$i8' @&g@~iwE`کy+Iv~Q¯5u ??L 4u.j`ȕ^$iTE?VȨy7u ??L 4w>:_ $iVMKϋ~Q\[95 ??L 4kn>> n~gILWOR2E7u ??L 4u#0OL45x{:dY;gFDFOȊ$iZ&^`+ީadbmb^6>BNï4Ru/- TO>~5? 21(׻ai`Dݔ $iKHJe? n9!ީkdbQG!FH=.I\Ţ76q BS 3O#݂R}UZV%IՂmS Pf@&z}!ՆS/I`~~9? 21Ө>O#w۲Ku8n<2sdbQe)G 90IdTu6F?]:g@&\}5vjkwzWT[D`ަ}9? 218>>J6m1I5mvяB~=T 3OPkR* ԿԘ*.T&ޭ'F?ҹg@&&v<Dzս|Ggƥy}UU>~IGST=M?5>{dbq )3Vu6 $wc+~'@MDŽG2?L 4N\}aUl7Vǣukw  ?S >H0] $W%NUh#hn*vI$?A0OT[Z_fw)11/^45x[|({Y2 ?[C7G+@=4I_Rя4D¯Mz*? 21Ӹչ 19ѭU\{W !<߅Oz*? 21Ӹ< qQROmFbWE?"Oz:? 218V=h0.Ejs&it*yһ;JOg@&:.>Z>5MWT'j})=@~ikcjMMnsӯkg/Uz:? 21ӸV]}3Cb7qaMUCYw@~i\k}ȡZ*~IK?C}+=3? 21Ӹ<] 1U=T,zS]')IRX`w@~i+50?IRً~0+/ 3O\>b1?OiI~0":2ҳ2 ?s?y)UU1`UOܟ~ILn/NKQQu@~i+.0檍kRyVTG#|Kϝ@~ic@ TcrTr]K~'Jn6aw&:m1? 21SZ}G;H[OL]1njV~0ƚ~igV#lR>|k*~7Jh_LK~dU1Ӕ2 ?խ;G;?:c4εNR~Uq:]e@&]RGVS1{R-rA .2~ijgXݣzܺEM?6Fy}M?>PgBM9? 21S]+>sq*{C})Jͣ> PWe/{:>3 ?յι}`}Lik.)n?-Ps\~'jzgZ+Sw l䘩w4Lޘz?VJU}D Bݨe@&sDAd\w`S絩{)u-RKHM/? 21Sk/%8w4EoJk2`n=13 ?պ/HUk}1}^J+Я׎>vZ}$3 ?սލGECz_Wj&>INIG5x^U1Ug@&{#?} `VGNS?UiO✔*hu/52 ?RȝGf|^K*M/H3>ʇ}`*5x[=e@&/΅_>0gSҢWiKwH+IUXi{y]g@&/bפFGS{.I~J?__OOKG~jgTΎ>0*>/H]zW,zc\T>zwY:Sc߯ydb'=Uߍ>U}Scj]R^9ӻ{V ??L mRϢ$dWm|8u.]=_j,UҽLU;d:zV ??L ^oRũX;X_sɻSR6dU[^.? 21y;Rc U>ۋcN%;miڻ?00K~kg_}, LZK?~'kjӯ0T_q+X;Y ??L g>ϣ% rsWRgp:? Gj%X7kN2 ?8UGGwuUm}~J"Cu'iMdb'=EMNUJ#T^Kx_ ϣzԘu ??L g:7&S{K~k:#{|~G ^5ggܕ}<`Tߛz7ڧ6\OW>SS^FK_~k2 ?FZO7O~TxM'ܑRUE`~tr ??L e)u# 㡪RԽ>ORwV71/5x{j/t^Osqmi4? 21FQ[Ugc꯺*u]g~!5}Oj&濌:7RHIHU{CF{?-7 3OzK?}D^zT>x}pD:wRsϫ s@MjSܿ4쯼(UVGښ9 ??L W>tS1*UO<^z7:cj<콩՛~mԮ/|jwo:ߛO兩|DbBs@~I}L-T5+&mSCS~*OϤַ~;5?5_jT,!!{|S3\荛w[/hjGйS=SR371`- /<gv{QZODU`@&yUM}l ZV{ &? 21_.0&7&慿s`2 ?ibPχo2 ?iTE_`TO,5lA ??L սr ́% Ϡf@&*)}4 3Oy^h^$GI3uoFa`T |db'ͮrDžWPLdb'ͮY-Ud  ??L YpTm\}iqz;e@&bIDAT^{Q@~Iu) %(6? 21MDg` Zf{1 ?injΔ2HQ>pm;g@&_);5o@Ñ@~IsV\{Wi@C@~Is_>V>r禿@Ó@~IZ}6>}ɟwʧh2 ?)Os+Ygb_NUgcZk4|g5GqRcb^ _db'-)c 7 ??L n9!@\N@Û@~IykcJe?@h; odb'w۲_uU wdb'对)UeqZhh3 ?i0<+sq; db' aM<J@ß@~IyGV֓¿k42 ?ip5`o  ??L ֿcc{5:g4ؚG}8XZS+¿kt2 ?i~ѹk5Zg4Z>jÿk2 ?)WGy34;F/? 21bj#|Ԙ*;F/? 21G9F3? 21js#FR¿kt3 ?)=D?`Tej 3O)UUFFc¿k3 ?)я UT 3Oyȿ\ 3Oz-~P+ޕ  ??L y)G ַ?]@~ISc 0w]@~ISM)я.Φ]@~IUC 0TW}]@~IUkSя Նթ5^g4|u7C}¿k2 ?i*xYǢRcb^t_db' gx8U/3? 21ۥrG^wHwsmdb' oe~DUN/ ^ ??L !nb^ucl 3OG_)UU 3OzwT,!{?? 21ؑdչU 3O.~\@6Sc߿U 3O^я {UZGzwoէџzgIqN/$M_mwQ߹U+/=?LC%)Z*s*SÿsV<0 2)Z 6IS}0gڧ6W5}gI_IF[0k{.ZV?3Ȥyo`4GZJUOb7V=x =?LZ'Q 6Iӯwqя9Z-uG`d:/$MbW>饩11/jn/>`IoĿd4:M#lLo NV,zS1?L:W/&i&kn~ueiպQ>`I֓_Iy>){_ڧ6(Ԃ@&UWd4zw(4R󀷅:P  &iv޸?d>`KU &iv }WVߝ&?gQq;_Ie _8g|5dUuѧ 2j~_I}^s__}$j 懿l47>?įP:6 2qF6IsSS굢+M-{}d_׹@mdle6IsW{Xڧ~&W,>aSY/ &iZ]*#@M~x|wc盘P5xK7IsVTяjzT\S?:MֻG uRS_>,=Wg ?z?<㥩z 5J5n[}Dj N6..śOj\}Cj,6{:UuV yG_I+G?^g"5zg_U t?囤XTu6F?bSW\+>&c0GV|` MTҖ*QQ?ip24TяHTfjo @- H¯T3ZG]WRv>-d0 75E?f);4G}\j`"NRv{Q*`rAjLlWo; /f8Ij)UeTmX_VJ>2_{{w]p<"WT\@28 g -K۲-%3s._RTZgqVQ.()9s|^ ~y=G_ys`\YrƘ:􁜤~ W *MJjQ5de`ՆҜnaQn[}0BZB#T>2ctCPNRk\1 t߲t+7?}lƚ?A봢vs[ٷ CzŨ_|tVnէgg AsDpNR<8-Od_7 W~/*͠ogg A95&IIoS"nj=/*ͤbGTU{4n='}H'$`tY߬L>@rObj􁝤׾+LUJJ=}Oq'ӇvQX@}KߦRu7>> ]/!;IX~RD}0`,L&LJ3y'a`4.HIL?}0@MQQiM粏a`Q[!}[AhQ\wKe ^?!~!T訨^~1Ϛ7MTb{.0|, bB C}CLM?ԓ4]};^jvN`, }$ ?̾vE΍Q7CE؝} æFJILŲ#ZYʢTqߚROM̏on_EG$ 歟̾v_e7לƔz}S4XRW$ Γ̾v5禿-^k:u*k\VO`_pdT7e_;/njt/>&=d`UΨ-=>}'i05V#ΨMOSJ=uAt1`, $ 9`ʭO췤k퇮>F̐?~҇Ԃy]wGۢ~ Hǚ}聅?ߧ% ojoۊƪSߏR593d$z``T(@IXN3u4WF׊>Uk*# UӇSOg:FO/JV|Wz),rjK/;!}8(i0u6UGV^/=.ݛ*wmڥǥ % EGk`uDꋏr3Y``Duw %bIQUn/de^_(>}%FXOD҇_}r_|tPe'Dsc1`Yq-OEw%CWf_9cob{߃R/?=?>F2 s@w-=>}(MoV-/zXѽ =r/{_0QR/=>+`n+;Ѹ7KΎ4O}b`Q|XujD}Y?zug"2GN+7epQRk97wO<~m`,Q0; (ou^})HI3Xvb[>> ?9;QmCGI}D{9ע`^[OA(Y]/D}GI~/EscU0ҺOo-̾VFUHIۂyѼOTQ`Yj7ˣNIUQUٷ @UJI{' #ӊ+-I#^e&(trLhv=}D1طVVD}ىPI EŊˤ~Q5_>( LOYF5Q>#`8*iMgd"e?~?勏d Xw۳\;%>04 }} o|;-maѼf`@ﺝ붣=ѼsQ7cjƗOKS5_IsinV_rl4h}BG1e+;hOQ:-&MJ+@U}=ڲ_ꏥ4M̏cX~R4V͛:w/Σ_|?Fw뺽\ ~"?EGx1ugoYQ ߓݦ|n~8GcCŮ/LkXP)IENDB`PNG  IHDRp4 pHYs{Rk IDATxygYa! ( *.6 :*3%}!5YB=!!{g}O:]g?{j[U|9}]ysw%qFip7RR焿L?>M/ip׹) z/_SNS;|w?W~@KmT_:'40a53cKvN=4~OpzGIH>GZ{;.-Guude_\K6JoHsQ3X@ ~fפ:~X+uhJV6;Rk緆U5^,J&% X@_MS;pU:F8=z}j-]|'EaY@?Ͱ954l9}'_08LS^>B7]g%Z۽&;&e wY) :/WIS6:_zS/m(8ސZ_~Ww|7Le{^W}2+  vۄXΑ7L9'|k{k_0,p` n9ְRWU{_bWmN;ώ~uسyҿ4eU/sY0ن9WgƬe[-DaY<:ְLUoMUթgƬ%[gDalYQ~yoOG<6.o ?3>|7% C.OS۾:|pŵxg$3z/vxS>y{Ǝ̑w寏zQ7U~ZZwQguƊ̅A/AuiȪW^=Ưq҆bs{eJ/m8m>Z4`v9#s\նNo~uXM0z2MmZyx|Kz"v{{/X=vCKԲW}G^F_H80K~*|iGpHûΉ~9D\LԻ`yKfapOk\sx&JԿ Z;oJAKfsx; /<~wƱBisįw`U=Zۿ!_Dq,pPݤj=R6ijf Zۿ>A7 bڇjXM/`pN\g5mEQ,pDo*M-yEm*͠?3]~%CX@I/;3{m5~CX@>&RUEu jpKIwhnk:\Ampy/ah IS_>&ֶ[F?} 7_jf w~CcX@k$6XG=|̯D~P/4d;&|MZo]cfwޒj^#?҅ư>,d>0I fPg 5_X@F>&O3D?r`#k{?SA-yEJaK2B`mM4jT'_8CmG ̅J>Bi#ѯZh ȘCmk 37GRk7P3=soK2cPO~яcU+?g }"81t6 ;:sP>vSK28=Ϣ/0m?sލ> `m\kj?xy6w8P2Xh4G ,Ί߈fe,p #zcD?V`UݟZ۽&36ny2&P?Y@ Ȉh'ëg~@j\/ (cm\y@!M-"36.u*qzgc+ (cm,i]я~+vG& (cmB3'O8P2Z:Dzde,p #z5eJ~@ U?Z˷,pdD&׿|X[^Q|8P2ZSQl4H}EY@ Ȉhl+;;ϊ,pdD&ֿ`4H ,pdDGSt s1X@F@kT6K{Ώ~d@]YF!Y@ ȈhM{gTvj3Z,pdDS~:q 6kiY@ ȈhMipQя C>F ք:rJU10zՋ|X@F@}KL'n~Lq`Y@ ȈhuGꙻԒWde,p #zչ.ߗRo*cw߇de,p #zչuGG?`LUgRk7ge,p #zյOE?`[g8P2Z-[YwIݠZ#5 (cMe0X"7 (cv-yE=}Wc&E5J}HVzg}1fp@,pdD:ͩ<HISU}? i~28=0wYHV{3 qsG?i28=_4[៉4Y@ Ȉhu7@-tV|<6 (c ?&1=|MZY#]8P2ZtߓR5~ _goFee,p #zE7G"IsY{:Zg%M8P2ZdÛO>~u' (c-~?RUE?zuL,pdD}4L,pdD{w9៝iY@ Ȉh <0 o?=6- (cmkc('?Ci28=ˢ`VJ聶-{UZOF90Ty4=z/u΋=xR콩ꭉ4ѰZ@g)mT8P2B;o~{SR+?:Zjij7hV?:_=忧%'ѣYԿ៥qY@ Ȉh ֢;Ls̿uOl+3KEjRߟ-' 6mm(: (cm"5}#]:GNjIS{w >+Yߋ4,pdDjxG ,ຣf~5{g~/=h>j;f՚WhvY@ Ȉh Q{G30zSix){_O|o'EyVJa{]{f聶 :(96zԿl9ij3u[RS'ou8P2|vTuWG30].̡Ί< (cm1cS}S/ΛPkN󗦪T#3WT_}F=|uTZEXS4`U{;=EEY@ ȈhY>^`S{ n9=9яH+/QQ8P2|6 {gԲ7&vM MUoM{Z28=ONiaFJݯ4e^k緦uGZ3!C,pdD>Z`=]/R9_"@{,E-~+Alzg PsſohY@ ȈhQ{D+TZ7+qKG^2w~ ge,p #zGv>V`Zoj'9|9q[;K) ѯ&`CR|z28=E{&SSkOМ>g黢_Vz/9}BX@F@:|8HaW0@'֡j=2}BX@F@W}0Q_kZoӿhC? к28=/OG z9#Z:[7hY@ ȈhsY+}0qVmHn~ _~oK28=uGG'LlG^ߋ3#fe,p #zY^ޚㄉ0z^hઃ_.}Y28=z̿t/zI6Kv~yD{ nZzg#[e{^6W V}%(a ~Uzg) c6ûN ѿZ;5+6'-~YZOE%_OF;ofZ;1j281C黢KSk﷚]~)C\}n_}{M-l8P2ڦǣKRkׄoG?acKHIݕN~l毴ECfe,p #zmjs%aXh>\y@KW7z}.uPZee,p oG!=m_~5-bOC㿷斓gQ_O-5" (cmSj衫RkۭƷv/14F]:~2vy[Rse,p #zmJݕ>> 3wN~5Myk/yx` VU?m~_4>Y@ Ȉh#j={+>krjޙ/ޚe[ w8P2ڦT=wA[}&Αo՚GSR:G~4.X@F@_裃wY[/E_L[39k:28=6)}thKv ǚm}Y׵,pdDmpG54XjmT=sO[ׯT聶Q-,USOD4RMXצ) WV<2&a?HY@ Ȉhs/E4কwV{_y4=36~Ҥfe,p #zͦY_>.h0zwGߨf}oQH_$67}\-&JsֲW{UmT3Rek5;9I`8P2lV?}\ЌU:GvHv9R{fVZk7D44 o=%ꙻg~wR[MX@F@+sدD4B簏Wi>j)Ҹ5de,p #z;G7'4DUwuw_:RkX@F@+mp!G7wUז"5ڠF|;/+u穽ԢNRX8P23"֪S/CQgSg$^Y@ ȈhE-|C[UiyVM g!Y@ Ȉh%M9a~WR NU_ޚJ-Y@ Ȉh%u6{*-tkK47*TϮ]. (cx]}DPKk $)聖j?}DPK2~J|8P2چj-&xZ=J|8P2چjZ/~J,pdD 9?FকS$ee,p #zm }OOIT聶{Xz IDAT@-uH$IY@ Ȉh}/D R{$< (cm}uD@TUZU$IY@ Ȉh뫻GSM=~7%I28=W/D k$I]8P2ꟿ,hv}3nJee,p #zF ຣ$I]8P2\l@ < nJee,p #zgF N$I]8P2i@]~7%I28QAw]@N|ݔ$IX@FmSwD N~7%I28=W裁~$I]8P2OG NȏMI4,pdD裁)If聶mRUE NOI4,pdDuvcZ$yY@ Ȉh몵wG Ԓ$IX@F@[W~0X|$IX@F@[W=},PK8$5/ (cm]cZ$yY@ Ȉh몽G Ԓ$IX@F@[W}~"X:b$IX@F@[W}C@-YHԼ,pdDu梨js/OI4,pdDu>gjs$I]8P2ںjOI4,pdDu>碏jS$. (cm]uP@-N)If聶B@-)If聶|[%S$. (cm]3nKv $ivY@ Ȉh몽{jS$. (cm]cZZ~?%I28=Uk>M+$I]8P2ںj4)If聶Z;%XF^~?%I28=Uk7F RS$. (cm]o},PKU)If聶Ζm},P[SK$8 (cm-,0hZ-J,pdD5"K)Iʳ28=W裁Z)Iʳ28QA]G$< (c͠)IX@F@[_/>$I*X@F@[_ûΎ>UOIT聶}4PKÛO $< (cm} ;:h]~?%IRy8P2\y`@-M)Iʳ28=WiMS6 $, (cm}裁j;*Iʲ28=WD V{QIT聶_裁wT$ee,p #za}4P[o;*Iʲ28=W{>;QIT聶Z@@m ?&J,pdDv裁wq$IeY@ Ȉh* {T={o$IeY@ ȈhZX@= {ijwT$28QaMwT$28=6j}$Ige,p #zmFV$)聶}~G%IR> (cmCb@m/3J|8P2چ5wT$28=6TgǣjkĭwT$28=6T{Gנ,J ge,p #zm.}";QI,pdD\[O>"'QI,pdD\+>"ѣׅQI,pdD\s%ޚ4h{*I֟聖G-T$? (c-I֯s$IZ8P2Z$ֺ'E=$IX@F@˶l#Z_m=$IX@F@+j=}LP[ $iY@ h{dU1Am*Jge,p #z4c%Iw8P2ZIK}LPk]?Juge,p #z;9T$; (cѿ}LPkK{*I֝VR{>&SI,pdDZn}LPk{/ $iY@ ȈhU' jz"Juge,p 1+ jÛ$Izi8P2Zi}TPkC>~O%IK28=J_SQAuOoT$4 (c9֯T$4 (ca>*gSI,pdDZ|_QAU~O%IK28=Њ[YJv*I^fi{*I^ϰP2lܴ2ֺ_T$8 (cm6/1.$Y@ Ȉh{_E$Izq8P2l6z{*I^6Z;%ުQwU$6۪#ZkT$ />2I $,pdD6#Z_W=$I/de,p #zͶޙ}dPk{.$,pdDY#ZOSIB8P2lkG$IZ6m6jwU$de,p C+ jw$IZ聶1 ="ؠ~O%I,pdDw?E$IZ聶1u6짩%$JY@F@ۘZ=ؠ/J$ (em ?$ Y@FcCWFZ$IR8=6GF3$IR8=6Y}tPkSId,p #zml~+Z;)J4Y@ ȈhwD^_ $Mz8P2FhzS;wU X@FCWE}GSI&= (cmSZ}|Pkn$Mz8P2ڦ/QAh2J4Y@ ȈhRgoD^ $Mr8P2ڦ=$I聶Uk>BSI&9 (cmSqFB2J4Y@ ȈhZmMSK$Mj8P2ڦڟD!^{UI&5 (cmSkcG=/$I聶-F}SI&5 (cm.\y@1BMOEUI&1 (cm.]wUIX@F@~0b[]$i28=e[4F%Z$IO}Pkû $Mb8P2\5裄ZZOSI&1 (cm裄kwUIX@F@:G~,(:^]$iҲ28=֎o>J$I6U?}Pk۾~O%I,pdDlx V=p=$iҲ28=E;D'^k $MR8P2\=jsUI&) (cm.k_^jZ۽&J4Y@ ȈhY/E/^_ $s8P2|9?F/^~W%I,pdDR#Zp\]$i281;jz{*I8ge,p #zw뎎>bJ~W%I,pdDw碏jwUqX@F@\C_~W%I,pdDyo) 6*IҘfe,p c"CWF3Zy6M-jѣUI0 (cmuvQCwUqX@F@[l}P{>~W%I,pdDsoG5^~W%I,pdD㛣joxIwUqX@F@[Ȫg>nj{*IҸee,p #z-d}P{~W%I,pdDw>n$J4NY@ Ȉh Y_>n_$S8P2ڂU)G6zwU1X@ 뢏mMSK $K8P2B7#k*IҸde,p #z-tݓkCN|]$i\28=>?}P{ $K8P2ڂhTuWG;Z=wU1X@F@hx-wUqX@F@9w$IQ}P{v$C8P2ZD]}P{{$C8P2ZTG=["J,pdD}P{>~W%Ijz8P2ZT}P{>J,pdD:jC nZ~W%Ijz8P2ZT^R5>~jcwUge,p c7G?^{wUI#jwU&ge,p #zE;ojopAwU&ge,p #zE7z*IR28=B[EJv#z Ufe,p #zE7G9$IMX@F@яjwUfe,p #zEڟD?}UI]k~PnZe}$Y@ Ȉhuz<1@*IR28=oF?ޙ~W%Ijb8P2Zꝷ81@ o9)J,pdD:9cяjj=m~_%IjZ8P2Zj-]JU({+JԴ,pdD4zG=$IMX@F@KU_~P{ $5- (c.wяjomwUee,p #zե~PUZ;9JԤ,pdDڴdWIVF|;q@/'JԤ,pdD:տl7z*IR28=T?~ЌMUde,p #zթ?8~}$)Y@ Ȉhuz<@/+JԔ,pdD5яjouwUde,p #zխy _5J~_%IjB8P2ZG9$iB[Uj wR?X@F@[寛+;/#J&/Kߓ+?홆]Ҡ\8P2Zm[YZOF? {m$mR_KNzee,p #zչE?hѿ~_%IޚT~(3Y@ Ȉhuwпl*IPh0 $~;Mjͣ V:G~,@#%J$4.[3'ŸK. (cε.~D]~g%ijmu;sij_%*V4%7gg$L*{kRy.e28=`W4ຣ$5W4[3ޚX@F@{oGPy,M-,JR%sįy2-{8V| Ac;+I{M;কz7?\8P2Z[kB>JR֌oœ7Zde,p #z5ߊ~LO p[ӊ~eWx_,pdD&nя _An~g%iοfwX֣<zee,p #z5W01Act;+IjWJ>V7TUoZOſ2Y@ ȈhMF?&hۅYIZo_ﭙUa/MPM=de,p #z5jя a$}*]ޚ1Ty4uX@F@kJ~T ajm;+ij-fBޚǣY_{,pdD;E?*hα Ƽ%[?{kHsǿ3Y@ ȈhM}/D?*hYIc◧Kݓ>WF^hVGMTde,p #z5%PhwVRckJo힆]Ro*m=qKk6֤F^1{pYX 3z׫x IDATq. (cIMQRDYI50_de,p #z51w~g%e{RwfKRtߚCûύg28=КTkG?.hA7:JZZ;5uDꝷdB~bB of?ִ5F?2hѿ~g%}^{k}o 7 ,pdD5G1;+ifWNﭡO2Y@ ȈhMkdefWk54CM. (ciuG'ﭤuS\o0k K,pdDƵl;ﭤoͪz ߯\8P2Z=xEc{a&u~o(߹L8P2Z_Gc Rk4Y[Ӊ`;X@F@kbVm:~2/1 9?UWBu{X@F@kb'A ="JRkD_iQ,pdDV=swƨ{+C~oqh_V2ԺuF響4JPߍP+~/sY@ ȈhM{44uO/je. (c-,U4J{w] 1|&,pdD&7;}65ɒ,pdD&;F?>h[ :8*Cm1Nde,p #z5aYQj+5'Fdɒ,pdDFU) я{R=tU5f[ (b 3{+5jk 1;YYFW-}eJU}6l/ 28=К^?~8ݕ RkG/J/˒,pdD-яgKX:jZ$ (cm=y{cfԶRWѷjs/˒,pdDqhp!я{]i[}uV{3^de,p #zCຣԴW}uVm~/K28=ơ֮?qγij+Ԥ\}u^s$ (cm\7QBt+5jk 1z;Y6. V~8 RSj+ 2{Y6.uOяgIۄ_ uHZ\sx,X@F@{pFtPԿP+ Y@ ȈhTяgxwWjB+P+ݓ?~/K28=Ʃ _~w}}9ǜ93|˻ܻG RcKTԒMw(P(/ȇhU?G ?$&*\@}=BVMaȇhoevcJ)&*X@W}E~7  8zU+ԏ(,m a"ռ4 ǟN,p|XVkQX }I~_79X3ߩ~@iE]wZy/pcpPzFh~!Q_GpʸgpP[~@iEg0Qj_Nvn78@>,p@jFhj[cP=&Rn^@4oV2  8zU5o[̲Lx {L̛&4Q_Ep?%Í A=Ъ\C V*&RE6>Q~?  8zUh,+̟}B} |kȇhU. Z3Hx=+Nu~ 8@>,p@rޤ#̒Hʂ]{D.X|?X~?G  8zUdj#J{L端PH~$8@>,p@z G Zk$D=Sv )X A,p|XVS?bK?+D*\ ˛fI,p|XVƛ5 Zn]&Q#W(~48@>,p@C׫3Pz2Qku%Mu )p48@>,p@CUҋr.uMQ_5;gHcpP:>ARg/D]o۟T4JOG  8zեtSG ^tLԭŧPhY%# A=R?<RwqLԍǯS02Gta8Z] ~@%D#DΟ}b طt4a8ZmpY7P~IӼ~S:Xvf$ A=T *!^{>u*oƯy . ]M,p|XV}]jH"~*SfFx&8@>,p@S_O%;M4ZQjN@e{hcpPՐ&yN&~pT~WG  8zխh,#*#~r&iޙo+! A=VpQ?r:̂(D#W>  A=j!5ԏ􅇭n #އ Hzgg<  8zձTJs(w}c,ٴZ}mRH6ު A=X?6tN4o1M𪯨 PAD,p|XVǼ3ޮ~@}O~\yShY%uJ#Xa8Z]K_|Dܓw@,V<ȼIGm'bpP~@夛F8&WO0+J}o;  8zյ_ ߒo_͛|e7P*Ѫ۩Xe;V?~zs'D\RJ'XG۩XEg?PI1p /J,p@{E>@?}cwU󺯫>PZa8Z<IJpV?ŧb,9OL%{X^cCPmYj]˚CZxwӱa8~bscO~S~ߩygò=ϩ:PnYj޴7scpP4zMKV-GtzԘ7,nW~  8zOKN}ZH^)M~}{9` t7bpP4i> @mw7V~yS`s4PUȇhZD}ڈ9G~y_5^r A=%ܮ>@4oS9x/?>@kvbpP4E>@4oSghٮgG?nȇh*V v;?`ɖ5^RYr5nȇhʒnR X␫/%MQ݊ A=蕅WHtgq /w18@>,p@WM~YP[Zc`g矶&nVKмIG{7cpP4zucd- r\QnUG'V{cpP4zuF},K߼oy[?_*H럏}cpP4zuיEhhw??nW}z)onȇh/Q %Nǂ&Pk0|j%yA,p|XF.Xrh,ό6P]K6V2S? A=h?d$OdcԑZ_Tw*͆5&.,E,p|XF/Z=S}<{¥>(k_l6qj-~RAbpP4ܓ~_YŧXm0O?z  8zc؏lf /K}Ȓ ټIG?75\ǖ<{T؏_ũ?'z  8z@Nݚ7}vԮC-\EC (?^8>|XFl {k , z-,˂] &u,p|XF9b =ơrJM8ʒ L2Ic q,p|XFQ{-Z=˼3CyRǵ<^}fCH@K%XV埫O莸,9XxIRA,p|XF[ש }_#)J7\/,ح~L:$ۻ ȇh>.$۽ϷO?pǙ?_jM.VMވbpP4ʟ7 f>2y yg]&n[־?'k}?KxG  8z-R=5λ7VY=̶ Ǯ cpP4^ 9dɳ?j:]k1\h}oik?-ϭyӷ-~K_xe ֗ߡa8%`c`[Ze1͚W| onޤ#y[S }ntT\j-zAtXƻ  8z P_xyX,WP!/(W;cpP4~YQ|#wRȇh4{窏͓3!8@>,p@;Yfߙ  8zKS}|)yb](a8Ϫ>O+%8@>,p@Q?βO+/,p@M9,-ۻߑ  8z?_}ښ7&7*Z,p|XF?PM:BnTX:SVQ518@>,p@,Qul7;QcpP4j*LPQcpP4\/84o[BE A=Ш lM#j&\{PcpP4lH:Nu;PcpP4pۮ>V&3? A=ШEwLU+P_OcpP4|)|9]SXSfh ˚CM{ a8u'? ѪȇhԽ>^KM:RSXw͒i^2ȇhu G THs5q  8zQwgoc*"ȇhW3P{7FnSXwo]8`Ԃה18@>,p@7O}@%P>SXz7f>nYϔ58@>,p@>nU1e A=ШwyS,ܫ>rD=[1p{LcpP4mSGHx/e A=Шy_oS}@ $φw 8@>,p@׼4E&{KbpP440GXf"a8ij{v}n3oQȇh$oר(pg* A=HWc &yZ;JJ_xXXR`84ɇJZ}@Q4IJwlT?YXIGʇghDc y&U,m~@)35>@,ݺKšpf(j͛td&@M%My ~@iS?H^xWG4o퓿T5o  _r|Qk{Xk hU?b4Xo#ͲT}$@sOTW?e4Xѽs働SnHi6 z]g3P,pxJ`M{e.]n]?Aת5P,ptV`b^c )̟;GJwoV?m4X94f'nTZ.]\5F g~@r|Q~YTMaS7Zo]5q!ZH>xEOQMAyӏcԥ+ԏ(8@g ؄,x ..ɛ.,>,Rt\{E }Bȁa/tTKBm5S)ޟcx/}M~e{(9dw'j- =P:,pa矬xTȂ>>`B~m˾~@)!|ƟP.}u,t4ƔCOSSCA=PZ,paj |T܂,e>0*)yz,mIGɇxB1e,}@*n,۽I}L>D+ u-xw |,MGk7VP?~@F( b>Y}LϤ۟lytJ0RYfD*pYnIgWnPӢ5IM\IDATG8($?dC}C?x½ @}eYOP ,pQ oF*v/)ռ[wM9ҝϨP,pJS"T/QTj'~`ѫG8@{_c 鎧GHuyӷG8@W}8to @;67_ׂ,8@Zo|hRq U12s-u-fMO} JbtXiI.^H}L8h/ԳRo ܄Zc @d~V?kZ믞=[է48@7d˿&T'XQT*^I|'t\kş;oatYn!NE-}Pj?0ռ͒X}`@֘r|Rkcר(ޱy&e×?P;,pIwo1./o,}!Tk1p[ZIjKIliC|3g7#ݺW ]5Cj ?syg~S },ߑp K7ܮSSX*Ilճ1HPԼ @ae;6.3iO~~~ }ނjCɇ4licC9 S@ "ݵkņm?Βǖ$y ] G6KS#,pI^lqc\&ns#rޭz~6WF+XEo͂+lGȇ;>o[,۹Q}.of ɕj` Ed#0 ,p2h?N33lo~SOgh]}lTR7xg ~ښO`-bPkj˾d޼[c/ ԕ'ESѺEmruӿ[iּ\ТGY6KwlKMIENDB`PNG  IHDR .| pHYs{Rk IDATxie]{+3QreDi Fۊrm@[ *}[RI%d2#I ! $L2Ce*gqUOPAB?w-^C]:aЉ"GJt~Ito!)bt!g0anb?Hjּ4Gjs vD\1(/;̰l-W}2} _[tcO`BU^v4ocxձQ=rG%bbtgwF?"UzVn>m WwUH3oD? FϾ0 dU^~Xt.E)1[>})Q(v}VVnݣ}'n[ٗ%AOx <:O~6VyQYLKXgIЊ{bx'#E )`*.g]tv}NOi *v{NT\}*S(vyz j3?r׳/QL0<U97␟)5Q=x]Li8&7ړ"Q c@T 1c/3k^շ}Z3YC mK߫E `W𳴚*>S~>Gۏ,gA} A<1xMtv^Jlԝ.`F?%:˷I4\vPĨ} ApZt~IIź![٧0FWҟ$M~>?kN̾l `N^ߜ2RjuC)̉e?IGJ#2qUo}Os_3Y_vO3` !ISԊmG"FK `nBt>/1;" S3vN.4]})%ySntE/q=MxDŚ??IΊ2;<)6b8ƨO7z(x^sXpZ QUEK+_J{-:]<%iJ[u z@  ͠ާޕrPsCu3`~7KjTGTe -`0E#QҸzߌLѕG?[Iz'AD9̾ DU|+ߐ"Pw݃~6[٧@c/-?cIa7rf0Ն8g_JK3{(hG]G?kI͈A}E`Lj(}E?iuc<`\Qohl< VuE_I㮻ODam)0u}tzm{;#a%  `BUG8/qW|EQ?r{)0V{ &i}#2S0D"ޔOwϏjݍg^.OO4s `0i*z''Ş4]+8%U|ftoL&i|߇A7/j(0tH12Ictiٗ3A^~X[>R H󙤩X(6ra0!ʻ.Ί_IcmQ^ _]GN4ɨz볯h|< Pm?:{(4-,6EП^4u{gDUe_6<l0GwҸ^[0qF ӟ$MwɾmyC ;i NS `bUkΪӟ$Mq+ʾ`ktEYu ;iOzODgScӟ$Mw~?1(/gs  I}4:{$E4zGZĨ}L9I4K3H;}/q="S `zU{G)naYnr `$}s~QejSo.NU^ `n,A':k^bNW?C7giS~(x^mpފK2Xb3*4V=-ʻ.>^yYmslQ1R0 PYM 9i-,7>}̌ѕG?Iںٗ1dG5E4>f?Oޓ4yve `,uƿ ` a>IYF+\1X ~<4zǾ=*2Uw/J4 xe `,exQE=x<y=Egvρb/aA ˿bdascxفς׎Ⱦ <1\&vgFu7O/?ҟ %M_>/(ٗ0`0N":?/j+.4,{k %M]ï" 0 hp?hZmaYHU?zGH3{k/_s `\*^MjWfYDDy磳Usjtٗ/g0&?MjIS oϊʾt<<1~-/ؤ}-0;UegFISzL3rݍYXMjbK>xu(yYipKL3J&QQ=pm)S*: )i:~U}Yyms_I[u7}F F_;,9R42hϤPhx ?=ϒi}Yy-}]/ԤOyfGwW?SJ=Q/[3 EUo}tV=-Ԥ;E٧[Z{EtVnl)iaТǥHT;fJ40cϗ&Yʾ\$<uO/Ҥ-nӢZ{ei@Suޑ)i+yy `&eԏ.OO&mi+>hI}$5/I֔4Uߖ}9y-zn 4iK٧-+0:˷I4vx `_I[R_F٧c0<usɭg_fA@K_M6|Q]<}0.u~-SdVʾR<TuYXMڬVս_>}ϡ&[̾L<n85ř>.`ҟE%M^o})y-7/Τi>mXbs><*iٗ'bЂ;86ao(٧ KF_H.4Yxs `4UjgҦTߓ}z(V?#TT~f `4T>xCK3iZ*[>eH6gTIUٗ&a_I=O&Dط?JϾ, <} 3;u}0!κ(UIoy u?;/̤+=}0a>*i2K0h8g_I߷;DuU٧ *)Iɾ <:L~Ҡݏ2URn%j03 _I߯ >E]Dgϱ8y kLY&}uC)ӟe%U0h`t/ˤiQ2`Tsϴx9<_?&Eo]~HUOKS{420 \o2;)6϶rߓ}  y e?QgLoMƕmL3hHQ&-bۨ,`ԏ.O֕U}=0 }O_I^k ^vPKL0hw_I#Q٧OJsWuW`@?HQQ?zg OJsTu7/;3 9E5'd̰%K4 ާޕL[g̺ ,i sZwctVl,i< <-eŮϊ;{]ӟ%'<v4`ly]5!oHF~y0h OKUe6YYR <-E>/>p18#˒ y i-&}wQfIe< 4_Ty͒ y iuوr}?ϒ y il6Wdbg?GKjA@; 0Ӹ^k dxAђg< 4.fi*)yZR aЀAZoQ=x] z6Zg< vËdEg}8ZҖg< fwZJNk^|-i2hA@yjj>3%mQy0h Om5pZ;i3hA@yj?r}8@+ Eҟ%m^y0h O[mT_}(@-i2hA@yjه1Eצ?wK aЀA#FƢgoIA@; 0Uw]}X?6)<v4`-mpև_;jpI?8<v4`-Xg$_^,.g< %}ve㒞:<v4`ͭ[XrOI& \ ̿JF ^.{2hA@yڔ}]yd y =U}䨫 쒾;<v4`la<0SsYt?K aЀA>D`b?5<v4`WF]|+U': / aЀA_"78ҟ%=A@; 0ӓ;u}xī{Fsӟ% <}O˷MKd< o7ه%Lrݏ2^ aЀA/zxa SgtҼg< >.; ` /^/[y0h o+o|!iԏbKӟy y o=6@ aЀA5>`7>@ aЀA|Uܨ{ev0wzK{i3hA@y9Kf=<v4`7?`n>Y y OkO>`U~-: HA@; 0ț>7{㽋ƕA@; 0țo}%뢳|w,f< fo>I_ by0h o+ 0CY];i2hA@y]ebҬe< feQ2D!4C ٭e^SY y h˷j هΊ#H3A@; 0ț'/6A?M Jy0h oF-`ԏ[2hA@yW3%6C>A aЀA ~;޺+`3TW<<v4`7[OzO!lx^A aЀA UT\}H[7>4 ٩»'~A aЀAތ GrՃ/~~{iJ~ y FOnA aЀAlTC hAuU߄A aЀAofF@zǽ3}4 鯼هТj핾%Oڂ aЀAt=!` zҴe< fBw^A aЀAUu}c=?HӔA@; 0țFW}c?HӔA@; 0țΊ(d>8utҴd< E{g:}Ҵd< b3=}K*>=vWԝ0cF(|Ai2hA@y>lU^oT\ bcpGڟE?'+zG965/bDgayQ#Q~=;◢wb~}(o;/|)]{ IDAT#QS4d< [Gه :^mIy+DطG'f uKފmOD8^w?%!i[uoO4 >d`nݝw6=5YCbE_^ѕGEʈr\? HA@; 0ț;}̫{-s7ksm^;vLsDށkよa7c~i3hA@ySe.0s k^⠬{U}[qp1g0?>/Mpy0h oz]Z}$ʛόyˣwGsV@So>`*U\eviB3hA@yQ #AS~]yTOSzZ]~k //o>T`{4 hxC&^m1(~q[^wWGy#Q{4 )hvQ?@gЉscpG{jbD.~QGLaoJgKA@; 0ț'Aaz^[>|[%1Z54 ɯT(o;/ge,&g*X4i ɮ{kXz~74~ kŶ?Q~` /;,MXy0h o]~h!K?Y`MG~o+}{F$e< &b3<}uw|%Q{]~x8&%58ai2hA@y3/Ck^~Ռ,zǽ#/>`ITnX߃ y MnՃeОQ/Fמ/$ig7~#̲'~#+MJy0h o2}-هZ{EO@>+{btg"*t(o>#~+MJy0h o2]}l[,`w]eOiZuOߛ}:@c3**%g< &>$*(zǾ=)֪cpފr}zcql~_3hA@y>$U7C>~)~?-dmxRVy0h oZcԽDz n0FW||q~Iz6[yۗRfy0h orU]ړW#ψ%FTe{ϤG aЀATio=MQ=tSi lRVy0h o2*~qD]e̹j ?ĵr^o`: QA@; 0țC9V'ito~O&aojݍ٧,@A@; 0ț.ޣ18o+^(MMËvc&ZL)!<v4`_П> C卧GiwDam WRg< ^v`a%z4 {IdRZ aЀA^r+.0` 18oEtVnfe18cr}wJi 3hA@y{g!(ort4u5t28Hi)3hA@yL! 7 ~bgGyi٧>ꡛ5)-Uy0h /b3>atǣX4w-l/,Gi2hA@yyO~o ;II^ߎX%btEi2hA@yy7}!`Ɣ^W=Nu{UTn̾40a{0(-Ey0h /bgGY1,'卧e_%s/Di)2hA@y9?=3{h1ts~,lOƜA@; 0iO @#0_,&&iʾz0zǼ-^(;<v4`?7eL.zGj=M;]?3 K4 aЀA?;S(zaLҖ=썋ZXRU/NJ y -}_RKΊme~ sz{4 aЀA^Ֆ;fЉIIIjbD5Wfob-oB [c?~ߓ"<v4`?߲?rL-=50I9QK ӬFoS,,KI 9S(v}VKx+V?3;/̾0 QT_+{tzmto~/&%<v4`t<=bᤳUKj(o9'7ӟ٣]~8%Mpy0h o7Ӡcpߦ߷$%b]JU$u((cŞ?o,<v4`tt vw{4׭6Fמ}5`܆Ew]KI?f <v4`D> Vwϒct ٗ%RQ=x]:&gwZ|O~f0<v4`4 V?r{t{UJb(o<=7][O4' it5({ lQ?[owyb|g< 򖠅e:/EgοWIVg_h؍Kbx~?ȿOH aЀA Tq1Mܩ-FW3v;EgIOA@; 0gL򖳣i(IS볢̪+F}&gm>(V?#/i3hA@yK"˳?f&HͳrQ?zGe `Qy?={E ү y 䍷bGU (o>OR"ȾLrՃkEFWGga빤d< [0!ʛ0ƓJC~.ٗ5T?r[:&gw/i2hA@ymtI1.$ivo}g{bt)18#;WX볤 aЀA[m1;.Kf{Ey1`}?E ӯÒ&/<v4`76|[5Q{mUٗ:QsY /;0'7*: ү&?<v4`7_# 'Ԋ<~$i[Xo|*Ham=)gw򯯒2<v4`7kxHRw?~/4'!}]y18oE}{huTd< Ss#* ð#ޜ~/4_{ ʾ|!;/=ӳ:z)i3hA@y{?Z2TeC泍CXW(UD?}b|UQ|e< ʣ?Z N`=H|;ꡛbt'cۧ_% y 䍧?ZC?y˳/7卧;Qk$=Yy0h 6,F䴰,Fן}iT=x<;/E>ӳ5I aЀA^ %T?~}QGb3ZwC%t(U{룳U5L4<v4`~MXX* z~'{[+EuC7c!Z%Imf< ZnQXX"?wG8lZzn [cM&IҸ3hA@y= )KdtIڔɾdcV7Dy1Fӯ=A@; 0kYHX+ěiŶQuIhK9j1{,~[{F& <v4`nMHa^~ϑͩǣ.}@am7s>wΪӯ)4 [uԽG?RƬ9}{D]g_F񙲼b-x^C)<v4`^Cސq0f-gGgaY=GWȾlЉ΋bx~?=!I 3hA@y58'cTE 7ԨGK*̟bt118c'~zvvI aЀA^{7q0FOnFڨOD_}YVoXӳG5:vL?%i2hA@y-UG?NdtIj˾̨;뢼 Oy[?7y y S(ۢIjѵ'e_ba :QyQ /''~,\$ky0h YG >[IGŮώ/02UaΣ;.t2vv=kڊm Sx8ԱKv [Z JP ڰ$Tw{9IΙ?[{?{<#].^#IKU-o450ٲ^M}(<< Ig bTEWڊ[ueo_={܋,I2  A^=vkhpo$_]K zw$5*<< %v}F2ſ/Tוhq eoG6]}+|HA@y jQoE߲2}P 5.;k~ I2  A^Z?}B2)f_E;ѓG,+o-ו+q/}/I+2  A^Z;;FwE7A%_?ܲaW^βK 0H`C?}B2($g4]qpYeCٙeῗ%INyy$0ț_kXA+[ճ.+{|9=$Ijbyy$0ț{FI}+IS9 czuZuA7$iO  <y′O߾"-=?dRv-Uewl}%Iڃ3  A^ڧ&l$U xO$iO(ˢH߳ h띻6{*۫Y~KI 0H`W>m;7/Xo(GO=Xmk$I{{yy$0ȫ_g`Bݫ>HRėeŎMXv[:$i_  <y>tc@y=E$MrL)z; eӪ{e{!~᷐$Iy$0ȫ_}k@Ij}Gr v}lg͡ u$IgA@z)LS^HX{[yaٻ7G W$U  <y0#IkYVgC_.{WO_KIA@y >^7D:ͲzpˆiUٽrvf_7I7<< իPWU7D\U6hPS8^\.?G$M?<< kPυ/^vZ}k9ܼnWϞrZH 0H`WbO@Ms~HҾοn= w$I  <yksPS})%uK˲7C*[6Tv/}w:?IfgA@sPSӪC_9hXsAٻeg͡]$IҞA@y ׽?$i_ueE?[uzvae$I{~yy$0ȫ^E .gg ?$i_lr?[V߭<8O$a z)\'Ig[q@ٽ]e?"I 0H`WzO|+\j%I$i  <yYVvĮC$Ida ZOLapYo$I$ii3 IDAT  A^:vI$IfA@j}*͖G $I$-myy$0ȫVÉѧwnH$I><< Uk+O@Ek2ݐ$I$-}yy$0ȫümwG ڧ|!I$IZ 0H`WLx7C$IA@y :g]熿$I 0H`7鯍>uO I$IRLyy$0_wD Z'<ݐ$I$dA@nxx7C$IA@y ׿3P[$I 0H`7w>P!I$I  <yU~wo}k I$IR\yy$0_30No]!I$I  <yc:'#_3$I$Ia oګ^}"*o:%͐$I$fA@PA$I 0H`x+}"*h7C$IA@y ~y*g?/͐$I$fA@qVcح$I$)><< -p0s I$IR|yy$0C>cX{!I$I  <yW^H$IA@y wGuG$IfdA@߲2<ѹw I$IR32  A :'<>U$I$a oᆛ}SQ/ /$I$I  <y 7|dcyXD}[[!I$IjNyy$0[xO=}1zB$IԜ 0H`pE_+$I$I  <y yeY`ό/$I$I  <yZypi$I$9a oګ> cy{!I$IjNyy$0țΚCO G{!I$IjNyy$0țߏ> cB$IԜ 0H`7}h$I$9a ozWEiu쏅$IdA@}ObFrvfY{!I$IjNyy$0țOFE$IfeA@ܱ&4,b I$IR2  A ,4,bo$I$Ya o߽!4,bЍo$I$Ya ol> wi[!I$IjVyy$0[w> yv[!I$IjVyy$0[wO=}ߴ*$I$5+<< _ѧ`}"$I$5+<< _o$I$Ya o~;4,wG I$IR2  A<,+ˢ> ;"$I$5*<< /> ct|_{!I$IjTyy$0ț[K^H$IA@y :g`΅o/$I$I  <ysk0F /$I$I  <ysk0F/$I$I  <ys0F7$IfeA@[h9o /$I$I  <ys\0F_/$I$I  <ys^'g`7$IfeA@uzY} I$IR2  Az_?g`5$I$5+<< ͭwG9$I$5+<< ͭwǣ,$IfeA@oY}|$IfeA@7}^$I$Ya on}ӟ$IfeA@7}^B$IԬ 0H`77VG1zW($I$5+<< ͭg?^H$IA@y ֿ0F蓮B$IԬ 0H`7gE1_=.$I$5+<< mpg`O$IfeA@ :',1B$IԬ 0H`7k /$I$I  <ys0 I$IR2  AVE1^^H$IA@y pbYc I$IR2  A_;>,1z[$I$Ya on> cl /$I$I  <ys4}(O$IfeA@n0hXfH$IA@y ֻ#g٣_fH$IA@y ֻg / 3$I$I  <ysPA{+ I$IRs2  AܺW} ,T>uo$I$9a on+}*7C$IԜ 0H`7e> t/}w!I$IjNyy$0ț[wF z3$I$I  <ys\gM3o$I$9a onE O3$I$I  <ysP I$IRs2  A:),T0Η I$IRs2  Ag.,T0ztS!I$IjNyy$0ț[{!gS$IdA@N|yYh=fH$IA@y :'@a9;,ݐ$I$5#<< ӑ?}*jwC$IԈ 0H`7h}*hze!I$IjFyy$0țli3$I$I  <yWl}*^7C$IԌ 0H`z04TлCo$I$a om;4T1o$I$a o[6D wfH$IA@y o>  7 3$I$I  <y7P I$IR32  A >?4TP<%͐$I$5#<< _ӢO@N!I$IjFyy$0țOFZh!I$I  <y[<4T>$I$)><< _ﺏD:wC$IA@y {O@E$ݐ$I$gA@^ѧ 7$I$Ia o:ViwC$IA@y }kO@E. 7$I$Ia oZ'<4T4|dc!I$I  <y:PQ̖wC$IA@y @~9;,ݐ$I$fA@+f>>$I$)6<< -o>OwC$IA@y ޣ@E$I 0H`p|)<T I$IRlyy$0[k@E 7$I$Ia oN> :7ݐ$I$fA@|dyhwC$IA@y w_FF?n!I$I  <y ׽PհW, ;$I$Iqa o:k>5Nxi!I$I  <y ^PC_ ;$I$Iqa oڧ|y{I$IR\yy$0[?}j]C$IA@y ifO@E[O;$I$Iaa o> 7 7$I$Iqa o}"*}wC$IA@y o'L!I$I  <y7PC ;$I$I1a o>5OC$IA@y w_G:C$IA@y {{O@ k*$I$dA@PC)o$I$)&<< -^{/D߹:$I$dA@kPaI$IRLyy$0~e9G ]$I$i3  Aۢ@ ~:$I$-}yy$0ȫmD :g1$I$-}yy$0G Y!I$IZ 0H`7=D zW$I  <yrBapo$I$i3  AzMaeC!I$IZ 0H`7>5=vH$I><< 䍯3PGQG $I$-myy$0_ėG ګ ?$I$IKA@y *ye9F :C$Ia Zѧu ;$I$IKA@y *0ۢO@ ;$I$IKA@y 5ѧI$IfA@j7>5>vH$I6<< UwǢO@EQC$Ita ZK}*jjC$Ita Z}*j\䍓$I})<< U}*jC$Ita b+~,Qap$I$i2  A^ߋ>5 o$I$i2  A^=~{ؾ5$I$-]yy$0ȫWF :l#$I$ii2  A^X}.jj濄$I  <ysPSw$I  <y^'M~H$I&<< U kI$IdA@Nxii$I$ii2  A^f+~+dPtC$I$IS  <y5' ?~H$IA@y 5|PS~H$IA@y տPSo$I$ia ^?}2jo:%$I$M?<< ի{;O@M~H$IA@y >O@M3[I$I3  A^Zǽ$dUeI$It3  A^γgi ?$I$I  <y`PSw$IfA@ *l["$I$M7<< կg.?$I$I  <y]Ph$I$ia ~E rvfY"I$I^yy$0ȫ_WG N7D$I4 0H`7AG(lL`pH$IA@y &}2tԻoI$I2  Aބ?{tSip$I$iza ov:س=$I$M/<< MV}:j*z;ٙI$It2  Adu/ѧ`OL"I$INyy$0ți}:&!$IdA@j}`YEwGI$It2  A;}>jun!I$INyy$0ț[@Mn ?$I$I  <y7PSQH$IgA@w`_H$IgA@^G` ~' $I$  <y>zM"I$IʟA@y :eYO@M;ώC$I$I3  A^ZųFFn ?$I$I3  A^Z9Tt3!$Ia /gE >3o$I$)oyy$0KwGO:k C$I$Iy3  A^Z }B&лI$IR 0H`V>!|7D$I7<< %′ @M;#M"I$IʚA@y 2@]ޮQu"I$IʗA@y >30_C$I$I2  A^z}"L{I$IR 0H`^F rL"I$IʗA@y k+g`;r< $I$  <y鵎Ѳ,SPSo$I$)_yy$0SѧbT>0 $I$  <yy>S0_;H$IdA@<:L{I$IR 0H`޺#O OC$I$Iy2  A^:V)I$IR 0H`ʟ>%(v<H$IdA@| Z+C$I$Ia /}N&9o$I$)=<< kp9`?H$I3  A^z,L`p7D$IA@y Y{X9o IDAT!$I 0H`.Lb/gWH$I2  A^Ɩ_VI@Ŀ#$I 0H`~[>)^go$I$)-<< mp'`H$I2  A^z,L`Mo$I$)-<< sF I$IRZyy$0[ėE Nxi;"I$I<<< <}V&йwI$Ia /- z7m"I$I<<< opg`o^H$I&  <y]0ѓ!$I3  A^:)Lb4(g|~;"I$I,<< uAg`B_H$I&  <yө0 C$I$IeA@4|0Uo$I$i 0H`7O>-I$Ida o:uzi@}YH$IgA@>ѧ`B_H$IgA@:,0 G$I$I3  A*0-+I$IR 0H`7}^&0 o$I$~yy$0ț^}^&P5 $I$  <yӫ{; Z',$I$  <yӫ}+ :=$I$  <ySlfYYvD o>2$I$  <yS!cF 7 C$I$I2  AtqV@co$I$^yy$0țnuGD VH$IgA@YshP#$Ia o,30ލH$IgA@W'$I$ia oK?nj~I$I3(  AZҔ*G@ N#$IgPA@ڵ=G@ /~C$I$I  < y ?#~+.;$H$I><2 2-lF}k$I$3(  AY8G@M7H$I><2 2-l'G@MO #$I  < y _#?vj޿1H$I><2 2-|PCٕf~G$I$I  < y _:wD$I 0`u/yK)H$IA@y )PSc$I$ia /dtu$I$3<2 24~Sc7D$I 0`S֕?zjj;"I$I 0`S?PS7I$IҷfPA@ڧ=57~G$I$IߚA@y ZzpzOEa'$I$[2(  A^\훢Pu{X}G$I$IߜA@y rjڧ&H$I9<2 2ս]wD$Ia /i?mI$I7gPA@ע5|[$I$}Syed0ȋm'u :iv9wD$I 0`[{5;"I$IFyed0ȋ{oG?j~$I$a /)~4;"I$IFyed0 nAj? a_I$IҿdPA@_.Phf H$IdPA@7 zQ$I$  < yu/zW3H$IdPA@Z'"P3I$IҞ 0`7UF?j="I$IړA@y ƣ築~ QUwD$IdPA@c5u}$I$b o<\@M]$I$b oPK #$I4a y}IJ(PǠfzn-$II  < yl@M:H$I$fPA@f6@M ~G$I$i3(  A^3]gOP$II  < yͬ}~:T| H$I$fPA@6@M;H$I҄ePA@6m:f$II  < yͭi7'H$IҤePA@ֽw5 D$II  < yͭ}ʫufCo$I$MRyed0kpKJU'@MX-$I  < ynOWG?!j~$I$MRyed0kvOipywD$I&)<2 25Κ_~B4zwD$I&)<2 25֊TU:*V4H$IҤdPA@7zg@M ~9H$IҤdPA@7EzI$I 0`z~F4cwD$I&%<2 25?>f~K$I$i2(  AtsSt5["I$IA@y &W~JԻ$I$MByed0țiI$I 0`7u-~JT=;"I$IA@y &~Jdho$I$5=<2 2MHKJU@M~'H$IR3(  A4@M~G$I$a orrysÛ$I$5=<2 2MNk4Lc_~K$I$a orj] ~9H$IR3(  AdU| IPSGI$Ijryed0ț^ixwD$IA@y &~R՛M %$I 0`7YWL C׆I$Ijjyed0țz^J^ކ?%$I 0`7y+YP`ewD$IA@y &gD?+jj$IfPA@ɫ{D?+2N~e-$I&fPA@ɫ}G?+2t/["I$IM  < y҃RipYD$IA@y &~Z4zdK$I&fPA@ɬñO *V,H$IR2(  Adֹ7:["I$IM  < yY븗G?-2oX~K$I$ia orvm~^4|;"I$IM  < y`˥ 4;["I$IM  < y[wE?/2SD$IA@y &9~^dVGI$IjRyed0ț~~J~?~8H$IR2(  Ad7z'@M;"I$IM  < yڧ:H$IRS2(  Ad׽O sǣo$I$5%<2 2Mv^0["I$IM  < y҃Rigo$I$5$<2 2M~~fUUuwI$IjByed0ț7~fd\["I$IM  < yܐtB-$I&dPA@ɯuˣ_9H$IR2(  AtTkMG=/H$IҸgPA@h@9 %$I4a o:]@.H$IҸgPA@hoV&H$IҸgPA@)4G?7jzOeI$I 0`7='} %$I4a ozqVs CwI$I 0`7=uxks WI$I 0`7=O{Ms C~".=8H$IҸfPA@)jA~rdhD$I4<2 2MW~rd]["I$IA@y +[. %$I4a o\'@ꩯ {"I$IA@y q/~rdj{"I$IA@y jg@o %$I4a ol4aD$I1<2 2M_kP}KD$I1<2 2M_s^:D$I-<2 2MaG[JA CwI$IVkKS_Nߝw)a o:=|O !'I$MP3#Rʷ5ickJ_>W36$<2 2Mg;Ί~zd=q_-$IT]Կ4z讔  < y @N{"I$iN85OL/H$IFc^:ކ#wlbgg߯ a oJ[zP:wO$Iim١{zvݒ44ڱud7_ZǼ8s2(  A6@jD$I^ԿuenߔҠ[w?&dPA@Ê@I>H$I8]zgpTfPA@s~?H$IMűRgpdl^oG~8U2(  A:L{'$IRcZvhj:"u-I;N[SF gD?dPA@ڵ=  IDATo$I4_=۽ͩ4ܾ)~;5Uϳ a ol4 u+$I4ũq& OU4I:b?&dPA@wͻ {"I$-d/LՋRoÑiy͞pZ?&dPA@s뢟 d=$Ie#Rwݒ_=;z讔Q6݋h@yed0ț~~J~3 C/I$Wo:> oJߎ=nϦ a O~djD$Iz9q& OUc? y5!<2 2ipYL$IƽE4ؼ&vl(3lByed0SF?C2 >}a=$IRHݏI}^=%0csk2(  Aڧ&D$I[SgԿ4ܾ)~+#}oM  < y]zP:"+0H$ik9q& OBoByed0\/\I$MX_:\]4rivm;a OsoX4/H$IܲCR{nIߺrW{s8:4 <2 2i΅o~dZ٥I$5 {zvo﷢?Ҳ 3M  < yuˣ"c7E$IWؗEImS5#+RQ2(  Aj@5~O$Ia}kSoÑiyMؚRUET%SӉoa O`˥L~O$I-;$W떤+p菥̃'ǿdPA@xc=$I~ZvHj:"u-5Rt?F2wvA@y qV װf H$iOOSo̞mH :7-7!<2 2_׽O:"I4yq^g\ѐ 1݄ 0`]D?I o:1H$M|3+ߞפю)U菂LƿdPA@<}SKJUgW 衻o$I҄:SwݒԿuenߔҠ)2̇ 4!<2 2i_.Y{#H$5{/u/~StB>Tu )7ri&dPA@<]rM$IjBc^:ކ#wlr- yA@y w #YP@3o$I5sXj:"u|h0/Ӏ 0`k]F>H$=+ o?#rgJ~4eA@y FO|!iP@WIuᩳvqmImS~"3?cM  < yWs_@u|[M$IZǼ(uV/J Gj`^ :7]2(  AUwD?M l,H$e=_=nIyvؚR5 jYl@yed0Ӿj @U{g]vH]$Iz_=۽ͩ4ܾ)A'cqV&dPA@UF<?ѿGA@y ߎznJn3$IZZ_:|]WiTQԻ~i&dPA@<=S/L(jL +$pMUG%=_=;E ]oA@y Lo9%PH?~W$IR^S~ u/Կ4)1 a OTD?S m\~W$Iҁ:%zQ}opT8~'5!<2 2jE?S }SwE$=M_g|4ؼ&vlM?>c{j@yed0ӁT= @ aj;$IS߲CR{nIߺ2 oJi؋oՀ 0`iu]Se~W$IZ':kƙ4u)[ eM  < y:zUS+$Mrc_g?7im}fwD`toM  < y::.PH5h]zpm$i"9,|mm8r}ckJU} ^3A@y t@ @!sÁ"IRZvHj:"u-I[WM) g32`2(  AW~һwEquᩳvqmճ'bsߋM  < y:Z\(dś$ITE{zvezs MZ'2we2(  Ae3PhZ+^~[$I i=_={`4ڱ55vl@yed0Ӂ:+u/yKm$i[vȞݺ%4ܾ)A7 /HTAvqmImS}r=ycA@y l~' @!s#٥I:ũzQm82 \\UfPA@<=z' @A3~t(_-űRgpdl^G.ҿ[Д 0`: >6PPo$iLZvhj:"u-I;N[SFѧ `o:>>4$<2 2NݏIc -ho`Д 0`:O @aS_~_$I }4$UM  < y҃S|(w_IRxo>IekģCS2(  A65_~[$I7$E~A@y T~4ֱ~_$IU_RE`/B}hJyed0S`&K7IRlUД 0`-M 1"Ik١)UU9`/S^#A@y +wF?a ZeIRL/>EC븗߈dPA@<Կueι?~_$I1O}u`fznhJyed0SNK()ESg3^Ia O9NOª]IRL}KФ 0`ܪ]ۣ1$i^^F_=>4)<2 2)g.~ֻ~i}$-|>!>4)<2 2)?~6z"IZ} C2(  ArkǢ1u+o$ia_'߇&ePA@4)<2 2D3O҆Z#IZt.zc}hRyed0S:>)0n$-PG??s^#A@y T4D?g l,H)?}v؇ M  < y*衻3UQ 1sF M  < y*Uӣ3so$i^;'iv7Ia O^y0#Iz׼+jд 0`R}yPufzn$oO>9eд 0`U~̃_1mu]`/7߇ePA@Oyҹ$i~j3>Ѵ 0`U_(Y0w~c$IS>3CM  < y*K5j=f~g$I\3>tѴ 0`i`t;#I*_꿈>1CM  < y*]{ՏD?kI3$|O>1~#A@y Tj #A@y 4 >/F41<2 2i^Zzp:7Wo$HK}V؇ dž߈&fPA@? sIҮ׻bsQ1aPAڒgkEA75FK :?&`+ׯ#&5<< *0Ӱy!FkF؊W1 0 Oîw9C4xFm ? 0 Oî}{? SYa o$I;?֊A@yi-}nJnG!^Hv%}} _~OLjyyT`QT|:CT_3 IqNtw$gA@yE+0d{7WnZ}ucA@yiW?;:$ͯ?}m 5A@yi5R10Dek}j,yv#Iq>}m ~OLryyT`QU1O IzW}e 6 0 OwwlpIҎwi6tN@=1aPAFUsq`%w$i;-=n#`ZG) 0 O)<Cֽw$i۵V}Ue{A@yi]`ȊGo o$Iۮ*؆rӺ{b3 <G1o s$I[op0{b3 7~'c$~Svt/D]1aPAF+?@9gejz_]1aPAF]w=#0;Gw}=C_~WLzyyT`Q>{F,S밟 w$IS};-Nj./&<<< *0[GJFG]<ޑ$̻xaPA">#PnZ;gE_ lG:dA@y{?E!IP7OtdaPA"jxkG8ޑiyR*+aPAB]?PuO=4u:dA@yjpFw$Mso}/ /A@y)`D擩dGŻch}Q 0 OQ|cI'j ,KyyT`ʍEFd5$Mc돉؁޵u  < YUGj}Ifr#яvg$<< *0Sd3$0BW=4MV`Z+~g%<< *0Sd^RYFF#{ IDATL~0iwO~v,Rcu  < ]^w$MKwE?؁ɻ:eA@ywa*~05fw $~S#yvVQ 0 OѵW?0b~7׻=]8ΨSyyT`>7~'(0B$,LƇCTrfA@y]}1o $O<:':eA@ysQ`7 $qRc6~iQ 0 OЖtS󀗇ATOyxF2  $N /!%)_C~<~0Oϼ;[yyT`Lrx{HPяu,Ss;A@yi*X}$9O IfwKuяtX6ayyT`qwGţJ$MrS?8`'uZQ 0 OT{Aڟ{H&=_~𻣎aPAƪI׊>y=$IZПH, ?A@yisQ Hk$Mb+~3"5~1<< *0ӸսoAw]~IҤ\T7D? cu  < 4nx} Pk["IӿyUQ 0 OX@!If{*iyyT`q@1o $iяlvAkwH]3 'kyyT`ql@1o$ikяjvAwH3 Hƹ]G?CA@yi\^HeZ+~I8姈nyN0y:E=R 0 OZ7E <>qlpEяhvіH3 "+an}'IҸ4X{q]'@?<< *08>wcsI4xwwI3 ᗣ ,S_$i5zeJF S%<< *0DxTv6FDu1 ~!׿yU# ~LKyyT`IikY~7I0kι ^7ʴdA@y:g$0FO4n~I7-SA@yiRjC)E`?&~a]= n#5~LKyyT`Ix#8)ZIrkS귣d2e2 :-1y7[*G'CP֧f2 }tc3>~WI|ꮞ~d0$g1<< *0$)1i$~uqm) zяL5ӘA@yiRr` ¯45Tn?Q x]}3aPA&930]}%I4G$CTnZLiyyT`IyR*#8R똷Y]4ol}3aPA&_>B;Rcs,IRT  Y쏄9ӚA@yi^OG п;KX*OF? w5<< *0$:G 9[%{@Ě{g3 FL]~0JFj,yv3aPAP~mQ`t/KRkΔG#4g3 <աUE%&IYɿ~Io#^SO;FsGi  < TZ+}0e:w`q`”Oݗ$T_Gx @m r1 Ouw 4X{Ij,=45 ]X HC"bPAR_>NL7Oiw nsˢgj 21 Oifa*7=}PKe&Ż/G?Tv7ƒgI2 <թD)&XK $MXR[~|lp$eA@yS}dE?? iv_y sg 0 OjvQ*G+&Yǿ+N4-#o?;hIsaPAVD+&\~:w1mKU⑛& 0 Ouk˯u5IUskQIA@yv-#G (7>:n45i*F 1:g({yyT`:ֿ@MO(ORj#xGcX633 <ձ>Zl:5EUSzfyyT`Z6(>^ԈQ4W/я TkwA@y䩮~Tf'_~IM 6~0IA@y䩮@ m ~.4fPc,}_yyT`6 >bPz*V=/G?f~5gA@ys>bT٘ǿ+֧S*Xx` xKߟA@yεyK9;I')uO&Dυ]zyyT`W'Pge_N.٩wO&LajyyT`׻|c2i, $ͿJCE?>4Vj{L[  < TZGl1`Jo;+5~Iqf*[OE?6@; Ǵ 0 OPG )1\O6Z~4Yϴ 0 OPwlQ`60?IϬ⭩xbM#Io沽4m;<< *04:SPjswg=R)GۙA@yiZ*>0m9#w4͵|c*4&:~ n3 w 0 OSՒ=S} :?5|E(MxO6 ^}uGy_yyT`iq攛'F(Mb/L+HiЍ>L 4 0 OVwE;xͫRsߑDx9zZFܴ.5f߁WyyT`kfA*/3W5 u>{X60ezWjaPAF=~ /5~WJT_NźO(SưB?<< *04:uGXOjz})E: $SxP;A@yiZ+!v Rjw4ZR3R*c^/v.<< *0Ӵ=vLՋScɳNiص}BY saPA?Ҡ}`^L~Jh˯hO7J#^~jZg|/T OEj3 _Y̍'7U%HV)<wv9<< *0ȓ^CS~_+OyyT`'=)},`S'A =-#V]q?/`M~l,aPA=.J&Lԯ߼*uS7ܒҠjep|  < 7 jl+L >l,(ns?z_Tܻ:ǣThkP 0 Oz~5x)צ-'ũsʷ?j^ZGiWvԻ4T3y+RcvEyOT-7;~ ugՙp׿̹'֤kFlCaPA&WٔST>uo*ߓu75ҹ_2YsrzO:w~m{  < m|귣)Q9h8aPA<%V-}A@yIۯ}/FS Wk2 <.A  < 򤝫lTv6F]`:a.<< *0ȓv׏>O;5A  < 򤝯צT؎fA@yҮ5 lC|25y~6<< *0ȓvG_`_ wgA@y.6 }Qv6/wgA@yҮ=/0=zW@1aPA5y~*OGc<(&<< *0ȓջc uG+P\yyT`'Uy+St2P Rׄ+P\yyT`'U Sg(6<< *0ȓJ,3L~@aPA]DgZۿn@aPAg~)8j;݀3 <)_7Di:xdA@yR:# S4aPAEXO1X 0 O[}`jV5]'<< *0ȓ2l<}w|1=*<\2IDAT< *0ȓ׻tIz+:h2 <)~0n#x@mo==/<< *0ȓSOGobZG!/<< *0ȓSW4Fq-'xfA@ytBt:;3<< *0ȓWפT9Ɩ}_A@yIí碏9à:7<< *0ȓ[7TG&^5aPA4}`ZyЏxgA@ykF?%*]4?<< *0ȓFs;Lxj.+?<< *0ȓFS7TG&NK ^  < 5#xX{wzMFyyT`'ʷGy(>}^A@yImpcx1 &'<< *0ȓF[3>0BxMVyyT`'WD}k;]A@yI};>bZG!&/<< *0ȓbsQԻ 0 OưS*G95xyvMfyyT`'5 я+݋)&7<< *0ȓjƔ"1cX65<;&7<< *0ȓb~3{&;<< *0ȓbk) zя5X{IwtM~yyT`'׿GRׅ?gA@yR|̓^R8 nzdA@yxԻ\x,50{A@yIQs)#NdA@yԻbGLԘY}\  < SX+ZWyyT`'WݯCc¿~aPA4f-3~4Дy+⿃vaPA4~uG M zfA@y6 _x슇oHE߽U 0 Oǿ3y:M߹U 0 Owlz][  < uO4E?&rӺ\ڪwyyT`'w뎎~L@eS~;;A@yI]sJegSvsÿ_k:*V *0ȓƿ%]Rv7 nxbMG *h/$IF?.`u/߫55ԂA@3(E9#я )[~}hcߩ5=ԂA@?LelɳS/+eڟ˚޺_X) < LҮ5XG}ɚzW} j n+5f0{MJNS)Wn?5 {gG0q_IڵzW`U ~,n> aPQs_IŖ>7O?`J;:40n#8ԆA@E38]sƇ#Lr~UƢ'_}j 4Tipя_U1sO@TԿf:gS*яD¿ K߭w#P+y i&z~0GK ,}_>bAc8T} G?N~'>3߁6 'O@d:7_I\{'X +ZG1XԎA@+y&)O[O~PCs_D 1ȠU/$ySXFcIwǿDiUяjJ[u[@-dҽh:Sw-LRs^q]=}Dj  Dˣ-LbǾ#o-ԒA@F~4E-3Oh`.'{*>&dQK+eOxҶ^w 2U4I߼*(A .+mbݍG r*8 Wn5{I*7?`ܕEjkc:'O @dֹo_I_s5]e\T>`^'[s)L <!knW_k/̂|]}h*yCn[c5@Ě=To_R}tA>/$ 沽RG CTv68ZJL lQ4E7%8%˲dj_Le٢vo**P_HWke|V,_UN(R X9pCRιH}׻Os3OmWec!`O?!x4Z׼7,u鳧O[@ yqY#ݺ*`[WϜR{>:cB<)S$ 9T3G de!`uJ4Upu(K5~j~MTee!`>u?Il}p:h^S>=cB<+jC0'iJulUURֵ <?8'i>sY}^\)ʓ|ng{QG:Iy{"n@zoĢR?}|Ơ] 3T>mWƲgIZ7| " yڷX'iM, :L4ּ)>BB@n;3N`k\Qe8N=ޝ>?J}|IOܗ}5OH s*}?ύlKXn><!Ѿ$ K|j[uz^?+J?赲Ga!`XE4>J}|Ik>Xrn?Is秲{鳟w+FM>YR8g+}(v`,ޣEmū% `A)vmg>SorY0BzU? JLu赲|h~M'Ss0bo7?JL˲W5oJ~j}Qe<T~:W+P`{Q50h}[l'SOD0h~ % Q=9Uͫ<fڪS0ʪ*:^Eyٷ 赦?=I3y[ܿ=0,,[>uZ#qQ5~} W?>I3L# <<7W(ink}oa Q޸,}~fRG7O d!`!)l=?j'?.J:w[0:7<}nfR:L`,,@žmѸ鏌_ξZNg5j9=Gn>. y U-%鏎K|7 3?IjvnTyd!`+Y4HI]7F @g4X7Qߞ}TH`!`et_鏑mf*izĢL:Z>&$0Fv-[3j+^8)i7|(yW&$0COFƏF4uTU0Go1饿 yc<7ڷK yc[FmrIçc֘zC˾9T؝Vso]BT.ƕw}9.ogo-_dVsךg$A˟~7z-DݐdMA V_ w>Z?KsPs0ySu7D7$Yw_}W~>43@:Vo<%:QV<'+qݳ:*4y+GGJ9LsEG%Yx2(|ely;`T5c&DsO n9#~H1@` 5s~^VfE}o9UXi9/ُ8 (LA7ִ4] uDp3}ԯGF zُ:HcT);Gk־/I?J cpͱٷH0B4zat/\e&q P0_s;ZBxxr-0R‟?Iܖ?;$ُ֣<X0(LXth-9)-tKv-g߆#E҂lQ`D*;_HZ:e& c,D8FbnQ>`"<('i Yݳ&Wd?`0v}m_ Q`.XyOtV1| lǠٟ•_s|;`"us)mG#*Q[Pn|8ڟß4"yVWe{m6 #oˢϋ|ҨT|^]}kLa/:ǿ-(iʿ[Y Pi%OK?I#O|0z_M?Jފώ-gd? Dj.1\}y 0uκhKBI̢]*qO?P'R'GKχ(ُDeH)7>O?I#ҝbxٷ'+q0ωIwc P冇8x4R-11^2{VK?/Jڟ(C P oGqOܤjbxٷ'?bpͱgFIS__>?`@᣷Gkߗؤ'ѻp&(i+>(0T5i.7|6TUtO`R7;Bu<T?~@FE1֧oO6ǰޚ4~'3@ E(4j/7` T>IIjgqA.@&Z?S[ž/N?WJR笿~$0 PXX ڟ4jP 6(&eL?_JRL)TM?IV?m4KZC9SҔ7] nB#)d]q@K7fߞ̑H?kJRk.1|G"S1BH:ǿ=b˾=c?~攤WF^H`0uEk.ijzoOCUF3~#, Wῒ~ВF'^UyTu7D_L?JR﫫L U+%R~/j[Pv~4-!}-0@` 4,md?`(̹u'Q:_bm @rcK9UTW(L(Tz,Z+~Fedߖ&UYUt=ُC& ssPҨۢXkUx>pU dy^I:Èr}[0q?g]%Mo#+ sc؏=N{ֿ|ُB& swL(OGz$` ts%ݍُB& ۬l=}^{oIŠ3W4ϳKLYK?(I-%};0fuX{VTV,{f~0! P&%)bxٷ#cjxυZ}VT=#ُA& ۤ?M? I[1)˾ s6ޝZX?ϾUݓޕ~Ε4u/OA& [s:'׈r}+0!κhU]IWYQk9Jh-1`$e>d:gߊLtswپُ@Ɯ [{?}^e߆L M?J_1g?c(l>ZwM?I)-)}0z]Xտc-ֻ!)bpٷ `؋o? K:G%3@`\AHʨٷSP8<,i>rk1e{IHʨ{{#*` 8ZwH?KzGc-9 ik"`J/7l,iz*{Ip` { iܛ1|Ȓ]_~0 Plo~;Ey7o=6^V4uco|kfQ n8)(F<-,i+V1g?3(lrCZ}GZz-ɾ",i:{I#1cf}PuOzkȩɯwg?3(l_i}Gݐ}6~7}^~4T1c@>ZKvL?H]s\sW-^%{嚻w n>=#{3/fnz_󴤉npQُ:ƈ :gyAGʾ`˔3ɭ`ШK:|==U}o+e֒&b#2Q0@) wW!G&[ s5(-i2+wgc1aS_wBG6 rٷl9J?gK7|60@)u4/l;;`n >ے&ޗ>`LC~>#G go/ScwDgnIU7g?(<_>Hs]ETe-snpQnIֲ]"J'5X}yF_UX{ߒ&d?(<7K?Hs^OoeZ0֣Qsixُ6ƀ Os_llpՑٷ,EkfQY\dơُ5ƀ O}䯥l{o)XP3"<.i2Gc'Z{FڇRD}KzW%ߙH` P1P#EŲgFmw(*ZK~>4޵} 1`@woL?Hso'Hջp&|.i+}q 1`@mgjm{_eJDS~N4l7,b@?HP_to% cGkuI[G#Z >~b3|FJ%o>o gMFן} 詪s|#Zߛ~Y}ȪZDwIދa8j{mĠ}H3kxُ/F OrFڢ壷f:0뷒d?q(*#@#mIξm`lTcG5sُ.F *@#mnݓߝ}pR^4#Z^~6bE^}X&(jzaFjl1VQ3opY8j~^Fjɲ[F?PE^D[&B~֗4Z(6ijٷ LMbŮg~I M PeQnp)ٷLG%n(41@Fi}{d&(2@(VkoXպQ,VgF/PE#v1[&^ i2@ P4jٷLWH Phb@-ROa/Q;ZKwNL@d@jhdQ>|c-S> H Phb@-J+ξ`: >?4Z(:r#Z3ۥF )?PE˟պٷL9 Phb@-e7xDgr3@ PY;0B7|6IZ(ʪX[TϾdn )/PEYmU);v )'PEu>ٗ>,O@RN(41@bQm|8ʰCHAg@jhtjelˢ5(I  M PeϾ-Ÿ ia3@ PP+vjٗ<(V=?sI  M Pejpٗ;&(2@B9ٗ:*:F &PE޲]Z{Ol򑛣x${(41@7Ͼ9;o?g4Z(GZDUf_kX{ 7PEҝޝٗ80:"3I M PekU#~%sI M Pe}k#E?H Phb@-y3E+/m`uO}g%PEs]̾yVmn˟9&(2@\Vz/k`/]Y&(2@\6ٗ4Ph3GH Phb@-U?}9 lx9IH Phb@-Eݣj=}9 :'# Is M Pehpg/e I;?47Z(:FDUe_@ޗ?&(2@6d(52UQ*$ms(41@W5F?Z(ڊ_ke_(>?mZ(چ}#fxǗ?mZ(ښ:'^ oKBg@jh[STkɾtU~hl&(2@іֿdye 33 I[ M Pe-WG ٗ-0GkeH Phb@-mIۿ}cw?ːZ(:ǽ5rH>/JLCҖe@jhZCܜ}c?אEZ(ڜzC rC~> I M PeUϏ.R?ߐZ(jjpQٗ)0:Ng6/PEOUSۢ|hlY Phb@-=i3bK/Q`Bt?!1PEOV?ʾ< R7ZKvLCSg@j%;F06sIO M PezC LjCZsg<PE?Zbe_?$=y(41@~d__N DR}(41@c?1f__W 3@ PpR% L1U/H,Dҏg@jkuU}IS韇H Phb@-{{.̾i2DK?Z(Twd_|E$p(41@Z3Euٗ"0h? Phb@-uO}eLu'>"d@jLy۳/C`Ue{m$f3@ P} ?'D(41@3z;ٗ @DUESy$Pez}ٗ :?I(43@tV,{fTξ~H_OD Phb@-wDz/=3K韛HӞ M Pe2}+v6> 韟HӜ M Pe2}"xRJD Phb@-XkTuٗSjQi&(2@/; n>-siZ3@ P쯟f_rͪ*ڇ6i3@ PE/76Si&(2@ώ&r|UC!si2@ Pޅ˾?W-Pe+=3֣ٗ+>g?_)Pe}_/36Wi&(2@쯟m؏E Phb@-ɮwٗ6\ud,Ҵd@jLpwjK `n E Phb@-ɭ{//9a韷HӐ M Pe2,//3F?w&<Pe2|/-9׿tU.Ҥg@jLfȾ\]Ŋ]?{&9PeٗO響H M Pe2y o?'7d`I&(2@ڇ|DUe_P IDATV{?&5Pe\}t%L.u|(:^û/:?7C o=՗ϕ{pT 5` EH M Pe29+w跳/)` TGg$;k%ˢwE?ooj/bŮ̒%>엢sۢ/}8_]mg} wߙy4Z(Se_N(|vv80zݓ~-^{63}in+et,/D Phb@- iɎQmx(rʰcwsOM98Z}&Y,AwE1̨};̣oD Phb@-ɨ{/%`l5xMO#~%7QٷLǥq&(2@z$V6OGߌvvMo~&W1e0Y(V ]/k(41@ʘ5]Tk;l`lb{_FYt?T]$ٷ Lޅ3xi\3@ PƫoϾd`Tu!>qisjҨko{Նd4Z(S/ cwD=l{?'ogJ0ֺui3@ P_ncITe :'3Z3ҶV\udD9Ⱦ`l1}.c(41@;/IUwC(xEZ&|!o7;#ߘ.-Pe|*%rRmx0z_(VMm[Ҹe@jG#ߔ}(=_h-1--x3{[ð?vpi2@ Pƣ5ξT ݦ?n[K.Z1eߚ0_](Pe+=3KҔeijZ_ h-)-K(41@=ϳ/HQ>zktO~WdZ?jٷ-4-I(41@W~T='V|^ nl- #ji\2@ PF'^QUٗ ,HPƹg6~7978d@jvKe_"0_yP+vMJRb\ud #e_ ~GK M Pe2,j=̫ٗmgGq+߻҄9Q V0Egi3@ PFoɾ<`ޔ\#ߘbbpiٷ=I7K M Pe2 >:9WF=xw4muO@D~ @rњ.,r(41@ʈ3˾<`Te ;!UJS\=|'w4Z(Y?ʾ4`Δ]_~k~4@M_M>F8Pe4K]DkɎVI?^{Lrž?.F5Pe*V bϾ4` _^Ե?(9 wҨf@j^&VuG?KJϊgd?>`AUVGkai3@ PF/;,`/OJڊfEG ,ΉK# M Pe2Z8f_enl.mmqU ,mg{Q&(2@z}%[ߡ!{D;/0ʡ'd@jV}I_*ZK4{?'\y׿dY{W Phb@-ѩeU}I@j9NIܒcpُWՆ&(2@zSw}97%-P3G̫IJ# M Pe2:^}9_OoΔu~mdF)Pe4*|`dU =KIu&NUENJ M Pe2KjxI?}j=hmSQ>z[ ;!z|(ڟd4*Z(Qy7/1Nֲ]ߓFA?Q٪ 𶳣wђ(VZ}{L&(2@ɫẌ~;`ZU3~Jy'#_F7GkN+IO M PeWwgV^tO}PdVzl`T~blrLt{{?'$i3@ Pr`AI]ϋ|'m᷿b$M(41@JR3E?~q|r%ME~/rO>B9VN޹{>U:KvLH Phb@-G!G鵢JJ~2 f?B嚻bpI҇,)"i2@ Pr_4GԍO~;'i:k Qf? xU}A.ZŪ;$f@jT>xui/H:FĠD׊ˣA=>dh,JOH Phb@-U`H:rd0Gnu'D=*%;$~(41@=ϲLɟRo$ǺgU`bUmg?U:ǽ5ZKwNK Phb@--gtu{/Y{UX 87oQ=.ir2@ P%;Fݐc`ٯHIғ5("/>Ͻ/_,4Z( [ӿ#`PN[{q#`(9םs|綤&(2@Y0z-IIV|^k~t6<Ξ=s;X[Y Phb@-|9jpQ9I\TuُPQu?U:WS>/LKR](41@ Ϩ9hx9ZCNqQskt:2} ڇE\Iڜ Phb@-e@߈ֲ]s-u)+OM;!zl&(2@Y5q0aMI\ơُUR=~Q,{f3T2PeN R6F_HIҜx~ُWRupѿ(yQR9Peaj5{$i+yaT~jt:2} ڇҟZ( SܿQ0ALI|>n{bp ;whg$B(41@45bxZ}M&̦rz|Xg$j(41@x:LjݷX{M5~cnˣA_SS4I Phb@-}L^+ڇ6&I ҝ|/0(F~ؤ}FkfQ3L8Pe?f&@sKIBWʨ:g?QQQ>zk =>z]xCI&(2@c` >&}&IYuO~OcHRmx0DwFgZ(10ƪDY4IJlOe?yVu7pѿٯ=4Z([ggUc~#}&I(. ̕r#7{_F=5]F4 M Pe21cw$JOz/$U:N޹{F7GkNIғg@joFZw$R?xT= .Zӟ-&(2@oUg]q/}$ihcxѿl({i3BZ(W0gu{LFb3\sWO9gG`J}5]3A4Z(W0w}9Z3c4u~KD9~d䪪(#ן7Fkg&(2@ǃ 0nh30I~jû/EKs;X{=.I&(2@uޅ3/I<-膱S6pѿhG,I Phb@-'{w~MDU|\w_s룵x{W4Z(Sfh3kKƱ޹Qmx0/4:G9ZKwNG%I M Pe2?-cdp.If𞋲ઍsf¯sEsGIDd@jOWehUwWe$i+xET ُt?V W_+i!{̎=Idf@jCKwwwt<֊]T:gntRvq.Vg~$A$ D%Ⱦ$YM!BP1ݗ$Ͻ߽'=<|.y~g\%I{AW:LƠ_ }ݶ?dY_c 9($L鯏~V;ǥÞ~$ihf߼m9\w&KI3@ $׹=Dk-Iڛj|U5<;|WݿJgeHc@qNOIJ P&W㘟~N <$-G`5}2PaU+{lϢ$I{J(d2Zg59(X+o$-# 0M_s)U܃ٙE;I P1@ eru^Jl3WG&a=6uuվ]}?c$Ec@ e?%)?cO`2ܱuwUw*@gI=r PH2@\D?'${'0l?]Xuo8j_f$IZc@djO @O?V./VIj|E~ww*[N'$I(d2Zs$s@O_n[SuRN}]5{? $) 9($LΥF?%wT#^~$IjfQWSfw_XuZ\T5>.IF P&O @4FI\U gb0lm]QuHZGW$/r PH2@L'~JJ3T͏%IJ׽Kw7U?W5]?Q&-%Id3@ $ U5E?%{I$}G`5l>}.5T'z:j$I~(d2g@(Is׹oE1;Vᄚ\x 9Љ~I 9($̿9fj(IRVS-43UUcw*Uƿ$I*&r PH2@k~F ӹI4Z3ګ;౛WQ5{u5;O$I*7r PH2@>dЫ+~8>IF˪p֪w9Ug!UUK_+I P1@ e g / M+hv4_uw:W-ZkG4R$c@<[U5G?#i$I-T%vm7[=xh&L$c@jO@AOV Ok,?`ȣn5غڊ% IDATtb>ﯪ檟fg 3$I #r PH2@_yPI4W/ [w*jjv ,$I PW#XѷI4~Q5|扩ފwMZݪ-I P1@ e~હjvfQFI P`۝O@!:W~$Ih_ z`ۗmkCv*$I3r PH2@G3TUyO&IDj[w*W3~]?$I$2@ $X@![7%IYT =?lm]{l%I 9($֚̽ߋ~> ѹwI4ٚܮ8,$Iuf@ I(s@!I$Iޒ 9($̽M'D?l3&I$I4 P1@ e2(@#o$I$I Pp#@6&I$I4 P1@ e-}aU @3W3%I$I& 9($̭n]~$I$Id(d2Zk~: $I$I& 9($̭ChAX$I$I$3@ $սcO@[$I$I PVE?- G$I$M:r PH2@['tk~c=$I$ic@wD?zjv#I$I& 9($_cE?o G$I$M#r PH2@ɯ~6u7G$I$M#r PH2@o~6ֽ%I$I4 P1@ e:lDw:{$I$I42@ $p\h]H$Iie@ I(svy@ޭo$I$I Po-@΅E$I$M+r PH2@3G?'&I$I4 P1@ eWUAeЯf$I$IR(d2^~2 ~$I$If(d2^_d}[$I$I43@ $j' P"I$I 9($W~2>H$Iif@ I(ݴ2X[$I$I43@ $1|mYd6~$I$Iv(d2^~2~$I$Iv(d2^'~26~$I$Iv(d2^SO@>I$I4 P1@ e' Hk͛o$I$IS PFq+ @͏T-$I$ic@5Oymse8o$I$I PF-@ӏ!I$I PF~.~$I$I#r PH2@~.n[~$I$I#r PH2@@K$I$Iud@ I(c|mMs};$I$Iud@ I(׿ H1I$ITG(d2zn~.4;$I$IRc@ z 8wH$I:2@ $wD?z$I$IR]c@ʈ-yASdO C$I$Ք 9($VcG?A|!I$ITW(d2ZUF?Azw~$I$I+r PH2@橿TtB$I$ P1@ eZkT^4I$ITW(d2ZsT$I$ P1@ e:;>/$I$Iue@ I(չCO@֙~$I$I+r PH2@O@i~$I$I+r PH2@K-D?A~6I$ITW(d2◮/Ti;$I$IR]c@h$2wH$I2@ $?x]S A$I$ՙ 9($`O@a$I$IRc@h ~oS`ck $I$ P1@ ev,Ϣ ?~$I$I3r PH2@>@c$I$Iuf@ I(:g HwÊ;$I$IRc@JG?A- C$I$ՙ 9($| ($I 9($\@ƣ$I$Iuf@ I(:S3ie$I$ P1@ %_E?A7~$I$I3r PH2@׹G?A7~$I$I3r PH2@׹g H$I$Iuf@ I(W/~&n95I$ITg(d{@ޭ$I$Iuf@ I(Lݶ&I$ITg(d{ݲg H3$I$Iuf@ I(VD?Azw~$I$I3r PH2@xt3wH$I:3@ $|?LwE$I$ P1@ %_c 7!I$I Pu*2غ9I$ITg(d{@;$I$Iuf@ I(#|g $I$Iuf@ I(#|g p$I$Iuf@ I(#||Z3dV$I$ P1@ e/\LD$I$Iuf@ I(7LDٙ}o$I$Iue@ I(7Lj|EH$I2@ $|MD?G"I$ITW(d{ݲg PW"I$I Pu9<<5H$I2@ $|+g @3~;I$ITW(ds @Oq-$I$ P1@ %_C @~$I$I+r PH2@Yg ;}$I$I+r PH2@׹@Ε3H$I2@ $|M3[$I$IR]c@JyL|r-$I$ P1@ %_3L}SH$I2@ $|Lwy-$I$ P1@ %_묷F?[7"I$I PL~[$I$IR]c@J'74lE$I$Օ 9($k~S3lv~H$I:2@ $|~#X~@=$I$ P1@ %__~&5W~$I$I#r PH2@<@i~$I$I#r PH2@8ǣ `uo G$I$Ց 9($k| `[=$I$ P1@ e ֹ{$I$IR c@hU^S{ݲ[$I$IRc@h [ۣ @[W"I$I PFkckS[$I$IRc@h ~oShus-$I$ P1@ e_bShH$I:2@ $?1T3$I$I PFG?{$I$IҴ3@ $QtTk3H$Iig@ I(#~mMSu$I$I PF{ O@o G$I$M;r PH2@ƣ `~$I$Iv(d2ZG?~$I$Iv(d2ZK~*6~$I$Iv(d2Z T}a=$I$ic@h?O@H$Iig@ I(Z{PSlH$Iig@ I(<ע hA5x$I$I43@ $j,&I$I4 P1@ e~* <7I$Iif@ I(#xOqM$I$ic@U Xg!H$Iif@ I(7HsaE=$I$ic@ \~f=$I$ic@&D#I$I 9($^ `~$I$If(d2ͧG?:H$Iif@ I(xTsP/I$I$M+r PH2@~. \7I$Iie@ I(׾]@Zk~$I$IV(d2z\` 1&I$I4 P1@ eZgvsPuG$I$I 9($^_~. ۲.&I$I4 P1@ e+2(@7I$Iie@ I(8%@ I$I$M+r PH2@}jЏ~2 }$I$IS PkO@Ǽ2&I$I4 P1@ eo~2 :7I$Iid@ I(տ'sI$I$M#r PH2@k t_7I$Iid@ I(xtP-$I$I 9($WC ziM$I$ic@x=8(ɻo$I$I Pƫ߉~2JkU3$I$I PƫyE?h$I$IҤ3@ $j,yPi~$I$It(d2f=gs2.I$I4 P1@ eOF?\8&I$I4 P1@ eOlwۚ$I$IҤ3@ $ePCo$I$I P3  wl I$I$M:r PH2@@ jvwI$IIf@ I(׹@! K$I$M2r PH2@y~6 ZwI$IIf@ I(Z{@!:/.I$I4 P1@ e'BP K$I$M2r PH2@ƲE?$I$I$3@ $94z'$I$I`(d2Ot3k}$I$IT(d2^tG$I$I P%3BNC]$I$iRc@nXtٿK$I$M*r PH2@[taE]$I$iRc@j;K$I$M*r PH2@[)(;$I$I PVcO@)jvf$I$I$2@ $96z,6I$I4 P1@ e z (Dk$I$I P^뢟B/wI$IId@ I("e]Pc$I$I P^wÊ/K$I$M"r PH2@{|b]wI$IId@ I(su[R;a M$I$7r PH2@{͓~9(HW&I$I 9($̽G?i}wo$I$I P>~ԹI$Iyf@ I(kBtox]$I$ic@wEP7!.I$I4 P1@ e_n95 (G$I$I PWE?!*6I$I4 P1@ e~' )6I$I4 P1@ e~5OymP9oM$I$'r PH2@_D?!^46I$I4 P1@ eUg;>~$I$IO(d2~F 1x|K]$I$i>c@sq3P^=yI$If@ I({ǣ4V*6I$I4 P1@ eu>@AZk~$I$Ik(d2gg K66I$I4 P1@ e5Og O M$I$5r PH2@#^5I$If@ I(iVSP3%I$I 9($L[4xIm$I$i.c@ʄy^SP)~$I$IK(d2~J _&I$I 9($LE~J ݴ26I$I4 P1@ e2^SPW/ M$I$%r PH2@L͏TSPGo$I$Is P&aϫ~'9(pX5xq}$I$i P1@ er ~osPɯ M$I$ 9($L=G?'i$I$IҸc@^ ݍG&I$I P&WwG?'߻>6I$I4n(d2ZgvsP M$I$ 9($L1~NJ2V(>I$I4N(d2f^+I(H_O$I$ 9($L;{Gm$I$i P1@ e\PI$Iq2@ $xtP=&I$I P&[s=I(o$I$Id@ I(ߌ~RJ2T_}$I$i P1@ e5'0͓~9>I$I4j(d2fUUg6Y(HO$I$ 9($L[t7 M$I$ 9($L ڹ @A_,6xP'&I$IF PS>6I$I4J(d27dQ, O$I$2@ $Թ}O @aGx}$I$) 9($L$I$I P1@ e:5zEP~$I$Ie@ I(kwI$I\(d2d$I$IR.r PH2@D?/%w'I$I+r PH2@^9y(LsՁI$I PWk[´?'I$I PW؟~^ ӽ$I$Ise@ I(SWUEI$I P`ۗ ?~$I$Iz P1@ e_΍~b 8$I$ 9($L5~b : I$I 9($L9o~b YH}$I$e@ I(ӭy/D?1$I$Iw PVՠd-I$I 9($L7תf{~}$I$) 9($LG?3i$I$IR*r PH2@~k~f 'I$IRc@kg0떅'I$IRc@k:0(LK$I$I P1@ {~UO @AO?$I$IJd@ I(4x|KSPƑ/ O$I$}g(dRӗ-뢟´V1>I$Ic@J=u.`SP%~$I$I P1@ ZgaSP?~$I$I P1@ +_f/'I$I3r PH2@Eհ#(I].7FI$I P1@ ~$I$Izv(dRͧG?7i/$I$I PsE?7n:&>I$I P1@ ZgVsPW'I$I 9($Wcˣ OU3o$I$I Pm8dP1?~$I$Iv(dRo~r ZGI$Iog@ I(ª'0ݫ'I$I 9($[I$Iog@ I(I$Iv(dWD???pM}$I$- P1@ %'7(̰t5;O$I$- P1@ %Ɗ~~ ؿ Q$I 9($60OI}$I$- P1@ %}G(LwQI$Ip3@ $غG(L+$I$if@ I(5 lS̢%I$IZc@Jlc:#@+2FI$If(d>հ#c@aڟ/7J$I 3@ $mPuG'I$I P~aUzY}$I$- P1@ %PaI$I03@ $'|5%I$IZxc@J-޷zi%I$IZpc@J Q0k>~$I$I /r PH2@)Ӣ? %I$I2@ $2\n O$I 9($Q_(PQQ$I 9($jЏ8P֙)FI$IT(dRN'8PK$I$iae@ I(۲.@aw_~$w{jz#Ng:޵uf8tյ9nu\]vSktYǝ&?$&J0"rT) 4*"F`AD~u}?{7|}/r-J$iIe@ Y(4~Ty$I$IZZPb@J= >@z~$I$IK'J P2@qOOi%I$IZ:Pb@J]5?3IP+$I$id@ Y(u5پ!IP/ O$I %(d~Tߟ~$I$IK#J P2@$P(I$I PwSjg@eq$I$- P(1@ f,I$I42@,|cLw\~$I$IK#J P2@s6^Z\~@$I$u?J P2@G]B(FI$I %(dWo)5@e%I$I~(eRgn~Tf|iI$I P(1@ &8/iP׆'I$IR3@,:}?F? j3c~$I$I PlG? *?%I$Iv(eRgcl<ho$I$Pb@Jv<g'I$IR3@,zl[<l$I$Iv(eRoMGG?jRoA7J$I P(1@ k'yP_~$I$I P*=lDQ$If@ Y(u77|cI$I P(1@ &_H2'I$IRw3@,m|[6Mzǻߒ$I} %(d]E?*487J$I P(1@ yRJQ32/]$I$u2J P2@=_~&TfzI$I P(1@ &מLL$I$Pb@J /~k3BU Q$Ie@ Y(? %I$I^(e҂Li2~*Tf7J$IԹ P(1@ ;{MS2o_~$I$I PE?*O Q$Ine@ Y(h#PQ$Ine@ Y(ꋣ ^7J$Iԭ P(1@ %-?bs2V(I$IR2@,4Η 2>I$I %(dD?j3(I$IRw2@,4@|Q$I$u'J P2@iOS~.Th? Q$Id@ Y(-jR3|0P5(I$IRg2@,v5'@efw_~$I$I POLGi'(I$IR72@,v5O xY$I$u#J P2@iW0PƷ(I$IR72@,l~lg(I$IR'2@,5g ~$I$I P~6Ԧފo$I$Pb@J?2PG~/FI$Iڟ %(d l%FI$Iڟ %(dGwF?*3I$I P(1@ Mn0Pfqg}$I$?J P2@igϾ3PI,FI$Iڝ %(dY6Po Q$Ivg@ Y(-=l|'(I$IR3@,6~$I$I PڵLi'(I$IR{3@,6/oo$I$Pb@J{/mzG$I$7J P2@iqO'@e&8?FI$IZ %(dWD?!*Po$I$ P(1@ ?O .y{$I$՝ %(dtUBׇ(I$IRPb@JG[J@ef;FI$I PtǕ NxV$I$՛ %(dtU'E?/*4Xd$I$՛ %(dt7J$ITo(ez'ZB. Q$Iz3@,n<'@eO'(I$IRPb@J'@8FI$I P;PC$I$ՙ %(dtٯ~bTh%I$I3J P2@v̢i=FI$I P7E?3*[uh$I$՗ %(dtώ~fThxo$I$ P(1@ 6U3BN Q$I2@,?ݵ5FI$I P@ 4E?5j3R$I$U %(d,߹*PY~$I$Iue@ Y(KO~jTht~$I$Iue@ Y(Ko~jThz7J$ITW(e4~nSBMᄡl;%I$I'J P2@Y:5P/ Q$Iz2@,K~Oo$I$ P(1@ e4E?7*4vm$I$Փ %(d,*P7J$ITO(et<$fMӤqS$I:2@,[{M$I$Ց %(d,&E?9*4|E$I$Ց %(d,FuB;~$I$Iud@ Y(K/~rh~$I$IPb@k)M ))I$IRx(eݵ5PѦw(I$IR|(eo]Ю}$I$IPb@kxћj7FI$I3@,Wo;%I$I Pf@%I$I Pf[7E?=*47J$I %(d,FG?=*4%I$I PfuSFMz';%I$I Pf㞱d7Pb@~fqgFMz'<+NI$I}(emzB* IDAT' @Q$I$ P(1@ E?h' @_>9NI$I}(empΫ$;%I$IPb@~CRjg @fw"VI$Im(eov߭J ;%I$IڷPb@~ɶs%_*NI$IR Jjf@ Y(F=YP][$I$:)i4ttl[f;e5?[K3@,|~j:wo$I%SpQiuMؒtۗ+4J P2@'4D?M*58o$I%Qos?NV{]WPb@r:iPV)I$Iݫ=_s捩Y+wjk(e\Sș~wJ$IR[80O{Im::MKSj.}$gK3@,^ @f[qP$IԒ/=*pwoi(e\4W*I$Iu[uh?26/*!2-ښ %(dz߳ @w8!NI$Iii=_sEyT魟 P(1@ EMJ;;%I$i-t.~kl[f;4V;.k P(1@ Eh @fc$IZɆx4ݱ%0쮫:4J P2@58 ֽ&VI$I;VL izHm7]ۚ %(d% FNml&#-_;oPb@M[N3QZ\$IRe-?O9, 7-*(+K/- Ph^' @|Ǻ$IzMG*.Ki܋5ȿ yhc(eGSo,]{%I[yҹ]iz,H W1J P2@ѣ?H[%I}Khim]ܞRD58?7- Phg @x̓$IgHSe^irYio4DڄGe5?K- Phm^lY$Ij_M ߘWN[R-FmpΫژ %(dѶo_"^I$<8 F+MovG_ P(1@ ECRjfO:^I$_36ߦ7/HG\3> P(1@ E.5MSg+I%SpQiu͞ҙ ?B_s P(1@ Eu~Tnx$IR:4 F|N菁P]Oi3@,= @&_=#^I$uފ*MG {?Agvn3@,=|Qr͏ W$Im=_s[dۺ4۹=?e?- PZ ~|\,I[Ɇx4ݱ%0tB0J P2@cmzeʍ6-^I$Voաi4ڼ7oLMmY6f@ Y(z/?6PM W$IV<- FN.JCߏKJhc(e?~T> Y$Isi=_s[dۺ4۹=f _Pb@k㞑RD?a*78wo$IҾyi4޺&MwlIi2y6f@ Y(z<5 P~$IoU#hB޼15?f@ͯhc(eӮ?R~]W+IGSoAi4tm##O~A6f@ Y(z<6UvmY$Iٖt&מf;̢?A{Iosϴ0J P2@hY$I?*ސ[פ-)M}{Pb@WOg @&_=#fI%96?26/Sa"`zEm Pxqy3r͏ W$V}E}iz'S󓻣?Om Px_qB3a͒$Iiai44۹=fqЮqZf@ Y(z {m3Fu͒$I-l~7vM_`}+)MmX%IҾ4X{D]4ycj7, Mm PD?kZb$I{SѦdۺ4۹=>KZ %(dho;+$I)ᆣx4ݱ%0 ]hi(e}ߊ~Do-IIU#hž?}Fg2v5J P2@Ѿhs6-1;$I?_o`{J熋Rн'GPb@EË"i;~$IK|oMmlv_+ Ǟ %(dh_#2Co$i[4pTo];4F_C]_}sښ %(dhl~7.IR>}c~{ښ %(dh_5\>nI`'yMv RѷPb@UϿ;yԬ.IRO{ nO[3@,~yEgn$u?o9i~tgis(e}{~)(+N]N79}wPb@e~%{o[n7E;d P(1@ EU8-[%In->uOߝ6g@ Y(ڗ ]Ev}5B$uugE:dN3@,z'>;". ]LX:&_=#97 P[3-[yH$uG_:d| wPb@umF?sZd~$Ils2 ;m P~/9-2%IfM3 7%9J P2@ѾE?sZ=yr$u4F9dpߞg@ Y(-/5:-Kv~%0G3^~{ڜ %(dhMoLSE&מ~$Iݪʿ>oQosoO3@,ͣe5"CeO_4E7樷 P(1@ E?Kԝ{Ci`^& P(1@ Es=th'/IRg}oOs P(1@ EjvW;-2o$;64̾-=J P2@Ѽ7$M}mߝg@ Y(W }seF+~Ig 9| P(1@ E9uu$un>k+ߝg@ Y(gwD?yڤiR}$~I_3|00' wPb@~hKz+}%~{ڞ %(dh6Uew^~$I}o =m P486,N|v $ٯf࣯=m P4ז=!5=-O a6G2!=J P2@Ѽg@LoB$񗎋>eQ︧ߞg@ Y(wϾ36i&Ijgo}q?t!J P2@Ѽg@ /&IjgF1dvmw Pb@S3qe\ $G1dӅ P(1@ EM@Lǩw3o$e䔚&0'o^{: %(d(h4IU}UoO2@,E_;OrI $D/h~{ %(d('4E?f2L1IRkm::z0GË~{ %(d(훣?-4&IjOkN>]/=] PhB~&Iړ;?ᷧ Pb@|?m4 cvWoOW2@,E75?QӤ1IR5}CJ(e[c@K>_$z+=V`ӕ P(1@ E c@K;-Iꬿws_+Pb@<84GrX-$׮a` ix̓OW2@,{_QƗ~$I5C' 9j't)J P2@Q Qݙ~$Iu5U' 9{?t)J P2@Q ]-6X{D-$UԲR3Iy`&}P(e 3o$' 40g/ ?] PTK7F8RMx̓o$'ѧ 9~ ?] PTKkNqņ>IhuMY`ӥ P(1@ E4hM2IR}ߟ.e@ Y(ުCh8f=$p`J~U`fݿoP2@,oGHbo e40g͏vߟe@ Y(ufw]~$I#LEhBZ(ej=k~ L4z'EpQ7kPb@jkrY?W3I^Og,u-J P2@Qm /zs-7$i~ Ե P(1@ E;cx|;7M4f}{O3@,l?~$IfM"u1J P2@Q Znv7$i~ }z0vm b(e :o4I|_*`wߠ.f@ Y(qHExrk>~$IivWv X7Pb@jmvע<hf_i}[g,Q_~ %(d[@ /zsM$v` P3@,`k<_ i}dۺs@n A] P;3E%41Kq-kjM9)h]4:ҤW) J*#0ϞApq==𹟹~QC˖ |}Dh $IcjfA*z( @~PK3@ P{/>"}4Ix~D_3^[= Pc@%5EK-PL]~I' H ښ u Pd&;GqZY~ףt{PJ(jt&5Iܕrz@Cm:(T2@Qc@K)[M4MJN@E-:(T2@QY8cU`. H&Iz'~@:.js(1@&э'GZxԙY~I6D_)PJ(_@yg&Iڌm(e:KZ u PdI(Go;+n$mz}wg@*hRZqDY~?~I65E$PJ(W}\h7$IS}/ Q3@ P4)N@R$i^ >j{(1@&l)#@ Mq L?~=PETq7 -R>yw,"~$mXSv" :30Nj{(1@&EK -;}$io I4d@*h#@w]~I6ul#i:(T2@DxT>6L7qg-)E@~'MC(1@& -j&Iz_5zG5N Pc@%MZ>6Mg~6$E[rѷ -)^ Pc@%MZ~>B $IN|_5@O~'MK(1@&;m3lqg:'F7~'MK(1@&ՇDZhx;N^>`p޿KӒ u PdIwGZIٲs4{iZ2@ P4eKK)DZhp'9IҿhT>`@eʖ7MI(1@&-Ty uvy^='IzN' Q<*^ Pc@%Mj?}|hY $IIWF_ 4LJKӔ u PdI_>>Tw$Ms#}  )PEww$MqgF_4H7MӔ u PdInt1G6[u4u"*)BX$i]sX@~7M[(1@&lN ơ\}"I\) W 2i2@ P4}#b/M]'I%я~fp?OӖ u PdIo]-V>ywNl쭎~0C~GM[(1@&a}hʏw4 /ZiAx@(1@&E[2^QΣ)[]'I-.[S*k4Lw4f@* ubQ.$ }q'I\G?h&um~_Mk(1@Ts}w. $i"Y~`s):(T2@QuY`J d'IX+@ .T}5PJ(j[mgE+ǂg8I*[]*>zG-Κ Pc@%}"k $i^G7MSgɶw4g@*me{,>ZLL~I$=)'7 WU5PJ(jc#7F-HMxOTe# 0|{k3@ PƆ>ZL9~IRX [Ӟ u Pd6;G )SJٞ/ %{>{N@L/=PElfa*>}2>҆߁[N~D0!Z{K(3@躣Swܻ@IjRh` / Pd; )T>yOʖn~JRVO&`}z(T2@Qku#^up=(I `yʖ~@=*r`e$E_G?0W_~(1@\E1T)[P"TD?0ËWa~(1@\GR*F )5bP潙)я`&Pwc:(T2@Q$0"P~0Fu{L:(T2@Qc++eK%i>A uQ=d@*ucp\}(I.[63w~ u Pdix?CI[3 SG-{3G(1@+SNޯ%i .\`xL?:(T2@4=עKRg$eߑRG?b` u Pdhfa*z(m/Ue{?A'3;:SsP{N:(T2@4rzJs?~OJlJgF?hՇuZo(1@,@JIS4IODZw;7PEXtFARҔ6 9,I@o3w֛ u Pdi-UV /%M_K~rwz Pc@%Mk?}YOܕ=~<Δ4%,0>`^ xg:(T2@Ѵ-aG@ޜ&i'W`JtOϚ u Pdi.#NMI-mіiuL;>f@*hG6H~婳dSRZurZ#)2tOPJ(~4b} `䷝5OI-iɶ)GSw@f@*ho?/WL]~Je;d%OGRgfa= Pc@%M{?} `"i~E*1Q]}h= :(T2@ѴoQ?(FP$mJCߘʵG?Rc'.Ԇe@*HIgDEh~Sv]Lڟ]'(PEzNG6I~)[TRhJe`yB} :(T2@:KMiЉ>I{.ISIkіit!я)HQ :(T2@S#lS|TRsV(w]x_MV(1@'aqRPEO-*%̍Hs)~4UJn* R u Pd"=5GKSMw-[c}G _Yl3PJ(c snti6worяxV]_ 3iPJ(hT}8hzV4-6>$~@?wj2@ PgW@KC~Jz*[ '8PEzf݃5hz o%m`J TO`mgߡ Pc@%ћ';W[\ DQmz(1@TOFORK]IO/[S]sXJe7l6=PE.'sBԃ{o߽:3 RGlMߩڬ Pc@%iw^}D`~4ʿWֺ._4?Um^(1@(*"u}e,MSٲ{B_:n~j2@ Pa}L`^RַxٳV}$]L:(T2@э'GS:'e{$.Ẑ?xcswZmv(1@O10e;}Ԗ)^}`,wSgі6?PEiі Gg+^/KZ_JGjxw&PEoxG•SMw4)et]wtJE}`zGfݫ:(T2@ QOWvMv;)_uNe^~k2@ P k݇_zG-浙wGA~^9:(T2@6DYhKS8˖ T1xţK(1@^}t`K_}K^ʵD ({\:(T2@6Y> wʏή5}b뢏Lb=^~k<PJ(Ɨ-1a7@kcixђ{^-W)_r?.]:(T2@6ѷN>>e{.%ۆ/uOg Ɨ u Pd"mZ}|ޓix{}MV?~<^6;jVn,:2@ PMlfa*;T(1 PYr\Tqg]sX/ROA)m;S~ϥ)5_t!4?PJ(7 lLJ+/D˖nzG]l*[o,7EPJ(<8G71 ;m)[C/&lޱJK}T*'州__' uxu?s4E[lNc?R~쭎ID u Pd"M/8Vx:' /';:+KMٞ/M_zǼ3ip?%{Ǧ;ћS9X@Bwk(1@4w .T&A1JeٿM\{دOQx(1@4|**:; u Pd"lŋR:(jF(1@4F}kݯ,* u Pd"g%+; u Pd"OGwg(kRlo'jN(1@4??G__D:(T2@E[򉻢< sw5*PEk+^e@*HW|ǔcR>Lޯ^e@*HC=@]wTw53PEߺ:>4+ÿPJ(:'SltөG Pc@%iL >f@*H1_})'FQ3@ P' Sw[¿PJ(RPHG?)Ro"j|(1@ଏD?)Q3@ Pv}~*Ǣ(.ufQ3@ P.~ Sw{¿h22@ Pز;4D? +O?g@*H <(QX:(T2@Qh¿}h2@ Pf4BkwMV(1@Ԍ>qL~<4yPJ(RsZ#hޑC u Pd"5ޱ~$-o Pc@%Y\XZ{诅df@*Hͪw{ o=#&7PEjX3 Rя`Re~Wqhb3@ PG? n<mC u Pd"5x0iqWchݔ->[Z u Pd"5npG¿a=PJ('~T U>qg,:Z u Pd"5? vve@*H.KSF?.)2ufP2@ Phpǣ@oj_(1@4A?eя ![N^Vf@*H~dMP{¿UPJ(xT>qgc6jm(1@4YOI/Ff@*H֢-RoG?: s?}B:(T2@&~t}'uvyn ;PEf<j}(1@40[:(T2@&+!|υtd@*H[ߊ~`x Pc@%i01Q->'PE캇!~cŸte@*H_~я` H4]PJ(=)EKe>/PEjG~sht4PJ(R;zYJn#eɔsMg(1@Ԟ~s߅gf@*H)[]*>X6Cթ30;7PEjW>X6U1J Pc@%e-2h6=-h3@ P;-F*Wߛ%/ PJ(R;0l :(T2@Y7Tя`nbg@*Hm1@T|iwK3@޲}~*Q?1<ʏCss g@?B#i| /+1G൩h.@P+_h$l̾~XY@{/>4 \ 68矢5^7 g@WHsL#7F?nW>ywʖn@x#@P); /4_wF?nu2~Gi}ǣO g@ 4?n9-Soxhّ<*NIRRt;0'wv>&L*hKkpL9ÿ HVWE& _5F<6|GL5j0@_j$o S\}_ʖnM@kpG& FR#i˿snF-@ڐ}\(Tʿw{K/Azk mhN>2L30F7l'Z-{a7iC+>0 PXΞ/ 4ڇAZ/mpLiԋ>6L֫{oǿH _F?F/mL^}l(WOH jfA$1;w6#0! PXDžH{TEEzG%}_؆>=L+/7b^OZaď~ϗ6  [H lɶ|LRw6MbLiЉ>BLU7ſH wܻE0F=M{OgʿHotөя#H3!^~<0A PxVo#)ld# &Jje,6_>FLU=~KHQv,}^o1@Vvk_v$70^H;f;m c@y ّԌRJ06wxis^gQ`Pkt/;ˣKXcRgɶVL~#]}P(lѭgHj^x0K4g-:k>VL(6\>J=~<%HRVȇ Rje,7>VL06JOIj^xyU/eDKsY~G fF)'!降n|# G1J..e}_RYD.& {_$5lŏrя(y.u>ZL86趕/CYW:3 ,m甆3@`drKf6 я(r)[woi^$x(luDŽIjfRCя)[ uS{4eK^@ ia#IͬwE?`Nmi .T% Pd>r$n8.1sbt8ʖG 0@` {~ -{a*WRb ex!/I[sRYF?`l_K(mT>f 'lY܆W}6IS #O-cf~/KܮۤћUQ~"ZS݃_RYD3Z9=-/M[W4F?`nfK-d.'Imcя*UnL)M/a[lT>qg )g~6Wg?ʵG7 *YC˘fM4E?hQ/]iewJw}r(̻])gm 6(?8˖n>m`@፧3 _$5 ~T0+?~+%ۦK2@ O/Iv&`B /3VgNsB =*~QغTD?0?:~On?/npgP$~L0A;/Ҹʖ} Ph5u<SL⑛RlXi\eد, Ph7OLkm'-YMٞ?+>j^(4gl2'ye{,GS4P}"uxU4zGmsh2'/uW74G?h|zG#UWjsh:xoHzf/M# (JciVix~ѧ 6 UVѓԸ8 @L/wTie{D,F1@ي":~zAKh˔'~"TCߞʵD1h(Lm+Sgَ/S|T<~{ ËJsųZ & x/SWT y4bQiTZ0,0펬䃣͛ű$Xq?';6璨<ͳS+Ph E􃤤degDt2)[W'7V]ZZJ Dm(uLM>TJJSuZQ*FLi4UgFo}ZR޿/*> 0dJ>6L}0B@_dnL>_J#|bVOH>pJտ~="[tSRIUEڒB~t"7H婯|xFyRVEm Q؝@RPh+龨%JƿK#yM PdKoM?KJXeٝ1ݻ,`TyAߜ|P4Ϳ"c;R_;晃-F뢶(nK}l`±@{+h%k^RXIpK}/g{&tk]>20aY@aT>~4Js$l%mfe U??3LJ̨oz3C["F8'zwGeތ"PՏhTS_1x&RSo==,>0)Y@SDcƨmx5ew%Z3"֚gD3ڰyӇMj_K#?9^N}$%X@a*ʧڨΎʊ9=,iX{_K}湣Qy䳡Z"{tՕD碾h\o}NƋ"˨}Ϟ(/*- nJ}{O㻤ubw4(J'KhwLQIENDB`PNG  IHDR.7 pHYs{Rk IDATxyu}C(ATb d)23*,30Sq&[tC7;aQDAeQFhVYʶlyoRtyysx9 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@: 0@R5sGSy{RXڒݲ%io1?Jjvk_;&g6ʙrf? P[S_MBrrSw%M^m/hۜ8sPwOWU5l*Э: l`*6\(i[h^F;s56WKsߗ--bs߆k8LݫSSܯcǀ>SR5Gܷ#3#(i:uVИi{Eq\ya;׆NVS7+u _*}I?>*u/Hs$kIݍGoi3z]RMڧ= {2 ~~|G: &{@S3Sy۲Òƭa%] z~TGd&dUw4Ǽ!?$ik4,S͈ϓTcߘz4Cd U/Tp1_JsVf_ι\)IEqoQsTiL̀^e*OP1sRoWhۙg;R]TG61M-R$ΆfH)IK`C;םgS/Af} gHq?)IKrԽoS:9WlLű 5/qfRϝT򄷦jR5j@˭sşfKMNi}@gNC?%]IK6II_Z?h!u/9<|crC%ؓ=,Uޘb^?RC^s)2tԜ-m}h< VuR_~vb{X<4JH so羅c>ϰT̲r!{7X9o_bT{m$m+Ru9n\ 5Y: uhoWf?JR1V< uxO4lo_<1~b-78:5#.5+~b.-[w_8zDK }Ogv`B>WϹT̥K's@|B'Xj`o} ̋aN$sb??YzkJ \To}p1nSIgbs$s\}P1&5'ҽ%C^=z#(r?YR]7y+T>=ɒT̡r;F/>zޞ~2$5ep8_"gRy%Cݫb<)#5΅^o 3~nb.3wV_L_-,I,+y}ǀ^oۜ#_ITӰPz_ghI*PSe2&U4|y`A ~bU_w@OԤʣ_-2LS>ZYVwX{; Ob͏eƴ4x潺a R'%i~ 蝋>Kiip{u@NnJŊW?cKYrOݱzԠ2EuؒT̲9z]>Jz_9ߠ0nzgmI*fYu3o;#R39pN7'J]3$}Rz ;85Ԅ:ZJߔ0ŖTwX$7YՀRjB?gg}C@S߹-+~b+׽.^0z]|/GAJ^ykRm\{@T_IFջлNV'n{h<.IKh@w~7^Icݲ}RO{hڧ+\Y{qڽy5X*~u${PyRT4wwC?(i` 6_f?KRl~-'e089S4ZT馷z]f0Ҹ>i>Oo3ul`${;݀>g4|[m|7g?KRW ߟAHcي 3wbՁtוNWm@=eK?in?c!_Ĩ ]Կ낹 .KXo &N?~%9 ~*ֽ>KcyC SuRó%U˖zЫҘ>gҰ}!Vĩ=e?KR8sghiܾP} ~&V%E;C_46-7 }ֽ%i.>l@&KcT}LaoQs%q >EǺbP?sw*V/Iŋ\=:^bq}ڿH_.[N~旤E|Ǜ>x*CѯN,K>/IŋW~R, a17Tvv$i?ֿaKO)RX;$߯sĀ+hix7} G>z_iRL0u.pM@W?}g/JZ̪;^ؕ0u6|0v izr e(i^91|Tuh AR+M~ؚ@F}Qb>_Tu v;s~ZԪ}"IQ|0޺~=ARkjGo~AbT{Y_ ;Ϧ7e$r~:߹!I ]oYs3xT,7 5=-[R]^Z/}|94Xڏe$+;K IDATO^ZerA޷sFMSϾ3HjMMMV~1BU}ӹXARk*赧>/FZ|9LW˾7HjMEGnޙb֩sίd$&G/;7gi>+|U>W:mSDW}kNX#g]r.P֓ZS2uh1p`1>f!$MÀ/Fޚr AobIkMX#u_'nXD&ό^gZŲ}_oZw6Aj컄cp19WG0Soٔg'$&*&r폧O] dʚDe@D4tu@nuڧ3N!ٻhDpEvc`̤Lڴm3m4Fӱ;ю5EU1HQS12ay:gu Ps^Y wo :ѷY$I$P7 :5w{,I$IFU.|(~R) ϱ$I$IzOLy@VjtJ~omGbI$I4µ.PntJ'卩,I$IFN3-JˀNtn>}w%I$IRjWw{*>}s%I$IR*RhmJǀNe$I$Izun9"|1S ͓?}g%I$IR+XSdb@gKU+I$IA=TEda@gu:=J$IԺdvda@g5Or]$I$IUL< 茬|w|Y$I$IRmάF4gV{*I$I*Z33g}-J$I W}* @l9wB$I$Is;4:#{YS$I$CE/51| e@g4Ob$I$IcTڼ7 ItFFxTEMI$I4f.v.d#ɀyJ$I$IX;OFl >}*%I$I׹}FpnoMǢ$I$I,|'b@'\֣$I$IR=2n0|">J$I$kF8 JUGEI$I+Rw`$ Ӿz(I$I^Ml$ Q?Ru$I$I g@g,%J$I$MZSmάH ̸E7J$I$j͓?Y(:3Rjף$I$IҫV~,廼1|O0tfΜY%ѷO$I$ik_0~SR:3yWo$I$IkJU,/.O$I$Ik{ 03#:+u$I$ISq' qt]TwN$I$i7mٌ23nzO}$I$I/3ʀδj]&I$I4/&|oc@g{TF6I$Iվrqd3ƀδuzM$I$InFfi8L$I$iZv\d3€-2?}$I$IH~3~t33tv>c$I$IZǗo0@6 U{$I$Iz>ٴ23T~q$I$Izޛj6cl$I$IҌ: M:1w{%I$I4gR M:C:J$I$)廅o303|֩ȟU$I$I1) ?LI$I$ֹȆ΀@vH׉Q$I$IT?7· *:>pIy$I$I_PЙ񟉾K$I$I#Uc7 :S3w{$I$I4R1̊n4 tu7$I$IH8 ,MXT-$I$IzO l fwC$I$I#]υo8@60:I)j7H$I$i=Tyd1tnY}$I$IJQ󌯄o9` l~R}{$I$IJQT[edSf@gu H$I$ֹ_dSf@g4{#I$IT3)MMW7gV=~s$I$I*ei* 輪}g$I$IJ[x! x53nzO}g$I$IJ];^+:y_GI$Iת|v[&t&7oT<@y$I$IDk=@z- Lu7$I$IRuRυo>@ l؂R"I$IT:7ic٠E߉'$I$IիN^ ~c@g=noIE}U9$I$Id lYO]$I$IRu4S߀UY/DI$IJ׾v^u/]}?$I$I_% ߂w?}>$I$IƢ{A@ 輬bnݐ$I$Iy#|Iw}s*ꫢφ$I$IXվrq.d2׺B$I$ijRhm6ȀNTԞ>$I$IcY]! mԺ;wB$I$il+Spc@w>:NH$I$uw"`=1:GI$I?]: lx I$IB" $k I$IȟKo ߌeq5g{ I$Iu?F@71=r]=$I$IjwPcǣ$I$I&xǩ6w {Ew@$I$IP?ߐ̀>n0$I$IzzO ߑ̀>n:w$I$IFXSc@^?R$I$IFԽ= ]ǀ>>Wܗ$Iv=kJ~zݔ_:w:,Oke'5&]ߔƋя}I4ux} ޾vԺ;y^yim%L55$Ir_?76 }`E\$ Po}՞/Ǒ\29Ƒ:wR$IBw=3 RV`j_45ݱ"?SP=I ]$ Ru[g z[$I'ͯ=PgR?I/$Wg@$*RSЏIs՗h$5TԟO[Z+yעߒ$iCu{qgRm?3Omڗ -$i#؁?C@ {g$Iz896o49$IRF= 2%IԪέG@G3Lק_O?$IP?ˀ^![G?%I?m~7S?P_NŋDI Խ 0 U塭lIƯ_~_.5j*jOGI(R}?+j2WHhNN 3)-}”y$Ije@c7F?%IO֊y)_uH}:oKIƾџVA iI*_S/ڼo?ϋ$iksU&$Iz\|U4L*^x([VTIgUog$I/b[e`+R-,IX+dCg@/ɟ~6KT?45X2ԽogIƮZK%fI*QSco;TI?IG%I"՗jb@/|$iAjGw*-s$MPz.n3Y6|/Z8itIfVѷja@/3D?%I*_ZN[&ͩs!$I\o}U8Y,IR*z/;q'R#OI*[=*€^R~KT&~v}/oލ~qяI*[=*^F^$I#_<hZ$ruV~Vjg$I].Mo /@=2!IR4Sh;3PӢ$l_K~hS!$Uߊ0 %/ܦ'$i݊ uΩ6g{ -G$IT3+C %tesW%c[}קmF?f$I*}|?2H)$I#ć|g`z5jK)m|7j%e@/yȕ$)tj'w9/IVsDz\$)]|Ѷ7yM~ ITʊjs6 P+!zI{'~JS;Oͳ~X.oL;O~"ITGa-Z Kuᷣ${TWo10"JM$gq]>=~ssV(R}Rmw=z'$II P+z ԿяXIf:5Ol F[_$I6}V2h]2;*IҌ{G_8]$b6w 1@;$H5[u#L>_f6ǀ$IH*/zG=~KLiohuZ175Ô{ 2օߎ~J4kᅡ!}ǚ$I3_].MSvH9o3*>z^$iښ%ۇ[BvyCQMMLGֹ;ơ;ڼ`]M/ygJEX$iZܲ}`z}KTH;NL!5T[UÀ>Z|#-I+Z1/7ocGT4^|U,W.Nc?7\ǀ>\ܖ$iuyo,0&n.$dv=~f@QmRIRQ{:H̜MRãqoO޿I3&`,NGT󴿊~K4L($QŚS.쿊eC M}Du>3Y/IP= ׹~B#QT[>*>= }-*v=/Iu|Yw{Km0oԽG$̵5}>yR{߀4 #q>$ ߦ}]XǼץύ~DJ~:g}-c@A>$ T玓?}S&ϋ~TJF Y@f@5sfGo$ISso*+YU>|u#STQ>u /ۥ&-j0!$M08l|6яNIti#׾K>OT}>icGLFITCP:J E?B%ICxYytjsjAGğJT&~(RQ_($ ۄ w[7[K?o<)}t81Bn'K~PY+G?f%KݻNOwJo&a@C>}$IڨzOޖ~;͜YsIя[I{ #uɜ&Iҫ[u#nL]ސzؕrmޣ7_J}RGğJ4s/3!_}*V?XxXjsjc-2 P2w}SJvݓ$i8o&L)jOaI XDsvj~*廿- P8$IWy%@ Rы~KҌU֮Ÿ о~(IҤ.~+E*[zݔ7Kcc@~}.%I`;OM9o%@9DI{b[0Ѓ{'vJzOL]~+Fw;,I]ɟzoß1k{*IzkJ1N:1-Iٴ0~$iz8?HQ<_,I-Թ<˩RmGZ#͙ ?IFߊ#}яkIcŸ1a@4ש$I嗆l}D?%UB񿿷|Ѷ<ˀuף$I/{G),EHŚ'ߒH*gßmd0~\4":~oFiz觸2wʣSܝ_z˼ׅ?^=KFJ}ǸQ~oīX}-]N .I_om(9D?%V4^L݇J+{l =H쿋$߻Y/EoOF?%DKcKS/@/a*ˀsIR|: IDAT&TE?L(풆=KFgDi_G]0[Ÿ+d K?@4kHo3o{ǼȟMڗOc>E?CHƀy I犢{PU}SJz^O8}R +z#?:HƸco!@յf^6[?Jɀ'$IcZx1K7gVǾ4~-?S)_u3T6ى:/IRDͳ6|;S?*U\].M͓>ۅU}5t IҘ{Ti-'8/nWtHjT_CowD_ k_8#$i+z~oAq4fI^[@5}$1}ݲ0ޒՏFi*^|8u<%.8c)M߫PLEJFIҘU}2廽55H# F2Ϡ!"IÚ@:}HGKkMSK23Ϡy+$i̚K[bѧA^E/+un=2T?7SmkP"L~81$ij{8SѧArŚSSkżm¿6 3;1o~|^[~Sυ@-}L|*@q(R_/mXT^'3uVg~5՗js6 ^0ϐQ%#$iqR`r͓>}*4-X:~oڼׅO@mDgH$IRbMKZV"ҽM1swWTF UWP+1 SIN#{i]їCe{  xWG+IҘԾvk0w{beШW콩O?jfW}4N[qM {6q.[Ś'~ojcʀ>ڗK4u8105># j=[2πD&$A~305o{ơn;9o805Ok-٣π>ՏEL$U/ w yω_rSSmkb@fm?IƠ1 y nDUΊ {[ŀ>Gq{"~v[0OօNT90<F^'3uVZҫXm to?>$kJw >}bƶ[U@ƀ>zOTZ}'0|:ČEEu[h@6R i)џ %IU|3+u&TV-u"+5O4 Ө~oGD$U͇:O_OEs!yL~%nJǀ>g|%c$[ܲ<ܔb9Hb@Fk)IhG sL|vh>;J+{ *ˀ>_RTњ~103ZNc[zߜ.߾gdcÀ>ՏEܔ$U"6>0ClIc'o0n83O|F$UWE9fVϧJ|U,5 P)i8w?J*Z'F0J݇Nem=뼷|v_Sٯ΀>Mg}-3$%~GR*4yo90: Ӥ}[%I/~MH[Q_r U}tXQVT@|ȼ|_42Obaj%Iլsi xSW}exo9ƕ}L$Iîy⟆8勶RΡ;SC~囄 P f@_#I+kRm70 ʣSܝSSm7F}4OҐI^wyF6ro?@$ Ӡ}n#[|!՗?̊ `vuЧAۣIRܲ<@m Їmάy"IP(c@|wG,*ծ.ooPC!kS$Bu9;@mLЇu7IRj?oƔ}HRKoƔ}Ⱥ=H*RƘ}zOH*REw jc̀>dEkm"IH;51HR;O[61p"IH~`u _D-:}xZs"IH>~`u Cb|X"I@Esu4Ї%ћ$u0}z\$Ib^M2̙RH*PcNw H!oHP]~̀>,#zr$U74 3I?\$Is7 C:wETg~5Y}HWH*+oЇETTEM>t&zv$㷄3 {}H]$I%sa ^f@9mG.:7 Hƀ>7IRj{7 ^f@\$I(_37 ^f@Q\$I%h~l!hѻ$u&: Cк;ѻ$un>,: CоfETZ+: "qb"I*yc>~l!>xy"I*yg@7zw$Hg@IR+<~l=Aۼ$MW3 4%G.׹{d1߯D.׾l{d1|ET{d1ygwIRk c@P쿋]$I%l{d1bn"I*ymǀ>uˢwIR4Smά{d1ET e@Au0z{$ޣ72 zHJ\3om}@~HJ\ƃom}@EETڗ.e@An+z{$ֹ;2  vyC"I*yS!KHJ^O3 v]$I%q 6Ȁ>]$I%ocm}c>HJ^d{dd@@E.W[e= 2yWwIR4oMʀ>y=HJ\[d2bn"I*q?e@6)W.^$I% &e@@IR=vc-I<:z{$W2 }/]Eo/ &e@@ IR[d25ۋ$un;.٤ =y{"I*q e@6)z(z{$uoMʀ>GIRk_w-IPԞ^$I%} &e@@\HJ\oMʀ>mGo/׾l[d2O՜MwIRk_:?i2ZU"I*yK3 Mƀ>EmwIRk] &e@|;wIRk]{d2OQ{wIRk]Mʀ>E]$I%uMʀ>Ee;D.' i)ѻ$y:d#̀>E5zw$~lR)kѻ$V g@6)ETڗ.g@6)ETڗ~lR)ETW, g@6)h"I*yg@6)5ETW~lR)jѻ$䵯7٤ S8]$I%}Á &e@G.׹ey=IЧqD.׹{d2OQOD.׽{d2OQOF.׽{d2OQOE.}{d2OQOG.{{d2OQD.{{d2OQ?]$I%܏Mʀ>E,zw$b &e@ HJ^?~lR)jETy=IЧq'gIR,Ч|ET[4 5ћ${;Ч~G7IR7 6Ȁ>E~3zs$U i@A)ETGaM 2OQ}ћ$5Odd@>\$IyWom}H*Po4 {+zs$U֊y7 6Ȁ>EwDo. Ծzdd@|ћ$un><Ч(ћ$u:=Чjћ$u<iC S5wETzO iC HE/zw$b 6Ȁ>mE.m3 R=H*Pm74 [}E\"I@i@\$I~oǀ>3Do. Xd1Mћ$5Od1ћ$zMћ$.nM}?zs$U54 [}/-ˣ7IR~BMоnY"I@V4 [}+Eo. {d1uETd1u?Do.*T6od0yDO./>: hETZ]u8IREjd0{$"5OR]uP?#{$".d0/G-Ծzd0 IREvl]u/6zo$U5 [} [$Iw H?ɀ>9R궣7IR*5 $3ћ$"vyC]{ET/ =r]"IH?~euxn"IH͓?~eAH*R k@2-[$I}d/3}ET:w~e_{$"6 jETk@2ETTIm>=H*Txd}՗H*T6 3(_}"IP>~π>[Do- : H Cy"IHk@g@b{$"u8)Y}zOH*RЇ{$"kk@g@gD-T_P}̀>/-GD- U/6 3C%[$B5~̀> H*T/6 3CGo- Z1/}?H*T PIR>pIm20䋶Z$IdIJN"IJf7spk[$I*_}mq1G[$Bhmq1G IRjc@r[$BV m0:h_G"IP[ m0:hIR>xEmq1Ļj%IVGo}8GA"IREj_~6 CRWIRŪ jc̀>$wIRj1f@Fo- : f/kZ$I} jc̀>D'oZ$I{ jc̀>D/Z$IjfoƘ}_[Z$Ih mPc!j_k"IXw7)5Z"IXC>~6 C8E,G,>.@tNj"Iʬׅ7H5c@ៈY$IkirVT#!hEa~9@0l,EY>`> CR<`"Iʬ~ Ո}H]H2w~ RЇ{ݑ;$)w]~ Ո}H+Y$IU<F C^M"IʰƂ׆8H5a@֒Fo, k_o0I{H2}o0-rЏY$I5=6oLԃ}'Y$Iջ& CԿ{E"IʬC77H5a@KwIRn;e~ Հ}:͍Y$I7R Ї}7IR~*@p"IʰY~ Հ} X$I[8@0ټ,{EY.q0? -zg$eV~Ls6 q2g@gG, k,|k9u7zc$eX~ e΀>d3H2s?8H3Yk駢7IR: @ʜ}Ț{#zc$eXKoЇmKrЋY$IUq07kY$I7R #пEaC @ʘ}H2s:8 IDAT7oG`j$i]_1Ea/ q2f@~-zc$eXx4@ʘ}&geH2ӛLɀ>"GoX$IZ)SrZ"IʰΩ_ q2e@wX$Iֽb)S$)wq2e@֒Eo, +8H2Hc_X$IwR 2g쵢7IRM+;1ᛢ7IRuf!o>9zc$eXo!7R #ԽxEa q2d@IHrۘ^wRf #<$)Ӛ;)3j,xm"Iʴ֑~ eƀ>bFo, 7~ eƀ>b.X$I6uУoG{ž$)~ eƀ>bӾHrl+Ӷ/ s2b@֒EO,LkwRF #XU"Iʴ~ eĀ>js6+$)ú`"X$Iֿ)#kX$IVZK>H2wͿ9He@H2mwREDx$zc$ؠWm_~ U}L^=H2 2勢IRm~ U}LOr"Iʴ9Hd@~;z_$eK 2y[e1X$I9Ieyj1EO,Lk1IR;b cs}Ei݋vs*ƀ>FZK8z_$eZ1ƮO"IʴHT1q2ghX$IX[a@3/W$I:wRLIRuΝs*Ā>f'm"Iʴލ'9Hb@3H2X{gT!qrЋX$I9Vecu0Q 14xEi/@]t"Iʴ~ U} u7z_$eZ0ֿ}Eios*€> Hrm/Ӽ-o 0H"Iʴ~ U}LzWH2wՁwҘ3(I0Y~ 9k_IR;eo1f@g۽,Ei}+2CIRm~ 1]{x"Iʴޕ9Hc̀>:g~3z_$e+1f@sſHr.-o1e@s-ˢX$I\u4 P+z_$eZ~ )zVH2{;iL+sοF+LwY4 Hr,[i +IR5~w4 Q<@"Iʴ ~ !zEo=#z_$eZ1d@IRFu2WDF+-o1c@n=H2o:Hcƀ^!Ez8z_$eZ sƌBH2wwҘ1WHwł}Ei5+1c@֑Hr)Ӷ?~ z4vy["Iʸ~uƈbW$I9w1WLӢIRV-sƈboH2muw1WLk駢IR ee4& IR5@4& T>z_$eZ1`@F+L u6:gs"IʸΩ;2\ߍV$I׻[i#nWH2x[ǀN9x}Eq[:HNٻmEq?~ m:eV$IF0S6~w"IʸW:HNl^'IRߴ:Ć13$)Z^ L^S"Iʸ9~ m :ZGi"Iʸ-:HȀδoV$IW4Nύ{€ΏOH2;o `@'_ 7H2}߅:HΏuV"IʸުCo `@Z?z[$e[o `@'mY^"Iʵ(;{ǀ+ҋ0NNV$I׻vi" SgwIRO~ :ZmEy]~1@zt֩1Ue9Go+k{y^oV$I׽b[y^UIR >@ztW{ٗIREu\u"Iʼw79,:OGo+^cu3w_H20/V$I9kiۗ;H`@L"IʼAw j]Ey w΋*ZH2:yQNV$IW({Y 輨Do+k.:@z:/#ѻ$):}=@z:/1Ue9Go+>.@z:e ۊ$)pl~ :륷mEy=~ :륽Kѻ$)'9@)tKsѻ$)z. w~39,:OGo++A0w_H2ۯ;H?b@gu/^H2} w~Āzk]EyU;H?b@g5nH2oҏ SkIR5vy[d@gCo:)zW$e^ؿ w lD*]_d@gC$zW$e$:1Ue9Go++o l7DO+k? lʃwIRu/3TҶ?W6~wD lmwIR ~xuo.GYٽtekwL`E[G*+ecko?YvΛ[o>,TO?ߚ2a@gM*N"I[yA ^SeSE :CL$I*%;]6zW>UVO܍߉ȃҽx-$$U`$-6gTSoL0QG}fQKo7`f[H~Km2`@g4n5_蒤z:7`}5潲ls75=*;>#eFېo\ I[>*n/MTֿ$)?&X4dc2`@gu'9 I{wxCꥱekGG򙬹o8 h~HjP? y@3Ysc2`@g5濪,g$)~[:w'π&?wg@gL*IRMmӯbZ|&˔:IRރӛo0 ^̫X[P>s7~S l >o-?Cnb]ѿȺ9s>Q}t6YD?$I5{ž7XO[^m&π&k,*y IAoyz QH03#'~&HjPc緄<缷uԽp𯕔:3IR j+Dzwݑ;[{_?g@gFt' IA<{{h#^kDЙ~&HjP=7|oԫXk?k~𯱔:31Ue9G?$I5ۯ=W?*ӿ1=zoyu/+.eΌ9Lʀ7[$ ~L {G?KT Йq|$դ֡~WC߲;1пWo;3VʀZ$&u/9P1[Կ_og@g(m4X*0lV6cy./^;c4%3€P .!ICŠlORXKf'P$Q { N}/ލ'E4ƪM':M03$դޕ=F{5+\zz;Q}t;T<~w`8b^Sٿ6?vJw1ῖS ǜʢXsBT=Q ^[|'-OGwݑ῾S M39kwטʲu({VZ]EqRʲ޵Kͧ ?9$ioZ~xOߍ(զ? LTi IRM*OiΞFD^\H03wؒQ:C. ^Ҙ[yp"eP 1Y!II {YKwϏ33TU4PyNG=IQ)g@g˶~VHҠ_6]{˧_r9[.eTEϘ:C7>`[>*?M^Ws'epټ,ZOD?/$I5;~desru{h ?$i~vG3Iu/54Q}t{$F5w{{˧^z<#1{Uʀk$FuNZ)^_sdٿ4-u/12`@g${$IӲQ\ 6TŸkg@g$̐$դo>o rICsug@g$\Q:woOkeϖ݋w)w($e^K03S̐$ը;>_]3bزxGjX/?S DsF?3$I5jkoPOeٗ~CTB3r ,G.2`@gd&IҨjT[c7?YvΛ[o>,EđSє:#ӽp$Fn8&јb]g$ij-X5eȴtsCT2M.{W咲uЇ㟷g@gd;1!IYS,\RkoʀO$I{hGI ß)tFwݑIRY~rIztʀP#I*鿅}09{%ij,|k{ TsG?;$I5}}f IT^,O03ZsG4Ҧ^~4y[?S \KU4+<1?WHf<zɌ03rKv~~HjVPOe|{o$~'Lȵl#DTo~Nb^KR`E2a@g䦾$Ilp˗q]~vY>U<;2a@'DIR*ec_PU[.Ij#e€N޵K#>*A?K6'y0sW#[}|q咔_;ߗ :!$լt ^[|7|JYO$i D/1tbټ,ZOD?K$I5c7Feޖ}oyQDcI:$MNgE?K$I5k=brϼ|U,N$i"ttΛ~HjV3WqNYvgV4Fu.VL :%76v([bz zFY4>1s?߯<Љ3o˲'9@SC l2a@'`ͪ$f^~`C)IXc<~L սl$n ecׇ@X_e_:+e€N? $iԵsO$b5@J0IR ]4>tJ*Vsw߯ :'~HjV|Lo DNIRj2a@'\#):7G#Ϧ$b5&~L 9kIR ^s ѿ)IREQ9߯ :7"IaGn >~?lJ*T~*vЉ79k$I; #FLIR~ѷ+eĀX߱<"Ia b'STkV߮:csg$ , l%IZ&a@g,|,"IcEQ65ik)IXk߯:c1e9E?_$I5} <梭O$bu/#~^|$հg@x>%>9w"~E?_$Iu._~`]e$U_ _)#tƆG.tNF$UQ _)#tFc_~HjZ# KgRTZ?~+E?c$I5h=Q/ lDIIRjWʈһg$|,o?;DJ*Vc7߯:csף16ͬ <'RTLs_)#tJs$մ4g[?h=}"%Ih ])3t<$մ~{yi$Uc߯;;ύ~HjZ o>52c@gt.Y#Iiڻ }%I+eƀiߢ5|Y$Uު+eƀiuYIRMX~ `JoEEIR^0~K576x;SW}%Is7Wʌ7}%I}_߯:cuğD?o$I5s[Gn>:+eƀXjl,IRM]}J23UGT{z=~$IR甿_)CtZcVIR;'P/}$IuħoXʐW+#IqoKG?IRk2d@g>4#Iyͽ#PeD>IRk,|k K23'$uW,G]O$j e~R 茽~5$Iy;4g@=o95I*VԚ2e@'~Ij 0*n>{5X2~LЩuGD?$I5{neY'IXOay2S 퓿$ռ9g@ޚvɓ$U{߰):!IA䭽KNT:gC K2S s6+PHTWZENTZGI K2SG?$I5HirvM _{.>w \u K2Sӿ,$l7mS'I`cy2SS&IRtkDϜ$͵7,èNuټ,E?$Iu(_NkG_9IRY~R TJ擣I$&&y'NTz7~R TJ~&IT<7&G8IR^k K3S)L$,Amw 'I`Sw K3S-ˢTsIs"h+ѧMTZ"ЩgE?$I*~G>m?߱1:9_K$M7"y^[Y$UƼW߱1::%I;"y{IY$U}R Tܗe|$o#69,;)I*߱ЩE?$Iu"6J0I6G߱9:9wNI|``SuNz9$UE;߱9::C'I);!6P]G_3IREkw,e΀N5ݢ,:OG?$InoFifSCi/߲ЩmgF?$Inwjj3&IpC-K3SY$5i&IhE;jNe5{_sJ׽|Qmzz.>a6;jNuM*g$I'ʴ+#R.ѩyE.FX? ed~ۣ*Oe1|>JFmDO.FXϲl @h7gV*7>KGI;E7ewgF-'DYr)]|$ w#=aŚ{gY6&Ykk3 qG$ikga`u>˲1]#_}7EY,ݻ x ,,UʵD[/Q4_RYDO+FY6&YunzҾbi|$ go1kyIDS>}n1|FJMD)F\,,U^}nFx$ YOecm`]X}G}(I>yQL>`#~1|FJMϳl@Wej 6Ҿ)Il+G#ugg])_kJvݟ0sR__KT@-|ec*U+0H$׾r+˔/zQL( tU%s1Hݓ='%I=qY6fYRHU>'%Iq~g(˿>Ӳ1]j?}F?'%Ia+zPϴl̲@WqzY+T?sRМmRCѓ h6{@W6F>'%IߎAT*W}[2譝|Kg$iu?*zPfn>ײ1]\{=.B$ ;6zPŊ]#4|A1yGGѹs-,U&PU?Խ@E𹖍ad◦TT7ؤ-'KIҌԹ1@/]>۲1]{lZM>/%I-_Ҕ:)@4p|4 tUY>`>/%Iu it>>`yʗ,|fJ/uϷ*_s6RԟG0zP1(og׾zY9U6ץ| {ci]q| Ծt~̔$m]ߑRYF*qg`6lKg$i >_H:7?,5Vu,i)gg$iӵi@Yƫo.QaSV?]N]cUE}0uE')Iڸy=%!es wYk*}un9!|vJ~;93{Ni" t]}ԕe)I־t~Sm2 t]?}sA$|KSX={Sm2 t_w1Ծ@ݔ/5|6ƲgFEǗl3TƹR궣GW>|L˚g|:,-:3TƹoGE<՞]cY& FIYr޻sTƱQ=͓>>T{& tmţ7F|E {\SqY}+:~[$S6`LO=>T{VZҽ9*IRNjS>}=+ tosIe*\iiTƠGEY7|:7~3\i)=ݟ>K%5R*#1R?Ogen[`T;|JReC*V}0F溔6~*dE/Jێ>`_(z/SIbgG=?6]c_KGMٜYTT}7iD_mƾ9>`4Od<*ս1T?gje/#l2"K^>S% 5Oc1T֟tÙ47EUw>O%i}C*룏tPj=@fR$l >S%idMyQj}gR,Х/ :$l2ܭ\$i.r1YZ,Х+}VV|\LQ~ȻR궢pT᱔͙>Utk>//I\iNx1ֹy,Хk|wKr)_*IPe6cy'j]qOecm }ѹ*IC@wE IDAT^TG6c.3QMf.D>3omla-u̟>sD65OX R}nU+~}J@\wD\T\O:fbA!|J0չ&5O7XKϮ{g'UEU[P(˔/}elTmYK?UF_E753VS&>U{,Х*ՓX9+IQ{h_|T9@zT<3{)]7oԽcߋJϕԣ_>C`F3|JҠ|lN3R~a.m\G0325Y+IuᗢO^HγgjS]DʛReTVfF Y M) ti.})VߙE/ 4S{OJ<}^>+UR&/-,ս6|JRXJ>fbR)g.mbg*̨$|K`OTmYKg*̬Lo}<|JR? \}f53S)g.m!}kS+>w%iZK>pe U6קlsSiYKQf\?9|JҴCunQ ϩ{isSiK@{F0Ś{SW>sa îyN-]z&E𵓷A4l:7}t{6~~*mIs5gV*z0|~R*|K3+u;")+%~~*mij_ վ+ImGEE&n>C4 ti 5g, \%3X6jyHjsTiK@ҜmR~E9 ׺$;G.~*mik_spY Wug$ wM/>`Z:7|#|6,Х)8g-(<XT<|mi8#Tie.mm\=}@'U<4vK_n>`ZY>SUVԾj#b>.i/\{[s)3Uig.mA3bYKPn*kO=j͓2|6,Х-iάT>sbyIDv/zQlUmYK[X%G/+:粤5gVj]2/s~|Uښ,Х-~/E08*9Ve.M`*B4_>mu4/- ӹ픔)|NK_/&*rZ%@YsN|ы紤._Խ# fT}[gj[4Z~)T-{6|VKꇽ'k>`F+o% ti!>`(W!>% W3>R}D蹫Z_@kcZecmjy-i8nҹc ~;j}]ڊZSy íJo}<|fKOGO#bWe.mEJ,eneZ ے܂]Ren{i]<;~++ ti+sFBS6-ikT>cBs,VoYK[YOF02?H> ߒf;KS* (.~+3 ti+ v=|Qnxlө3\RT-P%|&,Х>ԹFKI >%m}^>u+٬Z_@P?>`$un>>e?/|KrG fԏmlU9 #xƔ\Ҕ {% Y Ѫ= tOw`9 #lK3>>%=G vNKiF0\Nʗ<~V+; t_l|K纤kǩ\{1C{Z]cŪۢkyEXEuIA/>`5Oڌd.E_>2:7ݟ>ߥq-s)EqíHnf$ t"G?|KT%}R9- aVmƲ@\ˢmWL`ɿR_`'~4~+TRks*\pjg^\vH3?+_0r&J3/H]>&̰~g415t*z(e #s3]i&@f̐n;^.4xݴ\*?JW?gj345p c\Hj/_J.b*k_P wlάڌf.DOǢqݻIK{i˗2+ /Uօ>U,Х}8|s0T?ݩs)W'TOY| x U?G9vڗE/ ? y;>JJunWD }RtEW~Xh@@f韊>`M|ab/| ~8}s )u/56,ХlB=sxBSe7E`,98j]:7|#\~R:7)}4я.|BJ]G?\z'o}Q?M5l_{h*OFbR-ThL7gV*;|6xS6o..T<<ֹ^Af. օ_>)(?ڗ-J>*SMCWT/n;K^Af. |WTty`"u(5Ohm^B^}JKs;N@Tw<0 RSw7cH;B < ti@5sJc_H^ oi.qSe\@S96Ҡ@ռR>>)VݖZK>CCwkN;Jӈ~}01T ]`>~+}:_R}7˗"5OԹܰ2 [ ϡZH#aSʽR3ߊ/zQj|Sx_ ׹e. OlmH{/Js>}>D+UyG'c^AJeqߏ4|"kIkM͓"{lh~SY X}G̊4z熯A7gN~%-P6G?-!:Y"@jwBe%n=R^2)y_o;oMj}>F)2 t))`JᥓnT?=)ygݟ35OXjga~j*;O GſQ] {saSMh_{䗔6n393]~د 3.bԽT_T=g.<ϢPQGSթs}Şu?Wj%{pBx\eWGo}j_`_)_R@uT,Хm?yq Ѣ}m{癓_hށ}Ժ?RI3>mN4qowgwwug'?%޺d5MǦ]Wbܰb*6~w4 YK/[= _4;g=Xk}i_}@H] s e1|_d.8揢G)T,ХlʵG8"a]Z}9z>b;"Ն. tiʗ2n;zN#Rm@έ'E T_y;T,Х!qgXj]ݐjC4D|?z^v/ 6YKCT󔿎cwB m05oTnX=7CYo ) kҐվtA gT,Х!+U)u[_]jC4un:6z~TZح)3+|Pg. aj i 6YKCZ@%VlNՆ> tiHkѳZsG]nuGJ)kRw?J4ĵ.rL%sw>L/~iJF\V/ 62YKC^EJh_WG]Rl}F|UG]]=bFZCw<\83`tTM;F. tiD*1zMDŽvT,Хy'g )T?F2 tiT}*z0zguF5 tij3`ԏj#4B wMecm . 6YK#V%ѳ`$4]j#4bK_R=Z 8|3`oG]vK,P.?;|Z%@FgF"S~دnTD҈oD#ӽj]^=3|gZe@F=F5U* tiM*V=T?*e.x͓*z<=j]nQ>_[FjYKy'@ ϨV,Х*4oT?zV ^}QbREj=4|/Ze@S00ekCʗ2~/T,Х :s ``Z ǨV,Х*5T4zv̸2[cTZ[q3?QYKUk2[=fL.~T,Х ֺs `4HE]`d,⡫S6gVE]hKD3{& t{83 o:sQm@*\Es ?T_}jcTE/Je}Mxjk ߵ6vYKuїV)[R{. t??٪90mgXT,Х1u?E9i)z(e?/|Xf.Cw6yGw+J4&5L"LٜY{6 ti\}*=ߩ(s<ѣ`JK:5gT9zlVY_/ߥhXKU=6ugw(Rf.asfk @OŪR6w4]GA,qw'RtҘֽy,[N ߙHOd.i#3z&v_3]ώZ ߕHOe.q~!=1W>`+]:=#18#;)4K^9 GlYKJKFJ`݈m" tI)[s*z(zdcu?Eٛ]d6zfcXysnd.G&=;qP~{!g.G0z|c R6,%=FP+R;)BN|ZK~;R*ѳ )ֽmmFpԹѳRu>o[`$ G^NETJy𽇔mA^:e??Hڗ-@.BCʶWM>k/ 0|ᮩܰ2zP!I_g8{03Z? I_B00nYsBPӞyn׊ /5lm*T?wR֧Go|]?ق?(I_/Ec`OBR4@~g41O9!2'fo{s|r8Ѩq̇f20Lnj]Ix޺7Jzߎh_(|G!e}}/;w$N>OEg XS6o]l@/֯ `F5H<՗~7gTl@(it]*V\1@3?fq⟇?@IUL~a0w9wR6譫F zVluʗ"|!e3Tc7@﮸!J򅻦=A*8C{)JG6@ CT8# =$| e)@%fOX}g{u?}aThT6jvPtR+w{Ͻ@/>@%no70 o._^Ox[4&_3 ̰Ofs7Hg)F _F.`t= ]N}},ik_Lq`ej |K7y ~o Ffr3}݂4{05f_=͋%v>RY,f@+S6w𽂔 {o.ik@)5)PeM޲hCH쒊'KfwyΗ&k $~#~=Q%;)dvHej >e HWIƮIc ?H@wJŪ5>)O|كx{[@>r}" }ϏP@\OeQIF+I=wRPw[wIH vN;vwV?m}ѷw`Q+խ\ Paezu@|^@opt&:X:ln;5x_n@ʢ Ov %U;[9j옺ů-'>~q?T?]MDŽ,XҗIDATE>z*TRujgZ+V ew HYP{/kEPIjxi^Ԕ)u{ivLǴ_?[@P`I)S\7C ،).'ƴa6?<O6u޿_KY`U-^Oh\RrVfun=)esf_KYPޯMekE&e{8 :^ʵoՁHΔ/|Aֽ~-Mk>sIժq&L_X):_k򉾼@OeG~ !Z/ߗ KC{) ,_T/'P{҆;B$UۥWq::ҷV-';"Z!s|kz) yz*T?1Uďqн!z^\?d Sl$UMJ+_=~&:^"c*ﯯ,'o=9$R _'1Sפo:#-'4NT/JRޔN?*n;5@/ IPsfg>%/OSk Ln TE/JŚ{gҽܔ6Z]"[s*z_o3@к_JU?)u3ul+Vޜ򅻆_KYds fl>y*U󌿛c Vaey]׾栁ft"5_jչ=`ؔ}M.e.@_{3@Ъ_ JP vIcCNo~4;9oDM! Uͩl<5# ej7R`Pb_<: D|"y l>XXʗ TW/1ӹn) yg–_O(>T퐊7 fT3R6wniv\ rۖbʔI(R?q@];_oKYTsf0YO(O+ǐT_nԑ}Q'K^~-5oԹ4,THDgGiU +S¯=^_I}R}2GR3+un=)T-V6קT<~W6 .[6 ?o.x# kj)10' v 4{6٪# [M͓>~--4w”2 ZO讼5%OHomEiie*Z(_Խ4n/mgF}&kg){*=FP.'ej]o0oPI[O3H[v5C|˖Y?M)?mFۥ}De⯗Wʯbi }R!m=+ZT'$Թ&ZYX vI+N~a(:^}.iT6Gcm'lҠjǩ\pe#@Ԫ6. ij"` u9?eOcR}n۩ Fo[R~?$V}|0f\9ykbim_,n;U.'ejt\'iάԹ 1Q>^=,d vN9jF{czj] e d4-%_}rPqŪSeL5:ܰ2UU5O+֯Lͳ?61#i˗<k>b)__i&w~jT_R +6J6)$ixTf,*x׽R˗2.4.*@GRMBԻR}\PS¯w~8}s1rЩNJԹ'qS*G#xn66I(ixjO'#\U(_AŚ{R׫ïk/~K3S4_NCgl?my\xƽ9ۤFIr)״Tm˩uSދ|9X#קES~{҆ٳВۂS"F@})e͔osRsSx*3R,7O훎K?_d4%/;װO6l|'?]޹T)ri[X"o=95|ʿ_ӆ($Lޔlu*aaK =}ߐJj()[02l6mCUWtr{Ӝy Z˨Z &ӶLJ{.'pPZw?4Rrv< cǠ_"hhW"̱Be R#wo8G9膛BrH@}Vzkvz۲G:kA45#z3ِR/TRw`?/<(]$]G4y_&G=9|;e.ڻfW_|}:jG $_#'z'}Sܡ`wV$u׃NϺ\nby(fAo+]H"Ɲ4$\G2>d9JH3@^dNǤvWM4Hh #{/@]5H1+HH{7IUBf(!EDL#Hw@:vw%# EiT|* ?nG i6?Rm>P~$X4>Xԛzesyc;354?~R"o a-pSYJH{߆Az=v e>w Ŷe>ޯ<_o^s?f@)-lJ[v&麝CZߔ+!VB1xNw6Vt$R'8ԿuDX5Wn{b14c]vV#Ɉ9(1hp$ ʾ|au*ыp'&ݶDBؿBXb~ ]ܦO`|WGCD̬yPIENDB`PNG  IHDR63 pHYs{Rk IDATxyw]_Rڲ* (cU@qAQQdPi}KJ}O%ӖIӜ}}qn%IOn=x?nn7 yE82`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 2`@ wȀ0 ;dp 20ýN:WZg8tT6wT]h/~u?py>lR}ׅ\7wT;R?H399{_RF ~/]:W훚GI-ze_hŪ/yC꯸>S k*,5ԾhI=tFý-uTg*\}7M&krYeoNSz_Wo=ڗ{j_RcK{# 0//|y[_}{Z3ý|j?;&gjT~h&0z_j+MY_;~uRTߟ3pI[Uuο~c ~?u9`cK?Sw ޡNi[saފRc߈Fjl==]0Һ? yc ~7ϛ͎򿴷c~FE&kLԾxr{ͣq'aZk>_YY['Fsw9/ն{c7IE BY 3Zc?]:Z}~9s~/{yVkyxh eh5z_*3nsfk3+/9py#{7S*G]!gƻY tZw=_`+՗>gƻ֙ߜ:Zw]~.OU`ڗ43ý}?]}7rI=zjs7 1nάԽj&]:?%ƼyO ڼ! _^1&`-ڧ}ww%OMp7VNo i<k~N֣sɎ?Uu+pyf<)G넿*ƶW6pwφ{'S| |ۚ'~eÆ{}¿hSQ:Q>oGټns_W}+R3t=eUuׇ bnz<C:,Jc—~e?w{Wսz|RyP w$3zO| 6@z:5v{g^P1ۘu1_ "_5䋾?ȍ`ݠb.pýƧPߖ =k*ƮI_]p\{P缃̣"wIjBXUu)u?>}"Sjs6INz6=~K(Sݻzp4Rm_ԹpqS1_j_'TMý{_:o-sٮB<%EU^M]|tP1iJ EUWrսO3)O-|c]2*&^>w/͙zL &t"|k(^]&SE¿*>;+4i"ڧ,;6j>Q`u[範oY<&NEE_L/yC*~8fnI[o'KEӧ||gG?3sNC) _>8*K?T?TSooNEf!8^ZׄoY֯=?T?5@5u~Qeÿʼs/`>UUI_u_*>[Sӣ=qg*{ߟR<5Y{TDc߂RGE??#y\V}^0ʧOE**p|.ݫ +*pƼ#3) >]yG`HH[Qpڧcsp;-5NcTltD OPދQmS\ԯE<qgTdV^"l;շ}]Q1rS՜Ywѷ5oQp']K?oTTTDtcTYQ12S{΋m` OjQ i`L'3}#oT~}\WQ1Qow^jݣ"<}5o|LDU%}2|0SZ|!~)EfOyorCe;HEX;R6oys÷ ~so&շS&Rp߀g;{վHEHշyl÷p%;F)o#3>D6n+FSOo$3>DݛM?rC$|' #w VTX3+*&֪\u'o&p_O"֫}߅o&3ᾮlʧE*^j NJӝᾎ͋Cb3R}7ԮE PJŴfΕ{GZ zC T->l N^KTL[ ^LJ÷ipN~&^;&LTLKs^wpl%;o*Ӓl]ޞR}k]K%V*<ٺ7}fSsmb3ھv`afׅo,S>/)9AR1U~7vwJe?T\ۼ*|k*?ܻ}WӢ}bʪpϩOIUx2"|s*=;-'i>KŔTe?}KӪ\`<~{)mlӿ}G3u_o/]5Rr׮nK{/LKKwGq_J(5xjTg'O ^m緥.?7։_I+N)`5TSQUr:vTOIKvLc{~9&>uIN'v#*rýyoE 0"/s^{3w??Mu<-| @c?7t H;S]SO7?hs7x}燻釣* ݛ>Rl~:~7fm]gi=9hdIj۩{%ߛE!T>xw`5{ܢ4<!ܣ43nʧ`e&1`LkԽzQ`թ9*6 a}'+q/6?3Nշ{c\w`wv*+ځieD?Ϩؠ*1;/c?v'>i49jf_S0P~QAUbw.X}FfR7=5xTV jR6PKRЭCc5UBc/?#>}q0~Ћ4g>^^OҰp~JMC?xej[ڰۿ)n;9LV_\bz~*'G:K^Þy>'`5dMc=['m-y[Hy/ TͩwϹ-`bz8[Ÿ#4 ͙5w׉~yG?*; eQ\}+RsS0G?opoCYeڂŸ4sշIrmׇ?op?rc ; NPPs7K~Ch/J1 禣&)9ANJJnCXwy٣X΅Pm3o8|j݄<**4̚8 F;}Sq/FSw1*3| 1ջTU;5; <_O#l:ýs)}οym6Ú̜X~Jj775=4;n{7aVjgᷯWF?adjᷯ|o5e[+OݫK3i}jO|60#Un {x6! (~8n;9ϛ‡ͮNc5{w}KP Gvo yOOlwqeGwiόTu"wHN}tTMΗjԟy];OP}緅ߥjl{/Dk(kn {^?vs^K}'~_h7b޽ ׆ߺƿҏL[zw;oMEvpT6WE$vhcWJeЇI)O RO%o)cX G(t}^LKWm>N+[O^ qUΕ{Eu_~'**X ޽E2^'5VśYyF5PQRw1}7S󀏥—߄R//14h;$sek3o8xQYJXýߍu;~sk:`^>x=u雄?Υڸ%;D?Rm-I}d\yץ+CorS~:u5A>SǥYJ+"q+զuF?ki-r??_~ܗuҸpo zFߴ4Lc KRýsŞO#0OmΔU,lNe?%u^jw&>%=q'Ղz!~ giCpX0E-ǧI̓~;2%F|—F?@:$idXjp/r`k?,ML,Ouwy]։_tivE{~: ^'}ֽzSYc~[?>pzbdw9w,ME.W}R[OHm^Xjc^ý\hs,Sc߱4U5~xHe{^>{j+^g kciJu郗4~ץKG,{/F?AXlʕˣ/,ϗvrjg^`KIil{ݢ [>!U\?>V>"n;)Rr2zd}=K_~A\}jǩ TTl,n3ԽoI]KKi߅}4` K3Qiy]TT{G?_Bz_iƚy4檉]h7/5:՗>+)Ep\Ms(dyȧWɚ|l3 ҮϙTD oĝ~uo:*W\WZ95eKj~VJw:4RKOL|GRUY W=!Z۽1~U\U IDATo8Sϼ}]¿j7~xƟ|!weDŽ߮Cwd^.i̔po{1<+E7xo)='ފq>IE%jwkjx"RIJ{/io \>e31_}.]R-}u.1nQug{/^.6e5˧㠱߯߭4JuRk.]Rʩ|-R*;Q~^P}緥^M-T>`xI[ITTo7Yi.HJzý}?G =$IXpV0dž߬$I*9{w S!f%IRQ^'z A6bJ}KRwd@J4{bw׷KTeY Go!FYITTs-hk7+Ij߈B _~$p\s,3^%IRQ޽=Y|\Jýw{>o^J݇/pG|&^%IRQ:=Yh{$IE5{}kK߬$I*9;zA߫$I*;ܛK? . WITTx=Y.;&^%IRQ:{0{$IEu{oF!BWITTww.\ >~$p^O,4PJ}1{;U${΍Cvo WITTwW\ / WITTw+G!}e? WITTxD0S*IM#\`J={ћFoU$Uy"zA^$)Uv:zAo}$p᧢dwi*I'A/p$F{+{`KT}=P,$cHA ;NWITTxwdp$F{=Y0%I*ƾn $I7?C]o៎C]b:{л{$IEQC}߫$I**<܏|,W\~$p?E!B;U$y,O?~$pb,*I 4zA{$IEu{D!FmKoV$n ů YITTtwd[oV$vl4v{WJ}GdoV$~=z A6"f%IRQduoV${'z A6ڧ~-f%IRQۻds$IE5{}BU߬$I**:ܷ}mlto>.f%IRQ^El(f%IRp]F!U$eku,U$OCjs7 YITTs+zA6K^~$p_q}l4vwJýw[f%IRQ-?tuJýwi[Qy$f%IRQ޽-(6$IE{%Sw+I _A[߭$I*7[|!zAVڧSJzýyoG JV$1zAVzw~$poY?qgJzý6gVJV|:6wە$IZ}vʕˣdV${/A [ITTowo<_gd/߮$I*5ܛG|&zAvQJZý/Eo N߮$I*5k 4H`x]I5g|Y?tUJzýwϹ;RL|YJZ[B†+Ij ߈@ ]ITTk7:zAvڧ=v%IRQӽە$IE{m);ە$IZ}?qgt6wە$IE{ﶓgd/߮$I*5;m ;>~$poӹ`aJZýFo NoW$[E Jە$IZ}?ywe/zeJZýw37oW$Do N뤿 ]ITTkRt3v%IRQӻە$IE{mV)Y)OڜY+IRu"+G N}Ƿ߮$I*5{ ;C]ITTkw.>zAv[JZý ;ݛ ]ITTk7@%v%IRQe`TEJTe`R{jJZýw:oW$Kv@{߮$I*5ܽ l߮$I*5{/zA~:TiJ:ý6ozi$I:}y iە$IE{Eo NҝoW$9zAvz]ITTk7xU6gVJ:ýOT;SgW$UEo N?]ITTkn=1zAv:n~$po7/zAvzw~$po )k߮$I*5;5zAۿ9~%IRQ>x[2zAv~JT>Do N9+Ij  ;[]ITTk~3 ە$IE{cFo R}ׅ߯$I*3k6O׎@_IT>C>zAvgKJZý{ӽە$IE{Go N;oW$> ?e_~$p/zEJe?zAv$I6?m>_oW$@*IR1p ߮$I*5ܛK? K~$p-*~7zAvAJT>=,zAv:, ]ITTkUp;]ITTkO )OڜY+I ~ K~$p"^'zAvZGiJT>>zAv:~$p^s@0v%IRQ>SפMW$}{,5v$IEu{m)u[_߯$IJ?Do NʽoW$ݫ@CW߮$I*5[' SmKW$= K}>~$p{IJF N5~%IRpA"zAv~$p\{]~$po—߯$I*3|,5XJ:ý6gV*ODo No߯$IJԻ r|JZýs )^~$pou,w|KJTx%?Q~$*^r \sJTxݛ@? ]Ijrý}77J/ _Ijrý翇߯$I W^[eJNOZJ4Uo+@ ߮$I W޽j ?ywJTp K~2~%IUJ K ~%IUJڜMRZ ; _IfWjE-??zAvz~$*Ze{%SN߯$I V<3WZpoYj+IRUv*W? ;k߮$I V޽tYJT` ?e?շyUJTX?= K̓?~$*V{}+R7d}ο߯$IU> x vrJTXk@x͙~$*T{뤿@n _Ijýdu_߯$I U^YJZt=(~%I] EwI3v%IU(}v: K~$*>գ? K#>~$*>  KKw _Ijprͣە$V g~J:`$V gk;'zA|4~%IU ٚYjo+IRV'R* qZJT@s ;esU$~%Iysph,5$6ϩ}עdu߄߯$I1pN}? K~$<~$8b,u.5~%Iq jY?tuJT 6gV*Go O _Ò$ Ի Yj;+IRmL3Ry9AJT <dwE+IRmL3R}kR* Rm7,IRm 3y Yj[+IRm 3Qâdi;"+IRm 3QԯERo+IRm 3QcFSjaIjcᾮm>vk$ixe>onJTCdGRsWZo;~%IcNNece%7p`:UaIR^ץ^Tytd4=Lpp !jd﯅߰$i_O9+k_pƾ~@B:o~ÒTs/`gdYcG? [ׅ߰$Uu'=>lsfx Tw,Ic􉗼0%np߀zw>5 џaI*KQ9H4OPtY~Ò4͙H!F+ ,q"Pߋ~LAU߰$ҽ7Zmάŋeoȑml/yG߱$t/QW'dOLN䯆߰$o藃~73Dֽd{oX%/{;Z& , ᾁNʤ@JesU4%i/m KGzk {Zƾ cIz.Z0ڜMRZl;.}%/N%3l>8"}97-??%U]z=`e0s6я/,%U7<3_zw11ڏdO0y3cIc—M3_.;z`S?~pDm_RY@~5w,)nץT;CdO]я1V'ފs.)0{;XhVUϼY~kE?e1^&}Od}X4%~^ {Q- >{jc ֻ;4y]:#$}O>ԮE? _V/zE-Kץ^\kջ{&}#g`QK^ץy4)ֽ&}#|0yݫ cIhόӿ7Ot{j ynܣ*\`͙~˒6uVL{Q}wH=~˒ v a27я5Z߱ToŸTy$)Bv=ᾑu=(YwqKyK^Ns/#uY넿~AT_[ƹ^R}0Z~1Np3k[ƹFZЭt mάT~x }-Kc\sFZsGt xBdm?~ks6 ei\미.a5E6Rry-K3 X^;O6ܧyDC)ۿ9aO?~fOQKw~A:eijѧ #ȍw:l<3я;^NOR.5ӆ[~~>E՗!qcχ߳4NrYHtT>'~AgK-KTyg #sŞw:lֽ{я=^oY}0r*} k{?.,KΊjiS~fOa؃>Y}0ZGI>lOm+=߲4.TX~fOqeǼxQno{rkF^}S\~Xh߳{}024Vp'IPSw,^?>eie;ݐ wQ址-qKL\ѓ1YLfh'd,3IL4NNLzMm@dFD1  ȪJC@lB^̩}U]u]?~Ub2^_;?|E{ޚIZ9]H S!̄)>"ӻ1Zo:-|N}u3,9=Pk+J6ӊ^0;c:E3-28> ? >ܣ [<2vViqx|> >7 IDATx"2:xl~,|V}Bi+Tս`ɖu'E.۠_ ՅDqTVYJ$a& eI[Gٲ|Y(LDI#_>"YRǣGjᳺ(LܕkfFϴHOxkB:&|V}i5 3cظ;ݹ"Q~葅뜻*|V}YRu 3ϵH ^=P{ >4{mDiƍ wl DqtVQvb ;c\϶HMӿ1|A.&һfJ룿>"^O+׎QG"O!ms-RǴ> )txw.& e+~/ ma紎y]L)e\Js-R 9z4!2|^}J=VX:oT+vmykr6@qR'5zi}g[.鞷&z$!WbO)~?\pVa?5|EkGR]yt9Wܧfu]Z2A?>"inxy4B>>t/98z]vxlDi2Z>>Ŵ>,+`Z-7DO"Q~YWܧjݳVܕ-摯AHcݕ(~÷\fa wl+Oo.;,z!gvWO9FYI2|Eja{{A/>}&L=I.S*z '$|nw%r2^0ZǾ)~EG|Oy}}u 3-24{mA*Jcn᳻+Q>Ϣ.̬ѿ>"HOF|VjT7~#~)|E&0,PgwWG}y Ic;|E& i᳻Q܃=ou5`/y"/>-Ύ1t^>=(1zLk}-s.2toxA:]᳻Qܣb"&cu`xA:>K=0a\d)ӽh豂:O.E?foƪ=g]d)Rt豂G.|"{`A?z-LYY.O ᥈}\aYٕ4}"oB /UtYa:&|E8;1EqN_^0<]d1im{s/Uح waN+>)y 9奊^<:zY\hW.=6˗Ld0yR^̋LZ8Xgy)!Ix0%?"jݳ[k}y)$k>anOxk̋zL Ay^(5Ian [B="OՆ1y^(5IZkF:EϾwaн`^(5JkJ>"gS`Uc3sQkѭ)4J }QzW4z"`vZ GRGqQ_HLh=2|GfJYs=(5K/Du[D:]:M zc3sg{QkBs{_/C^bTW$,Ձ/^0 d~R2~[ʇ37{RQkw}dS2%3{g|RQk9+<75վ?Z23 IEq9@ѯ^g2{h4G`|jO*{M3ssKcT{` 3>(5M E}{kO({?ӯ۾auf؊{M<>0*Wn, 7Ձ/+*LpP^>^z_Di|B ϖ[0̅g~QkgxHOƪ=ɓPJ^07:s?(5NWG]z}4V=1|ogT F?ٟtgp׵s|Jc R=d23FØ~_>~e Je 鞿W0(5O/Q <=BIow>;j~iDqOƆz6+~-|T7"Q`Qs?Ft}[ ~Z2ܱ-zi2( Rå s<]<}~G =I7 TЎ/dBY[igeXԀ J0(I2)ѩ^!K桯).^^9iFqϒV~5ջ=٥Th]~R}bQwGGX᷾YZO{,<պg_| `%{Ŵ'J#=#B CS}f2^9=cQ3ee9aغtNߥrD'>)sW$jӎ,݋` ^]Zv^"NuK\CT=Y^>m:{ʼu䯎?ˠEh}$"{oRKJ_WgWl&`s{ڡ0"zf%6}hbY{isN#0K{%({Œ |LMn,STפ͊J_,/Xn>knxE>=izWn`q og{w/P} &0{ҴdJեyȫ:K8 wl>L?'2{֬ح >z~SiFOl+M=w鞿Wvi)~h`ƚEQDh4QX4y=mt~)*-[i`o8'^+zRӻ>/KC?_g?Jt>S_w~77^WEGqOѷm-W.S9rg}QAoҽpҿTըAq*`^ܷo0:gkxj$Ci3$Zfxj,,e''d6}~}{g `ݩ5>c=N#zeXNըaLâg`Q:.ըiIn d3lUkޥ5>o:-zswFhZG>zvڰ}|^tj8 g) NGq?_guZԨyY=G1u/\ߛ?ٿEkQ LQg=\;E$ꞷ&/-}9gEL|a[$|磸Au*ѳ 5'5Eqt/X=Vj3;R#Q9IsAwF(sEG(@si~Rx7j$>G}A)*zV9ԟF(sgcWƊ;Q#a9KkG,0ZއIa=o:-5GqTP)Fd/C^ރi_7z|9һH}N3z16> ?Q8sWF10:34f eظ+z6XӘ(s= k}NcF{< = ]{B|Y>;Qܥ??5ݪT$4f(;<fH8g+:ףmהƪ=McƢpF u䯆 Fq3z qջNӘT)Cw mLcF3~GYX ots$>ῇw we_B>/s$tZxirVQ`PU2H}epϦ(nL0պgeb^i=H}ûKcS~/HҿsPsMwuoe3b~i'J鵣"lj|Y_3 G @MOzGxWiIz6~ϗn(H=S2~[.2+v *9IA#M752l]}_QQ_Y6/QR=iyx։o QRߌ.<#]vxx/iY:gŽ{ձ/Jr\ ̧}Kᝤ1Ƿ(yVQ__Q<}deʠ}'NC?WʠeA:gKxiaZǾ>gEE@glAs>Ž)5O-{o7)V}(a,x>ɓ߲T[ 0a";}V?jnꠟ$Mz[ 0I[:GwYVzlNr5ej,NfSve/&z2?tv<&~ *e/A+y(7%y/wyOyȧ/:yoђ$,-/jqKd[{ZҿEe:Kuυ#: -z`8,=>)[KrQ}dм4oH룿SpKX9+{:%wX.u[u# G{2~]+#~ioIOY ĽW>!>g,]/\zhٱIokj3QYK~\]W&͒_ڸ{)֫K憗WM.iqk7JķiR6Aoɗ̳ѯڣDeV=tzo)=9~Cz-A?&Jm9Z~0wm.~/ |/$ۮ1XqKuejXɣgt;ko>oi3{S;Γ-kico,,gMcL>47"3}<쵥wI+NTw O?eǚRTkYw~uKfpǝ2ڳ{sxfjqA9oR}eAjj)E,GHic[iYO_,K.wE[.-]i#qȫ˰=zI@ wϯTIENDB`PNG  IHDR}_ pHYs{Rk IDATxwfw]fRP(EDHU;?rQXWTիr$ɤN!R LRgB<{~k$33gS^kkւ>=< &KÇMF9C;+hh}ybr͍o2LjQcyoޯٻ#yhNY{.e{D?GkѶƴb_mXSߌbWHRc-6(z- > mHt|tXOj݃ٯ9L{w֢m8䧣{Dt/ 0V,a?] >š?&a?U7FQ#w421XyqmFL~*7/Z?K^wFQд[F|It\u5â ([S$ZKw)sD'L򑛣%w4->ڟtl00 ,d)|GZC.MYS>8l@kXK]$|Kw).>EO+zbҔ="28EHҸTѻr([eSǢ @C_?ۥ4;#*H|$mnKΩ᚛qaZOM%EOd s{Y-}į`ٳ?>mP1QZҷ_,d`xyА} IZqOE֓"* 7uh02ŧ^>HKfDefl#I[_qgfnEO7ΒgòO` n?5ZͿ_18bp:İh_ϼ=}P=-&7}D[apњY IP[vg` WG̿a~p,ln\1̃5HҤhٟmO?}-6kЋ{Fk%}gd<}_$i%ѿ氈>ƎE0\}cL,ٗlV}T󭪢{G$i*~S`X^ >k_9+R= $iZ^O`,lދ%/f@kw4%_}<6fЋŋ50}OhJg~%NB&EFE0YmѕQ39,ٜ}d ǣ}&$iBk(=}$6ߣwZc+i-!}dIuFϫ($iR1XyVq0r,~;:$plû>5dDew4,|a`?aoX%m:K6w(6_g!I\wE|`ze/JR%qf0b^4{o~w!Iܾ᚛|tmֻbh,N%m$Y n?5ZɿÐInN1XyVʢ 0AtX@*in-&}r#npњY!IܢmwՁG>@6)}o6cKgH=#2hE`WGq[ӇOIslfa n\ɿא)s#QmQ?_>tJc3 bp` 97$i j"hE`*k־I6%ͱѿcUw}{Iڟ}GG?@#,oh!S_WLj(yU]$MC#~%vm6|h-5}4W>: R)_~!IP韏.E`b 'Z+~8}4zkL=GkѶw4 GrD6mT} Z:}4zMLGHҴ>NP 6)7<ŧ^>DJ{>Q0z_{I:'a?wmROFq҇GIs{(0 *|0>DY};6}^F ٧0MG]o0,,sڇӇEIs}/GZ٧0κhIfӳ~yc݋\зF~*X(Vp=$MEKwWg¢ 07>Z3 DIs}Л*>:|hs}$MC^/G~fk57GkNáU6>:γh{Iڟ}Gİ}l6*'ӇBIsXkߕ}t|{ߝHҴ=}bO0ڟaP*vA>9U?OChfAo;5bmԻdI (in->߸8xnNIeU'?hWdi\YN>6z(yU$MAao~f+e{myu'in:0,*4 .]}l66XO0+4-6~=,mѿOҜWGV];I6c`,c\:Z>Itݓ0* SUߵH4=O}9h -}ȓ:G+b>2Gޖ~"ISRo>Ģ 0+$mAoT0G߽HҤG >&YFZ^^>Iz^պ Z Zl~#I^edi3"}v[fpT=$Mz/r#9YFl,L$=G{}\4Ͽ sfɢ 0ڟ}G0'9Y>*SοInfa >xVmԿANsֿbEQи6d݌$Mrcޛ}<+6GӇ8I^>)Ҕ/LInp=3hWo di6{I]40,#lֲoao赲 ;k$izrQ},#{'Ӈ6I\+Zp10:At|W$Mj>EmQn/H$}/[ S=_PʾI۩G=wh>Izmû>"FVUZ]=$M`Smb eDv9}X9,yHǑImp_FE`$.-}H`ltOp}$Mbcޛ}6@~'Z+~8}Hu 9zٯ8ɾבIlS`E ]Ϧga?;{1)'eHҤ=G<,6@7g_>j`l 8#Z3 y$iZSG,ycZ}P&{0Q({Io>ށ)gHӻ|E0&uO|DUe |p(IXK}S΢ ,J$=/ڟ~;TXIIXkĠ}S̢ bp郘Eˣڰ:Hx/~]$MJ;>ց)fH=Ӈ0i[GP6^'$IPdh4FkaT7 }LZ]ݐ$yF :0,{Q&M{KeSŊ!I߸$HEq>>|I\ETUQ02:F${s&DEY ZwMi}n> Zz4~$HƹbWfh4j/iZ+vA>xWzeZM$sweh4{'Ӈ.i*Yû>ݗJԿBmF-}蒦e˲_WUF_M;q>Ɂ)dhL=tIVETU3?]$i+(b8>ʁ)chL.ij_s5 .IƱ벏q`X9OӇ-i*xqO~y;>IƱ>)chLץ[40w}1`hKJ4fuOP L6@#c>Tje˲_{6SQ%Id L6@#+JisFTekvJ$U3 >)bhDZ'j?gY=$So\}tSĢ ЈJoQ)u`+Ug*IƤdh4EC4 n8:U`^Eۤ9I8=fhԮ\{%Mzݳ2U`.{'I:}G L6@w>`I\зFٯ:D_HQOl`XjʲKԊ=^S~I؝ZS=$zU#muN@p%Md3 cxٯ85_}p]$xWehԮ8mÕ4/]zЄα~%I֓Ok`JXj%Õ4iuzOD9~hHau_~/%IZkghԪOIX6~h3$iT]40%,9}&1W$>G%I#X?>)a`Y郕4I/]ZꮏbKQs{h`JXj郕4)uyoDUf$w'gWI(> 30%,^<>XIPeQmXJ0"z~XI^ҥٯ2#|h-1JFEfhԪ}V9=0U`D_$J1dhԪ8C4+^ӏdgߑ~%IPz,TEV~?>TIĉs~+ ('ZKwʿӒehԪ+҇*i]Oٯ/cWHIEc` XjZkP%[1eWHw[Yaui L6@Z0}ƪv_]{֒$)jÚmZGy n:.`/3KV1 L6@ZIq{grO\]$edhEV4.xTٯ,|lO4Y`U@%EgLWv˿h4 PJW0ih/Ij26@,QwDTe *9Z~&IMehEV4^պ_S&XO߃IRSY`U@%r[0醽h0Ij"6@,Q{_ODF_!%i*h4 PJŊ_U)һbTwm&Xj=PI#~Wi3F7ߏIRY`U@%Z 9`J]EۤߑIR]Y`U@%RC~j7 K~O&IuehEV42->Gn~%rUwC{"LjȢ 6@*iTuf n?-LȢ 6@*i|0uߛI|ghEVn;GWK(v3I,Mh*{\Q$i>h4 PJʬsETUkϬDзߣI|ehEVUlُQV>tMfߧI|dhEVc_?~&IE mZeTRF^sVuG$ikh4 PJjbKzW6/߭IfhEVt[O~`t5Iښ,Mh*{{_9bFklY`U@%5Qx[ewm`U@%5gnh6Iڒ,Mh*{~` 2Z3 $ish4 PJbFW U?O{͢ 6@*OF߿IdhEVTgQUٯbpwp9Y`U@%ҝ|rU+h wq4,Mh*{Oe^P5 >NE mZeTRňrz@#}(NNE mZeTҼd(#TD $iY`U@%wKdVи{IҦh4 PJ>b~y^;:Iz,Mh*{歙1|ٯ{:Iz,Mh*{޹:@/N-6@,QueNzZC$=Sm&Xj=PIpYٯE7N)6@,{_#-"}_~w'IߛE mZeTTC9<-_H͝>6@*ikxL+#sԻ$;h4 PJ6^DUeB0Go֢m$߳h4 PJڢ哫_ys&>O-6@,-WB~*廦I,Mh*{6t_kKדY`U@%mnûx)>w{dhEV9uO|+cix$ɢ 6@*i-)g20:Ǽ7OTghEV4WX+9Z3 $Mom&Xj=PIs}Л"^I,Mh*{6̂~+ٯ Ljó_Ӟ~'i*h4 PJT?D]$Mgm&Xj=PIUNjj=DX?IӗE mZeTsտW&RC$M_m&Xj=PIV7FW&S9˾4]Y`U@%=[Uf0ц+J4]Y`U@%=S/~SsJ,Mh*{%GWBh,̿4Y`U@%}o5= IDAT#6@,Q~-`T%M~m&Xj=PI_ J ?~?(ih4 PJGrDUe0(~O(ih4 PJmfa]:T_u`]΢ 6@*ic?*~x}͢ 6@*QmX*1sw&66@,%_Ue{CIE mZeT=(;NO;4Y`U@npٯ*ڇbˢ 6@*Mo_Q_ W]~(ih4 PJs9tzw=ʢ 6@*Mg#ߙ0|w&+6@,4,}`:Vɢ 6@*M_SGcQ-њY~(i2h4 PJS| ߟ(i"h4 PJU|h-6~QghEVb.QOd?;FIE mZeT.~-T?ZKOg4Y`U@XkTُ;z|,QxghEVW~TmX;7J,Mh*{W~;QANs4Y`U@opُ90OSQ,{Q̢ 6@*Mv~s`/]~(i=^~)ih4 PJY?QUُ7P%"%Wm&Xj=Pi2 jVbGJ,Mh*{>k!/Kɢ 6@*M^ûX '#6@,4Yو~.IIE mZeTwH ҝ'%~m&Xj=Pirj3>TK~G)ih4 PJpُ3ڰ&ZKwL4Y`U@ɨ}#2qJIE mZeTw(ɪuFkvF76@,4zOfuh͢ 6@*N~Q{Hz,Mh*{x>>.34RhfhEVƻ Gg?)7ZM4zY`U@^# ~)ih4 PJ[e?*'ZIǔ4ZY`U@%Qu7d?LIE mZeTz,~tW~h,Hϔ4:Y`U@1lNQ~t1974%Lm&Xj=Pi}[`L qIɢ 6@*Yj}ُ-0FڇbݦȢ 6@*W>cfpwF#6@,4F,rMُ,0nam,Mh*{9W`L94SR~m&Xj=Pi|0q S9TTO}cދ;ωm|wûϛ_;gl}n_ @]({NIY`U@}Л"*q`>TUTO?2,31ѿtI=s{}/DG׏DkAoŊΡݓ(zm/]:Ѓ;NWDʨdz`6swrh4 PJd?Šwp1_lvAs}/E+強xh;c~1\yfkeo旸%Tm&Xj=Pi+:a/g.tO)}ufϏ=gzx_Y@z_PR^m&Xj=Pi]`*Uj1~֢mgIXKt> ?2ʇt&Zh-6}E mZeToՆ5ُ)B͚bp1;GDNjgimѶ>M=ѿ(WQqJ$dhEVFi~D&JY]|ZCܧfw{OJ#DkfA',Mh*{h7ۻlt _Gt>_U%;Dw~plα9xm&Xj=Pit`9C~:ZIPě>哫E8IghEVFʳOV=\wDtOOwU_ 6a/QYޖ>Ij66@,4&f?#|le94'A+^>i<*2 n<6` n=1}^lm&Xj=Pi4_w ==$?3&ED3o$!WOiˢ 6@*`Kvt*1|kѻdQ٥Lҝ{R_}pl&,Mh*{=ُ%@szqztOH{`,X1~+/%3fh4 PJWُ%@ãߞ4KΊ}~tS6>Ӣw?aɢ 6@*VC&E_u@t>h,HM60:Ǽ_-UUٯ@uDkѶ3ڳh4 PJIyS{r&+*~j=]Ϣ 6@*N9G`TǢ}/YtQ>|m0_?oI=6@,4:` :1|sDɆ+RDszh4 PJ#(\8]Uˣ{GlyJJ}Лbp"A[ 7>_I76@,4uG`N6^: 9}FbWϾ/_S-7Fe鳕h4 PJGE 﫡MS˗GYl33h4 PJ{Fk{h$[RmW`TVGkvzh4 PJ/ُ!w)W_ݳ>;JҸW,iX1ds=szh4 PJ,{Ca/cޛ?#IXϫbp0m}$,Mh*{RnޝSj?˖Ee鳑4 ~K bI#~)}v4Y`U@7SZ{_34m˳g5IghEV*/A`ʔkni֢m!IϋպW͢ 6@*;o?` g In;G^Q]6~l$i^h4 PJykn~)0J 6Ҙ>u1\uah-1}N4Y`U@ڇ-a_M{$mI=}gˢ 6@*ԿG䯈:󎤭I#mњY?I,Mh*{RBKw.&L59y}OG#r#ߕ>I,Mh*{RuO@cLۣs4-~~/]1g9qFL$i^h4 PJ7Kُ0 {ƟFkfa|#ڇ5Gn>~iT󐤭Ϣ 6@*5[`_"_>HJhѶѻ^iL%g!I[E mZeTjy㪪bp)QFR~O&`T]͞$m]m&Xj=P57f?rEYF҈0D?Iڪ,Mh*{RszcG{ڇ5 }4uzwT>)0GehEV^ُ0.A: _>H/f^({M#i˳h4 PJ ha ~^"iY )b> ֿ|y#ih4 PJ9׳5`U=룾&JVEc PHZGҖehEVip5` n;%=(}f49m-_> =I[E mZeTjvtj}97I[*)` qI#i˲h4 PJ=ُ0j*_?hv!7{V4u|gTGO>`TUx]#ih4 PJ7\yVcj9WgIU+|# +Iq$m~m&Xj=Pފ_1d?ft\ }F4-!7}*/gIE mZeTi~P(:Fl"I"aL>Hڼ,Mh*{R >/ 8#/MK$;ΨZfE\#ih4 PJUa?3$=[">-1>sghEVkT~hyD6UNjcx&0_?(}4,Mh*{R} (VUڧdYDܒbp'(0h-)4,Mh*{R={`D9~U=IڢfDG)0gY<#iNY`U@zG hPh3$mm/>V1S>tM#inY`U@zwy4dpqZc!IUE+0fڇl#iY`U@X2 Ӡߎ>{HR?+QOd|_}HtOp|Cf06E mZeTgecԬZP?s$UVg8 n;ek&;yO86@,4 W]X5'eD~of@ kbx9ѻdqt(>H,Mh*{V,ecS4h-.}搤&+('jPeUDE7͢ 6@*oS>Hu(_=kHRV^/;Oc`k Q>?sfh4 PJӲ)`U 9w Iʮ%Q>tM QaOD3o IYgΣ=[ jqI1I6$Q[31gttI>&;ӉLOڎT]vMQM,,@j)PR"[ R,VΩ[{>z_>GP7Irh#)k 3t) ;џ$IaՓGg,_;ϒ$釪ݟMs={49T"6P1;s7s$I3lǟ]`4Ӓ$jT{Mm86 >{>H*CIY^gGN$iFqlO$)Qn%oh\;SgŞP_m$ȡE/TȊ秪H$Ifx93W~u4}ے$5jJ5Ρ/ @8T"6P1)I4ڸ*u/ -{Kt?%IeU4i~.GXlϡ9腊m<)S$I{NPG;t$-톝44ip?>Ávrh#Dm$e-zbFcDJ$iM'i?u]4}$-4}hStZ\w/Ί=5m$ȡE/T,^oџ$IZhQ| &i?%I*^}ky_uRegFRHZB `g$IҸ;|hz$e|'M~Σs~;uzEm$ȡE/T,k?#I5|hYI/I⛌tiqU;h~u/ FRHZBtx$I5jI3~=|hRKMii|ip韥)oNFRHZB .xo'$IvQ/ k$-Ū[v  uѳ6JFR֢*gџ$I&mlW L-躕;jV*|FDqh#Dm$e-zbζOH$~o$MMFi4ڸj೷zY,|,m$ȡE/T,\ﴷG>$iWRwm6i IjbI~+i|˙izyKx~XH*CIY^X|$IsUM7=xESATǷW/Lë>gzP3m$ȡE/T,[?I @?:t4}ѣATޣiͫ W2ph#Dm$e-zbavTUџ$Izw~PwS}#BԚt44XwP?u/ [MFRHZB$i6};ͩ>=*$IQM';jn9+ >w[Sgnm$ȡE/T,֏G:$uy3|_*Ij~ire:r9fm$ȡE/T,p}OG$=MoJ^+܆W}0zlHf\5؞&[6U{ ?ȡ9腊;?I4U}+uW*|W`׍oX$-h節SggFRHZB~?ICUGSo?Ms{=#]z4tN^yp9 u'~H*CIY^}Cg#I(?$-v.NMS ̆CI%rh#)k inF$}_OyNySJnHVV ɖ iqs|H*CIY^=Hkt)1NJ$58MmPKߟzO{qh#Dm$e-zb[Hl?m.z?`vFO/Ԩ[R}ˡ9腊3zK'#IvǾG<|7`%L$ ?#^s%ǡ9腊]=ri'#I;mytW*UO>=m$iIW ?Lm\á IDAT+p>6JFR֢*v]ߋ\$IRJip ȫwگ4FIZMimso:gW@/#g5FRHZBŮ]b"IRvnN@"zHRدR}&m$ȡE/TC?IZ_IC_PGVm(M, ϥSWH*CIY^5#KF.$a'NzcN@Y^=$i&Uçdˆ4ڸ* z9 @8T"6Pk^"IR\}SޔҨ=$it4tYgTph#Dm$e-zb׌?1S$7_ kxǑ$=k;J5ΡFRHZBŮ>)S$UOܟG,| kG%I?&w6 ϥS  ʡ9腊jHԾ[KUoNZV5|*M&6=u?`1H*CIY^xn~/3$=*|`i}S G6i4jn}0Km$ȡE/T<'F&$鶯!,=ë:zLIjHire;JC_3rsh#Dm$e-zMHԮ&;;KeirgUu]WοIݣ^ 8T"6P캇x $I?w?ޣ#KRmI-h4XwPH/g,m$ȡE/Tev$M=o># .;ͩ?K H*CIY^xf[!IR+qiy?4oM;/Ks;/-FRHZB3vn!IRS _#o3bMo|:>Σ_6JFR֢*e|CƷD|c\T(MޜFWRo|Y9T"6Px!IR㫞?u{QAV/SǜT'KU3=FRHZBm8.Ӑ$M ѵGE:VU'dˆW} FRHZBӛ{M!IRUK`P`WHz&`AzYG߷@m$ȡE/T<{\$)O=t=IMd?8m$ȡE/TSտYH&; v}'ھ5M, ϥS>6JFR֢*B69t47ǟx4?wS=,ym$ȡE/TS/$$M{g=?7S)(-8MmPKߟzFRHZB?5}BF69@;o[=ݪzR}>9腊2wJAg!IRS؟RH4j44\?k^ˡ9腊迌$$IjdO ?RO=KkJ~/u7vqh#Dm$e-z /OB5q?>hSQmj:NmSg/FRHZBzv'!IRoDz'|JahT4Ν{L~CI%rh#)k ?hD$5G>7aѣQ PyYKQ/vCI%rh#)k j I4&߼*~;򈴫Uçdˆ4ڸ* W@E FRHZBN}[ IR?l|8MmNM{FRHZB .AF5}Y,|G@;J5Ρ99T"6P=N$IjTC|g='Svǥ V=Σs=!@im$ȡE/T|ώ߷.IfS3W|g3葩LUçwh4XwP?{X H*CIY^G˗jd IRc~;@ IR#:,a/JѣM;o4kHCsrh#Dm$e-zy{KROA7|Yl?&[6u+S큩{+H*CIY^x^@F4sei#^MFi4ڸ* zwx 9T"6P4Ϣ?Ij_5|jO0ßzM'imso:' џ$Inr9db4iV L-v ߓ+_ %͡9腪F_Z HTsiD^wΣ 8>P?m$ȡE/Tm7g}' IRmzZ,MR!;鷿Ʒ5'N}ksh#Dm$e-zjjCџ$Im|JkYgj}kyYK/ @39T"6PYI?Ij[ Pg2?ie_u{Rwm$ȡE/Tm;m/IRmz8uV>IoLi:޽9i|ii[,# FRHZBf (%Im'r(m|˙:IMR}3sh#Dm$e-zj$NYuFYXmߚ&w^6-kL# š9腪Ʒ$ղRgYQ{ksB8T"6Pt/IR-}iu`9T"6PY5x2%Ie>}m$ȡE/Tm$I_"u>6JFR֢O/IR-~^`aH*CIY^jp^Z6sqh#Dm$e-zjцc^5/ ,CI%rh#)k U[7~zIj3sh#Dm$e-zjCF?$Ik ,CI%rh#)k U[Uǣ^;3sh#Dm$e-zjE?$I~7u>X86JFR֢6g$v8T"6PD?$Ikppǡ9腪WuKTǽ.|8m$ȡE/Tm4.IR~sh#Dm$e-zj7~vIj37FRHZBFG$ժ>X<6JFR֢YgJaKTz'1~hm$ȡE/Tm=O.IRe3sh#Dm$e-zjio~rIjK7FRHZB6 %IUë>> 6JFR֢~\Z[ph#Dm$e-zjUO.IR}S}7FRHZB6}KT>6JFR֢>xcKTƷ>6JFR֢?$զ>6JFR֢V+j$զiǒCI%rh#)k Ut}sKT9Eqh#Dm$e-zjܒ$զrh#Dm$e-zjܒ$զmkg7FRHZB&O$6 ?7rh#Dm$e-zjцc[?߅nfˡ9腪Mv IkN|C`H*CIY^drg[z4Ίnfˡ9腪MjsKTJ`H*CIY^ڤ~7%IE^>=6JFR֢֘;~nIjnfΡ9腪-Ǿ6%IM >=6JFR֢}_E?$Iw[g7FRHZBs7%IM#_>=6JFR֢\觖$U'6y8T"6PsԒ$բ÷mph#Dm$e-zjUO-IR-qI 6JFR֢vnSKTF8|nCI%rh#)k U[LyUSKTW>á9腪-[o~jIjQwmph#Dm$e-zj-O-IR-Ks<H*CIY^"O-IR- @m$ȡE/Tp,IR=Rg @m$ȡE/Tm=u,IR-7|nCI%rh#)k UN}[3KT)|nCI%rh#)k U?E?$Ihr%s|H*CIY^`pE?$Ih|G68T"6P~fIjp @>m$ȡE/Tm0F?$Ihp68T"6Phq,IR- @>m$ȡE/Tm0iM3KTzJ 6JFR֢6o(%IEU?>ǡ9腪 &w&%IEݣ,|nCI%rh#)k UL1%IE68T"6P߈~fI| @^m$ȡE/TmPu̒$-'FRHZBi2~fI|o%|fCI%rh#)k U'$M6~nCI%rh#)k UuyMKT&w~*|nCI%rh#)k UV\KTƷ>ˡ9腪zO,IR-m<)|nCI%rh#)k U'$=:|nCI%rh#)k U'$ ׯFRHZBtĒ$բU FRHZBtĒ$բ>ˡ9腪W| %IE;S6y9T"6P53wKT7|nCI%rh#)k UӍ9"%IEs7|nCI%rh#)k UӍ6~bIjQwmrh#Dm$e-zjgD?$I @^m$ȡE/TM7'$N}k /6JFR֢|'$VB /6JFR֢|'$Nzc /6JFR֢ܳ>%IE>ˡ9腪&]Ē$բ ?>ˡ9腪[o~bIjQ FRHZBtm_~bIjQ׆mrh#Dm$e-zj{XZ=5sH*CIY^ھ5%IEݣ_>ˡ9腪wXZ=sH*CIY^. ;O,IR- @^m$ȡE/TM'$u @^m$ȡE/T|YJT8~vCI%rh#)k U$զ??ʡ9腪}aJTG,~vCI%rh#)k U7%IҮ=H*CIY^{~+IRm|u /6JFR֢&|UJTD /6JFR֢& %IҮ=uH*CIY^{OE?$I{Onrh#Dm$e-zjއ6y%IM>ˡ9腪zyJTz'1|vCI%rh#)k UN$6VB /6JFR֢&$6Nys /6JFR֢& %IҮ;mH*CIY^D?$I @^m$ȡE/TMF];g7y9T"6P5Y#"y%IMnrh#Dm$e-zj26$z>ˡ9腪H >ˡ9腪z5y%IMK>ˡ9腪H <8|vCI%rh#)k U9$i^ @^m$ȡE/TM;m+IRm FRHZBdm$IF׭ FRHZBd~u$IhIH*CIY^wʛW4 @^m$ȡE/TM;W4mm_c IDAT /6JFR֢&+IRmqi /6JFR֢&$6M @^m$ȡE/TMF?$Ii @^m$ȡE/TM=+IRm~H*CIY^{OF?$Ii=ˡ9腪ɺxJTF @^m$ȡE/TM]$VuFRHZBdݣ^$ժQ/FRHZBd#_$ժFRHZBd^$ժ)o FRHZBhs{E?$I;78T"6P5]'$6?;|H*CIY^.O,IRm\|H*CIY^?Ē$զ<|vCI%rh#)k UUD?$Ii7|vCI%rh#)k UUO>Ē$զOFRHZBtcD?$Ii|g78T"6P5;wD?$Iire|H*CIY^nmO,IRmw} 6JFR֢>'$6M+|vCI%rh#)k UM\Ē$զ @>m$ȡE/TM7O,IR}Sg @m$ȡE/TM7'$Vuxi 6JFR֢wO,IR3<H*CIY^n|O,IR}_oph#Dm$e-zj 'G?$Iο FRHZBt뎉~bIj?FRHZBtsO,IR^ @m$ȡE/TM7XZ5<H*CIY^nǿ/IvMk7y8T"6P5?~bIjOoph#Dm$e-zjĒ$ժ7oph#Dm$e-zjy.%IUoph#Dm$e-zjY~bIը>á9腪z'$vu9T"6P5]蘭~bIjW7pfϡ9腪Ǿ6%I]>=6JFR֢'$v >g8FRHZBx+LYZ5pfΡ9腪 Ҩ̒$ժ ̞CI%rh#)k UX%Iڽ7~,|~0{9腪 ~3%IU;. ̞CI%rh#)k UL5%IU7ofϡ9腪 &^̒$ժoofϡ9腪 &w]̒$ի u/ ̖CI%rh#)k U7}"%I]ݣ^>-6JFR֢6m\̒$ծ)o̖CI%rh#)k U E?$I ̖CI%rh#)k U <8%I]K,|0[m$ȡE/Tm0?F?$Ikǟ=-6JFR֢6,IRߴ&|0[m$ȡE/Tm;,IR|l9T"6PA7F?$Ikm3rh#Dm$e-zjѯ~fIjW}$|0[m$ȡE/T0WJUԒ$իJČCI%rh#)k U[TO-IR3qh#Dm$e-zjZ_s@ `vH*CIY^bЦ觖$v 8T"6P[~jIj8T"6Px觖$vx| `vH*CIY^b|O-IR8T"6PcZ5}8T"6P3Ԓ$ծjC3qh#Dm$e-zjkSKT*u'|0m$ȡE/Tm18=O-IR-}qfá9腪-g+%Ie~+|0m$ȡE/Tm;O-IR-\9l8T"6PEG?$Il~.|0m$ȡE/Tm=GZZ69l8T"6PI[5g} `6H*CIY^ڤz|KsKT~3|0m$ȡE/Tm2}-IR Sgssh#Dm$e-zjɝE?$I{k8FRHZB&O~nIjY_ ,CI%rh#)k U9"%Ie |xm$ȡE/Tm2-IR-^?8FRHZB&;m|In89|xm$ȡE/Tm?7[Z699T"6PI7F?$Ilms`H*CIY^ڤ{K[z6eqh#Dm$e-zj4D?$I{k8FRHZB6G?$I98T"6P\Z6XwP`qH*CIY^frO.IR- ,CI%rh#)k Uیo93%Ie[?>X6JFR֢]{TKT&[ ,CI%rh#)k U ?\ZV=@`qH*CIY^fpF?$IR}g9 FRHZB633%Im>X86JFR֢O.IRmwg9 FRHZB6#~rIj ,CI%rh#)k U,_d$ղO,CI%rh#)k UUO>$ղqΡ9腪)%IeӇo,CI%rh#)k U7_$ղjT`H*CIY^ht.IRmY8T"6P#%Im>X6JFR֢6\g$ Y8T"6PQoͯF?$Img9 FRHZBF^$նW,CI%rh#)k U+x~JIKT˦[o,CI%rh#)k U[U۷F?$Il,CI%rh#)k U[MrKTۺ+_>}m$ȡE/Tm5޼.%Im>}m$ȡE/Tm5ڸ*%Im>}m$ȡE/Tm5O/IRm]{T,`9T"6P?~zIjxEFRHZBV$ն÷rcޣv/:!SkjXv0mLS4i*Z45d:SY3g P@9"j  A!<`H j(>𛅴1~s^׳ߛgmm$ȡu58^667v9ǡ9TBzD-_6xٷ9š9TBΖwߖ%Imx|{HCIEK/Tl?~Izg9ǡ9TBk$M/}Y|{HCIEK/Tlz1_vjz{HCIEK/Tl?J$>6jFR :+_6v9[FRH*ZzZg%Iu##>:6jFR :/IRsh#Fm$-P}n6N?Izs̡9TBwܐ~$g9[FRH*ZzZw/L?Izsh#Fm$-Pه^~$ݷg9[FRH*ZzZw 4$IulCI5rh#hjݍOV H'p|5m$ȡu7<)' IR<`kHCIEK/TnpO@^7<`kHCIEK/T-'_N?Iz3qh#Fm$-POg IRogg9[FRH*Zzbn$Im>6<`HCIEK/TM/?6 $Iu×w|km$ȡ*&AHF>3>56jFR t7BH&<`HCIEK/T {RHf:)>56jFR tþ1 $Iu/sv͡9TB?,;OA޶,`HCIEK/Tkq IRFRH*Zz^kߒ~ $I?<<6jFR S$׍~~|HCIEK/Tkro$InFRH*Zz^S~ $ sCI5rh#h酊{ S$-tK|HCIEK/Twb~$Crh#Fm$-P˻nN?Izħ9͡9TB}7^~$[=>xhm$ȡ*3s$MwD|HCIEK/Tgr履$In~yCsh#Fm$-PqѩH?IzFRH*Zz>ã7$Iwe783FRH*Zz9]7$Inx“3FRH*Zzwܘ~$YϋsCI5rh#h酊'!IR^<9T#6^Ǧ$Inw9Ρ9TBM'!IR[yS|HCIEK/T?~$<9T#6^QK? Iztȡ9TBn>I? Izg:FRH*Zz",$Iuӿ:<>x 6jFR 4B^7<HCIEK/TtR|p6jFR l}[yH,>CI5rh#h酊6{C^mntFRH*ZzMxUyHG~G|p/6jFR mI?Izgg:rh#Fm$-PFC7O3{9T#6^xh}[yHfyS|p/6jFR X8Gw$In9rh#Fm$-P\~"$<36FR oׯK?IztHCIEK/T<ɻ8D$I}ӟ8T'6^xx7|H8T'6^xxW|OHם8T'6^؅8L$Iu;?8T%6^ص>~&$HCIEK/Tcg$IotS3`9T#6^ص{I?Izg:sh#Fm$-Pk3~%L$I}Ρ9TBŮ {RH<>֝CI5rh#h酊-8knH?Id7?֘CI5rh#h酊-.wޔ~*$+'>֙CI5rh#h酊_^HHCIEK/Tl}~*${tuFRH*Zzbkg=7T$I}ΉtuFRH*Zzbk`Hw}*>֙CI5rh#h酊-:kn1O?Ir {T~)6jFR [ߦ$Iot3`]9T#6^غߚ~.$g|+6jFR [7}!"IR]ur|+6jFR [7>E޷LXWm$ȡ*nxE7vȡ9TBn8n6N?Iz:rh#Fm$-P{HHuHCIEK/TGޔ~2$%g::rh#Fm$-P{&YHx{|#6jFR gƟO?Iz򋟎tuFRH*Zzb z\HD|s|6jFR icGߝ~6$k]~6jFR oqg#IR{nHCIEK/TկM?Iz_ơ9TBg#IR[vM|6jFR o~6$ܹ|6jFR ooM?IhxܿuuFRH*Zzb#IR3`8T#6^3O]~:$g::qh#Fm$-PgW*t$I}ġ9TBŞ#IR[67uuFRH*Zzb _##IR _=.HCIEK/TCuEHƧR~ 6jFR {nq #IRK3`]8T#6^skL?Iz3`]8T#6^swo$I¡9TBŞG&::ph#Fm$-PG~GHDS9TB^-Gw$Iorџ:ph#Fm$-Pw7_~B$ΈtuFRH*ZzbLxe Iw9TB$-ou9T#6^;~B$5u9Gإz IDATT#6^KM-g$IRwsqm$ȡ*K?#Izg:@HCIEK/TGOK?#Iz⶿t9T#6^{,$IIyW:@HCIEK/TѩH?#Ihxܓsem$ȡ*Ͽ=$Ij[[|̡9TB6-OI7LhCI5rh#h酊1S$26jFR cW$Io:6/>ZFRH*Zzb{z^)IDcrh#Fm$-P=S$g>'>ZFRH*Zzbܿs$sQm$ȡ*sK?'IzK3Um$ȡ*SI޷|7>ZFRH*ZzbLs$G?>>ZFRH*Zzb^$IRxv|ȡ9TB ]\$Io#sEm$ȡ*OJ7LhCI5rh#h酊5-'%IR[mnu8T#6^^,$Ij˿;>ZFRH*Zzb{NyzIID~9>ZFRH*Zzb{ tIIDK_qh#Fm$-PQ`I$o(>ZFRH*Zzbͯ?/$I}Ǝ\hCI5rh#h酊7}g%IR \hCI5rh#h酊7~J?+Ih-qh#Fm$-P%I76jFR l;OK76jFR eo8$I}6jFR eLTiID#ph#Fm$-PQ-~Z$5Mph#Fm$-PQ'$IM4}! 6jFR _M%IR_^~4¡9TBE9O_~^$?ph#Fm$-PQK&:@ HCIEK/T3~H?/Ih-ph#Fm$-PQJ?/Ihza6jFR <$oxg~49TBEY:$I}Ǝ\;6jFR eͮ:9$IjQ}FRH*Zz9~b$5_ush#Fm$-PQ'$IM4ewm$ȡ* ۹ͧg&IR=sm$ȡ*[vMI/v:@9T#6^(ovg&IR \36jFR 3$g<;>̡9TBEy~f$5/u>sh#Fm$-PQn>M?5IzKsHCIEK/TԱS$M:@_9T#6^cvkOM&Wm$ȡ*ꘜS$g=7>ʡ9TBE~j$5W:@_9T#6^d]7$IosHCIEK/TԳs$FAu>rh#Fm$-PQפ$IM4ȡ9TBE=8$IjOu>rh#Fm$-PQn>M?9Iz֫sHCIEK/TԵ$'_9`Muqh#Fm$-PQפ$IM4<7m$ȡ*ꚜ$7m$ȡ*''IRͮ~m|CI5rh#h酊vuiIh~CI5rh#h酊^~v$żu'm$ȡ*}$F'm$ȡ*N&:@8T#6^oH?;IhsOHCIEK/T_M6OO޷\6jFR @ID}FRH*Zz"cz'IRN}F|CI5rh#h酊[~5$Ij;s/HCIEK/Td ~|IDϋuph#Fm$-P[J??Izrl6jFR 9O'$IjQu>ph#Fm$-P3'IRO/m$ȡ*rO&\6jFR 9#~~$5KsHCIEK/Tϧ$Io:6\Xum$ȡ*ן~$5U?Ρ9TBE'(IR~~|:6jFR YS~$5CuUFRH*Zz"kpOP&ZvM|:6jFR y/~: %Iyy#s`9T#6^ț}3$F'=5>VCI5rh#h酊Ʌ~$5?uUFRH*Zz"oL?CIh7:*sh#Fm$-P78nL?EIzs`9T#6^X ۯO?EIr ^HCIEK/TهOM?EIht:rh#Fm$-P&0%Ij{uUFRH*Zzb5 O|J)JDO=>VCI5rh#h酊sQ޷\XQm$ȡ*V3L?GIhpcs`9T#6^X+^~$5_uUFRH*Zzbuzn9JDȡ9TBs$\XEm$ȡ*VƎn9+$%IayWg;qh#Fm$-PZ|wIJD0>VCI5rh#h酊2')IRM\X5m$ȡ*VM~$5Ss`8T#6^X-}kIJD?ơ9TBY~$-$>VCI5rh#h酊3Yg)IR^SJHCIEK/TɅ~$5=:*qh#Fm$-PzF$ןġ9TB]$Io9B#>VCI5rh#h酊մ)IR _]*HCIEK/T~$5g:ph#Fm$-P& 4%Ije:ph#Fm$-P`iJD[uUFRH*ZzbE􈮛S7w;vFRH*Zzbu)IR O|J|6jFR kW$IM49 HCIEK/TN?OIh7:*ph#Fm$-P/$w9TB -_H?QIr ^O ̡9TBj'*IRFRH*ZzbM/>8D%Ij{fjz9T#6^XmS~$5w:@CI5rh#h酊68[OT&Z67v$6jFR oyMg*IR ~||$9T#6^X}~$5_u$6jFR orT&^y\|$9T#6^X}~$5֫s ɡ9TBE]$Io1|]~8T#6^mפ$IM4z͏:@CI5rh#h酊~}*IRM.\Hqh#Fm$-P㳟~$5o)m$ȡ*a~$5rFRH*Zz'ܯ[N~$5g;@CI5rh#h酊U&:@CI5rh#h酊s$W2>HCIEK/T_J?WIhqUFRH*Zz?G>6\%Ijjsh#Fm$-P/M?YIh?uHCIEK/T'+IR\͡9TBE^S'+IR-\͡9TBE {T-g+IR lɡ9TBE,n>l%Ij59T#6^5oH?[Ihz1PCI5rh#h酊wV&Z|PCI5rh#h酊$n்vZHCIEK/TA0t%Ij?8T#6^ŧ/O?]Ih?uZHCIEK/TOW&}\š9TBE?xvJD˻ouZHCIEK/Tߕ~$5g;@ m$ȡ*zjcGܞ~$5gg;@m$ȡ*k~+IRM/;:>jph#Fm$-P_~$5+s6jFR 5:gW6O͝g;@im$ȡ*ko2%Ij?9T#6^7$IM4y:@im$ȡ*m7$IM4:@im$ȡ*mr OX&Zn67vg;@Im$ȡ*mxSOXfPCI5rh#h酊۹g,IRz^~FRH*Zz\~ƒ$5C':@Im$ȡ*ozg,IR->\(ɡ9TBEg,IR-8T#6^+'%Ij~6>Jqh#Fm$-PрrS$8T#6^hw$IM4\(š9TBE~ʒ$d<PCI5rh#h酊6,IR3 Ol(9TBE/[.Y&l(9TBE;w~2%IjGOuHCIEK/Tc7$IMgs6jFR 혜,IR3 xL|l76jFR GYflnm$ȡ*󀮛OOZ&^~l~l36jFR mY|C'-IR-n*>CI5rh#h酊LxUIKFY78`;9T#6^h_K?iIiڟvFRH*Zz-ã~Ғ$57>CI5rh#h酊l;Z&_~~l#6jFR xaYKD]ƾ]HCIEK/TgCZf]HCIEK/Tgt3Zf7`8T#6^hoI?kIiv`8T#6^hO$IM\.m$ȡ*4i-IR3 xL|l6jFR m\Ӗ$Ƨ?+>CI5rh#h酊6NzjiKL+^9TBEvuiyKD~8?CI5rh#h酊v-n:%Ijl[m$ȡ*5 -IR3Nyz|-6jFR $8>CI5rh#h酊v yByKLOU|-6jFR  -Gw$Im4w;wFRH*Zzm/J?qIixҏg;ph#Fm$-PѶ%$I4yg;ph#Fm$-PѶ>%Ijug;ph#Fm$-PѶN?qIi97>CI5rh#h酊-9%Ij+E|)6jFR }3$V|)6jFR \3$f~c|)6jFR 3$HCIEK/Tt|~$5;ph#Fm$-P^~$5_v=FRH*Zzb=>xBKL+v=FRH*Zzb=z^KL~$>CI5rh#h酊0< .IR;-ˡ9TBŚط[~$5g;nrh#Fm$-P>7^~$5җg;rh#Fm$-P>~$5ӗg;rh#Fm$-P>Fos$nG;ph#Fm$-P>?:%Ij~2>vCI5rh#h酊$á9TBz}$柺$>vCI5rh#h酊2E'/IR;`HCIEK/TIOM?yIjt`HCIEK/Tt|~$5[FRH*Zzb,n:%Ij vrh#Fm$-P~W~$5rnG;V8T#6^X?㳞~$5wph#Fm$-P~¡9TB-Gw$I4|6jFR i~E/IR3-G_6/>vš9TBz^rXKTFRH*Zzb=s/IRSM{a|CI5rh#h酊48/IRSͮ=3>vš9TBZ$mnwFRH*Zzb}>zZKTcǡ9TB\$f|<6jFR ktS_}hpأ\utˎ֕CI5rh#h酊5󀮛O?$5KwH;'vF7n=w: IDATknwߚs)6jFR mqIjpj|R3}]7o/וCI5rh#h酊6$IM5~;2xٷvSMsP7n9c?ozoﲮHCIEK/TYMHTk~}7:~W@-i۾?/n"[Wm$ȡ*KHT/nx+fzu]\5FRH*Zzbm;?$5ߝ_5>헺eGwuQ΋ۯ3XWm$ȡ*xa@ػw;rZ뤭RږNS;ovҷG\ԶVqtZvvN9H@0FF`8Q hD1`8p?뼞{ĖS^y>J~7$I$IO?i/;:uWM,9KSshTB%> @o?/|K$IY1^rd<6.P#z( PJjwJ]$IԀfZHl [R*i'khm^~P;E $I}T·l=l\RְgSshTB%MWnV:-|K$I]5Wx8o9rphT*zqaSZqA|$I$GżCS{ɑ_4 7KM0;& PJ{J99MM>%I$I#Sk_5tKJAjh`m^ZKvZD$I$W@n8! 6N׊qud'"OshTB%mm RJwxI$IR/IsJUi~E*t6YshTB%{M_~P+;/$IwHj/92uWku)ecu9606@mJE/Tҿ׻27& $I}lY~LY+;^#?϶9rphT*zΧ"9@d$I$YYm_u5)/k7nbm^uʏG?e$IW,8<=jQ[;)yM̡ CR McOjny$I$mk!]yl]ץT?:6Vߏ398*PIOopOj,ISxI$Ij\HGcRo͢4ظ:A7Ds9i`m^׻n~i/I$Iu8թsџލ'o;? Oe& PJzzON|W$I:U,8|W@]4X"Sc/t>WC 6@*@|33^$IƶɃR7cS4ܼ.Qйo|506@mJE/Tҳ+l~P+e45$IoY~LY+Hҿ398*PIϮDžjuτxI$IR{ѩjrW@DFF!`shTB%=~P;+)|K$IRd#}ԝl粉y{@mJE/Tҳk-yS}e$IlMZaQڥiy]Je#{{606@mJE/Ts+Ԝ$I$tHGcRo͢4ظ:~'0ƀC 6@*i{ 74vgR$I}X8+&`Tq1սynbm^ջӻvn$I=^r䶯T~5g9rphT*zWS4v>%I$iM+._4 7KF(EuW͎s98*PI۫uʏG? a$I4]qSg1fQl\RS 7 PJnne@?%I$5b^vtꮚL+Rz4#H/M̡ CR \<vz7>%I$ջba]y֯*7G!خLJ& PJQG?ჷxI$I5j_տ4ܼ.rPshTB%_% ̰L /$IƳWo=YWoG{o}ɡ CR _<:q$I4 gmpUi~E*G5}0ΚC 6@*igfyxI$IU1^rd<6.Mcߌ*҇^shTB%F?a=%I$6Z|֯|fn^R9Qtz{l`m^սOj8Us^$IR\_3ظ:^+G Ӈfﳉ9rphT*zvVkɛR3o $I9i/;:uWM,FVlshTB%/LiЋ~&P;Ϗ$IbSW/ T>q0VC 6@*iW 7Lvʩijb9/I$i7}`j->"u+;rWΉ ̡ CR z7LZ9/I$i;MZ^:[sJ~)?B@ꨘ98*PIjo3]s^$IR%}Qj2 ֯Hep  M̡ CR Zg4es^$IjZRoNݫޛ떧oEh M̡ CR &KCOj<&$IR]}`j->bolYnIi8QޗNh`m^io3}/yI$. gS`zEDo)M̡ CR ;u?oOjw9/I$cłG4Xod1?KC 6@*iwjOjixMs^$IKLݕǦڥiy]Jew?_C 6@*iw* A*}^$IfZHǤޚE۾jЍ܁ nX98*PI;wD?΅o $IRTYm_u5)ȤwqAM̡ CR o^\gl$IrT,8|W@]4X"Sq P ?C 6@*iw| Rec$IfɃR7cS4ܼ.^һvngUshTB%nS~"@mX$I#Rg1fQl\Ҡf#n+?C 6@*i/Ǣ RwzI$i7+JeGo{I;Rc :ˏI5`hY98*PI{R%)gԻn~$IR}+JeGm_z,z{{?C 6@*iO>g49/IzTqj/9rW@y w^613 PJ_9'@= xzI$Ym K6.MR*`}gghshTB%iF·zI$vɯNǤޚEiquJN W+98*PI{ZE?-gzI$NIL 0V>Γ++KџM̡ CR MOjܲ1~K$)bS{ɑԿT~Rӿ+9rphT*z7WE?֢ $IɃRk[C4ܼ.rdcrhTB%M/~:P[9zK$iQͧ2n:- }sJ^ ߉n`m^5Y/IX8k;鮚L+Rz4zIs nbm^8)ez{I$baȭp+&F_obm^mj$IzVPˏILR*ѫ#j ̡ CR o[|zkzI7P ߲u7l\R&JkO716@mJE/Tֽg$IRӎjˎNUi~E*GWBk}5M̡ CR N_8J$US1^rd<6.PdWC39rphT*zԝ~BP[o$ISkԿmG50z`?'C 6@*i_l> @m ~Y$Iǯ\[( 6N׊^؁/ M̡ CR /nXSij^$ijˎNUi~E*78᳤9rphT*z>%IFbޡ]yl]+_nlijm^}8Ojw^$){LGc~p-) T7 ͡ CR [6D?#毆zI\_ջ4ظ:^+z b9rphT*zD?#?>%IfbK~=fwd_ʩ-[6Ϥ PJ׺+:-|K$MżCS{ɑ_4 7^Çևϩ PJZg6%^$i>0:ˏI5}ԠJ0] ͡ CR M>?~;)@}uԜg$I*JeG 'l;[cd/ϲ PJZy/I[>]5Wr1798*PI3QƓZo^$5yٿWԿTn PCVϼ PJ:ASZn^>%IR }`jөsߦ-gwHi8^}h PJ^Z|M̗$I]pVj/;zW@sMJ"z_H\ljm^j= jw{I4> O%GUK+R99z+rhTB%TK+$I&Jߐ+N^_`98*PI3UҷE?'~' $)#Rg1fQl\Ҡ> ͡ CR 4S>^$)oY]5+[WgOEmjm^kbT~RPk[Ύ$/N%GUvT?PS"I\ 6@*i&uyZ+6g$I&J߰3ku)eYY98*PI3Y~RP{3k̗$I{Rk[( 6N߉^+ L댟 ͡ CR 4?'׻vn̗$IW_L קFJkя PJ0A7Y@ 7?%Inսѫ>C 6@*i~ ,Sq|I\Ss_>C 6@*i}C js߆|IzkN^` 39rphT*zf΅o~VP{|IkF 0r98*PI3]_lK4MT>vonrm^**l~ZP{V̗$I;oFgtshTB%UQOD?-M|I2ș>DMΡ CR TEǿ& $iMk_,|F796@mJE/TRN}]Fh/Iv\y"z]ӿ98*PI4*ۏG?/s_$mTψ Ρ CR TU~^P{M_ $i'C 6@*~fe>%IS 6\)?|F7=6@mJE/TRo??@#o9+|Knjz#gm39rphT*z{?D?3hrjs}@$I*ۏG0r\>C 6@*Zt3h-yS$IKS^ `$M998*PI7Tv~j~IZ^H}qqnzm^M:PzG$y_^ `$uWM PJQ9O uO~I^Hx{nzm^ѽ_g$IM{?E0:qnzm^Ki8~nn $5ޚSWIs~%|N7=6@mJE/TR~n&|KG0Z.|N7=6@mJE/TRz_:5@ctzo$ &zT,>C 6@*)W4@c )|K-ISsMϡ CR WD?7hLI $5ɃR9e9-6@mJE/TR-4Fw~IXqIÇ>á PJYǣ4g$IM}ίD0\>á PJY璿~rаzE$iu>-FR9-6@mJE/TRZ~,@t?/IR]7?zԻ9-6@mJE/TR&@F $5m^`$ GTB%宿ny(X8+|KԤ}!z9y8*PI|WF\w_&U>)zHjr IDATsZm<^ܵNg2/IRc󂭿QxWj9phT*z7T~z~*@ZcѓFS9LSrhTB%E4[$IM߉0ʩsZrhTB%EԽ4$IM{?E}In ږC 6@*)YYT@׿#i紶 PJ i)Z;$I5opߍ#FR3紶 PJj2={$Iu,0&紾82phT*z]7?@e*Nze IR]+}FV3>-6@mJE/TRTz^@ZQ# ږC 6@*)bޡ) OexM;$Iu鿊0Ztֶ98*PI }si}GwIXcFVqg PJwO{Ϳ$ձK<A7MM>-6@mJE/TRdOOg;wIXeCTn>š CR Y%) 'IT2zHl>|V98*PI X qz $IS~1zYrhTB%E‡!4{wIT0&gʡ CR ]ߋ~HHT7=`du>ZO PJxT"4NoI{$Iui5ѣFV>Tm^QhmO|rS}@ I7*ߍ0^?9rphT*zFޚS"4RܣIƽև~4z%ˡ CR 4 u_4|$i\#F{gC 6@*i*{iJ09@LԼCwIƹuG:7?>98*PI;wD?Gh',|$i}U8տYg PJz_\w_H4Mq#{Ϳk=#6@mJE/TҨ; H9Lʼn? H46zH\?絞C 6@*iT*{׽$cOy:Z̡ CR 4J sgF>x[ I8[sJV,>98*PITK~XS_ H4n NSk=36@mJE/T(չ$4VoỀ$IcA)Z#FZɡ CR 4Jǿ,~H哛Iƥ?=` <|^9rphT*zFu}$K=`n:=|^9rphT*zFޗN~Xۖ$KsرU znm^QsF?Kh^$CEOni (|^k;;C 6@*i*{iJ0i@cu.}[> IҨW # znm^Ql 5]@Q󩿈0a PJz7~ i@N}}> I(׿q #ܲ!|^k9rphT*zFߎ~h/|0|$i>q #mpZϡ CR 4KiЋ~XeHspN I(V,=`, ~m^Qm5s$b$zL PJz_<w]H4n:-zLk+3[ϡ CR 4M Rq$Z뢧4>98*PIP~0vn^ IR&Je{K;gvC 6@*ij-zmSRJlѻ$I9kףG0G9|vk9rphT*zƥrˆ :A^ IR_>#z(YshTB%K[Ύ~@Jip5{$Iٚ?On0gf.shTB%K$r:F$u'/7um^qiWrdR  $IQcFoI[Ρ CR 4N 5ӿԦd*8|7$=v`lt>98*PI㔿Iw$UY9zXi] PJd>45~ IRUuWMF[^sp֮shTB%Us^Rli/;:~?$=z~٭ˡ CR 4n &3=wI7zX~^ PJW7O:u$I3]o)#J>{9rphT*zƭi%Oӿ@mߎڭ9@mJE/T5_*~RqKwIfߌ0v^>õ{9rphT*zƱF?]ipIR clo$gv/6@mJE/T8[.4NS$sIeѣ`3\C 6@*i+Nzes$kOyHӻϡ CR 4 zf$IG*Υo 98*PIZKF?_YA8U)q cuv?6@mJE/TҸ>w/,o~.|G$io]\(S9ϡ CR 4KiЋ~=A=nT~1 cgs\{C 6@*il|;$I{Z?0>ǵg9rphT*zƹgRC?'H' &zX^9=ˡ CR 4εN/O؎$I݊_R90gR,מ PJ&KD?cT,+HnX=9`ϵ9rphT*zPڹO؁U $I^+$A/M}a<מ PJC%o~éwh Ik-z!}0|yˡ CR Tf֣؁/H7=`o^>ϵw9rphT*zR΋3~$i*YJVxֹog.6@mJE/TR]|3+/H4]9c^ ڻ98*PIuX8+~L/ $I o %Wv|~\^erphT*zۣ4w Ijvo0>ӵ9rphT*zToO؉y 6T>q8׻Ρ CR Tjv{Ϳ fֽcj 98*PIj~7Y;QOq/$Ij 6!??۵9rphT*zkD?k`z7, $IͪPvHS98*PIusD?k`WTAԤf0ٮ}ʡ CR TR* B3IR3^Fs]C 6@* 5i2)?7Hl=6J|> PJcG?m`7(|o$ջwP~*>ߵo9rphT*zX̟~(υzV?H4] PJer Z[}bZ9%|kshTB%յڥM~/|w$իWD8΅o 98*PIus~n*fsp IO;/oP;ʼn?>9rphT*zZ'?HQ7Tѣ j|ɡ CR T^TvL /$Ic~ipNes^3C 6@*Mx`|n:=|$wOY8Z\ws^3C 6@*εN' >S;$iLTn=V98*PIu|{$IYs=ijbYɡ CR Tz_\=>wwIxkR굢GWz\m^oD?s`ߗyipս_gf.6@mJE/TRsp*;OF?u`n8!~$EgZk^3C 6@* vIS԰Z.|$vłS5襩/ 98*PIMsD?u`/ 6\& %$I[3f66@mJE/TR*`Je_ѬM)Qk}C 6@*)M `#8w I҈54|1>f46@mJE/TRS^/K_ KHF=45Es_3C 6@*)dsVYGߎNP{ 98*PIMj7<MżC IRpsNoKUgf<6@mJE/TR'>OHb>)z@cٯϡ CR ԤgbE9:ϣw IRL/ ;&>59rphT*zR9P O喍ccp_ PJjZ[ύ~>ݰ0|$孿{?UC 6@*igrZKWH>'4N TMm^5E)ZOGÇoễ$Ҋ?RMS&6@mJE/TR_{$f78uUC 6@*u>̐ywc{ˡ CR Ċ 3,NY$if>Le=fZx.rhTB%5}7F?` :MM_Hfև~4ǣ 4RỀ͡ CR ԺWSfPw I 4iտmY>JshTB%5֢F?`&۩uw IҾ58O}@ PJjrÇG3h7R1;$iQW|GwUC 6@*n8!#au 1$I{^̟O߉#h11z'P9rphT*z\#?T]{$i+N~U*6Ghލ'>6@mJE/TR/1̴A/kHvW sGRJs T}m^[(c@Rq4yPsuuԜUC 6@*"o\&7$Iۯѣ. '6@mJE/TR?On(*һ}CWssɡ CR MG| ISu.axʓC 6@*IKs~5RZC:gSѓxw /6@mJE/TfBN;$g/A' ʗC 6@*IrvP᦯/ ;$>T>)zwˡ CR mfA~ệ$5WrˆlGy"MM/(_m^$}ɃRz,#Ƞwq$5C_vO ʛC 6@*IO_ e=$ ^D33(om^$=UߍHrR ?$;$ 1ؙLʼn?7(km^$=9/@CZuwI[s_^)eϡ CR gֿ kwIMs_w_ʞC 6@*IϬs[?KI C$i+\Y?(m^$=yl Y?~1m3ts`7-ij; PJs| @ჷbKwIS~q`o[C(&6@mJE/T[l>M}a>"IRq{?=Թ PJs+G@ ?|'QuʏoGl}G{V ذM-DMi&z͊zsMz6C& iRA20w]sLP_e\g=||9fv 黄rrh4 PJC7d,!}'I{ܝ=-0]By9UB%$_{l#IQﰷE[=-?rh4 PJôQg l#I?YK1dg`K(v~FNMph*{|&cI3(g/VB9UB%}G0!מFRh IDAT{[]u\(J͡ 6@*IВޗ=& 1(V옿HRm[=PUQB9UB%]zX&HËi;$5QwD ,r hCV G=& S~Y<3}O:zd\` w hCV GivQu):ݞHB7(g~,gZ`uW2Pzm&8jPIz: {ThSP-i*V>9FW=^w_kh2rh4 PJңod `BUw}E~1=V )}dhCV Mhn0{\jԏ{"I[XD Q7Mph*{i /;{\bp?,9˟+=Am!ܢCC mZe/T6A=.)0\je.huW";@7}hCV MlnQTߔ=2)CtH_F :hHJ?499UB%issXE~b5_@omMNm&8jPI.{dS(xA#IQu@Æhrh4 PJU}MH~n#mZˏ@AoNG4Y9UB%iLAg7Id1WGSHR-JI4Y9UB%i*G0m*mI-hgwv"/hCV o|y٣R㫿'3fޡ7d;`t{Mnˡ 6@*I_=:)VsoI ^bfb+n~̡ 6@*I_InX5cߗHEDUܓ= 28{&26@^$mY+ ]rptHκ>[d2`u~I̡ 6@*I[Vs=>QFT|r oD9a*~+}_hCV -lvX8n Nh#iΨ֯͞Z|wMn޵&8jPI=BS;=5}ϑ4yuxCo:'{L*9黋&76@^$my݃ޜ=BT=pkx{#i2*] ьo:7}dhCV 1̢%Gb}GRNNOFz "?hsh4 PJ5\fX;;[} NhTu#6a;?=DhCV 6Uo}*ON}$6?>`K?5hCV o|٣hۢwI _?f`FC mZe/TɟR-HV6(zG3ʵe`TYGC mZe/TbS"Fqɠ35:KO߅$mf+' 0CF>4ThCV ith̻w!IВDDyu٣ACޒh*rh4 PJgNe;hbpGzQ̨,eޣȡ 6@*I ԒDչ+{m6pͪ(v~Fn$);?dGӓhCV k=G @T 1`?{?XwUqAUFw MOm&8jPIZ*{j忊$i&zG37QUٟ?"N߅4U9UB%ia+ofX պH5TxU}MTDMph*{m|dDFDg;4uWX+GIR濋r `w^3i:sh4 PJR - fbtFwړ#Q' C̡ 6@*I48`TUwVzq^%]S4dV6M9bgQMph*{TOύ(#`\7OO߯k;b}Z63lkOߩ49UB%ן=bƨ+o[n455kVE/ `>+Mmm&8jPI=b-7gk?/}ߒe$FUo] ]Y]KSC mZe/TjlQu3(V옿{I~\s;c#?,;\Mph*{To 3tb8l<6Ԣ涉oYG_@}2=.ThCV z1Шgo?YC>٫g̻ctQ=x[?_wJ.ϡ 6@*IWVHQGE+iJ[}wcgfMph*{T&{b3cpG{=rKyHW%:49UB%6v5ؐ=n&L2p} ;OQvG xLYH49UB%F=n&tn xt,.}S}mF,FWFTe?m8{I:.{'jP}MtMph*{`??PA'ʵߊ%+o(v^8ſ_1Y_w{f+6@^$5?w@(o?}=-Qvtmzuѥ <Laʧ@^$5[w+#*{F?{4]rB}{ЛY=rs+v~Ft}U{[}OB%FCuDFt^ˡ 6@*I7f:wGyQ_pÜW~8F #݃u.{'iQ.?wU/~)z܍iG3nmkO?)2os@0#1-SC mZe/Top^̡ 6@*I -޿LmhCV =~ TFg059UB%)bFLy+/59UB%)_A$yoMph*{W= 2g-59UB%)F1LoLhCV g/Ctn{f?6@^$V ?5^ϡ 6@*I{L(m*59UB%)!oE@W6Rȡ 6@*IQËꭋb(ՎMph*{4@8 /-}Rɡ 6@*IҒpGHTjMm&8jPI,I@F=:]Rʡ 6@*ISDc hH_NTrh4 PJd54`oG}9UB%i~ЀhCV ɫuMhjTStohCV ɫf&F?vhCV lvQ_=li!rh4 PJl=WLѷM*6@^$~=`: (vnP9UB%iw0uLߓ26@^$'g;*UqO+'-dm&8jPIjG~!*GL)Iד:6@^$wy0{ΒΡ 6@*IK#QIuhCV v5m|)xR]9UB%]{0b}0ƃzy;TWm&8jPIj_Ë}0~'ՙC mZe/TW۳#EX;Mph*{Ά_={DvR9UB%;?=%љ&N;6@^$9KG :Mph*{ފOswTKKʡ 6@*InpƿdAHSbgIMhCV qQa(!Nj06@^$iиt9Mph*{ΒMzG~ۜpm&8jPIǼ;{@cמ&'ehCV $7([dDߨݽ_&'%hCV ${݃%"jOIY9UB%I?"Ԧ,!Nʡ 6@*I^1dFXxU; N̡ 6@*IkVgFXpKO{sh4 PJ~bFս/{<{ooRvm&8jPIC58_#, Ls&!6@^$![بݒ="`o>?:sܤ ȡ 6@*Iz [g/M7&'kZ¡ PW6}mxβ _ˤihph 6@g/I_$i[ݜ=Bh5Ym{4.=,Z¡ PE/V% @ ]w2iZh 6@FמXIҖ61 @K N1i[ʁ8j5JWF٣)^OFI"Q C^Nt/X /;{&~t}u4M{| Cv`IҖV|rTItqhԮ8M $mM>=Jh2JڲS Cv,}jnQ~3{02Uoa63_0"m .=}{#2{0gk4_ -3,IZF=RAϏ6_]UIIDATTx6@_$i*v~zT*3=Ş/Lqh43-IZyH`o^4_g@8=鋖$-Hsb*3`t߻)otٟ22mFd%I UwD ٣)V_NOK뒦?gepZ%I OdVUUFN㒦bןrh4쭏 sۤ/\`-.;.LoI3Pwe@ 9SK!o#T߉Β߶Yhx~ٟ4BmOp%I ⃲+bԋ~%J}7f@ 93KbSz ,iVzY' C1eo}lX]%I ]dX&33(-K]g CQC=}:_{r`BU=Q7,ixz CQwI_$=_1dY&P-JO?m~E%Iu58,ftVҬ?}ٟ6bmfUUtxA&Ix(o4{0!;ef'e@9?0Io(٣lNtW2JOp$} :Y=jH?ߩYsh(zq"&IuU,bT?{dOQIӳ?q)g~<}:ֈ4,{|4{rhLI_$zG^DUe_F+ER/`8&Vս?:;==}&^Oh+HjSU/?}MhKM_$іg_}ۻhs ?}MlUޖIRu}UİȞSh߇658dš 0~/6,}\'IM68U~ŮJT 6C`* G'IM7 `Ct]{Ժ?u9ٟ?fshLrŁo_$ՃeO`VM kC`j}?:wL_$z18߀=MaESex˟$5{d_4̛t'Fy ٟ?shLߛJR->.3e|y.o?R[OC`T/`ݽ_U 0obgHmkpdz?Jdž%;/d/ezUo]tW"Gj[nD9[͡ 0JRӍ.L^8z7m{0 S҇ӗCIjO򮫳/TMYjbœ`8xC=}I&a=pwu-yLo<#XPmW>xGtxa(I ?f_1,6MGjUsbtٟ?sh̄WGgSFIjѥg_Wye+#K?Z8fbÒGIje(UFq?CU=j)?&`~eT `T/Hm"2{ơ 0s+}& 0YFwm~WD9Ξrh̤H_&%ɆkVe^PUQ#Fj[sh̬YH_*%<&?FH78judC`ORYQ=x[H3o4R+x4ơ 0"O/HjQOfD9ʞ]m>#I;*?F9ZapΊeSjGhEg2R? 6m\t@lSjonOpAyQ7--67HhGĆmPIbŎLZ6=#q|ٟ>@*6@n<#:+JRuyiTucU}t]Ԗݞmf4O9Hz kԏaoK{R_۲|hrQ|˩$̏e\S{\4F_>ph۠ߛJR-ѕfO\WU_翷Hmhbt粿z`͚ձacVIO+-V,R ~Ew^L$6fUQd[-2QuC1(}r+Iu41 |9:KKfbg;GfSš # sۤ/-yLo:'{< Eg(,6('~(޺O`8Gk_IZ}7fXd|Yi`j9TQ .':˞KB] ?Lˣ&ҬUYQ?s`3}?G~B,I Uߋ( ʻbgH3Ւcp?;` n8-կ_%iwch$4M}?lퟓYeOUo/NfDyٟ6Lrh,b-I[b|i#hۣo#,(2imPٹ7_[;/Ԓ+v˳)Ն;Dn?Q}M' mjPn;p#i*+xkS~E[4=;UUԨ= vK_%is~#1 oY7iZm]u\x)C&1Q|pIzr=AEI_Q=pk' zm6/i鋹$=Z&{l3^!MCψ-_ ˠeGF_ K5\*{b3{ ~q sh0u}{[H涉ѕfJ`l~!C>6zG=mߎG`”C_%icK{k7 Xa1ޙn' frh0^y\Wy +WfF`TŽuRJ˟/U /?ۿQ?KC)2^rhQIԺݟ#^!ڒDwGAy+c|{UP6Spw9)_$^>(_,$t^Uo]&YU9uEw>?}2NoF~C @ 95N^o,r#i^&_H'IENDB`PNG  IHDR=2 pHYs{RkIDATxwChb#ߚT)}{_qj0i&ڻg\V[T܋D;koKX`4;{eoPלI|4gAX~?/~,Z2*[`\f3~.E &;w,TnSrHu8+8Tv-1azcvt-mz\h ) j(3v3t ے4ąϏ-4N+d>:ΐ_|9A'=w, So<3Snz nyd9^ Ng!=Jj>S(e9#޺2`@7LoNBk'AV xx%88׻£֝ s Rr.@g;- N v [pS[hqn4Q(vK-dKlx ^ў5`*9`nF@Bϋ!\ FMDbSY#j6QQhaO0qB*DlpS  BG$>JPY/Dewܽ$ -ڷ$bOoS~unc*#[8B|_#&)f** X3/3:Z6Jh\bcQ ڂ_pq}S 2u-:<7^%Έ[U,Q_VwWRB^*_נlD{B|vdis7nA]WCt$F4_tN4q'>P1ZS:ޠ49x<&>")|LyoJxVgد{d^ܦORd"8B- #B?+y9B qņS!/8G!7IgE  .8G!46.8G!td莲SE9yW7G$$Ѡ;F[jDBݱz\D^pPD@wW#!; jò/sy9BK Aw#{"٢.8G!4O]pPDR#?eEz\I]tAEz1{tWS/;ɋj{NuKhک;E5vF`u8A/4n{f B.G7&/#n*jh>K4Zh|0aΨߐG G6?D>A/4.ѝpk)`pB+Gx)H6#ڛ$=JzmY/G ;Awͳ#j;cۈ {fPh|choi A|ꄡ_35>y{S|8D{QZY9ynX;e!>Aݫ3+|0pt/03/yL/q#y2yޛNi6I%@geo펻 t6Jn2?+V D@gY/V%x Lh|jd V/Xϒ+u|-Ŀ)&qȄ^&JcLhLU2Jk%X5t&޿Ο51)R689@:nN/42P^sz9t~?;ЦL?;Ar9 !7ȅS>ݠ_V;Aw~?TChnG0 ?KZx> u ITh{$ ]Ib -^:/-?謐0;,;P [iPqݬ߁i9M=i ZCg-A@*ZB2 %wm*UBC6EM^h\aG5_:#$pB4Bܷ@/sAk7LӰ{^иؔ# vs|Ѯ#BUGu☖䷒}4L=Px[w`{,Lh-۷mh`,qܠӍ ]uXW"r]Z뇭¬aXǦ2Bӫ s[o+`[r>LT w=zm5Jp3N~H!q7X3HgOCZטmA2*4'0_F43-t6\2 $pe'TxM ȌK_o_ڠg4`TO >Mg9 ]TIQzK5dT!p~Bˣtfm ZK%CL|hf4,޿ ! ?N4B\'C;KQaգG툙,K5xF]⿁GF*'r<=ŏ%7+oAOR1xdaêU [GY@|N$7qFI~}4t'%+_>aF%z c'LHk@ۚ0)4/MF%ׄ1`dtD{7׼VЈ;irw\l泌;wڊ;NxFHI)MrJ!7QEl}/?B#e1"n㙨9'pfEr.x3#~7%HRõ}oTGO ;oa݊$MTK^?#~/gmk7D G>Р5 hP9WE/F縿b4[Fy2hO$M|^2x:e.+\=πd׊ϊ }Gx/Yߎ跳O M;Z$ie>f i#zE#0'G+E[au3?yL)~"ISݢ-gcxo`p8)1_$mPcDUf$s{ߦ߽H=10-lu0w_S?^җq>4wK$=I7Ϛ֞h35| /wI̼_kPrc4>FvyStB 5<%"W~9%.i[Y :0dhN9Q/#IzfEE##7} 8` yolҖ47-<}4o؋?#Izv6}.;p@os'f-kcp G @ο$_3ߎʋ 0 8i0724-zI o99oGH6bFC#7 LhJ9}=+v:w}^+:~0F+~"QUoP}+ޙT_/]g89H6?̐,(0 8FNbwX%[㫢#`dU'q$I_b_)0 8Gn!"TFеȫǣOH67dV`"p*[EDkf/OIW#Q ުbH6[3:ŀ v֒W0%5R뛣|`씏פH寍_ LDCD_ok#`b n<޿$'IV_10 8`C_޸+8k̼I`螻0b8~X14|(zw ORxF Ib_ ֗GkV/9IgЌޙO $}mٯ c/6I97(U>~'$I>~H30|h껳"R{ I=Qrŀ֡C/1I9񨞺/(Nvt;"IRM-{M FF|a?g~!%)b7 dUh"IRM- 8Zk翌$U,}e\}ywJz^ʁ4L7fywނ{%IRgr SwN/Iu W^}*'|*~IT=~@ 8*sg_8r3o^tH=$4ցFp05.Hmі1MTu?$IE[LB=_0r[Y n<.8`TO.?$I[_;&^ﲽ_,r>cߊb?IjXM VkjgDpR̼\_q@MCIjX>rskjetL~Hʭ.5\=$v}Kk~@m 8H[D$;w&8!O$_{#OgvLrZz|:8IU<^JT0s΀Rvbw4$=/#2Hi^tH$gmց9g}Ї_r [)VwSIAٯSLIIHʭsf- [(mIm~1`"9<!)~!>彗FkK$IV(dz_;0' 8{[$ g\+IRM^`X+'/IyhTWfGޙOÒ$__9 8k'e )bvQ>zsQ(+oeIjnf1o$$xsIQk׻$Ij_qeX>r?~ HJj11R+eοے$Z?~F3` zQ_RR3bp'chxZ;.IR;*ŀ=釾} 0~%Ib+\}O+6cehO?%;߳!&@H$[gn`p0>(VDa/)QU'`؏AJ$[8A 8s=Sߌ(j?=~`Nւ$I553?\b]O.eEحGS0IR}~ 2`qC]R-~i 8`td$dH\ȐM'd?LA'|$]~4~2`d 9Z H?%5[򽳏T(v~C$z,Uˀ>c釸f띵}+,Z _~W&I%/r̓ٯxNN?%5[QUDez <'FR JSU-b>z{e$mef` 89[pKjbGz4kE{wߟI~:p0Z2}ߟ~hKjbm|֩|(n~&IW8?5?Āҿ[R3-"w}rrfߧI;?Ā=4̋5e:^zgm&Io?Έ1`d n=5HsgXUC#^M4si~#}ЇiI="* RG[$IsW"W |#|CP} _d9QE/Ig$]뾚z1`$tYR-# l7Mk$]ޟj1 ]h-"pT_WF- ̉~&I\jYo釲[Y o;-3D{߽IfYeIտl\ze˶K$mz/&tR,'U1zjfI65eV\Va,:_a/ZΝI$mz?JւcIs_{x<Uet;9I&63?UweUr靿8 4K^#7e1ИH;>nNi$”3 MşL?%q3cx) 4nx7$y}~6u”3 `Is_ݳH;$IV S̀ݳ-4uOTatp]$i_Gۄ)fAbO?|%]/a/htՓFl;;IdJb4nxUQy h1hK$mD3zW Sʀu @irZe}3X;swjp!ٯ+yO+in\u`i؏?~'Iy[)eAʧ١CWҦ;G ;X>`"/9O;,f2"4{?6IUFJj՝o hU^ΨOe0ѪbWJme."45釫9򑛲 M$=wK~U0E 8]op1L~/(IZwݓ!51vH?X%_3%SWE%I?\e&"ԮwѮ_ Jõ2̼{BIVWSĀuNU <}\TOwg53/b~E0% 8]1tOJ~j]o+vCUs?q1|Gjxٯ*ZCUҺo,I;$W~50% 8UUҺ+v<}LV9wg_"0V/H?P%1#xժ;XDIR>0VJ?P%pe \y@]$E=o_ L jջlU9C0xC?LSi{̟fԪ{UU#Qy0hSz4^~(I\gԪJ?P%}1c@ψ̼;FI:j)aA:i*/>ߥ1JҴ}ٯjEG#HU(v{k]$Mc~ 0% 8UTi+:>M4JE*v}s+)aAޝ~JS̼#$5M1VŊw4;30SQGIޒ}3% 8UkҴ]v11JEG?S€Zv~c*Me볏&>)ISR۲}j-{u*Mc+~U'G"%i*v{ϔ0V%ۤҴ=ُ>Ѐ_KiǏeL jZU]UGhH~/)IM1VȐ]~UQ#4pje!5Wُ<`pq4pje!5S_(ُ<{')%iR3)ʀCj۳w QU<WJfAS 8To#`pW+%i3)ʀCΑ#?HIˀpP+bz$1FH(v6R&)bA 8N~4;LI 8h2wgo`u{LI 8h22~V=u_%iN2)ʀCnWd?_g$M@4ŀZpHs[ُ50.2_{MI 8h2Qk`|+Z 6Kߔq΀pP+iZUߞHcw8%i3)ʀC8׊bsJҸfAS 8uHDUe?tb]$k4ŀZpHVQ^(syJ8fAS 8i :01&DQ{OI 8h26!Osnw4npje!m\WF}ُ00iayO$S4ŀZpH#_`B_߃JҸdAS 8uGpS).T%bA 8 Xꨞ~8&\}*]ޘ~'*IM1V҆5MqȀpP+i;ُ,0e:d?z~8 (bA 84m o?#]c% 8h24It IDAT=ُ@3(v{K$5M1Voُ@c7+I dAS 8Ef?nͪhYI;bA 84 a?qhL3)ʀC̼u~sJRpjeI{§3TcFkTW4ŀZph+n՚3t?wTW4ŀZphsG `$TG$Mh4ŀZphRk~FF?wL:2)ʀC̼(-v9W8bA 84uG `$ >4W:bA 84i;,5d?Z*r%i.3)ʀCVeُH\I 8h2$UA'yV$U4ŀZph|R#0Goւu%i.2)ʀCRd?NcOەȀpP+MD 6'Rbx%i3)ʀCPd?Jc;^I 8h2иWmTُx귣Mw)pjeqُX\u`]$mJ4ŀZphkrrL󕤍̀pP+s~&|%ic3)ʀCZg?>{~%ic2)ʀCc(*([OɿȀpP+c"H?~,IM1VmُD0X60bA 84n>hC~=.X6$bA 84N;*ُ D+2Z3%i}3)ʀCTُ Tw’pjeqmn#0GnaIZ 8h2и4`tdݰ$O4ŀZphjsULj]Z;bIz 8h284G`*uO;bIz 8h2Ш97Uy Z_~W,IϗM1VfEy7;%y2)ʀC\?~D^U<ŒKseAS 8FEُkܙ{cIz 8h2Ш=<ŎۦKҺ2)ʀC#-Zug_^}x+m/btO_"wgGXJ 8h2\Jqv/#'Ct_Hj8sGwu_"*#V5gJ 8h2\75cꮉKcp嗢wʧj,.b+ftbTO?Q` S~e%MV4ŀZph.+v}sD9X0y^/?}њ}Vs_w_W:!Wo4Ypjel<~;+/EFODӿي寙Ͼ}|O$#sȯW49pjeeQuVgHV;}5z}6\n]UU{= ӿJ 8h2\0e*ʇo{=;>{ƬE/7/~1'Dа>N*i"2)ʀCs(= @#ٞ=X_rfJ*i22)ʀCsQ簏eIze <_0PK_c,|=b~C9b4pjehx)eJDҿkJsό9aSZ 7%4ŀZphS+v{ T1W>v[/5:$Z^Sz]35ʇ~t "eۥϔ4pjeMNc6TUFU;o_Xf?g?Ul9RxgAS 86E/h(7G_]Rf" T=u_nRfAS 86o~o+]~ o99GQo]Q+w*iy@wGIM1VW}9 0.)b٫ӿJcFժ;_ap%e4ŀZphc*2L{N^Xy?Wf?|a?]ޘ}QeAS 86.n n86:Zf&𞋳r/bA 8̋۲?S|q҄91~ZZ+bA 8uP`Z1A/> DTei0eBIM1VHժ;wQ,.;E{ϟE4|+bA 8!K_/?eGZY=I?_}AQ0u:rwAIM1Vڐz|:# 0_gW3;hf^tQ>zs05Z@IcM1Vڐlz蝷0Mn'i#?9ժW%E4ŀZph}k+*!'|*Z _N;_j?}LI 8h26b+(:|/d4;*( Dګ$~4ŀZphZҨ:?ccx9Ij˳ߥߓ4pjei}*|=} fGx,4(#7UCI/M1VZ+/|f{ӿIʯqgJUfNsGҿI 8h2 ^gpl$^/b^}RL-'4pje.S3 ![YNLD}l$l4ŀZpy[YTkˢsЇI;>Z=ҿI 8h29cQP>tmt[$q3wʧF:OFkI 8h25(@F2Yw3I_xݓ&̀pP+=WŒWD(@~ wNL63ovV>Jy$d4ŀZpWOUU n86ޒ}LWu~0V/{ˀpP+=W.iS{@I73?zgKİ} 4rpjeuUƈx4j?>;QI'}$Ο 8h2кoMUe 9,eۥK^k>F^MheAS 8UMZ W^ߝKUG%*.;ʀpP+=~XԦR$E/D]}l~1;ɀpP+=e{f,j1Q߷$i[e/]}|Շ_42pjehQX̩{sג{G]}~;M&i42)ʀC_H̝ubӿgIҦ|'+HiF#bA 8 =<# 0'wGX?3Go̼i3)ʀCkіQuHl_&Ef;":jw4Ipjed6IUDc$_d}5 8h2w\T` >4ۤ&kV>r {Q,mw3IpjeoU#OEOescTLRn?{wY~8+j=|ZmԶǢZgƩH[ǖ83ve%@ 4C8QH0e H * F !9~\Y޵U~uWם|OJ*f.}S$Izʍ!{e-n~4o˒$Ia;ˀ0*f.;.~$IO( _/,(iҿД*$IRHݳ~q 8T*èIiЉ~$IOSwA7ÔFoג$IqQ-1P 85z/J$=F\]̷xmI}Ob@ ʀCY3`ˣ$Iҏni%IkZWgRp(kֻ菣$ImkS{Ko&Y>itφo$IY?.Y7PJep4heOP$6ش"~/ix%I&ӠFߐ_x] 6pTʚGs{vJN$IԻ?Jx4$IO(oIkRCSwAd :*f\$Ij9Mw@m$IO vQj/{~ ʀCY3hmD??I]?%7@#F/I#iϥ=X~@,ʀCY3h}R},I$-4y7@hIԤFݿ Ro!aiMԇJep4SwD?=Ijv1h{$IҤ' 7I+MU֒o 8T*è7~z$ {w"]q$I᪝h¯BYhʀCY3h=Sw$IjpU+.`A?2$IO]{tUiSw2pTʚGtON$5#w/׻?u*$v[NX ?W`SˀC2P 8gG?;I߽={wɟqHGIkRCw%O,ʀCY3hoF?;IFBj[m׿$Iڹ-O vQj/{AtpTʚGtN~C$I lZ_-ӿ$iUe{λR藆fRp(kҿf.I5'Skn;fƕ$I3ذܘ7zI~.-r3P 85fuK$j`[$i ~ ZwA7@ʀCY3hQ/NG?9IԐ/xv}?$IQ;iuO]G0V*f(IԿ꿅>Lix-$5#ِ_<*u}wjSw3P 85c$IVU_=L?e$IoaoߒפޥHܞ7 1P 85'UǢ$IsUzy@KFm$i4~kioS3:)Y0 8T*èg&I7.G<75SG4ں>7̧E}?ȀC2P 8apqOM$ոU w(}O?z$Iʪ ?jiE;dBo&0P 85f#$Iru(k׿:DIx۷5šsSkni2P 85%IrտoobtVFJvG$Ie47ֳw5NZc}Jep_~f$ 6~_/cIV},:7̧E}ԋ?wwD IDAT 8T*èFw]$IRrFj~K$=ituiKc_ SgRp(k5) :L$ըRkwScOe$i&x4ܼfWtWZpTʚGu'&Ij=cJ]1%I?ڹ-PVZK ʀCY3਷ E?1ITnIß~0ڇh$)}aP߰x/|a#pTʚG'&IjP۩}o-3Io}`ӊ[wH<0, JepW{KR'&If#uNY) {_:5-5šԚ73bRp(k[K$zA~[]lIҏ]s[m]Swt6JepֵK$x8`6 ;"cL4Uw*뗧E}O0 8T*èHF?/I4 xdM#8L4M ڻ7z7MaRp(k9OK$p6~0ڇ=;&Ih3A'iIYk4H3PK/I'IqtKH ~eRp(k]}p$I3Xc{i4Gi3R?O)OJep#$IFw^Zs{1[{ R={j4ں>7̧E2P 85# %Il}#݄9) Ըގ4oclZz'$3&ɀC2P 8jf)J$JV 7 һ菢?% iMO 8T*è^~R$i]frfǠ$գj۷WV)oL}¿@i*fQ/뎈~R$iF/΢og;?%ivnKS|]^=Jep$IƏܕڇ?'v:+>A;cQ3۸W;$unV*fQ#KOiԏ~R$i R7.7$.@'$MG_ySkn0+ 8T*è>$I _- o=;QW=zXšZ0 8T*è>$IҔ7Ԛ#n}O,z/IkՎo{օ{{n 8T*è>F$IWuOc_~9) {z;辍iiE;$MXhʀCY3ਉ4G?'I4.|_?Bx۷,*ޥHܞO 8T*ègVS$ISK?#ؔ\UC["uNԚ7{'C2P 8ap$Ipj/? ^'}ԋSăY7̧E} ÿG?JepG?%I4{OOEwD|JjXUoG}4Q{S/ʀCY3ਁ{-LIkU0iUǨ6-)oL=ÿOJep̾o~F$i 57Y=+zǩTܶW\]uPj-}f8` 8T*èc/P3$ISXx::FTI3TăSw>E2 8T*èc o;7I)k~ 40aDݷ1 6Huÿgq 8T*ècU$I45ʟQ`"Io9URtAo% )ww߻L ʀCY3m_$IҔ5xLTܶW\]uPj-?{0 8T*èc{O$ISۇ?'FI_2U=ckRNe/ʀCY3mM'D?!I4E. d1g{]G[FmLM+Ro!Ԛ#{ 0 8T*èc$IҔ4K7>~4KGi}Kn^WW'ʀCY3a=+ Iih`pTʚ~~$IS %PZ,ճ(oIkRCw*}pTʚf$IUR=@S_(fj4ں>7̧Sg1pTʚlj*Hs]Q:+>a/XiϦKRo>&ŀC2P 8fSwͿ~:$)]?5O]E$K٠Fߐ_x>5^r2P 85߰8Hz?&p;?ƣ4޾% 7I+MU֒|dRp(kiˣ$I l]xA75jTmiu}oOݵR{D3P 85T=`ӑ$I.|_=dx?,Uit4ش"{Oj/? 42P 85>F$6~~e/HUk{Ǵ v*NKuSkn?_C2P 8fO6Hv{ѮP%LQ4Ի?)Z9U*f1{l$IRPGkVܖF[ק](=? @pTʚsM$IA?L_ҠWuMJ/g#$@pTʚG?IP^j[]V x4鴅_uYy`ji 8T*èc}y$IA7,E`&V okթsz;)aRp(k{;$IJ#_~Ooՠj4ں>7̧EòC2P 8fK'#IlZ~~~Gfx}u\wD> 5w̚1/KUOrMcaoߒפޥHܞoJep̖{$I*p˅7̪3\SP_WJ%LJep̎K$I*\go!0Mㇿqca>u.J#_΀C2P 8fGD?ITo A`uz{G2Uv}`ӊ[w_2o 8T*ècv?"I ;7hezi}Kn^z~`Xcnt0P 851"I Vx Aǿ:A']OZ79Mdw2P 851~"I ֿP'kDTNm]Sw>EbRp(k3b~ߔF"IJ5 P'Ko|Uog}4~yoRſ fJep̆Ή~*$` ?zA|x4ܼ&84uNycjʀCY3 T$IR9Z#!U;U(W}4uWSO¿4Jep̆~*$Pw,˥sگTU3_},:7̧E}¿4Jep̆G?ITPwï~:#O}`ӊ[wH<0kJep̆_~*$пi}+St? 4'SΉZ bRp(k3`~)OE$hx˙4eSQs[m]W}4uWZKSeRp(kӯs룟$I*T7ÞIM>Fw_Sw>_ʀCY3~ HU~3=IzImVݷ1 6HuԖJepL??UfԿcw4ܞii{ o:ma9ux}ʀCY3~;/~&$)w8}yM=i֪vnKw*wH*f1ƏL$IRFw]~s@|֪Sw>'icRp(kSn3S$I\ߏ;:O o=ָ;}Y`Rp(kӭs$I]Z=+vN`U) {>h0WP*f1G?I 9VLP_{nPg*f1݆D$IRƪcdح}R}}iGo!Ԛ# 4JepLD$IRƆ7*_(oIkRCSwAƘ0 8T*èc[$uW~ogj miu}oP=??pTʚq%IR}Zo|y1P 85oF?I-gP*f1zi$I{C2P 8`1C$jIÞ~o@pTʚm,yHL5. 8T*ècz<$IRzIuaRp(kSj)C$ ʀCY3N_4$IR~k@pTʚt[OC$eaqubRp(kөwɟF? Ii~k@pTʚt\,iH URkԉJepLW?4$IRw\~g@pTʚt?pcӐ$I] ʀCY3NU!I2HFP7*f1}ڇ=;YH U~g@pTʚg!I24iUudRp(kӧ{λ$IPo!wԑJepLg?,$IRǿ::2P 853tB$Iڹ-2P 853ں>YH 7ʀC2P 8[$Ip+ 1 8T*ècTG$IpS~92P 85)t'!I&\"g@MpTʚt'!I&ko 3ʀCY3.G? I4_<*:3P 85һOB$My 1 8T*èc7,~$iµMufRp(kexOB$MXj~c@pTʚt}sOB$M= ;ʀCY3.[$I`DŽPw*f1]ގ'!I&XPw*f1=ڇ?'9H OPw*f1=:'\s$IlN=o ;ʀCY33$Io%&0P 85ѻ$I`[/ 8T*ècz?A$M / 8T*ècz 6$IC2P 8ֵA$M ?~_@pTʚ}us$Ij4H} hʀCY3[$IPw*f1=$IP-o h ʀCY3TUA$M/! 8T*èc:}ES$Iwɟ*f1:jS$I€C2P 8CwD?I4:m}MaRp(ka׏Y$I5i94Jepīv|;HI44JepKV3$Ij/&2P 85`D?I4Ə[@pTʚG/~$iB}SmMdRp(kǿ& H 5ȀC2P 8?LN' I&D*farگG?I47~[@pTʚGE?I4N- 8T*è#VwG?I4_<*&2P 85XuD?I4D*fO@$M - 8T*è#֮#IQD*fkp' I&TD*fkpqO@$M - 8T*è#˧F?I4g3&2P 85X[ώ~$iBuW~[mKm IDAT@pTʚGѝD?I4 - 8T*è#+$IPS~9&2P 85X{~$iBuN|]mMdRp(k$I҄Oo h"ʀCY35' I&TgτD*fk' I&Ԯ}[@pTʚG{$IP^~[@pTʚG$IPc_~[@pTʚGX$I}Ko h"ʀCY3' I&T{4JepJU$I҄jȀC2P 8-//I&X{ h ʀCY3>_~I4*aRp(kqGd_$Ma/ 8T*è#NF%IkȀC2P 8ⴏ{e_$M0BbpTʚI4˞~_@n*fArE%IkȀC2P 8?HN/$I`D*fAr$i~i}MdRp(k$/$I`c_~_@pTʚGi$I} h"ʀCY3=_~I4:m}MdRp(kqg/$I`?~_@pTʚGE%I<0&2P 8585$Is h"ʀCY3](/I&X_ / 8T*è#$IsꯆD*f{;$iu?4Jep/$I`ݳ~_@pTʚGIUwD*fǀCz;4Jept%IR}]ȀC2P 8pHT?~_@pTʚG9$I~_@pTʚGIUꏅD*fǀCz54Jep/$I` / 8T*è#$IjpI4Jep/$I`[ / 8T*è#NwD%Ivn}MdRp(kqk~'/I&K h"ʀCY3=_~I4Fl/ 8T*è#NߊK 6M4Jep/$I`ㇿ~_@pTʚGoK V=`}MdRp(k$~#/I&٠~_@pTʚGɩoK ZwMcRp(k$/$Ipe1i 8T*è#_K >74Jep~/$Ip>ߣo hʀCY3 Yy`_$Mo hʀCY3 OG%I҄ƀC2P 8ⴏ{e_$M~c@pTʚGD%I҄]g74Jepi/{~_$MKMcRp(k$InpƀC2P 8-;/I&Ɠo hʀCY3ƣ' I&s hʀCY3' I&讫 hʀCY3Uu~$i~_@pTʚG= H V=ƀC2P 8bU+ H Vv4*fkO@$M>74Jepo$I҄k/? &1P 85Xm7G?I4:'ĀC2P 8b> H ]uPMbRp(kFw]$I҄ĀC2P 8b$ H ׻74JepvN$I1I 8T*è#ӣ$Ip떅$*fk' I&˧$*fkp' I&p˺ĀC2P 8b7G?I4Fm 1I 8T*è#VʏD?I4FMbRp(k( H Wv$*fw$IPk3 h ʀCY3;$IPW*f_G?IΩ~g@SpTʚG~3 H u~GMaRp(k&'R$I]w4JepD6 H XMaRp(k~$)C[~g@SpTʚGG?I*flnƣg I& hʀCY3Wu~$i~c@SpTʚGj@$MhMaRp(k $IҤZ_M`Rp(kg I2>ew4JepsM3$I|*fot%@$e{*fo@$e?*foOD?Iu hʀCY30 $IR_9+&0P 85x~8H :&0P 85x8H 3&0P 85xs~7H Uw4Jepg I2>9ԝJepg I2YԝJepkg I2=ԝJepkg I2ջ}ԝJepL=SOA$eGo 9ʀCY3U I24wԝJepL{$I ;ʀCY3mD?I7Pw*f1Fw>)H U;3 8T*èc: Ir4o 3ʀCY3O~ $)S_~k@pTʚt\$)HLuN[̀C2P 8C3$IRz^ufRp(kӡwD?I 5 8T*èc:t I25[̀C2P 8C瓿$IRF[ׇPg*f1ǿ:)HL-:3P 85>'$IT~k@pTʚH~s$Ij[ʀC2P 8GăA$es/PW*f1=$IRkPW*f1=Fw>9HL/PueRp(kcx I25[ʀC2P 8㢟$I5 8T*èczHs$IkSueRp(kӣ$ITs[ueRp(kӣ{oG?IjZPG*f1=:'!9HMudRp(kӣ%A܉w]IHRVܨVT.:HU,Qkk{@ MY @!;YH!"$$BB%/eNfyxV$$IRP[/-5 8B3hg~$)}wGʀCpҷW? I`'7ʀCp7T? I]?S~o@p(+f.SIHFǾ1PV ̀]F'!I72Ph2<窟$I lz2Ph28$I l3 ee 8ZfnM\T? I ee 8g9YHfm.2PhJ682Ph3B$6:W ee 8gv B$6>2Ph3g!I||S}b 8GLg!I]st}b 8G?GB$6{ĀCYp(4kB$r{}b 8G g!I"[._~s@_p(+fBi!IʀCp;$I lt܋ ee 8iqUOC$69 ee 8iӪ$I lv2Ph4]OC$6' ee 8ir$I l{€CYp(4veOC$E\6k{O}` 8G;|NӐ$I 7?>0PV ̀>iH'>0PV ̀|w$IoC=` 8G{-~$)GʀCp⫟~$)-ʀCpsW?I; ee 8kz!I΀CYp(4|$I nxϕuʀCpyH'A]g 8G{!I΀CYp(4F7ՔB3h=4e$Io3PV ̀ݖkߨ~"$)? :ee 8mk$I n'eʀCpgT?I_,9 8B3h囫$I n|+o2ee 8mr몟$I nzo2ee 8m|K$I nv7t2Ph6uD]b 8G,߮~2$)W.+9K 8B3׮~2$)xKa€CYp(4n}'#I ee 8ez$IJhT~w@Wp(+f-S^Yd$IRB0PV ̀[?HfW0PV ̀[~_$I o0PV ̀{{$I n90PV ̀{_Yl$IRBZ~w@p(+f=Wl$IRBCYp(4g$I M>wt2Ph3˪$IJhvee 8gx/V?Iee 8g'U?Irpw]` 8G7m$I3PV ̀_dӑ$I z^mg 8G7>#I΀CYp(4n|$IJhzšw2Ph4>$IJh~w2Ph4O~:$)[~63PV ̀}HFGfmf 8GwoH&缾63PV ̀fWHf]~w@p(+f]#IZ|̀CYp(4{G$e45kS~{@[p(+f]w>Hdme 8Gmڽi'$IZʀCYp(4n['$I||Sme 8G?wZ$I ͮ?2PV ̀ۦ[$IRBn,; 8B3/~B$)żY2Ph6|~B$){FʀCpt`'4rY$IRBS^Y~{@p(+f}-U?#IⷖFʀCptV?#IFʀCpt$IJhȀCYp(4H$%52Ph7:׫$IJjtsohee 8oT?#I̿*=m 8B3$I]ƀCYp(4~ziS$I o1PV ̀f:)Io5kv)=M 8B3ٯ~J$)[61PV ̀F<)IFNmb 8G? |ZS$IIM{cmb 8GOlصi$I}} IDAT2Ph$IZucmb 8G̮;9Ifoh ee 8cMI$%5i'%Irq-a 8G,'%IZ4kv)= 8B3gO~R$)?V~{@p(+f/o~R$)q/,= 8B3W$IRR[շ2Ph2<'$IJjv)2Ph=1M3V?+I7ʀCpWW?+Ir r` 8G>g%Ip(+f?sYIoT3PV ̀Fg%I]p(+f?p$II-rY 8B3%I25kv-=2Ph4%IT2PV ̀fWV$IRRJʀCpT?-Iod 8G?%I*p(+fO}iI\~{@%ee 8kyK$e\67}oU 8B3MU?/IPŀCYp(4^%I7T1PV ̀ƧyIf]~{@ee 8k_~^$))=2Ph5 M\V?1Ib֬*p(+fo{\$IRRC(=2Ph6OL$%5>Oo` 8GM/ܷIo.=2Ph6>OL$%5*p(+foÃI ̀CYp(4$IJjxÒCYp(4[~U3$IIOp(+fOY$IRR += 2Ph7k$IJjsof 8G|N3$II-,= 2Ph7x6rY$IRR~LʀCp彷T?5I~LʀCpϨ~j$)yo,= 2Pha}$IJjvod 8j🫟$IJj͛od 8jǫ$Ijlod1PV ̀cElصYN~n$)ёϩ? 2PhcOV?7I#]~{@ee 8Vê$IJjvob 8ꘜ߫$IJjqǵd1PV ̀cu&IO=[~@ee 8V`'6rY$IRRC~ ʀCp=_~r$)*= 2Phe~éON$%5|s 8B3X-o~r$)W.+= 2Phet$Ij:h6V~@4ee 8VU?9I]?S~@4ee 8V̆]xK$IIOye 8B3X=[/~v$)èCYp(43g'Irq 8B3X=^]$IRR}ǔɀCYp(43<竟$IJlxOɀCYp(4黚f>~z$)_V@ ee 8Vk$IJjzɁD2PV ̀c5ͮ~oӓ$IIoHʀCpɇ_[$IRRfmîD1PV ̀c5'Ib 8jY.$IJj|Kb 8Zuc$IIM/~KQ 8B3X]N~~$)>^~{@ee 8V7T??Irtoa"p(+fFGF$I |Z 8B3X]}\$IRbʀCp۪$IJjz~D0PV ̀c?'(I"p(+fڦY%IRRD0PV ̀c{a$I 7ee 8V?R%IRb_\~z3PV ̀g(I~b֛2Pho:J7U~{z3PV ̀ET?CIr֛2PhOzi3$I C'ee 8P$%6:'ee 8X۰k)JU:2PV ̀^R%IRR*=`=p(+fVU%IRR]'ee 8j|ꫪ$IJl-?`p(+fVϪ~$) /)?`p(+fwlܭi(I^_ĀCYp(4(It^ŀCYp(47(IZլmإ` 8(Iee 8p󳪟$IJl|KXʀCpmܭi')I^ց2Ph<˫$IJj~ee 8xT?IIrr_av2Ph\~p(+fZy}3$II-w7kv)? 8B3`gͮ~o3$I |Zd 8;kr_V?cIT~p(+fG3$IM/;2PV ̀i$IJjOʀCp^Z%IRVqc2Ph~ʒ$)aX~ 8B3`=?_$IJlזp?ee 8X÷?)Kf[~ 8B3`]lإY~Β$)7Xa 8egW?gIr 2PV ̀2=,Io2Ph1ϯ~Β$){2Ph~9K_< 8B3`=-r$II-G6kv)?CYp(4$IJlxO` 8ir몟$IJl|0PV ̀4:W$IJlz 8B3`]MU?kIV2Ph>]%IRViV2PhU~֒$).?XmʀCpƧYK&gf 8mZ$%6f 8nc-IZ{sJ3PV ̀/~ڒ$)?X~ 8B3 T?mI.ee 80>$IJlx`up(+fA~iK\\~ 8B3 _~ޒ$)Y]ɀCYp(4?F$I ɀCYp(4L>yK&~mj2PV ̀(yKf9`5p(+fAi'.IZd 8wX%IRbR~z 8B3 c$IJlt܋V2PhD|䯫$IJlzǀCYp(4" O\$%6c 8|l\$e56kvAX)ʀCpmqU\$%6<V2PhD^qH3$IM|Mj1PV ̀h_Q%IRbk-?X-ʀCpmxOU?sI/ee 8af9K?`ep(+fAM~$)q/,?XʀCpa}$IJlz~ÀCYp(42.I|A0PV ̀ K̦fmn7CYp(4,ケKĆQ~ 8B3 $IJlr_ee 829o$IJlv1CYp(4.I[|` 8i|\̧O^$%6ozπCYp(42-zu$I}A@p(+fAٕ~$)2PhdO^$%6'πCYp(42 '/I2M 2PhڰK[%IRbwB @p(+fA>V%IRb~3PV ̀l \%IRbN,?7ee 86:^$%r{@p(+fAO~$)[ 8B3[V?}I2PhT}O_$%6;ˀCYp(4*Ly}ӗ$I-zu@p(+fAV%IRfy3 7d 8%Y̪$IJl_KʀCpPeOW?IcX~OʀCpPev{$IJl~Yd 8UƧKĖ{ 2PhTg$IJn1PV ̀2vm-՟$IJl| 2PhTO@$%61PV ̀J $IRb 8B3W$)O)Aee 848՟$IJnt܋oŀCYp(4-VHĦ_ 8B3?IKŀCYp(4M@$e67k{>? 8B3V$).Aee 8(4bV)H&缾7 8B3 _S$Io8? 8B3 f:S$I-,?ee 8hi$IRr[Q]}ʀCpϬ$IRr_Q~ʀCp ,'U$)ٕ 2Ph ?ICYp(4bz՟$Il;K IDATl> 8B3-'s$Iɍ3PV ̀_W$) 8B3M[n$$IRb[/-?>ee 8h V$)YòCYp(4d$$IRr#[~mʀCp&WIH&罱 8B3M$I 2PV ̀՟$IJnrkoˀCYp(4fY՟$IJnv݉7e 8ٻhBRjs&vj,iY̜8f.ᢄ1rR؈\@4 QKP".ٿXNB|o?k=^_ɀCkbQ{PP#7$I$IF6J1 +5PXW $I$I 8(ŀ 8O~@a~H$I$i432P^O(lpD$I$IpX~@a~H$I$i432PSy$y%ujoI$I$^bAVjj]WE?o A$I$I4zpPYp{O o>=$I$IeA)deֹ (l/ $I$I 8(ŀ 8Z'Ұ~"@IU?M;D$I$Ip;PoኾA$I$I4ZpPYp rA ݰ,$I$IheA)de&׽]O(Ƶ7$I$IF+J1 +5Y~"@auow8"$I$IdA)deF7qDJg>w$I$IF&J1 +5 PXA$I$I4:pPYp7Lª A$I$I4:pPYpu/gVHSC$I$I4pPYpN{e3;D$I$IpFG PXo~H$I$i422(TuUS qY "I$IȀR 8ʀCPD?z7$I$IF#J1 +B Td"I$IgA)deQu) ֽ/I$I$5?J1 +J~.@akoI$I$5?J1 +JΏ~.@a $I$Ij~bAVW3Z_I$I$5;J1 +J^\KI$I$5;J1 +LRdC$I$I 8(ŀ 84JUd†~H$I$pPYpho>-Z+_~H$I$pPYph^OнI$I$57J1 +R^d[ C$I$I 8(ŀ 84jO?l†~H$I$pPYphԪ~eJ:w$I$IpFu~6@o C$I$I 8(ŀ 84ju.xC?F"I$IffA)deQu) 6|;D$I$-Жګ~*u,gbAVņt҆Uj;D$I$^:16MjTE15qD>̀R 8ʀC-w$I$IZ+^:kMK`4ܹ?1£3kfbAVźW37/$I$I#䑩}/'& r}z߿pPYphk~w$I$IZ+Iuǥͧj9DK332H6(ս(m8kJ%I$I>kԹ荩i2U7z;YzjfbAVժo~>@7!$I$)/L5ǦƥiumܖR]YpPYphT߼2i"I$I 6(W/NKR˪Rn}/opPYphT^0֗I$IcRgq{? SRt.x}FpFi~>@a3moI$I4Z'xG\{|oHto M332(W?ptv"I$I#SצƥiumܖR]Qӹm[jFbAV媯_ͧ!$I$M,JՋSw߲*U;6T8^jFbAV 5$I$I߫Yw\mQ('Ӹ^53J1 +r ^*NzI-"I$IBuΚcK{K IS)̀R 8ʀC\kŋ`|woI$Iƾ#SצƥiumܖR]E322Ш7|g;D$IjbQj^뗤Uڱ9A7w?pPYphv~3 }{"I$I(ZyL;.6M(GBƓ 8(ŀ 84u~g3":᷈$I$IPH5(;/OGY~+h332Ш>ҹoI$I{? wֵis[Juc5#J1 +|Rӟ~H$I\W%{~NvlNiЍ} ra皙pơ`WI$IJZyL;.6MjT||?pơ+S딗"$I$uѩ۸tGO>8)ꮫlhfbAV~SLѷ$I$Isn^8u~מp綔aCu5^4#J1 +C^ /E$I$I:Zg*u/I-RcsJNupPYph\~89~H$I\b璷MKMun 3pPYph\~es"uj#᷈$I$IӵN<:uz(z?93φL332иԻ^[D$I8"W/Q([MÝR?&[iFbAV:>9A_:;$I$[Vj 0|?pƥ֊4`oI$IxZԹRƓSu </ 1?pƩ+0N[D$I4`gͱqil]P`?gV33285'^g᷈$I$i8"W/NK|R?2BO|#ϱfdA)deq{_E?) +"$IZyL^=cjaq\kfbAVg:IA E$I$IcκRodoHuWCS pPYphX3 O#$I"V(uzֵis[,3 8(ŀ 84nU Ou-"I$Izq_PܖҰ1XЌ 8(ŀ 84no^ ;/E$I$IQ(OMՎ)?r44#J1 +cG?- H3~H$I&HՋSw߲jGTazSK32286?F?- Hu5᷈$I$-Z+Iu(OߊtߛffA)deqwO oG$I$ikԹ{7zjgOPNpƱ~Z@y~H$IشⅩ۸4 MÝR N=pƲ/Li8~^@g#$I4M,JՋSw߲*U;6T̃ƙZvX{ճ22и6| [D$IFcRgq{? |,%ܦ&zvbAV(Ajxt="I$IMuҋ~ʵǧjTO F燿i=;J1 +kݫ*y:k~H$IRXG9MK`4ܹ-Q /zVbAVg\?{D$I4(W/NKR˪=+`͟ˀR 8ʀCc۲S}:A~5$I V:KM{? d`NzI=;J1 +s~b@Np="I$IsuKSgSoDTvFL8NzvbAV7~b@e~H$IA7ydj۸4 MÝӁizVbAV:-~H$I>Xgl^4G۷4D։Gѳ22и$p /$IκRodoHu{WLL_W 8(ŀ 84O~f@M="I$ia:SoJaXc?ljQ_k 8(ŀ 84 ,W+$I4MګcumܖR=Qlj?zVbAVz 4vE="I$i|j]$JՎ) :?H΀R 8ʀC^#@ӟ+=5(&$I4zV:KM{? D8@u'̀R 8ʀCcY7= I$I$5։GΚcSo=Rz GU,̀R 8ʀC 7D?5 Pe$I5qDj^P;TtFEՋ:pPYph!qs="I$)P=JՎ~c/07N5̀R 8ʀC eHAjD$IRFgqi2U7Hqӛ ZpPYph!:Ǣ I$I$oN5Ǧƥiumwg¿ifbAVZ(O?@[ G$I$͡#R{]$ n=7 wnKF,@upJm룟h=$IC(eoO-RcsJv{L4SH̀R 8ʀC g.ZgxM"I$icκRodoHuNM̀R 8ʀC y~n@ I$I^kŋRgͱqil]PFH穊pLˏJE?9 `7$I8"W/NK|R?I__5#J1 +-9ΓijbQM"I$Go>5U;6oG0ꧾV332BO/$$I8:%sSodoHusÿkfbAVZHu/'ݰ,&$IF֊ΚcSo4غ6 wn>ԻpPYph!:UOV9&$Izq_[V#4Oy~՚pZGi8H^~H$IMYw\|jvlNߊm_53J1 +-~v@o I$IZޱVkR~"<9#\332Bw{˙7$I/L5Ǧƥiu:y-5^322Bs룟l=7$I4M,JՋSw߲jGT`,U}>fdA)de׊4D?= XK$I9C{{Ab귢OlF( 8~{ku?77$It0NzޏBTmߐ꩝4V pb/`O$$IҌ&Ls^zֵis[Ju}>/ ]B322B/7??.$InbQj^뗤Uڱ9})[?=D322Bꧢ #.$I©Yw\mL}0z pPYphAT~~@I$e^:kMkO X <qùR 8ʀC Ɥ6|D$Ic䑩}kSo4غ6 wnK]2߼2{fdA)deZeh:.$I5(W/NKR˪T؜Ҡ}PP'?Ҍ 8(ŀ 8P\4@w%$IjnǤκRoޏBi>aֻߟ43J1 +-Z'Ұ~@W%$IjF uP<ջ>Whާ=K332Bns>3ˣI$nȽr`4ܹ->OOM1ȀR 8ʀC mE?A:z]"IxU_[Vj3#ffA)de\~@o>5.$IZyL;.6MjT>9#OI:̀R 8ʀC _ 0|kw$IfWH5Ǧƥiphy \ptKu{W3uj$I{Jkp綔a5 'jFbAVZU߸6 нw$I]W%eUvlNiЉ> upz.~@ ]~H$-Z+IuǥަTmߐ'"S#>ffA)de^g[!u=;6$IZN<:uz(z Y^pPYph:%>+أsޯ&$IczBznbiU?U322xr]"I4ҽeUvlNiЉ>`^N﷚p44۷%$ITk+RKNI7TIٵNyY`̀R 8ʀCz^^WOhoF&$IMu΅z׽7U_2O?}@pPYpH9Ӧѷ$IRxG%ipis[J0TxNi3J1 +yijan?*6$I*o!^߲*U;6oGeHwbAVު)9MЛJSˏ M$Ir5:KMھ!խǣ/0'\΀R 8ʀCL}sm"I4V(uzֵ{? #@[ IDAT׾329ע#[ M$I#R{]dGLTO++}fA)de!N^~D$ ? ڱ9~;Wuu }gA)de!}n~@CD$kԹ荩i2U7z;,HI}hpPYpH߫3$~HYkŋRgͱqH4ܹ-> 8(ŀ 8ս$CM$Ih^8u/I-~JՏ>xr}fA)de!}֩/~@S :e$Izߩz )Wpz~GhpPYpHϮub߄M$Ix6|kѧ0 ~GhpPYpHnch&$iqYj[B΀R 8ʀCYuϧ&M$Ix.j᷄X2 +if>i O'$i|jߤ}Kh?7p4ϺgO;>$ISߌ>oY<2о32 /HG?O!7'$il^ 0VgA)de!_~@ST:%$IW#fhgA)de!Uh~Hw>mY>~OgA)de!eo~@ <>$IQE6, uKgA)de!WD?OA4E$~\}P;BπR 8ʀCF?QA:D$~ g 0 / # 8(ŀ 87ǣ( [ O$I7|ZgA)de!ކ~@ԻKSQ$IhW?fwwpg& > Q$IhWw>iY^wptShͧ($it[s7~32\k) ~Hѭu+`k~%32\oD3 Q$Ih>E2,WT-YbAVҁ\h޵LJ($i4|Mѧ 0K(32\kŋR* on Q$IhֽϣO`6UZvx-gA)de!=wGT&E$^ӿ =8J1 +quS{oI4z;MÝ8J1 +~O*0=oI4z >cY1Ё32i?TtS--I7}0=Œ#t 8(ŀ 8~heoQ$Ih`4 ;B΀R 8ʀC:w\\|E$POG0,o<932ާss>~HѨuˣ`z᷄ptp 4P~HѨ}kO`Wy-縵 8(Ā 8lbў_;E$DO`4u>[B΀R 8ʀC:~@ԝ')$u?7ѧ 0KӿI+Ё32gG?Y:k~H܉g 0K[B΀R 8ʀC::fhpyw$Ij~>[Y:᷄pt^n}7MMHFW=+sgA)de!ZolM]w$Ijv3D,, wn #pPYpHVh S$IR[~TJ0df[Bϙpthu>hzcijbQ"IY{OG+, n(A[bAVҡ:3>u[E$5G}Կ[Bϝpt # ;E$5'&Tf~K32Ύ~@O?~HտS%o %pPYpH^tj[E$5>SYj߇z 8(ŀ 8C 4Tg*$y rRWz 8(ŀ 85| 4P4[E$53z& %pPYpHkpEh[E$5)/>OYw?~K22fWwD?_"ISE', -eA)de!ͮ2 U?4{E$5U}Tm~K22f_#Ohy~Hf|Zi%tppPYpHop'0P[ U$IR37wԻaY-ˀR 8ʀC}O' 4T=45qD"I>~OiGE: 8(ŀ 8>5OhE!^$IMRՏ>KY}K=ʀR 8ʀCCOug 4IZC?}s>22Vu1Pu4$IsE$NyY=ˀR 8ʀC[?h'^$Iq=>fkMS 'tppPYpHs}/G?c_8^$Iq ~,f~[Bp4&LuowSjN:7$I iW`o |bAVܫ 4X? W$IR@GTO`_]O32^F?e_{E$}֫`[~On/ 1 +iJSlI^~Hu+'tpPYpH+Q{ShY$IRO>A9\{Bp4?U]t"IV{M A'tpPYpHS~@ uꏄ,$\G/`45qD=πR 8ʀC:.9 ۸4f$IejO`' 'thpPYpHԛ~@ 5f$IE\φ: 8(ŀ 8' 4\{E$wG ra=CˀR 8ʀCz7,~@o:%f$IqiG: 8(ŀ 8sޯF?iJS[$IR]Gt{Bp4M~_JVsI)/MO`:.СeA)de!o~@ rA"IoENBp46MF?ki-$)OnFܠOG0J1 +i~Oq"ITݳ1`==J1 +i[ 4\u?-$)KS׆: 8(ŀ 8zsOh N}y"I29|#7=J1 +ivyF@o [$IğD{OMCπR 8ʀC:!i#`mw$I?#?)tpPYpHZ~TJNF@{E$[C_>/9jo zbAVR>|z"I^RՋ>/9j_: 8(ŀ 8<6MD?o`ԻKSG.$iu.tMeA)de!s뢟70":5v$Isg0Go})2225yd{80ퟌ]$IҜlY`o .J1 +)_սD?q` ᷋$ICߗR}UsԻ *J1 +)_k'޵LJ.$iu}N{]bAVR'e/$iv{o9̃?~WhvpPYpHXgy_$IҬ10a: .J1 +)o]WE?s`D ra"If/pt>%9w=WhpPYpHyQћJ_$Iҡ#T`~wFH}:V($IhQ)[0Og|}9eA)de!s<0bW+$I33/uV022ս<0b߾=$I3ܺ&LIC᷅pT?Ұ~iw$IM,J'սsbAVRن9#fpE7$I^-<QpTMD?{`{~W#I`uBsπR 8ʀC*[7D?{`>;F$@ịY/4 8(ŀ 8-~Je2$-g|Y̧o ÝfA!de!71$-[}h'J1 +|k[F4$i7|G~᷍$IR dV~,P 8(ŀ 8f5oIFO3ߎ dVC22UģS_qPSo$Ijz+](i2P 8(ŀ 8U=xc`L n]~H;E C22WFiƅ!I|췢[N}y|pPYpHͫ}/Di o$IjjUO=~w(obAVR[vXw?U/N7$I }ο. R}Co; 1 + CUw]-(w=7J1 +u//8q$Ijoߨ@!CpZ,z%#]~HԔ?(S딗ʛp܆R`>oIk X@O|#PπB 8ʀCjnM_"1SG誻)[2Pʟp6K0:!Α$)gm} AT32ܲR_&131mwF#IR@ӿ XXګ ʟpeC~HTonJSCT32]璷E;Ģ[GU^-(oɀR 8ʀCjx+^ҠC$I\o@u CT&J1 +U߸6K0JS'|#IR߾=[/s"ػf!x'5FMmڦX5&zf]wML]cȚfġDc)E:Cs㺒(eux}l̕ȀpP*ѧh;#IR H\ tz?=-j2*ʀCA/>@[$IS蟸@",bA 8f?s:$ݣAƗQupPJe!5eF <|C{G.[F蟴@QupPJe!5}.3 <$go#R)'#.bA 8xT >@ O{_ϋ] IDATGy)Q?*bA 84XoI &QpPJe!5>@ˍ_oIٿU bA 85td^$iSe4Q/''P^-1}3*ʀCj^}:񍹿,#IS5uyL&+ (&bA 8dT 7D# #Iғ4@GK He#@:"$IXKvJ}7FjjxG+ ̀pP*|C(೿$ueFjlWGWU1TRÛYG>%@)'C78)y>WWU1TR+"Lsv[H_y@M9&͢ 82೿}J!IRK[sW_nQxTŀRpH-h<}Ngo"IR\r@Ew3*ʀCjG>}NW_zw I  h-GTŀRpHhx q IQ_6e|o#bA 8v씦tYqoI]׳RneO5!'+zdAU 8(Ԟ}R+zkSE"IRCY9;d_n èpPJe!W.靗ޢF5:_MaT 82Stה"$Ijx:.5:o'bA 8vseYOyOHԌG!q h Ǩ>pPJe!ѹ>+s#sOGzTl?0ņ57 -dAU 8(Ԯ^}V~ _}]-9$Ig^N߉q4c2WTŀRpH+_s}iɷ>>$հ;mGjxǿgT 82>-?dt?$IjrQ?'sW{FʀpP*}<"ON$գ4gT 82YC#$IRlϿ?4hno/bA 8v6hIyxl焿$I1 >{)M?wU1TR;}Ro%IR {SJA!GIo/bA 86oJkmc6gTŀRpHm|>'ID{IT~~1u?vG3bA 8?◣O +45S~nIe$}?G B-zgAU 8(W}j6K~U)s$i/{(;wTŀRpHoߎ>5m[sJ]*zk-6yT 82:vذ&l_JEǿ$IR=hb_̀pP*M>2l ' QQ'opܛSd-7?bA 8n48w f$Iop;S T0Q3*ʀCЯQy&~!I5k4G`2LٞT 82e'`:!I5iT?~+5#bA 8?עOV\sC"[0<41ó>R#2*ʀCP3 Rg`G&Iٿ|~T>Mپ/ pPJe!u%Gm2#I|Ԝ 82UGm6[}J^7bgW!=dAU 8(Խ}z/ޒVֆIJ~:,;gDjNTŀRpHk|ѧ`^Li+Ij[}JE}W_&R2*ʀC^C^}zw"gFݟ&\iH fFjTTŀRpH,0o{Nپ/cIR+5Gt9C!}feAU 8(F2̫U,IjbޖS0'_2}eAU 8(Ͳ^RQD yUd1֒4 VRGp_;IˀpP*U3kIRy~~WqGj[IˀpP*x (G>M/U{K3GSlXz3ۅԼ 82[ 5@/oD$V2t}#LjdTŀRpHnz%gTK;$#mGe48-&53bA 8n7D!ᆧ'ك)KE NjfTŀRpH.)SPol_Teٞ5GG`2U1T}*Q<|{/{EK̯Uѧ`;_PjnTŀRpHSPbho0I*%;%OO.f+ߕz3 RjlTŀRpHxfJ^9N>M$i);W`/7-fgAU 8(&7}*7$ms 6MFgAU 8('-2eKw I68wRw)VĢTj~TŀRpHkx_IQdg?M&I[Ps䚣S*3 MF̄ 82(~@ow$miME 0/^R3*ʀC?◢O@sSfDyU~Q7XjGTŀRpHzlڛ@{ Ii|ف)M'`^ڑU1T>K*/K;$uH"+ڑU1T[vS*Pפ~.&{43PٷNKɀpP*I?ߧ Ê4⟧̂𷚤n '7h\hG^jOTŀRpHцg}$4t効b5&4Zh I7ZU1T~lOi܏>OT ֧YfԢ_Tl/T:UpPJe!鉚|Pk~%eK_nfK?u+O@g~8=VeAU 8('jpۣ@zshaMR.Ę S׳djWTŀRpHzm=WᯋI}ޜw^}BMnBLˀpP*IOO@s4|Y%'~ 4]ua }eAU 8('O@ޛg|0f$dqEѧ 6 4/bA 8$=UF)F?9Il{+Ɨ^S+3*ʀCS5:g i_uDy^NR-1 !<SwZU1Tls[Ks>zKvI=wIsg*'Z~o77bA 8$mω>U0_[0'ia]xnP qjgTŀRpHT}Z%_{+'iiR'9&ڛU1T6S=}Zgz73ޓ윆g|0^}:iro::bA 8$mN˗E+֚yio>IOx|~=}*mp[vjwTŀRpHڜ&\t幩ηha49)yihb]7];O΀pP*I*/J~O߶=S3*o跞ڟU1T6>Ywc[}[PjmKvNޛRQDhHwZU1T6lg4G-׭xFPjE3 ӿ&?6:U1T 'E-*RvK߅RitQg@u#bA 8$mI}ȧir˙i Ju/i|r:mL pPJe!iYuE.]ibT}g|0Mo]R>c Y;pPJe!iK](t&448-s7TuFo TpPJe!iKxqJE}xڛ:(Y+h?](5379 825MW}ؔ"O;/MóV;.4pqW_' 0:Gu*bA 8$mM}p+'-9s1Tl?c2woIu+bA 8$mUwLE` `+uiwߖҏ?Uib4?2l ')ս 82/?8fGkN:7ҍ~ceKwM3?eT,_{s_~p)'ߥkN>&7!OxߧlTŀRpHW}?pk\sL~ῥFUI-Z* iOS @M{mÙpP*I\%2UlX.O H>j [5`_,M4Q/?Zoƿa 824}'S)irÉit+uifAQz[dvU3*ʀC|4W(*6ޗ+W%2ZNKvNC! N4:irݱ)T6F+ޛo^u:bA 8$KKvJE`I% #kKAio7jG&W.HCJ3dAU 8(je+6ޟ{LoƗF?'3zcʖzw {O/L_'- P]0&~:MW8 ]T?fV3*ʀC|5HoP;\4444sap11+E^67Wd{RyfA~Nɹ3ޔ' oW> PF'<_mZ̀pP*IrhQ/uxx\)_}5izizŏ_k߿TN)F J18ߥ 824 O@ kRoߥ 824->VG6J6pq7i3*ʀC|7h0eTh?2*ʀC|b&-ZzlTŀRpH*ˣ%c3*ʀCR > Lo;/pPJe!fK÷G8~$bA 8$OF8QҏfAU 8(ɔ3<~¿=KOU1TlrgyPץ,=QTŀRpH*}oYz 82Tv=WF:to,bA 8$D:[ ,=UTŀRpH*;{[5KOU1ThtL`+Loz7fiSpPJe!}_d}BYTTŀRpHG<@nel}YTTŀRpHᯏ>ylї6۲9pPJe!ʦw^} dAU 8(*'g0dofAU 8(J[0}x*aoffAU 8(-W-Yڒ 82TuIiԋ><|:_GK$bA 8$E4|oҖfAU 8(:>sH IDATUbi2*ʀCRto} :mp;ÿKےU1TsI[RofoҶdAU 8(:4sI?X 82TU>>R<*mX 82T&}:emX 82TG!$tF[sai>2*ʀCRyIY9&,WTŀRpHS0,^{ e{<34_pPJe!V,HڛO#@1bA 8$խY>UlXz?-[4pPJe!v-)VGGV-hw`i3*ʀCR-<N.4pPJe!e{x*O$@ 22*ʀCR]_v`h;Ro~22*ʀCR]˖((LʀpP*Iun$@}?mW*+bA 8$չRQDJF_ÿJefAU 8(7O%@ckoN¿JefAU 8(?ѧIw^ 82Ԅ}.' u"bA 8$51}.gp;ÿJUdAU 8(4'1צ̂oRpPJe!) {sh %TUTŀRpHjRӻ}6jo[j\ 82Ԥ'-l +UU1TV~ѧ9;;TuTŀRpHjZ}:)!+UU1T̂wCGÕ2*ʀCR P/^RDTŀRpHjd3ۥO(@m/ZV ʀpP*IMm}BjMG΀pP*Im”?3 nJpPJe! H5/V̀pP*InxS fpʻJpPJe! Wѧ D~7 ;U1TߒR=rc~=T 82ԆF:TjrfdAU 8(VxT<*T#6+$bA 8$>_yX7YNpPJe!5-Z}VJU6l&+(bA 8$i>]0-V[TŀRpHjU3 R Pb]J5ˀpP*ImkpۣO+@)'T 82Ʀw\}^tՅ^fAU 8(66>' *5bA 8$ O,_~p7WpPJe!|CJE}fI_}UsTŀRpHjs[GYm2*=bA 8$ <l|ͷRooR3*ʀCRۛ|S UoR2*ʀCR/{yJ$lɍ_U1T-g);%VdAU 8(.4:i2>etWU1TãO.&J%;SU1TRO4E]48SeAU 8(.5pqxRUGU1T:Hņ5ѧ?UQfAU 8(5?P+e{<3 82'-? n*59bA 8$umE`4R3*ʀCRWڔ< V 7lKgAU 8(.7gW.;Ԇ 82岥/JiEbצޢI6dAU 8(7ѧ|GrQ-pPJe!e{EcCTQMpPJe!I?F?}(g_,.*lm:€RpHҏ|-')&*!MGpPޞ ?T'+$-7uyP}o:€Ry~A4]uaYj젟 *ѿ'0T_~P%V ">@ x7P >J;SƓO32N;F1# 8(U$թ4Gg-@~uo۔Gɧ# 8(C$չl]RaMb|!5->aA7~P% pNZ0(?aA&w\T%,HWDlΊ" kLce8O?bAG?ԄGx"+ )ug~+?bAt]z@a&58wO7P_r[ÿWJn)k@pPU mr)?ѧ1t$5l)z'ͯNjG:ƀJ+IMkt?Goj$ÿOJ4@pPqo ?Ըmn>@F4KOcA%|0w%Rm\| 8\v$!+`h.eKw (IZܟSbAF|%%MlHMQғ78ї3rӵ_IjK/L`}i6a|A%=uN>t!C^~%-gx Wjo%;bh 81GXviz7O;);%=eS}.~%M&0ǀP%e.:mx{¿Jڼǽ)dpjrۅGYZR4o6ɷO>*φfIj[~1(@^zKv >(iʖ[:bAgIjcv>`}zYwAIO彇ݟ~%u-1}q7AI]׳R1|4t1&HKR&36oъݢO<[6l~%_gZ+[Sw@I[Sau167XKR_}uo}> pP{ ?ֲ֒^SO೿OV}A pP+c%wgZct'¿I|+ 8W58ܒfsO=4澷eT# 8) ?&7}Y< N|{=I[eW6ɀZK80KR[y~*6> דu~eJqM2࠶&KR֔"@Mo]z3ۅӓuMNbAmSotIjs>PkCO^'i3̀Z]qhQVd甯9@-ȫIoVFl[>M١?: @EwF_" xIjss1@//S'ѧ08CG^Zvis0]uA-ZNֵh63l]^Z\tTE|-e'iZS\}M`p(kRoIjsKvN}7F|hGIڦƗ}J`p8 ?T6F|C¿Iڶ="3ࠑ_gEMWHEۇe Df4(Kٲa Imor/>&_{KzVw8IТis€ƚwSڸx fxJopD74(HR)M'd$m[SޓRQD_74p7:=̛MҶ_T >'0 8hQ?e.$izl|$mn9ygA+ܕzl-gv$mCwHӕ+ €֘G{$-7cD?&ʍgF ^QghV{oE.FIjrq/w3I FqVMbIjr6g{_7MgE9=N`Y9鏌$5#f hM74ʍg|>Z{rc#IM\wJC1WEoHߗIZϦԝ ph>)ёFu`LUDqO$Ϳ?vD'c:7u?>z_x!ʫNMߏI~/'cz(6IR#8*9{0N(7znLҼlHD5Ȟ&c.FHX1ubԇj0wbѽgU$ဃUDyo?LʍgF٣lp.L<<.ݚ=F`8` Ѿ#$5οI^_;0Ig1C!+S1=$5#ݗUn<#OeJ8z^鏖$5c{G< 2ֶSKҜg~~^!귧?^ԤK*C{G< 0xh]xlK|}ڜ=B`9SM?ug?dԠOZD .Is\}8{Hp/D`E&IMsDu`U}3w\V.f8Uwo'?nԔzdvFLu(V-}%io|&{|q:DFC'Ih|?ڟkIuD#F5_G?zԄj[Gy/$ͮ7F ~J]Q\yj(I^qGڟ=Rupלǒ4[΋S٣Fn?+_J(׾A/{0lh=+I]iFq?4unq0w}ù{+IѪc{f-X<8`!2Z?4vϞ j[(}_%ko>'͞H8`T?4M=wer2utn]Wp].,1b)Q䄨$ڦ=*pR[TIux!{̺_ݔ_=puD=&`l8%Rsq$JO',޽;)I?Zmy]-$pKjC _J(Թ,5(I?\w7zExI5Ǧ?44Wo;(I?f٣ƞXfՑFKdI^=X>{ƽ7Fg뇢z׉C7F鏴$ e_ʞ,;Ic\yumԝ#x8 [UE(7H%i*.yST?=XN7IXg{_۵pC:/]'?4,kOz vK3ITQW#%0wF2b IDATccyIʮxfD=?"-O_>hFvr'VڟhMKRVQ2sqe^IjlDoUQz2X8`T=rsoh]u>̂ iq+.{koo<xrDܽ2g+?8HrԽ{e5vJ{kixK?;ƨhB\t(6Ǥ +=p i6(ם23(cQ?c hn'.ɕScz?Hb4qT -{cԉQLY.{kWs5kN F=w?rS ng"*O28`1`;&-EhM4&'+@,cu^IENDB`PNG  IHDR T- pHYs{Rk IDATx10 7ݺ;xCB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 c-;˂(OPQQ *"zPxU=gJI:$71 )2$Fzd2-k^{LNəg{^B,B,B,B,B,B,B,B,B,B,'je}y?q~"eKvLXMe;k_>xyvyq}AZcv:HGozx/Oݝ7gM[ƷVxm*Xr&ѽ-) i-ڦiԾRUn!Xץm= R/_T<}wK؂Oْ樽~05ԾT4֧BDj]wP-6NN},~Sн뜔-.!i[mԾ~E*]`dEsSjtd?\҄T*7~Y}_4F}9ẋRcFك#>:5/s+ޕ 0էY JUhYߜFh,N=a^ƆW 0 [RԹ㬔nýlu)?Tj)W0:7oMMLl8fi5N:W0:7a)(UoH<н5#R4j_`'!)|S*4Lf!y)?tkw)EKGW;u* _JQ4Z|a/DA$6UjDt,K@:_EB*<"}@.ONa(Ͱ2"t[q̇$T{ @VI3ѯ$ R;O9n")|ח>ۂf`ųOW~7JMͳ?3п ,2v;qR?@,;]_#ֹͦ h~S]EҀIoN v!XuSx?i5e }gM H7Y݅`ܔ_?iy0%c7#}w485ǔNS~¿lk)E".fPFT?hlBfUʖ!.Ͷ晟 s):.#603`羋S_/eKw&Ky'B y~TvMꮹu;Nْ⿹, f,Rďo$|Ωȵl-&*ͶOKV|=GRmw{y>vp/xo4|0Ns>_.@ŔSw$|Ws!ع>R]#Q|T +6{`S}õ9[o4#u2>xKJyK*c!X0e{6&ͶoI5s>NNV I~/ԮBO?͒f[rsآe߅$I9-t!mQMf[앩x9{iLUO߉$֥ BysYˋSȵs|(n$) TI{/`3=@S[K`zlXw$Ii8G7BΔ-}q7E}is⩻R+J cbVW\7CU[΍0^Eߙ$Ay؅`/־bYC}LjբmSkb.Ni.^@yNjU?R^6M?/ͦYN,gXfj;@<_v!? 'ʹMGHeT?w-IhN.lq j]<6s` Oߓ^~Tg.gM4qFQγ}ȈovX,lQ4k:͹8cV I Ds~n2?Fnߖ8[[I~Tov|W{xhe6~T ByGHTGs`(^A%/JV>`ؘ]}ZS3\ IJѵo!}KORmAjk/=_I[+R`ݘۇ$|<!X.)6'>E/FթqG2,S OJͺyYײ^Ũ(2\Pw}iRRmVV~eK_Ũo_}0CO' [JJs\mѯuF]|0~)6Z+?9ע~Jۊ>wJPb4-}Q*+`r]SRIZ:7}V0"5ڴԼ8)A=)[SSRmZYj^TOGQ̓jBPV{EM[oTRjZ|!X`>D2[c=TRmJYj^)ug }ٲ𻨤ڔܷdT|UƷ JY)u#yʟ{YjoRKXfk\k_,+eBPT67E n+{k=X*&{yGѽk`)P'},,b_p}X*WaG*x->^,eBPϫ}gZ{U A}?R=.^~?BP5U>piW.#Kc5)u[[R6Y*廾,D||𻲔pJ?2h~ϦTtG=oNӌ0n[ʆ4  sx򶔍o~!Bp}R* y'R6Yp/0oI٢mR6dYhc>=`5T\ʆ, x \Pʖ~!Bpky u?ťlƷNg1,2[]^'Ɔ# yڟEaXp ~'!BpZ]*/z+}2eK_7? yg/-9R6YJKg/)7Iҝ`g!8"5 Z~6.evg.+7<եBpjy 軺 pޢmRoEZ冇4,晟0pz; hہO=c`ܗEݥBpkV?Kf!8o0z޻`e!85O ylҊG0we}BpkF]vwy),}_04n Ke!8dzgJe=K`m}Bp~J wz),|7Ttg( ?~BppHYu|^ !)U) WMRԝxԽ RS'ރ͋oNSTץmESRDMIOU{ysӑ}?e;l|y=^55ojyߦc}~S_/0s~Ǘ,2[_un9&.yaߘǟ3i?'~4ԾF`(~?_\Bpj% v6έyʟw._^Gzj||tގ G3[z9v0+5OT?)[my=-.zGjҴ\@#}"[c-d!859 az} G/Ʊ= lo s!X:{fpy,eAYxէGHXew L~$ReK3? 0o+e ?, wJE7zFѾry}_~;-ڦ.{ۢR`4OX+-|\#knM˖Ƒ;Z~8V~.\SsxsVԖѳf}Io?_5rpͭ?]0'Gz*e qRx3UW}ŻR/?URYh_[PЕu?|7 zM{/L,"`z"}Ky*-\0芵Syh_g*D`W9 BprL,IOߓڗ.I2Ԁd#PaP67|חƟd!8`v?EpkKߛJ _zo/A{I)e պ 3R*:{Ǚqol|QQ}ŻSgi3{U$ Aj|T*n+GRYP=wQj-.tejWEwҔ[]j\*[F_? BpsѳQ^Y'ʹ|R_NTL!P, D:FEYSwo\8w{E'e`tK_Ɔ9>xyM5r|#' +֮`Uwۢ_zT@w{R6Y !Un|,5ۨ:rS궢_+uu-),F%#|חwR6YF~0)Ծ3LoW\kwg46YV<*z0$5a~vI\H5/WFL}Ig!Ti VNJS+5{Er1C!9B0{G3\|7Y5Uj\JvѹM,#ZM*7==P3Ʊ^IC^_NG_v^~Ie!PD2QIo욲%;UҨ}W7#u?kR6GYԹ9)=GJ%d}S`?"\fBxTߎc έǥ|ğQ҈$M@Їu2/5Og?+r ѢmSY&z@ş?fT.z0T%վ/ y*%)uѳ9ҹ-6|485O2z<)Ӻdqj,6,W0z60G:l(izP 7UTQT棢5ssIX}G*X:un=.V~.>|JYVܴ&z0 2u"iߺê\w_?C%Bp>_,"/9<4\廿*=Go?IibPK>3Tn|,{),4T6G2N޳wIYm}GG0[sTdsXOE/LC=)燤Ѯ~{|T엚'<{@<;YaU'D9LQܔ-T}SGynwڟ<|HR,r#SQ>7$UMGFO?`?IiX/-ܐT옊o4~ԺR_O/'46,Y>I{0Խ?6N!Itej__>?lzu*'F4Yͳ&zJpR}݁y_?_˒ YsPch_W9!I[sѣ׈IRmNe^?}Flg$m|W'G& s<+.8)OIF4 Y<5hyV IDAT&ѻLD4fJe=6agܿoJRV,gY`tyb!Iө} bԹ[+ޝ_sU8 YVoF~S IsU/EOVFTX]Z,N?=^.I-h3,ҏD|U 4o~ʰkeܿ%I)2 PyC!<= ͍x$^_j?oI9BpkQ*{%g$ B>`dtϽROo?"(Vlfݻϋk @5@ۧ⩻?Ig!8ʍFU=5PhX冇SgiuƑ]^%IR6 YN|WEzVY IVsSՕu{4N3\$I8 iE)_@~?^u$Ie!8oTV#IׯH\w$),Q>PY?$iP|]*Ұ=suS|חo%IF0 i}#TRmg$ z0-0]oϏ%I*4*PIE4-ݩɺ<ܿ[Kͳ?$f!8=^(jRkIgUSS=OBpa>= i|T<~ӂ/w}-.Y$廿* IҖ7._xN ?$ijyecCqj_{jє/^ITvS' ,Lo~HҰսgpG=y_o?IF# )ֽ ixxa}ǬtIT,~b=5zKҰֹrӚ {u+Ij TZSJeW`zl6g$ iMesc*[ϦCW5LIZhS~;Ӿ/I^=O$YNTNI$IF0 |.TJӅ%I$il~B[}77O $IhSx1@4O/I$Iوf!81@u/I$Iوf!廾4j P)݇ $Ip/PwDߍ*u/I$Ig!5NhRr$Il|o?Eߍ*lnLg$I$e# Ծ1@et<+|K$IR6Y@ݻϋTFﷲ$I$e# T#~ PC~>|K$IR6Y@Gߏ{~$I$[(c>piܗ$IYn?}?7v $IU -8ʇ$I$eBpKߜs?}?|$IU -Ծb1@% $IU$ -wdJuN̗$I"YnCWDߑ*u/I$IYEB8#3_$Id!ƷJӌ#TB$I$U# ͔/{eֳ$IU$ T?ৢP%I$)P;2+-!|K$IRV,7S#h$IbYnoFߓF^+$I$eBp3~kչy/I$IYŲLGߓF^%^$Ie!8YKv#TB󌿊$I4V,')wdJh/I$IYŲ?}Go $IU, Ij;2@%v$IU, Ij;24S6U̗$IbYNR̿&r^$I f!87/DߓF^ȵ^$I f!8I˖EߓF^γ$I$eBp:7}Oy $IU0 I~j=`/#|K$IRV,'{d׺^$I f!8IŚ[#yg$I$eBpEߓF^䏇{I$I*$Md8^$I f!8EۤTdW?g$I$U/ 廾4 P },|K$IRV,';2@%m̗$IYN(G/I$IYP#TBh/I$IYP#n;|K$IRV,'8ע#ll$IU4 5{2+}"|K$IRV,'FߓF^y/I$IYEP?'by/I$IYEPDߓF^y/I$IYE7S%I$)hyv=`uy/I$IYEPs#oJ$IR-, uY}Oy/$IU4 uu~=`uF$IYN{ף#^$If!8_݇$IU4 u4 0G$IU4 u< 0o $IU4 u2 05{I$I*zϵ`~O>%I$)h*6 0g $IU4 }OyG$I$eBpB0^$If!8b-d$I$eBpB{I$I*z| o>%I$)`*}G|ח|I$I*#TB|I$I*g$I$eBpBŚ[P?3_$I f!8P?=3_$I f!8k8C3_$I f!8Gߑ*y|I$I*_}G晟 $IU0 uu~Z+?>%I$)`;2@%.$IU0 u8# P +|I$I*:}G |I$I*:#TB'|I$I*:7}G|I$I*:7}Gkg$I$eBpB#TB3_$I f!85Eߑ*̟$IU0 ; P E7e[}I$I*ڗ}E|s_$Ie!8KQ-s_$Ie!8rQ?$I$U- ߐs?}?q>%I$)XjWchgs_$Ie!8TFk$I$eBpB~'~ Pr$IU, 5|_2ׯ$IU, W;~ P;$IU, 1@et*|K$IRV,'/C2g $IU, vTF>%I$)X[]R/$I4V,')uc/I$IY.~ P~1|K$IRV,'h2'Aܗ$IBYNR]ch/I$IYѺx<|K$IRV,'ech_wPܗ$IBYNRѽ/I$IYΪQ%I$)Hn P)/$I4V,7Sz6~ PSw}I$I*f*7<}??D}I$I*f*X}?|+g$I$eBp3uFRl$IYngDߍ*qGg$I$eBp3un:2n P) $IU ԾryRW})|K$IRV,7Gߍ*/I$IYL3:n P)c7~I$I*fjwcJ)}2|K$IRV,7STKYlN_$IBp3}5~o $IxkV`4`$IBp uwcJi7_$IBp O}77v $Ix[ewcJ:!|K$IR6Y?<ܲ< *ILԎLڱvIwbcD3&F<&&&ުQ EAEbdeZg>g~nPν{yKU}&6mp1wcIʪ/ ?RYnF[{Gߍ%),7YCX?@j0 bIʮ>~܌}/ 5f{$eW ?RYnFkKRvM}SBps>#^,I5?@YnAy4n,IY5 5!n,IyoirQBp }5j 5 .?$^,I9P[?o{$eW,{GŒ]S}܂aKRv >&H e!}_}/syBp ZdX/Bp~+n,IE?@j i={$eW7,ax9bIʮ ?RYNCŒ]w ?RYNCŒ]kV,C:bIʮѽW,sDߋ%)2M. a,kŒeBpZ0N,IY9-3 5tL.*~;^,I=gDXNᛢŒ]+04{$eS04{$ea,ZCXk4,g@j ibIʲޯ A,}',BpZ(N,IY[3 5tM.*~+^,I5030z{$e΋ 30{$eWy4H b!8}/,zk H a!8i}',BpGqX{Gg@j h;$eYυ3wbIʲ!,g謉KRvkn ?RCX+Œ_ŨL˶,ghxbIʲ~,gz;$eYwg@j NxX3 5 u~{XlxI3 5 VRYR]Ēeiisb!8K>}',MO Y;$Y1*Ӳ@) Yj+$e[{7TSsPtE߉%)˺u H5e!8}',3|GD߉%)ˆ7>RMYwDXXwO H5e!8ݣ8N,Is ՐoaIʶAo ,br4KRND 9=xcXlp3 Ր ;1N,IY6jBp}',+4(|qKRV,|oKRu9jBpZ˟[E}',s ՌkKR {x H5c!8ÛWE߉%)F]>RXA}ĒgAn>RXxǣĒm}_>RXA砷F߇%)ۺ}0|n/KR/lH5b!8&E;$eg@ 1ޱ:N,IYV F,dpwbIʶ/ &,KRu}gH5a!8&iXs Մv$eણ@ 1*}',m H5a!8FÛWE߉%)F29jBp~.J,Is ՀuO$e[TcoF߇%)}>|ֲgeQD߉%)ˆ>R XY;$eYYSEs U ?9N,I@8 1럿k}XsĻ@8 1~/ÒmsTqc«ÒmO ,mve9D߉%)ˊwjKRv9*Bp >&>,I9@0 !>,I;?@0 y9]aIʶdžTaKÒmo ,Iz(N,IyVekTQɓ IDATdxWbIʶΗ>REYΓE{E߇%)zdHe!8O(>,I6s URYOG߇%)~)| GCw}Xmtes U,Is U<@}Xmx9*BpߣÒmEo}& B,mrЉKR?_gDuX.]F߇%)ۺyHb!~)>,Iֿ3s UBOX}XmxYs Uh7ÒmE2M. ",Ž* N,IZY0Q  dtaIʶ ",໇G߇%).",}ڿD߇%)ۆ7|=|\ N}XX_Ha!@Z;=,"N,IE U*}l|T hpqaIʶު@ a5}l\2| \@~?>,IV,IVek )+}%l{s \`}lzkH,XÒmO )GaIʶ6DBpxi}X> R XDs  0aIʶy;B0@aIʶgB0@?KRG4(| Z(>,IY/B0H$e[?)`u'F߇%)~6| Q?&Òm/)`ΡKR[eZM,H,v$e]{_ )`baIʶ )`5+ÒmK)`KR,|:=>,I6i3g@Z`Z;,"J,I> -0 `oKRN9`UGG߇%)>pF߇%)F_> 9aIʷbT?7|d!9.:_~s,H BF}l9` {x}Xmp1s - }aIʶ[@Z@9MaIʺ֮/ iXV*0>,I9a!XKR^>G߇%)ۆ7>)KR iXVD}kY`U,}FYaIʶBBF\}l럿kH BB}lrVH BB'}4>,IVt-V 3 i$e]{W4,dve9E߇%)ۺ_Y01,+ft%aIʶE{4,+>aIʶ4,+aIʷ~LK iYVL5:,IY«g@GU3,:kÒmݓ>~L ޼*>,I6W@G?o$e@G9aIʷ([; |yb!XA^}Y扅`E~?>,I;{qHB׬KR o<5|yb!XQ3>}l+irQ,HB:%>,IY  j-{vYaIʶ4,+ltaIʶ iXV;E߇%)Fw'| $hPeۇ4fuaIʺΗW,Hcf!XeK-~+>,I;_gxYVaIʶ5+@3 _$e[9By}XKg@# k’uݣ> YV䢲h=}l^? &B7~#>,I6Ns ` ^}|tʴ ` tÒu=|1.?YE}lYB&GnKR {XHcb!XKR)|17>}k `Mt[waIʺa i ,b3r؏KR]? &BFF\}l޼*|1%D߇%)ۊ2-:|9 KRֵYBF.'m,Hsd!X'.$egXsÒm i,kݢÒoŨl-n,Hs`!X3#}|wg@ i軰$e]o ́` kKR ?9|9G߇%)ۊ@Hs`!XC3>}kg@% 軰$e]k> ,YPkٳr4KRw,Hd!XSKR$|Ye_KR {e ͂`MuOHuX74 5«’uU> ,Xˢ>>,I6Y01s56$e[YSɭg@! _$e]{_ i,k{ԟD߅%)'},H3d!Xc=^}\YfBuwG߇%)ۊGn i,knx݉aIʺg~6|ޙ}YfB:_軰$e]g@ k-NY$eKg@ m}Xm4([˞> 4Y6;_KRM!zilI}락8|il KR o:#|il۔e/E߇%)ۊ2-:~Ll`C o >,IY5`:,zE]Xw?4  =}waIʺG4  Z軰$e]YBAF߇%)Z{4|-l'E߅%)Y,H[`! U;D߅%)> X6HE߅%)F\> X6Hke1KRy6BaF\}Y6Ba}럳c,Ha!0?}rV,Ha!0^}2-&|Ml%ۖe}ky0q 4cu]Xw?  ԿwaIʺDŽ  =O’uźg@ jxy]Xχ U/.,IY_ 5軰$eg@ !.,IY7Y6B:-.,IyWekI,˲E_%):~<HOb!` KR[,HOb!` KR֍Q,HOb!`?}˴lyB.*,IMd۲췢’usv?b!p;VG߅%)놷> X6\waIʻALK>,{’}>,`Iʾު@z`E߅%)7> ,30軰$e][ߣ@ԯIbky,9m`Iʾ B0W(.,IY7y,1z軰$e]yL= < .?8.,I5krQew.;3D5YfwǢ}yMewlxEOzD{]%I?hpyuZs[.Wk;U`.l[\w%Ih=TɭgTmޯzW/ګ}٬,w/d!z+II}~-|@e=w *B0#{偒$;ީ> Jk痝߶ *B0#ݣ7o$iz =>|Bh-{vomKYރKHk$=ma?C.d!b$,_xu<z_d:S( ?)y~遲M@v,3[C(I7yl(:6D5Yffj/I)g[F+o'B03-bLJR{]L mߛWUltץ?TQ=p]3)I; ԯw[*B0C~&%)7>h%ۖ^߈7& uOh3)IWtAfgڻ{MT`6$MGp_ T[k1ZW%e/EME~,sx$U?{uMSEYfj?)$6y@d!=KIʾ cxo_+\r@9 ?6A7D5Yf{KI{3jsػK#;l4*B0S/~,%IS\CL` ߫-F*?,3V'єzN<`Ueď<菔LirQKIҰWeۇ/ݕ/ؗsџ5üie!ު~.%IeYv~{LSpDt?[,3F?,-|&䤵9?zŚۢ?j8O( @:Fw]>޿/~{2kK_ NT`F\lJFòOfiOv~ATA\~p)Iz>j޿CTZTTAgS4>j޿Gng \{F?~P?/1?ZH5,1Jox݉s2*ڰ~>Ǵ={]_]W%ۆ v|c˿o|\uTY'~\qh9,)/izϟj&EVxS- P'Fw_&MT 5Vx+ PU_\v{W;{I9h?=%U>REYQ&[Im޿{Ǵ 7yU*BVFlG5l,߼T~ *z6|j Oz_'zJyS8lKe!&m8IR%yq\{ѣVR\.U 4gWQgTks~޿+-Gn2ipTQlR~v%IO{_ج<޿/~{$ֿD5YI[+IzB~*ozJd( A6mrQYtD?+e*~>Ph?g3U 5W!|6{|ᠤ:;?TQl6]TzgMf^Nǖ\Q?c'BWFw^>h{&IR ?sSEYY-0$bTv{Q|{0zI҂==p( AhtwaI7lLkٳOPළͩ,٢~%IOhp@۔_UvWï{$Ixcy=QMlQk KP[_ۅW{$ize*B-jxy3,IzR>ܼO_D驢,b]ϱ$ MzXl`<:_~s;_5_+G1ԘҲTQLccI*%|60K=R$e\OT ;eIғjWslj$5H*BiigY~,z>07^=N$kn ?SY2=𭖒4xc8F63>U 6YFòOfs;$5,ˣgIғQ"IlxTaL[wF?ϒ'5uOQ"IlpQg|0 A˲E?Ӓ'Tt֔iɶ3oѣDTa辫iIғW#~Ƨ dF6쒤jտ \qhF'TaHwiIғ*UE31"Ilj}Ƨ dFZ{B3-IH>#]FIjdS_}Ƨ dƊuD?ג'?wy|`5GIjd=Of!Ȍ Y M IDAT\K辫3W[#DYkTaԋ9%Iի_ϊZ˞OT 3>ϵ$i#Ny?$Sn*B[_m 6u|S萤FV3Og!Ȭ o;/$=Ѱlt!Iltg|8 Af.Ϸ$i#uP`zzKؐF6yU*BYϷ$i# ?9|F0=+dž$5UG,/(bKܠ[?7|Ne;Og!Ȭ6$m>#زD Ijd,_~%Iipq3-+%zdHR#g|8 Af~%I*Ӳx'$5?'BYkg\|?=*$?TqI\^T=#شΗ=*$VՀ 1UY~%Ihx2-޺, IX{g9?QeSTц g@{2z"HRc}[| AƦw}IfY1=$ :*O5a!شxc/ILÛ 럷S8?s>Մ x讋~%Ij4kfG ?SMX2VÛN~%Iw'g@Ί5EIjlC~Χdz3$mѝ \vz~YE(/&,Η~+$mo9#@[1*Tגe} H6S ˗$ik ?SX2v[ω>$IXs{& <2zHRc~A9jB럳4$m΁o =|s/ImpWT#]+}H/ v _("IXeg} Aog}H6Syty>329G$5~֧d^ X}HP \^}KR>Ո .g$i ?9|^bxף}Ijt/?SX2/:^Y IR~3&ES_hPğa!X}Y{G$i Np_}KR+5O5c!ȼ~A IB M;cǽ$5N ?SX2o}&HQ7 &\ydQ/IT3̛Ao>$Ihp3ɊG}KR>Ռ gveoG -Ttזig jyIj|~ާd^ o9+\$M &#^_kf,WU}.Hg@ .?$FWtוirQyjBy>$Iө(6Z[hEe^Kd~-fû$IկsA_xu.IoTC̻ Di4X"'zn4E>%^~ާdNA4ͺG'|n4suIj|ݣ~ާd޵}m IfÛ ltuIj|Sg?'B7UY>#$Ir^?;js>%23?Ր bpcB4W {\_>Ք wǣ I4+Zi3g@mM.*wE7Oԓ _>'$I31,_3?Ք Xs[Y!If;. unǸ$eQ ?SMY`}9$͠ou4z#\TS,>+$I3hpg@ݴ?+Ƿ$h'fB'7|%$&P'U;DޒE?SYFw_}fHfPO:yW5_ ?SY`YU2-6|~As}lKR6Κ ?B9mg$iu~oˢlIʦ?SY>c;$IixP}dKR6s?՘ nx$ixcgQ-ITtוirQٟjB;_I |Peo}TKR6 0O5g!ȂkC4ӆg@%-ٶ,ZFԒMKOԛ orQYI PA ?՜ !W}~HfX][vz^  DђU~$D>?$Ih=3JZ{,GY(/?SYۋ6<ĒzULK>GΎG$esD4'|8|T;eIʪWg!HK4U9G$eW?SXs[I,Gs ScIʮΗWB8K^ug$i8~j LDbT?'|$I,9>ǰ$ekD4F߿(|Dh譏>%)>RCXG'99m`V}JRND H a!Hу7F)Y69nW>~%)Fh A/|"ICN,X(>}JR es 5 :3X$͡m1h %I +DsXog}HP砷y9[Iʶeρ T3I r&zV{ςzd"Ic#>OKDu^> RXR ^}H˴x0/:FosxYR}HXq'ǫ$egAj A*^g$ikn/g xuǫ$e]`Y,o>c$Icw?qǪ$e_ a,ەEw]9#IcEzl0ϧ}JRލeksgDXR)k>j$Icgg \tq*I7yBJF4_+ey44_OLH d!Hv{QYEy#ICS;zVE,YLH d!H,$/+3h}JʲlBʙ:qIRx0O>>%IS_VgBj( A*}Iw`:Ga)IzUGυPTVesG4^>_decSxS>?&BJ|+$i sPlؒ>.%IOkgCj( A*{G;qVe/ue9F+뼋zbXRI)A7$}Wiɶ3)o]4$=/x e!He wZ#Is?>_w?E';Cj0 A*{GIҸ륲χhˢ>t$=)|ڼZd;$Ijx9e\>gVEIғ*Zm8DsYRi.>$IPďYǡ$i# >6|Fzv>$IP][9d^q(IHS,>}I-ga glsIR5kY1lTᛣ"I<=CsO[{GMT3|N XRy ?}I橢n7|F IR\qhH:_~sy$IǦ@*-6|Z \)In>>/R,[E3I4Y?o7ˢ;Ij1|?$5b_G9($mу7ϋ Aj{{%Ifj3aAe/M[\|`Y$),&Qf~qcR4ƶι+"IAxя ϕz5\ `3>~IZ{L ?[f.UUj3I8mj`H}IK= [D?V ?$_#ޑt!^qAu#'~<\4Z~ n3)3qAuӆx@U~6I^S?=0V*v|z9S8ƾMߋ~0Bg}!l-*u.>0q<]uJYym&#^~>I[Ŋ_JΎ~0Z&A{Tg+(I\6|*{gN zןH`u%4_T̳ 熟95?Y6sS}ɖg4(\Je7q!p X]Jvs [*՗?9?9!*>Q ɩwi5FXyEޯF)U\h` ?TdD?qצ^ ?k:G } 51;=3n3-5sKm^W HcׅE 2jGlJ՞N/i%Tw[RvyY5QP3q7.&bN>gjgdlT5~0FK?ä qrDTsI3j^zD1ӻT|A&ML˞:Rً`7_6)=2&o~0oMC7ƽ(w4[?O=*&-Ru;Q6mW V)APY]yOԗ?%<Ƣ%[NUo]FPoǟUJ 룟yR?ӤQqSy֪߮?T{\AMl字F?we7uYK ?פQE{kbvj }ڿF?6l+vx}6ߖޕ']m0&b ~|G?o֩uS5}Gw"c)m(&էE?0kJ_~I Ԣ:ÃY,?˔6AP]`u[S}:i^ZY*~Iwcc3ed)ySwKjNVS[?ה6AP_Lޕ'bS}6g]g}>U-gjOAPY>{i#TޔZ'~ܯhjԽO|x~y&3*^Rً~.{ >xdjQyL[5ػo2ş}J l]sFs\G0ER5}G\gj ljG#rթ}S}ٶg&e>ӀWRٍ~eGƟJ3 |ZMGV=nFjk{V_dy((U{z04yM9WRϦk_{('qae/֮Jc,՗l~fj4k>?RySW-<}sRgTv]'TMߞ:z=_>xލMU=?3UqAeWOE?*`[פ։},׭~ &~:TmV]Ŋ_Jی~^{QJO(ۥqkO}D`V_}_Yڬ2*˺W|-y siޕ' IN ?W5l9d=+^'UsY6ve#RRďbXm>N>z?fFr`(|Hm,3*ϦH=E?7`27_:15x_-l֩q[S{=0NuR/ǟJ lkG'̯;P+S?NeO ?'b un?@?3X9eT?xbgc;}S#Sy ͪ:·7U<潩H}ޯJc?^WWNE\2*뚇a3FNumwշRŞ{^oW f霷mmFSOn94 ʻE\69 4@S;}1O8Obq{|Pc?do7n??)KzkOLuWXRUEmD^vT]^B ʽbg)05.fe.r闢0[/ ëŵ8-Ty>~Wm3JV޺& #T_M] (=X kjC (=XRպ/ Hw] IDAT 6 #\#FNC -{*~訪uwvՆAPzLkN~]}Z]]fS?~hjC (=E\we•wxpO+ 3ڧ|* Z;j= +vxZF?w LU_˶ 6 F|og/霳6M)jHyp (͠ι+0)ڼgfPR40ozW~VmA2J3{ɡf7~?ڂdfXMUSUF?`z7~Vm2JvU3y{ܪ-XAi5g4 Uye>(έڂefYF?`h_j APeͯ/Y CQ޺O./4ۦΟF?`yZ9Zg6l תdҲ'ۢ0g#V (ͱ9xAZM (ͭbgyo3fy߫U (mF v~=3>ZhAi3*V>?N,k;iB3JY}0#~V-<0n38-h3JCstxBϪDAi$^;VRcׇߟU Ґ^;lPߛU Ґjn3jO>ެdXD?Qg/ /6R!)UeeF*4?>>y>~OVm2JC Wҭɪ\Ai] sc~?Vm$3JP㋿STZ~?Vm$3J J 6yϫS*g;j#APǺ}^;5~U}X (c/Mۊ>D]ª|Ai\|@y@;R3|Ai+v}aJ"\`µNHX (-@ v>`ԢjcAPZ}*Sහ}U 9gy9,ΫXebg+`X;jcAPZg|6`OjcAPZȖ?%UӷGLrT_u]Wi2J \ďGL 6nɖcvUVi\3J5yoew[6TڳƐQ}33JA52`(mnA)_>KU-.g+v{`S:}1Dd뜷KoON ê6:W& ^WԢ/Fʵ)>[QO 6QkV_M#eےRnm4RJT僗W_sc}0bg|69U.rwùg #T_u]UW}Z} ÿ)zJe7 ZM~OUm"^ˬV/FR-u.b@wv 6~z:5/FR-+~)UugA:Y_mT%Z?b$=PďE?DA~/Um~r5_"\} :'U覶Hj3?Iz!oK"_V}*v{ïZCÿ I{ѡ *S;h<~պלIztu_\[T,jj $=τJ̯rUOղ>^'M/*n=x &P|S)zW˯?~5G3x`t.=ΩZVUA $mON<'7U˦bgTU $mbIm~okU#`lu&iOTQOtSj`ټ/MOmIHS[ +w황>([kz EѮ_KO`TT2lVjݿAu'@IOX]#-6S)gÃ`_ %mOI=-f9<>l뜳l`9.M/{Ҩ< }v0G(v|z]RVr "%m] (qʷbTO<$ 銕OU<Kʻ7vG /B%֪ͬ.,n8owG]g7=J_JASRﺳ(`T{pٝ KY}_R3Qy{ROleAuM,i|gP缝R7}w`_¿hI3lɖy0JPc?ku`_5)uu UTsT:{`9}g^u/iWf5HU~/m}ͯ}0 iMm1tV]j&_}' iv5yuJbg4E*]9A8-I}FT{o(f}A󣯅A$2: 025~OPZ?buTR0fWjOg}!'Qwă`/>($iϛ{R}jQO?ԢTr$ͮEw홛yHS3|ٿwO ^zdLuu\9jTdKJW >Ju>2ǣUUj;TLSi/ )5g%ͭ:sNw;ۥkƗ4*iߢ ~@RS}ɖw;:0]פۄa%;o|H3WT;TL:xyZg|6,in^:@:Ejw9ؖn;2ibW%;%[Mߝ UZ8'-~|sm{`Fn8?M/^4=^潛tsߤjzZ'c_\lXR}B6zTj_s:߯EHSˏ)o]˟~g>?uaiL+v|z*v(IP{s*v}a}Mok} Q i0ƪtj{T@0x ԝ4ڧP&c*S I TTkCt*}}_94(֞8GXjw3iZe]2,w|f_'d{Qw2:;/ }ݟNK ˒4)nsֻTaZ(i-J*<Uo~?XA,S?)i5y(Nj;T@ v}Ao+{yB%;q9UU kI ~ǒH^a)(_KI_|N7l hτEK]2.q[{b/2n%sa 7>{!iz74N5eUrq;Td˶M+`_SR}oHijJ KIGT}*o,#fzyI3sQ )6Xcޛ=i }e8 fҭSs"O#5yuIZ`KJsw|ƨ*%M/^$i+KD?9jޛ)$+½/H&~|PڳS}CIt/Zя (C~'$uF<2CK~;LҦk~})Uec ^;5~O=I~*wi ;?7PT]BH/:\JFu#9>#&MGcJxSR_~\7R5zw*i#;>}_+i#TvyP).>5zԾT_hI%#Id}߅w>q4/Rkg'Kzt~;N2w YKSCSu8A!:?m_1:}_ޘ=CX)m@S)Lι+<ʨ[O뿓&X)[ө{!U/Ib0L~Q5yuꜿr+"Խ_@RMmWD&D]9lT>Te˶MϏ~c{j^Z4x_{`,˔w5}Ti:'eTbT2)&a땩u_>=,ADҹxz6/xik|)+{5KԻsm*6w_n?l2$AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2bF IDAT #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2b #AȈA2۱c`aos$ yCB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB A1 CB Ar\N.IENDB`PNG  IHDRB8 pHYs{Rk IDATx{u}3 ^(xO՚fi\mL$$M]IlvŦ9seFn" ^P8 \Aȏ9緟~z}yx=6UXX! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH A 9@r! B3$gH Ah1u[7D+s[u/E_D5=%i-'F/($nkG_3/=3qv gZmwG3{qjѤ&)1J*=x[{n%i!Z^xV.}M 4n5EGu[CڭV[>[NDg]/'Do)vŰ})>÷~YRCJPgJت)Z*7$-z_4\[/wJߎ DՃΧ0UO+/%gJث1ZXoyI*Ϟ61薾-7Aܲ!:3Y\JZk ~ҿ=ߘ}KR> :llL 4Xջr{a>1kКm/IcӡϙKߢǒA57Eli\ijUhڿ4V-3ڧl8b4*}~'xziRijU1j=P7VWo}IZ}Ȉ^+&B{{tTk|u>u @͗FbKضYѻbubRM 㛽=&Ή!FGJ Zw%i[_t7[[cL TwEʵQ~z8iBƈ~n<7{?ox<" oGCZ?`="wHopQQ,@!?1GvZ?P҄=mqCq1ԤZG$.RB-7GXHTt?zP$i"\Pgղh$ME13]W$q;z_X1iw֑ٺYĨ.}k6E3*~N IMucxՑE5:3%8$_sꛊHR#[4ʚу`Q?{޻A0n|5 $|I .Р˗G5GI?gu,~~ Imٞѽ|YD=&j 4ܲ1Z%] jKzIsIjr^wE4j_ɨVW-.kc4ۢu賋'HR[s` 6_MҌAh؏KکގTh9$5e{Fʵc?_4V>$5oU1z}]Tlo]&n¨UA^#zxB[6DiſvwEҷ ` ?-=7HR[Wc9HT˖Iک$eu3bG5ut/@o_#a;zك$hSSb܌ Tsλ$Y7G B?,Wq256cЧ7HҜuNOn;hgVŸ(? Hc[ߌtJ)E2/.~&!IYn`PP!i:'~ &K}h9ل$e{B^OIs>c^5KQػ$ew v|fYo+KM[1F/}V!I)Y Bus /ivGhkWHRfA{_%Y;yVBҴ|ܲ! Կ/9kb9KR5OV?-ސsl(e{%\gDo.hQw{}Es IRk ~oAhxuQܯ+iVۯZ[p̾| IJR룯U9z=Q;*iV>з gm$%s$h_LIsln0AysIRFȖf B{ojSxvwD~tNz]IR7DuC~'Z/L4jo/.~!IY}f B݋WŒs#b؛_yQCRb{xB[6~X}Kcjj>cKZ9$e}+#TEǼ|n,kHRxB^őZ??F_s7ES(~&"I)ZW x BMa$=[{| wpL#QaEҏ)1yIAgo icu3I^O/ Խ|y/ZkM`1?4R$jp#^1. T?%%MEkA1z]Xlϙg*T55/ ԽſXISQ|jw~m~J}U$iֿ`ГmDr_4,g<_xat>+4םP"%MEÞ/;U[usHRZaa;Zw/R̞?f73Oz]/Fz_6Sл|y$U gfmZBuOQ=TmTG7?a } B S&U8h}Eg$jP3ߺаg"I=| uʓ)hyy W\ G6 Tw~}鋖&ό[ Fgc>ˑj[oD疿`i#.ZG&U[u˟Hx7|:罻JPCY wղu$zß_buNshI8,}#ITB쵏~Y z}3IƵeKc~ޗחP)q5Dub>"3zsg=TiÍ> >_=b YRGǯ>8P]G)eC ޅ)~#I9?ynXuxKhD >~$Z1מPzIJ<Wou$UcV}ƹ9,~qRZzM%&/~$I՘8 :/NK<L_,H1wUL.B?g~0Z?$UcRyAhx7_J=LKYRlH1}<qr ZmsD]CTC3{D :|IZtDA'D4]zM'EIi]"Z.IS13ZGEIMsDF%uG/.~^$IU_;TèV]&:y1j=P!3skIRUޥT IDAT/Hjt_)|FO+~$IeǏ߻IM#> X#I 97N$5Ωs\/~$IUǼ{T5/Hjb>7FZwP$I2ս/Hj\>7Q|6%ϕ$izjTIM4Ow?Wj1Y1gSOI 4TQ/)~$I"6=2{ j#5Ĩ`GvQ}WZ9$UhgS#-jٞ>7 gg&I^nMU=HMեUn~Y&IuZ#{_QK?0OujB:{ߛ~fƹ֚bQgWIEVWbqn&,~+G$U Xu-oZgƵޅ-X~Q,)~%I5zT ƵG~1b)LϢ$Z Bb。WEC?WLJ?8 =chxuȘAH uNs 'Ϧ$ B>+FՖ0n+~F%I"H$I$i=tKf0YQ ͳ>l I$I1udBj<*6\ I$Iq|`Ӱbuo;;H I$I1߃dOB~O !J?N($I$I*^yV}@Y1>fWFzI$I$_{;3Y16FxI$I$gu~2 !EwFxI$I$IuxV@f!XC=pCl$I$I6YߡWX1ZMDtI$I$)뭹-e3w GBV_:.I$I$=ms]PmBi%ѳ\$I$IzƊ憔;5 U#y$I$Iu;&N U#i).I$I$m~E~*BY[$I$IzMvk@r,9͓"znK$I$I[]O߱ʱb-kWElI$I$i+SڀT%B$I$I͵80 U#mGjI$I$iS}ᯇ߹ʰb4LLKݕGiI$I$i{7 U#yFgI$I$ikGwo@,(| /ړ$I$Iƭקlb;86,(5GeI$I$i`5ODP{BZwFdI$I$i`kN٬]X&Kǒ$I$Ik}4,(yÒ$I$IP*kS>Ewr@mlYQJ>/AI$I$*/ jcBR82zJ$I$IíN^~7ƒS?F_I$I$iun==~% !J{%sW$I$I q{c!D4Ox$I$IBwU&b!Dy5kWE[I$I$))_qb!DiΊ$I$IR)*_Y;a!D)2V=g%I$I:+v@mlXQ O$I$IR*ꏧ|ww@m,Xq{R**I$I$`!DR$I$IT:͔{< : !B5tH$I$IJ]cȳ"]Sy*I$I$^7~c}FaZM$I$IHԹ<6,T4GQI$I$i4*T?mz@mdY}a#T$I$Iw~FCW_)uS$I$I=6,mgGMI$I$i$뮺,~$ !w;$I$Iu5}_=P9B ĴԽy)I$I$tW4J,=+%I$I~F1s{9)I$I$EnIv~@B EGHI$I$ij~@mdX1xwM$I$I4V3e3w(bZ|5z6J$I$IcYj#B~^*G$I$I4V}JBj_<'z&J$I$Ic]/ҳb`y/JEsC<$I$Iƺ"${='>Ӿ|A,$I$I*Q@,|_I]$I$IR%*RZiY1g$I$ITZW P+- !\)u[O$I$ITEw X1:7=$I$IJRbJz}JNܓ$I$I*Y?9'jc!ĔxB̓$I$I*]/ұb|$I$I+x0ew /jb!Ĕ\\$I$I4[B}!S"_$I$IJR9Ss3N$I$I<@4,fIۊo$I$I~b=)S!P+ !YgőѳM$I$I&jCV Bl|W I$I$+e3vGj,&ki$I$I{#pBl|WiF3I$I$IOS;R6cDB־|A,$I$I5OD}"P e!V0 sL$I$If[s[& Wja,*%3g$I$I-yGZ !R_$I$I÷-!^]Bly_]$I$I _j!,23vHڻ$I$I;F Eb43zfI$I$IچG?@m,|R$I$Imó4lBlJ$I$I"~c}#P* !6[wղQ%I$I$i 82 3J$I$ITi|ߗ;btn95zDI$ijx{Gھݗ]>ٝO[NeroâX*ꏧԮG/$IfԾt{G64B<|WD'I$bF@?hi/_Z?:RI,5~R`}af0Rﯤ!oMc?%{εGmg=WSEs}WS$r)9@m(,xFeE&IUKNW.J +5TjT_˝eDL/JnbT? =ts__IUR}_@ !~I=z$IV X낯7mZKfcwE͖$I&C:B'}*=w$Iރ7%sS;Ɵ?R۬+/I45u)O8##G$iuSwղ1 یS ǧ!A$ij/TI?^$IԹ[y_|煟`RsRLn$Iڪ'J٬U@mJYS_q$IRk{yƞ)3/M$IUP@mJY]SQ,zH$n;uo?'5Ohf^0]j)Ew$I8' M !g}:zH$=|kj]Ք3 RoIO׉$Id[O?3)c!D_E$UbԾdn/|C-_G\sxJF$IғuRK@mJXG+zH*VR S󔏥lg"6[q%3SX)Iڗ?')a!D\wt\$Ix|ej]4="e}A{DJ$;-ԶPs"I*Pwղ 4c39Oh$IygF@VB<$I&bq/zsFU>oZcH$E{)~.jBz]=O$I{ǩuRs;0.MOK$i5P&BV[$IzM3X87-EKսsP&B־9"Iơ};5|Oq7DHTRׅVY;"4zHQJkJo?@UؾxƢ6A$U0?ikYUTԏGI4ʋO-Ll=/~!I4Њ憔P*Bս!IFN3uV,N~ ?V?Sk?-$I<@mXUP~rP$m~Fc0cRX!Iưޣ?Nvg m) j_<'znHQIG|W_-i|J'$I'|(ԶPLLKڻg$I*sE: vMau'$Iw^~j[BbGA$I%SY{$ISWQ2>z,*s1B$ޚSU>B$i*j_~@m *J'U_>? 0Ί?$i -%l6P4Ox$IeLK|焟Q͓Tdk?$Ilv*x(S$ޚ>'C>/I6}_`K HG$I:~;&@I,Pc?%IVֻ杖z.8$ICx|e|Jj}Slγ$@Xۧ"$zHs)ky`[-uAǪ$I@Ec]Zu|K@BcqEI:uWSjΩ{۷?a%IҶmkS{EԌ$IhޟG1d!4Fڗ=[$IfԹc־xNG$Ix÷Ίg!4Fzkn7$*"/i,IҘ5\1|R~ITz߅ʠ}OeIF2m`!4&ZMG$je? ?/I{џΒ${^>HF(IT?]gҙ:+$uw< f!4^'$I*Wź{R?+vsqג$ z0u?6T?H`!4g&zI_x|e~N(ۧMߊؖ$iyaRYD5Is 3H-n>%[mhn{3 ^?god!4fQ$I*GnH>/?#;]FKuwU}˟㢽^^B#qG$I:s_~>U^IFK-un8>|3DNl Xɟ@$I2` LeEK*/g3 FB#]Q{F@B=RăM  69$IRloJ M6+pn IDATc^4n:G5vs  EPI*?$'m}&WcߗRq/IՊ"#unfj}狩~ĻR6kaݻ/$UCTy/$*6< ϱQ$I~ﵨ@Ux:$iY4/'E{eJBhD5Ohܕ$u~UY8zHJޟwꇽ{o9 C$ԮQ~;ODOI*6 G'ewCGЈ*_=%IVn9g*z=$IS8qR> SB#~g$I/_OE IڊjYj/_gޔi  :[J^g Iڂ6sUvvH$2un= kJ}nړX;.zKTz]%^~pJVd֒qx ԞЈi/IR%*6<^>x3vHݕG IZLB#tv1@H#>xf>/I'$G&Sg=)a!4bz.>H4Ej3W?])uDF?KfƱBh{??^' IX׾tk"I֤q?MvP* >;H4u$e3lεGEI*Gvꭾ{H?Bh808!I6|{SkG$ 7`!>bH4u\yUHT+?{ }AJE/!IX6ѳ8$i,*GSG٩q‡RK?c, 8#gIƲ LG$mYzsyj_qPjT?u៥ƊЈ Iޠyy`jYϬ?;HBhDx$IS\K0|08~LEHđ_~FP 0rɟ$ISsأg<柦TcGR*^05OX,2 A$Mm{%=4:ٲ9oRׇ@,FH4T_12zI&/ҼlDY$ij}쑊ƺ1$i*ݛ:Z{j)9em ~^ג$i\i?=$6uAj_w/lY\F$IZY@'GO$Iu۩𭩳bqjg/zS& |l,J}c$IcQ~~*=$g"X\'KM$|STTI*6NM%3S|9P!'R$vV/zs\TFO(IXܐ'/xmg d%f!Tb}$ik/>(Y;C7G)I[?7g{`*w}ܒ$i=rG/zPNCMRI%(RosRwlN8 |rLq9D+s۷S+y ! +}&$idTRˣǖT&ߕ?-sWPI:&Iix0~og/ߕ?P c!TR>}l$idk/>-4~Ժ૩q{R6{mSB%^~p9NXf>13vHF1id*6^}BY$I׽;13{{'m{~SBlf?Iͯ~;g8cgZRdfj]B P+= iJIFm'G:U.uW-K N>/ j#BdZ%)IHU?Y*kǝR+KU~5{ g$m~ݻ. 9yz]0YL;$L?>R+ǞFm}SzBD򽞛RQDQ%Izݒij-)uO#Y YOIͫyg7Ҿl27.805Oxw  i}XIFb-*{fw`3*uGGm%IZ{}"z jV֒6d!T"Eu%I*}EsC~~+FC ~ߖ/LS>/ M! CJFW׾ @)n;z$j[7>m}ASQIB% (E%I*u>>^\lj~;R6s?olY@D%I*uE˟( G1| \1c!Tc$-IRk_wZY`{|k  *_>KTzݔoh:vygR}ћR6]@VAB%й#$Im1ѳRޟ5ǥyO;e3w M*޽ˣ$Ɖ 92U?v3,MLKEc]9^RV/IEsgg;_Wg~P@c I҈Խ jlذz.jj5/R q I(<4l|γSă<'{ׅ@B)2$ij 9 Su?n,ZOe|ajGg!=4IFͧh23vH5mz:s/aHٌHB(P{~ýa$ij|hJ͓?- ZeXvv$Ij19٬]g4Li)RYꭹ=MRչ ! (3Oۊw$T5Od>~,;7IUyhl Yik7IJUw ) }&IRj}3@6,>4MR/#|>dcB(HGG߻ITz>1f!dK$m} 1 R4$I*M,~>L_B^}&IRyuRs3@6,47IJSwe sBgwo$E sBZKfF߽IT>1g!swo$V;flY|W$IJ2@VB_G߿ITKge,mN)7IJQfBh{D߽ITzݔ UА5o$7e",y'$I*E>#MR,MRT?s  !q^$I'R6c UА1N𺫖dB,?}'IRxdB,ino$晟ӫBh =MRT[2@V!BC8揣$I]Oٌ2@V!BC !N_> R*{8IBf?WЀs}'IRlv<Bh}_} 'IRhEcm<Bh>NЊ 1@BU?mp${y Pu`5zo=$I9|T]a!4X?}'IRh UWX VFIZwy Pu`5{8IB j{8IBzz<BhZ?{8IBp|<Bhω$)5Gc+,l{8IBk/?8|T]a!4X+EIZ1@BY8NUWX 䋴%Irc+,s˩p$־dn<Bh}'IRhc+,{p$Z23|T]a!4Xݻ/$)օ_ UWX Vᆱ$I UWX V$I  UWX V;$I  UWX ,IRUky PuЀ$)5|T]a!4/p$ֺ 5p$ֺk GIZkɌy PuЀ p$^:;|T]a!4X]$)%{c+,+up$־ty Pu`$)1@B4c;8Ik_q`LBhf}'IRxd+,hnwp$׾ PqYI:+WX МgEI^od+,BHԹ Pqs}'IRx; UWX $I)urQLBhp}'IRx{.UWX $I)V_> !IRꭹ-|&T]a!48^ύ$)3 $)g2@Bc!$IRJEc]LBhp9ώ$)N3|&T]a!4@v$eee!4H3w$M>F5|.L. A.MR 0,,E$I)|&df!4`׍$)wd,,u[wp$83 0 Kz$I5OhL*Bh_wp$<d,n$)w)|&df!4/ph$I.YY ăwp$^L*Bh_uFI^#g2@VaB{;8ItRL*Bhz}'IRx;> $I {3 0 {e$I> ݗDI^=> ]?$)^'e2@VQBֽ+8IJQ2@VQBֹ7IJQs,sIo$>F߿IT} |.de!4`$5OD\*Bh$B\*BhZKfF߿ITZKfe,$>9$un ?wuy3h4&1ƘDi&jDF1=1ǕxPfBoE^E@@@D&R)~߻d%*)سݏyw~iuYM4uxyl(- :{~GM4 PZAhuvnM4O PZAh-lWU$)E3?Ah a7z&IR>J 9ME<$)E"s7IR4 PZAh &n޿I=eBBS0$I)<2@i!)yaM J\(- 4[Ό^Isg3@i)}ݛ$Ii PZAh F׾?z&IRzMl(- 4O{$)MS(|6q޽I>J8MwD$IJӦeʛwo$it>ѻ7I4 PZAh tM4U>J8MAwE$IӨ_etVz$)U(׏ IDATEaa&ѻ7I=`=B{$)McwEBKg3@i)mM4 /Z>J8Mwo$itg3@i)xrM4ן>J8Mâwo$ig3@i)^*z&IR PZAhJݛ$I PZAhJeMTu PZAhJz'1z&IRzf|(- 4%BMTx[|(- 4%C~4z&IR%ϋn$jtд轛$I}Y|o)Gݛ$Ii'|6p=ѻ7I4eM&z&IR:$|>p޻Iޑ?>J 8MD$IJU. /Yw$)U >Ahg]MT9"|>p)o޻I _޻Iɗn{E$Iհ[e34uVv$)]^>J9M²n$ 4n$[3@i8)]MT .\>J9Mx9{7IR53@i8)}轛$I}i|( 4eK޻IM׋lp?D$IUUeo ꛣn${h`BS;ꗢwn$w34Дu蝛$I PAh:s$)]O>J9M²n$j|3`"^Gw$)U/~:|>s 0轛$Ig`B7$z&IR:34Pkwn${τhPB;z&IRk>JC9%z&IR|mMtn8>|Fr ;7I5 PA(guUE$IJU}(~F7P _w$)] L.z&IRGL( d|;7I?34PU޹Ig4@i  -z&IRF7>J9+q$I6 PA(Hs$)]U PA(HwE$IJY?=|NqYu]U;7I{ifq|;F$IJWC>J8|蝛$I^*|Fq 4蝛$I} PA(Cwn$kOFh0B'z&IRcuYX>J8';7IR;4@i@~)z&IRz9 PA(Pg޷Io A"ء'蝛$I~9 0B_;z&IRƷ>J8ߵ.z&IR A;*z&IRI]v}v( lp蕛$I)9 PA(XF$IJY? !}$I)Ss4P/޷IѧO!-,Q/z&IR&_?A(Ƀwn$kPs4P?r$)e}^>J8%0}$I)s4Po$)e>J8%?m$lx9 PA(a?o$)e;.~~MU>J8%Q޹I;?7|N Wn${Oi2}$I)%|N m$lx9 PfP.z&IR6m(3A(޷Iɗo e9%]}$I9Y0,v&+7IR=`~v9%R=roMO}s(3A(F$IJps0DFWo$)e~(|N ޷IɃi2}$I9(D`MuH(3A(Ϭ8z&IRQMBT_\M /5|N m$lt9 PfP2+޷IɆφi2w6Ir6eŎ dzn$)m݃8|V LG$IJ[?e9e|%$Izb Wj d6IR6)s ώ޷IɆ4@AB /?(z&IRú1|V wF$IJ[w+g5@1B >kѻ6I?g5@1B u]$Ii^*|V vu=G$IJ3g5lqJj[m$z9 PfPR?o$)gUUwvn(3A({F$IJ[ e8%ПF$IJ[ e8%=Uѻ6I6Y PfPRݿg$H'6Y PfPbգG$IJYy0|N ΏG$IJ[gj2#^&z&IRzGr(3A(޵I9>ʌpJw/E$IJ#g5@BuzaMM*|V \}(z&IR. ۅj2sEMuY PfPr뎊޵I > pJn޵I e8%;uѻ6I6Y PfPr_k$)m 7j2[m$l2gkfm${Oj }]$Iig5@IAh /Zk$)m %9?Mѻ6I6Y PsC^k$)mUwc(9͂Ϫ8z&IR:{WAhFL6k$)m~+|VfD$IJ%11x]$Ii}Y PsSk$)m/>JbB3ѻ6I6egkЬXC]6I=5|NB3dgwm$_j xRM \>JRB3d]$Ii}i(I9͐ o޵Ip]k ]$I=$ 4KA޵I񯏟8͘}D$IJ $ 4cF::z&IRF7>JBB3fp?E$IJd$ 4cz]$Iy&ugo%Eѫ6IR=g5@IAhUݍѻ6I68$ 4w_k$)mk%4]$Iiwu(8͠Yk$)o^]V>J"B3wkWm$$ 4:v޳I]5@IAhFU~!z&IRچ/|VDfwm$m|$ 4k$)mU,, % _]$Iy PpQ5?g$)u>JBju=G$IJ`>6ѻ6I6Y PpaO}0z&IRڪ % 68wm$$ 4zGRMy Ppaϋ޳I9|^f\}ѻ6I6Y PpqD$IJdgg5@IAh /]$Iy5@ 4)z&IR꺇:|^`B3{F$IJ]kAh-F];ѻ6I6y 0A&]k$)m{ %P=2z&IRކݺ,>|^@B 08]ѫ6IR=5@ #_g$)u>J mu]Uѻ6I6y P95Dwm$m|rj-gF$IJ[5x. ۅkA!v޵IA?>J{6IR?qj/޳I' %PS,,ѻ6I6k] ]k$)mUE(dwm$5@ $z&IRQ(Gl$nx^pjk$)m;??Aa&]k$)mU,, eftѻ6IR{5@2=$ILPtuM /Y>ʔ95ͮTדQMo?/~^OPM6k$)mULP?6z&IR:|w(S @s!z&IRz'1|^)rj~!z&IRveǷuUE$IJxLPb%I{ |V)rjME$IJ]gk2%B 5={6IR;LPC9z&IR eJ l$n|G5@bMUKLPןk$)u}^>85p{6IR?w5@=$I^*|^)pjMG$=u e z]$Ii벰,|^% pD$IJ]g e95p{6IR?5@YbB ; {6IR7ly PPuyqMԍ(|^% cD$IJ[. ۅkZ`|۹ѻ6IR=5@YBB-0\{M׾%|^% g$)uO>rj>/޳IݗkZ*wm$mة5@Y"B-1U$IyE(KA%g$)uY(KA%z'1z&IRW>qj>/޳IɽWkDZ*wm$mԫˊ5@YB-2U$I5@YB-2x=$I5@YB-;{6IR7y PPt=$I](KAe!z&IRú|V(Aeω^I e9pn{6IR78,2=$I]L(Ae:{~GMMtK(AG޵I;{|[(A7j$)u~9|^E B =z&IR[(AzGjMԍ?y PP uVǟ I{5@YDB-5xGMuy PPKn<)z&IRz'!|^E Rs1z&IR e8Tȟ޳IkHjdk$)mU,l?淝PM6k$)u?|^E bOg$)ukZlp;l$nxA,=$IsE(AV>G]$Iyb 0mZnrѫ6IR='5@FB-7=$Iy PP?{6IR7y PPu=$Il)|^m v˟Q׃k$)oդ-3`~9Q?U$I}5@BOg$)u5|^m D?l$nty PuwF$IJ]5@Bl޵I^/ e+9l$w5@JBrk?{6IR7̩l!!Fw+l$zl!!vu$z&IR:{}g|Bfp)M5z&IRzG6|^ S]LM y P6Oip;l$nkxJ_g$)uգkxj+vQ?z&IR:{WzB<ɽWE$IJ] pi 88z&IRꆗ>7 =$Iy P!V޳Ia.˷i8UU$I3`9 8?z&IRgM(OAohx{6IR7y PPG$IJd< !Ξg$)}=_>SpbT>z&IR6Dm(OA2imM /Y>Spb =$Iߵ.|^ f=$I,>|f' 9u=E$IJ]??A6y=$Iy Pmt{6IR7y P޳I5@yBl{,z&IR~~(_Aͷu=(ѫ6IR;g6rb,z&IR 8E7z&IRw]>qbO=$I,>|f 5$I P[z {6IR?m|!3l$nd IDATkUb g$)uׇkUb%z&IR~~(A-[뺚D$IJ] 8U&_9z&IRv8U6=,[$=u;?>qb |{MUG38DMuye(Bl;g$)u~6|f; ƟdMԍn8.|^!G$IJ]]8-)z&IR:{0|fTBl~c$)}~/|fTBll$n5@ ĶzVMM"|^TBll$n<ˮ@9Mz5$Il&=IM {wAm6y=$IrFAm6=$I:eaYZAm68ol${\k9ͺTM?3k-!݊z؍޳I5@VB,=WD$IJdg50ZB,F$I]U՝U;l`XSf$)}cw\+9(4z&IR>VrbTeCMԍZ>Vrbьןg$)wn]V>qb .\f$)}~*|fs Ģ;6I78]3k!MgNu]U{6IR7 ̵jۢl$zy ̵jtq{6Ig60*B,G6z&IRqZAE=U;6I73k!׊zԏ޳I??MXt{޳IjRwV>pb 88z&IRzVZAE_KM /Y>pbuxyM,|fs [XVW/G$Iݨ_ϊ@B,mF$IJ_ \+8$ޱI>VpbI9z&IRƷ~4|fs Ē~^]WUMUea 5Kf=$I3k<!'D$IJwl`X2c$)}O>sbtuMU>sb|f]{6I%sA%5$I}KA%5rMM>,|fs Ē%z&IR&|&|fs Ē$Iysk,!²|9z&IRzǿ.~nuS9Ʒc$)}K \c9ޱI?>rb9z&IRƃMsk$!\gN?,[$=}#_>Frb*&ޱIg60HBL'D$IJ g60HBLwE$I߰S;m`qᯎ^I4u 5ӱu=G$IJwmn!frU;6I7^vA^qpMUGsk!v$I3QП\815^_$i&sk!gaY]uc$)}~8~nu81U΍ޱI. ۅm`1E+wl$D5\c81Uc~3z&IL48sk !j$IxrAl=z&IRǾ>pbF7c$i& 5S78]5If>Fpb꺇:z&IL4 5ӷu=G$IJ_mn!BL*z&IL%s DG$I5|n6Y}=;zrsͷ!k_$i&] [ q]/ݳ}Y]O;c2B򀕚$IsJgԽ_Wnܬ]g/- DeuypWh$5/s~zt1dMu]U[]ws{A0,Lf?sv?_6,w77ηa\I0 .\Q︠%;mͥe;7E4x{9:{|]o9ʆ׭7u(- DΪKJԶ:|wY6=c>o!Bmϒ$_K X,jzͷF7#IL4 @M_i!B >;$DO[Yʊ_"BIfξ/ L??]goAX+vQ?sG?,sZ3=7Ifѧ,s6Cu[0Ap+ܑ$i&|`mh?gӯ~̩u_-S=J8-џ;$L}'|v>ܟŬ{o!uY$I3S>ZY̺Gl|{8oaY]u$i&g7@x/ݖq"s?{$I z 6ޱ;}q"MuIyuihs&_ZSߍ̷)If>fQg⵺ڷ'J8Bg꺪?$IF7>]=]UseiL6#ILT= Igs?+6M/SZA46kgIyuxy||ioG?3̷ǿA4If& h^/'4Y q"ᯊ$ifxRXl_TN|c=du=º?KKϕq";$ILT uYX??V{"B2 If s$ >/p"EI43z`f3FR[{׾%3Hi|Y`wo׃ W[ά΃_4# >>-- D*_$ITˊ7ݾk~MGti!rYX_Hu 4?~k=Gpnp"s?$Ix=ؿmx鞞4xUl1AIyZ>ѿ? m1 EHwoDI4;u9?{woWYz|yYkTWkW[[;h[Z[mmVouj d y&2̈! dBkks2$'9g?{~>?or~^{UѬQB/O("(!>%I${A?[`z?=off}H?xSYѻp-I$iTE6ZCe!Jcѳ[$IR{Ds6K=5BH#Y{_><%I$Ma;*>k3듅F־}@td$Iix۠ vͬOBfoR}@i.+~~K$I{&vYCm80Y,4w]}@io ݒ$I]6%?}?#!e!wJ% [$Ij?(uOԿT<|k?`Ww;>YidJυoI$6ylU-ϬOBZ5<R_uh$IZۛRؿLvK/Lی'G5FbgF=[$I{|FӢŁe!n|[$I*Us7>*}// Y,4u3 JoI$TwP[?f' !t>}&@6z~K$IRkS9[+;K ?'5BH#]6E)s ʣL9ۆpI$ie^Nz_{@ ~Y,4]}.@p$I[?跓WUץTWq`z?vy2>Yi_o;~$Il7{TPϗfYs J%-I$M{bӤÝϜfZs ʥS3\$I{:4knMCԻpQ9ԬQBf&LROpI$iɣ@ ϦBHhpgJ$Iݳӎ&#wgUFY?3xţwoI$'6E9WFYh3.I{W_gie!Rg$u.I7ksgSRT?f' !| JeQ[$I{[Oy0[׬QB*M+>\Ԝm $IRI=}j{fRi'($I/O{ģuOY,TZK}>@Ο>%IޟG\?H~gd!4E*:FQP*g$I_;)뒔k(Fb9:>YT n9+r)-|E $Itgu`uNRڬQB*UEQP:c>>%I4 ?k5BH}EQP:$I@Nߗc_y*CBH*[}JE}N@;l9.Ig?w4)ZFkqFYt}N@鴖;|K$յlKS4~F7kJ3s.ITvxi'7BHkY n=7|K$UY[w~!uNl]~t~WBH{)(A/e_>%IޟGrVJ,Pj% ?ۛ5BHk֖讍>tG~"~K$/xjY,T}V@/ $I#v~} Y,Tz}V@>%I›lsaf}R)kgs\$iyfh( !lWEUPJ%|K$M{v>ޟU/cWѳY,Tڊo>t?=;|K$MIN?e5ϒBHQGϠ^>%I6?N Pt/3땅J7ks\$i3+SlY,TZ?R]w$Iy/~?~T?knA͚e!6{zs JXs[$I{xB4^Y (Rj9.I*}+gze!R׻hs JoqIT0;>5BHsG[PJ $e ^ڇ|4u{|?LsYfY>6A; |K4gZ∔?xן?f+ !U?b`rGi$IWۛޟv _uhk, !UE]PJqI4jy(@M.Y>5BHs?D]PJc،Y.IS6EU[#XᳱY,TZK}v@iY.IY[w~aoKS꺔<OrfR"/(ÄrIye=gfY n:=R^>%If'{0J9gjfYuϞ}~@9Ev~},$Iޟ?rCm, !U}~@iu\$y>7gze!j Rgg$I5wɒk Mk_ ͚e!4`t9gY.IR~a*MY,Tz}@iX,$_}n>5BHş0(%{rI\]ofY2e;. *#|KT O>{5BHXs{QZY.IR-UJE})?g/ !UGFePZ{,$e _} W$|6k*U>w\>%Ic} ^>5BH{2(|0 y.IRj[ f R"G3(Ή$լ}\>5BHkpK$Iïş0T+ f!=gVyRs$Iu{Wo0Tv f!>w3(>%ISsF-|6k/H)GiPZ+$ըޥ{Gw>|6k*Y~gV= $եuGf!JֻdI7$IuipѣoYu3 J >%I^ѣoYe;>LR%|KTѣ*[}m0 !U;5(֒wsI*)Ó&_ Y,T}@uϞ>%Izَ0T㿌͚f!=gZ~y.IRk-yw>|6k*[kFmPnE]~&|KTڇ|4zP n |6k۬-Sy,|R.IR,b<1|6k*7(-?$Uc|im4 !U޹s7(A/e ^>%Ij0TfMRk^ $U 'Gz>5BH.A6X,|KT{0T>>5BH/oEolދg$IUX{jY,Tz}@utL$r*"0T}?g3 !Uq}@=6|KT]~&ze)|7k*_8(65>/|KT(zy$y#, !բb^? $Uj@l83Y,T+>+$Uc*_}cm8 !բI_>c9g.IRU_qPx۬qBE>ڇ<|KT=`Ɵ=5BHhlF*;(uI*RCջpQm8 !զ;(&5go>%I*}J)Gvi_3뛅jS߈>ڇ~,|KT].zuܬqBM}@%/?|KTߜ IDATvHk?gpY>2G<("[=.IR,bHl n8 !ժMGyP ~'|KT_ R9gܬqBUݳ3J/_>%I*sO0TE[ !թ}@%Ss6]?pC8*|ֽBHjζ)gTB?$Y[4ErON5R~aп.IRk1C__ {VgTBy,5>/|KTGI;'|׽BHu}G>Q $ߊ0t>^a!”~п.IR_q`k\ !ձˣ?~;e^>%I*S;.0t>^a!:TF縿$P&|׽BHu}FPN $l7DnA75ǶuR<">=%I*C(zr>հR}[}@etg$Ie{Dm-?jX.#p$i_st//|a!>ϢA|E$zGOm_F`5,T߲{L_ $tsK)GlqJBu}WGP]vIFBw',Ji-~G|$iT,B٢ׄa5,T:G}2,J7/|K4~{RslFVBH{`jknwї$9Q C?p} Vc" !վkD>%IfmR=`?9-~+g!׻dI__|$ijK#B.+|1j_迈>R#9y3^QsҗG49DB}َL(E1 $Rb sX,.\JpJ|$i&z<@ jLd!$GҽEE$D;`b6@e JYIr>"TNԯxIF<>x2 !i=B!b]xIFi@]>x2 !U+GwxI_wBHNjrz. $66#U#B.#~+WBu*X{_j:|KUk;1YƓYIO-xyJE}F@崏9/IRT= L j<{>#r7|KUѣd;!|dBS]k ՓS5s^Gۜx^,V%B>I/|K4= ӘgOBHzJټ4EP9}3LT:'~>z@5Gb5;/>+Z9/I0_~@0sfb5zϏ>+?$ /YӲQ߉>+ډdzFzIQE^Xe!$=9ۥoGPIe_$ )=v NQlc5}d@% na$i ?)z@ѻgBHZGݳǢLwzI[h0?(]G$i:kq z>xVBҺU*:EPIE{Mj}~$i]0z@>xVBs4s* ^*Q ڇ~XgBzj*->%IW=Z \Od5֙o>Cf$iJC| z@l7eue!$mPG{I6=R c[e5֙:|*jtSkg$IS='*qLV96Pp<,J;7|K9y8Կlz+B<,JBsv3_MG)_ jS+O $MGO >XoBF=_T|>%Iڨl #a=Yi}YIYkDP v $mLXoB$8"\Z/I,~'zdhtSsYf!$MΉ}@-_R $=W=.`djl0 !ie;>l/IsQ #aY f!$MWs_u$ jl0 !i.#|h/I3]g>cY f!$M}@m n>3|K>/G$lWh e!$MK׊>c6Z{r$:˾=`kn jlTB&4sjQ_*#qYBHڄ,G>H>%IjSFN jlTB&Zsjwɒ/IRҽG"A jlTB&V=e^R*I -ᅩ<=`E4|NQYIXjw/Io}-zW$|FYIXOFP+Ewm" IaLCDB9GiBHIJy/NiЋ>sVz~$կ10FVc6mDP+n, IW?0(|NYIQ>svz H]:ZBHڌZ{r SI$IhpwGkBHڜf{^cIRk}m)yԿYƤ6UEP;E{_ Iޥ{G<YS)|V1,ͬs_GPKݳg$I-)q#﯅k5&e _h=/ HY;G:]^j.|^1,)(#jw޼{$_+k+BHz}@=u)[$Z.-zH_oVcYISPk`%{$IiYƤ-R\}@= z[Jѷ'?>՘tBտsj$ulXNͱs[Ig!$MQc2,*r׻xqD73[MBH/xd cpڔzq#{ jlRB6j}o$Ic Js[MBHºg|3<ZgYK&]k_L)D1}vj6|vIYISXk;d~'$gF/(m569 !i%\Z+;5wxA@TڇHJЬR1EYIS\F@]~/$vS=<"e _>,nζ讍>W/$l"[=4U+4 ?)|"`@4~KR//|~kI_>oyqjHF?R=T:'] WclO|+9wI56# ~zNxi}ms\is+h`qU)[$i4S?|YITy4e $Ie ^>E`r+O jlvB4Z4_<~ ~ IŁ J{?q56; !i"j =W-w&j\BHW}VO=IR@IcJh?u34Dy InݳǢGgS4}~JV OG TBs])BHRGEj$ij:k`8(|1YICwg8Mَ /H6-'ߏ)P6~+MeBҐj-3Xc3 M{άQƔf!$ -&} _3H&]I)D_Dw5< !i}Rk; /gR| z@.Y>՘,!>r`{Hۄ$IGTNOyBHfsKEwmyl@EI20Ŋ՘,!_yblH~o$=wc*zZ@%\>՘,!9sg:l{)g/xLOLhT6 !ie O)GF I҈'?^ jLKBR@[Ί>ԻxqADsK;~=Σ9{4YIuN~76#W=?+ !)lѫS;0oɵ;$չ T^ggӖ w`7lKT?YQlׅ}5- !)i_>I|Fj2!IujiЍPy=W}55 !)lOlr](!Iuh=}@-Λ>՘,;/>M9oTߐ5EP>>՘,K9l~;$UlW|jcY[Ԙ,}x잉oG'$je ^VDP+k1YI\}(_u]4>!IiFP;>P,? [K9ۆ)$}^znS)[tg!$ۢ|`*06#^!Imip9R~ewad!$@Df??N!Il֖u F9ad!$@sfG{$Y[#o־'PFBZs E:UBJmROn"[c[ 4"o>0a~n3OlJBHz/>k_H(49'50f,ΠFHB=snfjIߐ{>] jd!$`?&PqVjGwIX?T6Bk;jd!$h;~=atSO=$iS~kg07BHѺ}=z>R{49:&w;FlkR3{IP㏚W]}l5²FOωWs Hs9)u%0Iţw،aYI#\/E ۇE$in◌@9.YPBH?J^_]~&>"Ivk[}4})BH?~ޕZK~T:_<}$hJY[+BH:'~>z^>wI+UipI 0<.NM !i$~;zf93Is_"[}Sjg!$u'D ZQc96#n"e ^W}SxPBH*A#4zn#bp)>&]TKjDBR5O:e)"}^](">i QBH*IK)A H*w?o>i1d!$D`=gvjm~WT_W}l #pPc$JT'3A_~WTfo}=ݵG0(JBR3+z#Xs{j-ѭ}o| +jTBRv"z*?HY[[$N٢W?x8Z{#Tw\=K7킔{fm~%50lE]6>4JYI%s?Dés_]$>R2#T/K߉)@I=.e;2#i8_ 6+{#T+ED9/0oX{O;'j\BRI0Ykk!be;6/7}#bpYw5F2 !6g PBE`,Bj͈Hy/JvHی>VY#T&_Z;/}=k>FQklK,jdBRIk]3 m$=_#'0W~oQcd،?tK*x9#'`َJsfhQ@1YI%wTRk_ Hjl7eL`cknKͱ-1jlBRv{sJE=k**vzm]GcH+I)G@Ν~QcJsg PE,.\/ HuyGh&V[4jtBR*uOJj:#UlދS{_KD%7軍#T"0 IDAT>/53;R/欭?Rk}m+ZGi9w5F> !Ml`H/6-RMNP`Jݵ)QBH@}=wWߘ:'~ޣ -zuT<|k-PQQ,߷"z5T/uϙ=.426x_{\J^)Pq>Q*CBRE~ѳ"[bh+ERTxwÒ?xSjQ,->~'zuU֞~?QS!5JTם=4٩}ğ$i*isM7_~Ԕ{Qj ~zv*kS~7SYIc T)ggڈfo=kl=S~) n]MYIUn@)N}Rp;[s'wJN&#}GoJeBHxG*6S٩}ԟl7،{\Mj93w4?tKJE??@)ߝc[ʜTZ=J<w(/? ufj'g}fmޔ^O|O&wʞT=aЛXp ~rZ]W9өﯦlѫ}m&~=>ésgS왩|4?pCJn:l+JeBHA`zT<|į+%KRYʼn_HNM9lEEykR?L>7_WxǻEF%mR\=x^GJC7N,a+HK}SE=5Li 'oLcL @9`JUBHIwujT& !&?c>#zh=; 3E5*TG~"zw'Q,:5kTHno PJg!$ռZc?'TYI5}Zk鯇NF{.yPKݗ>F-:˾=:|:A5jԜm*=VnIY[>T,$M;~Z|?T6YI(u) z3jxԜMj& !IOֿ97?TVYIzDA"{0e;0@5jui<J=9BH*</ Pe!$&=zR?lׅF-y/NEһtԨmBYݢ#TG>HBH:v~CJnJ_uhg~wBUEI(H% OBHsZaleI5y ZBHjy 5) ?ߓB6α=7t7ٞ|" !In֖) Q?ۓf>{WG(FIͧd!$iTd("O=4Ν=J`9:<,$mtS6)|ZY|FB&UҽG*U'5בI-r!o Oj# !I #IBHҤj* cKno Nj>GB6uGXގNj' !ITkTs) Id!$iprpNjn !I\k_L٢ׄV'57jp#?{wli]y:"Q0I,MJ&K,'1853FSNe1NnhEP6 ""fG>:WҰ9w^Uo>wyCߓr\:T@!I r@Uq*}V3:؁ B\֋rȵgsR$- #rS*w~6';AHR-n,{0Lf?9dTK0{0Dbji39C!Iտ0tcޜ,N*AHRm5OOߋ`7N*AHR~d~75gpR1 Bjuڟ~[\ud7g!I6Sw]fU՞I?V/ks?@~& $i(nhEUlN徿M*AHPjߧs>M*AHvijX7bڤb$ 1o~ e?g2Ij=wפ BZ RU~SWd?_2Iz sҹtms51ܿK;vw*\M*j $i$u9)8W?wYʤb$izrS{N/V&~!Ijo,b >L*FAHRz_}Eٿb|L*FAHRGRU~`1y̛I3I^~`^!T8 >/u[XrK*3T8s,3[0ȐAHXTGr?Xo%Z,L*2d46dg6SWd?L$Oӻ~4 Ʃ_Ҋ|U BƢ`8g?UaI1K#IڻDQUw?Vj><{I,Y[#I8F ϻb |bsIz g~V`U<`g]R1?{],);j L֙K*ơ]_K^I/Y\[.g\R1kcIyث I5jY4N/Hmf}`rnOI+~i~,i/H3Y$?YR1fɒ7_$IOV#>L0Z|49TaWoN. 'RUn@%OZ_~,/HֹPj\WR1nl岤{_$=eS;l|>J+iVmk/HƆ7TUY0MSqҊhzהkfufzy&Is{,^U{&_J*Ƹaf?塯$*흪ù3_Ϫbk__$Ho|*scwۥ9J*Ƽū?.t&I;.s=oSHϾ<bp5da5O9Ȩud? -z]I\^F2xN3)5T?^7L/%iG+=/Uͭ?؜u{g? y;w|J)](IsQg? qœBs>JҜ)rԏ PG?VLVP_%i5zQ?0oLݲAI$5S? /RQ[YauR7d?{ q> >? 9-z`N>O?5O/TSw~ wX,T BB%iu9iT$ Iܚʃ_I*&ջm> zg+IT[FlLR15O'~i({u,Iu3 CҽKR1uZ/XtɰMY\KҊ mjiڴP hIZ@^R5gqo~$\}2{ T/\R!>PƩIR1uX?A(ǿ%iAMo3 5m8+?OVL{Bݛ%i5{[JU5gzT;9TLxcBI~HB\uUsGRHAxٸs> zWXg@g?;Vh3RxhPwӥIqoO7HZQ_~{=S ti/Jjk3RM }~`|n~fNBQd$~/~o/sNgBRUSȽBNIRu.?x0A}IEZgd B8%ٿ@IU8GvT |nV.b Rj_$X R3'Oz{*3Y5ÃPj8dB%:)Se?5k6Ah𯄮84+Iujywݼn<֙G Xku9A(u8ٿ`IƑjҹ?,aWR B)ђTsKF n4ӻd?"־3 >< /r˲Tk+wN;*b6 庽H+TgF< ߏKRݕ_ֶTn+5',2 48ٿTw3>+b:#u5617~v]Z!Iu׽\ ;/-^+=߯Z 43$5?& Yb9R}m~`*37Dq̛RwkDS7Aq_RAhs)ٿ)4N MǾ5wZ/B,7GnjtIIPZm)p?Ru[ T I[%@+~f#E<%j><@窣$iN@]JSrY)l+wN;[ *5NzOo$ Nv 0oHgg?"׹dЮ%fOźeIRyfo[&Ĩ-ٗ?<-){1 to:?͌7Nq>):u6[Ǽ)ٌRCkZ":#6 t7}+ͬ97TԿT-ƑO]W*IèsaBFzTg/Rʃ~#U=Ahy懳s%i('tQFF]~'rsR#G2^'5Nxwo$՝¨y~"nztqK|ds[*xmo$\w+uސ& B*84L/× @@Ry }HjTm=Mu<ⷳHҼ[|ԥz!Ei3RSR9uRk4bi_ IG{供Tͭq볟wHQjBzQ*׿7-GU͇SO]RIjyqE'0*X iB+׿4uݴw|B5:rBj|]KZ}[Fq*y4\Ǽ)u.YwT5J'QYs@ҢL/~IU+O5\oiN\6M^ޘ''>sAϘ0Bzd̵6N{h%Mln@M"MB}0O! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g A 8@p! B3g ohO=>6!'@BqB N !8!'@BqB N !8!'@BqB N !8!'vڞEyCIENDB`PNG  IHDR x6 pHYs{Rk IDATxyw]{ &LE%*WQQE۠6h;*,(I L&@32dsB*$*U=?:AZ C ޿zWZp_rΏLz1]4:~TGB4u}[4'o#oGJޒ4b-mܮswٲyn뿕t?/ugC rt/qoֲ^KX_KDʾf_5ewI8v.}Eݘye @A V]݋wTG)Zw?fg(bϾLߚ%iZcTG9}<^3s>%3,Vo==:A$Yψξ\y2G9;LϏF>T((ߎg>5\K4G򱈦ɾM^OBZKt>_cpN f(ck^gdi.Z+˾R4>g$Ӳ]s_Fُ8.A77o?(棩1Qw@fc>$W_ͧD zُ:jdhg4o-!7}#PIsʗG騫ُ;bz~ZK!4-1} :$۲GFz<T%;JqVm0@%KKw70 @)ugCtܖ{}+;ߌjWI*eF*?Pѿh|yՒcxEw#X-}~4[Ndߞѿ񄈦~nꪨ>RbղpUٷ#X/)dIǾ-o~ P[)jQkٷ$XhM/J4A-q\3L8PR :?Z*VC_Ͼ%S<]`0jmtNYiȾ-п(R'iBѻ~0! @SǢ?|F$`5ut?&+!93֕ҨT=Gn̾57EwJ? !3`Nvx~*o\}C 01ަhҿ%MnղU{Wj.1\uU 0qh߅&ѻbeB0{}J'@fCQCI]DG"1`Vԛ7J#Ւbٷ'īuO1'J:'~$PP[+U/dߞ|fҿ%MtFݍُD a v}+~"Tû˾=f4;m6|hg4r;>}{ zO;JOrُDƜ(ۤ^*Z&TSoOMD?4͌@9x([pRiZo|*`K 9ߒ&qd?SlzӚQi__ Vh}ӿ'%} `k69_H?FSٷ'۠Y*^])Is?H` eAOPiP!/Le?3ly~*Z38oO/Fkߙ&1ُDƈ(ϩw҈=}0` qT$7f?<} 9^ ,]oNIz]uُDƀ(Ϩ^`V~)RMoS \hߞwEuSg w:(OFZ}w0hsߠԻ|e#g ~pJTѬ_}k0ߊjKӿE%Mxw_~$0 @!o^҈T=5wdߚ̣+5(TdW;(POz4M-]g?A|O3Q:Xl :TI]un~"0b @Q֊dJR}oKFD^_*i^!#3ޟ~)Js*`ԏ]ӿY%Mpwe?!_?F)QoKF/ ]%Mn 1t~T~p)z}W0W*ixBa 0zW~`)B"֚[1=ӿc%Mn{Ft7e? n=廥XJU(Dk@J}O@ɿ,ir'`=2QזCfzM{]T6[YD=ϳ{#P o%W~0 @ U3\Իx*YU?qOTK_-:j 9f PoI>`f h[ fcҿ%]"jgi%3(`U,Wh'o/3ޛ-'h`#YmG7o-SM}EwbwQ 9d P9L?XfuGgV0/RK*~0 @ >W٪{֟dR0e2Gs@{,JQ跳o)WMoS~}wsһi!Pt7*JQQ?~W)ꇯҿ%w#ߔ8`f释l4 R.J>4U2Q2({o%W_JN4M-yP&PvxA'VP?qw.i|k6~0G @ ӽҶV-}aԏߕ}HovI6r{_(J擲o!=Mޕ.i<.)1(L(JRf>0֚V,]5|Gs0~+@QG1bɾ}` n\7kxyُ/(@aObU-9̾u`,tO_$m][O~t0G @ SW5 ?6TOS𒶪m~t0G @ SEiK[Sӿ%O~l0G @ ҖThkoKSߓm/i<2((@aZ+_~(=gwWg.0MFϏK.1(Lk[ӿ%~2(Fαoٷ sK @e PPr4];Zk7\1(7[3o~I(@ @ cQ{gP L40Ū^M{]j֯jً$^2(F1|[׿sI#(@ @ cQξ-`r~ i2((@a @5J?"&Fh-9L@d P.PjdQ?vk-F&PrTRCoL~I(@ @ cQsh&Vף50@R~2(8oxs*@R~2(\dTI0ʬso0B~^ )7PrTYUwfCٷ62((@a @(zZSف @e PPe9/}Y/[~~ )'PrT]bh6=}f؋a{#H @e PPwȾ-0\ue%H @e PPg'B~ i~3((@a @5_Uwfٗ<ڨV4\Ae P.PjxBlǧ+H @e PPGޙ}۪i_O?_4?0ͺ/u`;kn$y2(Gf_,7 >PrTsY_hM{]T+H?o40w}h$i2(+/o`5uzs\1\>~ ́_ԂIs(@ @ cYoja߾&PAH @e PPv/ٗ50ǚMFf?PrTYukmʾyпbeY\1l6ٗ40_hSf7PrTU?ɾy63 I(@ @ c٨ZG4dz/g AwMH @e PPFOξ$w~>!iv2((@a @u>M})z_3 I(@ @ cjzQԏߙ}ɚަ{eY\1?g_\lY\1նV^+FE=?~f!i2((@a @ <'F/YHھ @e PPmKs H?0ͺ/]`DՏg)PrT[[eٗ-0g3 Iۖ(@ @ ct/[`5֒2$m}2(_Ⱦd1ѻg>PrT[Zg_izg.PrT[^s{ GkHڪ @e PPmI/} z~&lCҖg P.P깪V4KSûK?ߐ0z}csoqHڲ @e PP=[O̟j#7EkjaY\136 ߺ" ?0zA Y@yHz @e PP=mӋ^{_ w{Hz @e PP=]/} H~!3((@a @UwN wG?$=s2(~f_@6ղHz @e PP۪,b;,/;Dg P.P6KMoST+_~"3((@a @? M}I!~8PrT/G` :Q3Iߟ(@ @ cuNzWL7J?0jM-/E` >'G$}/PrT3ޟ}lpӉ#O2(脷x;2&YSG7染H\1e%L?'T2( yٗ @DDS^"`1z_H={/L?/d P2PNfFtsi3((@a @'Ͼ~/H(@ @ c:yUw.xZޒ~~"Mr2(տ|yew~~"Mr2(dU-5Y|S940U%ٗs~f940?/94>)$f P.PNNKg_n[lp)$f P.PNFղG^}l?~"MZ2(dԻٗV|R4i0W-}a4dz/5W}OH(@ @ cZ~se,H IDAT7~"MR2(h-o۰A?"MH2(h.p%~"MJ2(h-1/1-6E @e Pr `~Dy4 06 n;fϠ~?w \1-ɿ}i̺+]3((@a @lٗkZkًTr2(hyu `. @e P}~e0g GkzQTj2(hYɾT?I?J\1-f_R@h֯[^}} ,]{a n;ySgW#uGh"Ahg1R0T#ξ1дrb n<>- :'3Gu7W:2Ӌh9?˗OscWgܫvIN?J\1-ϾQ0E1_}P.ptO{o|m~~-/a{ >6ֿ}oA'<~M3((@a @ izQ4ɾ2G=13soάz]IVS fw==ѿtI <'P_D*,Prg~ Rc/EE7Dk?Sݢߌ;YY252((@a @˨~K ^ u%3?gZ3;_o W]1e_hB*%Prt|7/#`k'GEDk\1U^s/'^Q/` ;:g @e Poxٗ\Qa9wZ!Uhtx n95+x6NT" @e P:u~;sUѿlYt{s;Dط۲.ilmf \1W} ߵyؿ«]Q?rSe|W^ղ (@ @ c:-ɟ#DMzZt?QgJ}^3Yw% O@*!Prt|<6Wާ~cςg<jjA~k~x45ٗ*Lfh-1i3((@a @Ƿ/(_Dеf~c_c{{bxE307gi3((@a @dz~)kn%>}wFS=}YD2/{2(x6KS>z_xM^d~Og~,0ڟ~i3((@a @ǯjNEh|0Cߐ>1팈ξHOK(@ @ c:~.hecm Χ#ZS ڇT tİ}[@YݨV,]/k2(50ud_60{_EEtT]2Mѻx*/k2(x9ٗ >_;,G1=.=WՊݣho{G5(.c2(x5KB=ѻZK[ڪ}^+跳o%k40b;d`t5u (:';ZS Vg ;:d]0קϥq\1z_FR~"_oh N_NK(@ @ c:>kȾ\`4WG+jnii><`*2w4n0Qf_*02'4ZӋҼ7 g~ Mfߊ03.Q2(x43ٗ ۰7ZwL7K-%zLG {ٷ&e P.P~Fݘ}@۾;!,Z#sh'd4.0_ȾL E=guX? lz,忳1\1o_}j+gSʪSoaI7q\1ڟɈɾL`^45;Cњ^ƹ)O4;`t>ii2((@a @GeK/{^9$廦{Rξ`lMhi2((@a @GѬ?95뼨z]{W*Ifٷ:a//K?K(@ @ c:u}[s~h[iV̾`$.hY @e Pmp̺ٗ.z|8ZwHJVDei3((@a @G_Mg}cpӉQ|i{Vڇcf? UQ\1ͺA~htp\ n?3},p2(h6 ٗl~;zLGkzQU=y&S=j.F5PrtV,bϾ4` (^^?Q=wҨf P.P^:mt7D?OJe/gg?>`^5WEkai3((@a @GᷮȾ,`IJچDُ7ޕF0Prt{eD=̾,`XkjaTyt~u^W @e PѪwe_UꇮOJڇwxW{i2((@a @G_;$`4uX祿?%~>/d?i`/[ޕF-PrttxuDd_MEw;%qӋbpIُSGGMd P.PN !r4Q#)iZ+Vd?z`NuO}O;W @e Pѩ^}}ϬiZC;SE O")]+R2(hT:t7F/%93(ND?F%Prt4}/xZc G%֚GlbpӉ;CEYiT2((@a @Gk/![N]ߓF!> e?`5]EV8-Pr4j=wFK=HI[uk^{_ ~HUWEC{}^Mi2((@a @ٗ|Oz<:ZQW;$~ѿ=O}50){2(h~/ɾ `FhSFISeQ?zs l\Έ1%; 3((@a @sV>gv [е3CwZ[Zc 4]EVΓ&%Pr4 <'ZKvN/Jߪe/d?SMwc ,WSNI(@ @ cs/&cxwZk#Q=78G)ZwHI?0yUK_og_LsCI9g?!O)/Sth-)}%3((@a @~&հ3ޟ.Tfʗf7&O鱧ƞOEwFKK>Pr4 D*:v{PRU"'~0ަ~_u@tOxMGd P.P&50Mf0~+=(i"3e? `;n:1z|?>(]#in2((@a @sjz&Mf;PdUcl\`+k-Fyjdw\1ͩz&n&?M{]gt}EV,!)7Pr4zL SG :ODz*3?Ԃ\1^4LOI#TߍOFQ^s{ n:1z|?>(} i3((@a @)oMIҿ{j6]=܏{ܗ40 w@~$_4) 0sA/;:_ZG]R90h(Y=3vG飥{J_(准VIR @2Ht 8X;gU)cR]wn)ݫ#K?ÐYd (@2SK~"Xª+='IR`ό8)]Jo}_7GHҁ(@^N/~bjXg2IRx+Y Lʰ_~wn,OEi;4$ /Pd @[wF?1KXLRvoWot]( L$e tܹ%XwCo$թ΅oxQƾ.ܽjyio:4Ox~g$i @2HtspOD?1KQYZk;&Iuywϰ_~e{WNYi I|y$c:[2yX\^s$չYRp yUU~ҿeWƊgݗ$&P @1Jo=7yXjZc7LBkWEjCU2ҽjyio:4Ox~qIR\y$c:'vE?/KLʹ%IK凔C7FtÒSu.]Jo|Ti;<$Ve tj`~뫾ZUƬuKK鵢?¡2|+sr?eqw%I /Pd @Sߏ~Zׅ/IZu##jڳ R7Q+wT2 %叇.IZ-+(~ t+퍯-Q"P @1NÇn~ZTi%IK?\Ξtn vm+kKgQ}{e ZR`^WKԽm0A>߹tܗwLtd (@2}+%b︣qKR4wPI @2Htu/{wD%IjyIOG?j?ܯ[]ڛ,U/{#I(@^N],Çn,ewKxo+;Jo|Ti;$- @2HtUO<,s^~$)W.cpP~wn,ݭG*}$ie dk'` %IkR{|~^7}֯Ʊ^Ie (@2]U֙/YUˣ?Ij?YuK{ӑ?ߒ$M3P @1lGfӿ{%ID-gp۾t6UZ/e%Iay$c:w]pPZ4^IҁRWOѯ΍pDixF[I3 V5~Rjo$ho>'㟚.;}_~$e j @͵N{%IZTǢO3V]_>w,JT2 > @ 2VIҁZ7EiU7/GֺKcnY;Ijy$c:zW~NjuJ斕WG&a8?[v$)Qy$c:wn~Njjm~$BM,-՞VY$){y$c:'~NjjWG)Iҿ*DU2ص-4W0ό$Iby$c:'|oSPSSCo$_7JRri}l>johmgD$df djO @Mu/;%I?2{΍pDixfIOg (@2{ٻ:{JSܲ2x߲:sK^7Y?/%Ie ~(z˦z@$NR3B~ 9}}i$I /Pd @'#7 IDATۢ~$ItNKϠ[_b|Ti~j[Jf (@2h3J%Igkj=}.cw΍{J_ 7I4 @2HtNgڛ Qg:\Fepҽjw >$)&P @1]| 0ɯ1(I<-? yW9Tݧ`׶۾vW;<-$IRm2 ׻gf}o}$Vc]RtKSK7)/-Kf (@2op':KOsyɢڳot]( +IVy$cj3P#;&Ix }w{tdi$ig (@2l3Ki$IMKUݧ`׶۾t6oL$ /Pd @W봟~BjjlȲ2ܽxz\'KcF$ /Pd @W8 ko$i^r?=) Gg$Iny$czמ }$I Gz+{^9W<{sK$ @2Htq n( cw%I^n vm+kKgQҘ[Q$_ /Pd @ۣ^uL]$M凔᷾:!ѯ΍_<$Icf (@2hR'&Zk,6I&R7_ٽܯZ^%I&(@^.~>jb{G]$Mee9_,{?tdi$IS /Pd @^{k^wI4Z<^$If(@^.wD?5%I$IY2 Ѕi@ =&I$I4 @2Ht 2޵'$I$I&(@^.hEM$I$iRe [R*V=pi$I$IPy$cZ~:j97I$IIf (@2 :$I$I$3 Ѕzt$I$I&(@^.?t9I$I4 @2Hta Tw{$I$IҤ3 Ѕ5|O@9G$I$M:P @1]XUgO) G$I$M:P @1~6 v}=$I$ie |yw݉H$Iid (@29@G$I$M#P @1e~6"UUi{$I$I42 m?%4|[$I$IҴ2  @ E$I$M+P @1C7E?[~$I$IVy$c:~G?Zg<I$I4 @2Ht̖ZJ5~6 H$I)e (@2\' [o$I$I /Pd @ǫ}+ @/}$I$I4 @2Ht:Q{o$I$I /Pd @ǫ{ٻ @j-$I$ie x_djzA-$I$ie ?' Hv$I$ie x :2wH$Iig (@25|' HYwH$Iig (@2U~2t/;$I$IҴ3 1ZR*[$I$IҔ3 k P?~$I$Ivy$c:z~.T} :I$I4 @2Ht>R=;$I$I,2 |ϣ ]ׅ!I$If(@^^~.wn C$I$"P @1k W!I$If(@^ϝ ~$I$IEy$c:z.~.?kwH$IYd (@27| H딟C$I$"P @1 ~$I$IEy$c:zUgOsA$I$*P @1ψ~* wH$Ie (@2< ~$I$IUy$c:ZuG?A_~$I$IUy$c:Z T};$I$IҬ2 jo|]Sw;$I$IҬ2 \GO@w!I$If(@^Vw[ ~$I$IUy$c:Z+.o!I$If(@^V ~9I$I4 @2Htz޴>ZwH$IYe (@2#G?A'@$I$iVe h LSYwH$IYe (@25x  ~$I$Iey$c:Z7G?7H$IYf (@25O@j$I$I,3 ;3=7H$IYf (@2Uu~* 5I$I4 @2Ht斕2D?_!I$I4 @2HtV>;2;$I$I 3 kzA3dp%wH$IYf (@2\g +I$I4 @2HtZ~&o~$I$Iey$c:.G$I$I /Pd @篵ᗢ g!I$If(@^_WG?A7C$I$2P @1V3$I$I /Pd @} / C$I$2P @1L}wH$IYf (@2׹@'!I$If(@^_w_F?Azם~$I$Iey$c:ݭ~&]~$I$Iey$c:KL1$I$he u/{w3;$I$I,3 ^g H5wH$IYf (@2׽ !I$If(@^_Lpj$I$ie u:&ҿ;$I$I,3 ]"ҿiC$I$ie >wl39wH$IYf (@2׻g H;$I$I,3 ]*ҿcwH$IYf (@2׻g H $I$I /Pd @篷@[$I$I /Pd @D?A^~$I$Iey$c:k ]~$I$Iey$c:/~& wC$I$2P @1 F?A~$I$Iey$c:~$I$Ify$c:z?\{ $I$I /Pd @GopE@7G$I$M3P @1;Ύ~.uH$Iif (@2vRsP~$I$IVy$c:zϾ7ֺ I$I$M+P @1Χ\@{o$I$I /Pd @Gs I$I$M+P @1G^\@o$I$I /Pd @Guˢ znM$I$iZe 5HsP]o$I$I /Pd @GywG?5P=`M$I$iZe TpdDJc!wI$I)d (@2U=HP͓_~$I$IFy$c:^Ço~2j}+o$I$I /Pd @kpg l>*&I$I4 @2Ht~޲)#&I$I4 @2Htzd@ 7I$Iid (@2ս]O@ ,&I$I4 @2Ht:~2j`؝7I$Iid (@2oD?uoܲ$I$IҤ3 jO@M4O|Q]$I$ie x5W0Y~$I$Ity$c:f\J5~6jO$I$I /Pd @ǯj<l@7I$IIg (@27|g;7$I$I&(@^+ ~$I$Ity$cg=o$I$I /Pd @ǯwg4V>;.I$I4 @2HtmPu%I$I&(@^_7E?5$I$I /Pd @ǯ@Mt/y{]$I$ie Ng&z`]$I$ie 5W  K$I$M2P @1]@sJ鷣>$I$I3 ЅU=~_Pƾc@]$I$iRe jM$I$M P @1]xG?5>wI$IId (@2 o@Mt>$I$I /Pd @[ύ~>jwwI$IId (@2 w݉@M t]$I$ie ^&~$I$IDy$c!A4986I$I @2HtF'86I$I @2Ht5W0G#6I$I @2Ht+`$I$IZdy$c߾7   K$I$-6P @1]\{~BjbMK$I$-6P @1]CoD$I$I /Pd @W~BꢪJ M$I$-&P @1]\ 0 / M$I$-&P @1]\~Bjs&I$I(@^.â]26I$I @2Htn#mK$I$-&P @1]|Go~Fjbp_ IDATwI$Id (@2op%@]ۥqI$If (@2wÇiyIm$I$ie ^gF_~$I$IZhy$c:n3P#um$I$ie k@o<#6I$I @2Ht5{n3P#?~$I$IZhy$c:O @MTO?~$I$IZhy$c:o~Jjyw&I$I(@^N臢_Hk/&I$I(@^N'G?%5䟅&I$I(@^No~Jjw$I$IB2 F\~$I$IZHy$c:ZF' M$I$-$P @1P\ʠEUqύO$I$(@^N7~Njuo$I$If (@2kp% @t.zsm$I$i @2Htr>Fz~$I$I7P @1\-o~Njdp$I$IҸe j5 @TO M$I$(@^N/~NꤪJ} O$I$(@^NJ鷣i I$I12 6|'F:)6I$I4Ny$c:w|*Iu'&I$I /Pd @'[ouqm$I$i @2Htu>O @T~$I$I'P @1ljP'հ4$I$IҨe dkO @ʹ$I$IҨe 脛[VJH?O$I$(@^N÷F?+5һ~Mm$I$i @2Ht? o$I$If (@2wgF=M$I$(@^NEo~Vjy$I$Id (@2i$I޽G]w$JEWۑ֩Um3.{+-Ӗv:uV֡i.A1r ĈQADcTGξJ20 |~zoď&Iڋ @2H_g+\$I$Id (@2 S-}$I$Id (@2 K?Z*2$I$Id (@2 ړ?Z*/ O$I$=^y$c0 GT O$I$=^y$c0:82 ~$I$Iz @2Hta#-\7I$I /Pd @n@m$I$2 Ѕkk?^*2$I$Ie (@2 Gd<(K$I$I(@^.\K&2ݵ$I$I(@^.\s^Py O$I$=Vy$cpu׼42\~$I$Iz @2HtYRʨP/O$I$=Fy$cMGTI$I /Pd @/K7FTs+I$I7P @1]؆L~$I$Iz @2Hta 6~$I$Iz @2Hta1pf}$I$2 -e2$I$I(@^.|{1PQ, O$I$=Ry$co c2wT}$I$2 ЅoxQ3$I$I#e (@2 _ߏc$I$I(@^.|ݵˢ?f*3$I$I#e (@2̒RF4߹3>I$Ie 4t$I$I3 EKӛΉL}~$I$Izxy$c8 .yGG @e{[}$I$e g'I$I(@^.N/>~$I$Izxy$cH-ߧ4?nj2٥7J$Id (@2kL=/ O$I$=4P @1]Ŀ8?'I$I(@^.^-2ëNO$I$=4P @1]zgqP-[$I$I /Pd @qϋLӽ/'FI$I`y$c5߈L'I$I /Pd @ETwO$I$=(@^.nkFTfxI$I3 ŭ?xG$I$If (@2[?r*|$I$I҃e "w2GTs(I$I @R3Ht|cG@ez{U}$I$iWy$c;7c2Oe}$I$iWy$c >;$I$IҮ @2HtmLnO$I$ /Pd @Ϗd\|f$I$ /Pd @cj:DT{/'I$I @2H4FT? O$I$e hLëPgN O$I$e hL P׮ O$I$e hLS~.6nY~$I$Iӝ(@^u3J?~*],FI$I:P @1k2=2OI$I4e h_tN@eWO$I /Pd @\?zY}$I$Mwy$cWC?~*S?-FI$I7P @1 u%I$I @2H4f~. Py O$I /Pd @c'@eW~$I$Iӛ(@^6'@eƷ|*>I$I7P @1m׏j(I$Itf (@2u׼4 P(I$Itf (@2-ZiG?*Q$I /Pd @ve32ˏ O$I /Pd @^6P/O$I /Pd @_g@eνI$I4e h|ݓ&P;4FI$I/P @1٥zO>%I$I @2H&wI$I4}e hoS2 O$I /Pd @h-O4sI$I4}e huO@:H$I$MWy$cZIG>89P}$I$MUy$cZOo|!9PG'I$Ite (@24@e;6'I$Ite (@24_F?*W}$I$MWy$cZO*9PΪQ$I /Pd @ssJi'@ez:FI$I'P @1[_~Tfxي$I$I @2HF7F? *3I$I4=e h] .yG2Me~>7J$I4e h]'@'8FI$I#P @1)i%I$I @2H&J2ëV'I$Itd (@25ܹʌo">I$I#P @1'*YPa, Q$Ie h}|eB,FI$Ig (@2YRI2 ~$I$I3 :ܳ3iPᵧ'I$IR @2HF74$I$)y$cZg@mƃ23o$I$)wy$cZg3^4Po$I$)wy$cZgUd<`[o$I$)wy$cZo}$I$Iʝ(@^h@e&s$I$)wy$cZo͇G?jLJg~7J$I7P @1_~Tw+o$I$)oy$cZqG>(P"FI$If (@2u7'@eF;7>I$If (@2u7'@en O$Ie h 6%P)coI$Id (@2u=}H$I$ /Pd @+g2D?*3(I$IR @2H&wL 'I$IR @2HFםLLs?'I$IR @2H9PΪQ$I|e huOg@z:FI$Ie (@2-hvi)^S2\$I$I2 v4ڵOʌ|q}$I$ /Pd @ړ i, Q$I\e h;__ %I$Iʕ(@^I/~*To$I$)Wy$cڒf-e0\7J$I*P @1mOۯ~.Tf|I$I+P @1mOí~.f)3Ko$I$)Oy$cڞ P{^~$I$Iy2 ],Po Q$I<e hZ~2Tfx)7J$I&P @1mW^d$I$)Oy$cڮW~2f<(G<#FI$Ird (@2 7J$I#P @1mWw$P(I$IR @2He-ߧ4{ }%I$IJ(@^>ldn{}$I$ /Pd @# i&b%I$Ijy$cھz~6Tw Q$Ig (@2sF?*4oo$I$e h;k@e_H}$I$?P @1mgϟtL3?~$I$I /Pd @tP Q$Ivg (@2_~:To$I$e hK;LF >1FI$IZ(@^7F?*3ck}$I$;P @1moE?j3#~$I$I /Pd @[?~>T{/(I$IR{3 =駣l%I$Ijoy$cf-'@eF7}0FI$IZ(@^W/~BT$I$Ijoy$cW3 Pq Q$Ivf (@2G?!*;7J$I @2HuN'@~$I$I /Pd @_ףzi}$I$3P @1m/^`, Q$Ie (@2o uOzy$I$/P @1m~FTo$I$}e hR&)P g(I$IR2 MRS2$I$}e hF7~ )P)~$I$I /Pd @s4O %I$IjWy$c*)P%I$IjWy$c# 9P7J$IԪ @2H4O;~NT~/'FI$Iړ(@^ix u׼4FI$Iړ(@^?~NTo$I$=e hkE?'*}$I$I /Pd @|o$I$5e hƷl~Rf2*G}_$I$#P @1co$I$e hz|MBOU$I$#P @1UgO o Q$Ivd (@2jsg2w'I$IR;2 |o YP;E$I$՟(@^kp;%I$I?P @1W}o$I$ @2H4_2G?-*3%I$I?P @1dn{6^}z$I$՝(@^ltÙO uO=0FI$I /Pd @s~ZThp[o$I$ @2H4gݓ&iPэo$I$ @2H4i32~^Tf/(I$IRe hƷ]P Q$Iz3 м :!yPކCo$I$ @2H4os_7J$IToy$c /~^ThO(I$IRe h~bT/Z$I$ՙ(@^nO uOzy$I$ՙ(@^nɿ~bT? Q$I:3 :8PѶ(I$IRe h:+]J3~fT%I$I3P @1_~fT%I$I/P @1gE?3*(I$IR}e h4PU'(I$IR}e h\3B;(I$IR}e 4a'PwJ$ITUy$c:o*P{5FI$I /Pd @'F?5*4o$I$ @2Ht:@_0FI$I /Pd @F?5*t) S$Iz2 oG IDATy u%I$I'P @1_(P0FI$I /Pd @.Puo$I$ @2Htz M涇(I$IR=e Y)$P)~$I$Iud (@2/F?9*[[7J$ITGy$c:]~rThxي%I$I#P @1YB[/ Q$I:2 {/D?9j4/3K$I$)>P @1f^ʨЮ@$I$g (@2䎭 6y$I$g (@2pg@v|7J$I(@^N_Po$I$)>P @1:_TS$I @2Ht:k碟_%I$I /Pd @O ?#FI$Ib3 le&P=;o$I$)6P @1zmFMS:;%I$I /Pd @=w$I$).P @1&~)P'(I$IR\y$c:nτ(I$IR\y$c: .zkFQ/NI$Ib2 {J:8NI$Ib2 )n饌zO )I$IRHy$c:M& P- Q$I @2Htn]`. S$I /Pd @o~T{wJ$Ie t=OJ >;%I$IZ @2Ht[Oi:D?C*4wJ$Ie ;7G?C*cQ NI$I7P @1`L3R5?~$I$I(@^w!J?GwJ$Ie :+/i"m{$I$-ny$c]MRSBͷQ$I /Pd @э";%I$IZ @2HT\@ NI$I/P @1ծ)I$Ie (@2R@&~)NI$I-P @1ՃM&9PΪS$I /Pd @`ík#;%I$IZ @2HT?J =9NI$I'P @1ՃuO|qsR>NI$I'P @1Ck碟$5j9$I$i3 P=OJ>;%I$IZ @2HTme&IP')I$Ig (@2zh~Tjr wJ$Ie Zg4MF;}$I$I (@^M,T~$I$I (@^፶?YP$I$=^ct~f (@2zx,䎭wJ$I[wPl>/4M|gkiy$c=g @j$I4[kp2RƃGy[(@^k饌zOJ[%I$i*~a2j簳v^uBf (@2z&w\4W)I$I|~xǦ=?|Nm /Pd @HZHƷ_~$I$٥{ϗh2^J|W2- /Pd @HCVQ/VI$IjI3e?}_?n:'{K3 P=R_4XCo$I::6Z[f(}!n|A?f (@2z @~$I$Y=?息Zw~,O[3 P=Z㝛'|wJ$I"7tϏrem}m/iJƷ^Ϭe  @&[%I$iwsaeuMve)~isliy$cGw!V$Iݩphl-Jӽ5P @1գY? X+V*I$IO]6޺`eK%=_ g @2HT䞝OJML$I8./|sm[_&sKi&e4߾=K3 P=Vm~j2oU$Io/*5e|ەzeZ5sG[3 P=VDXoáJ$I:|ewl*MDJӿ?3jky$cǪ{O :!VI$IPg~2|wk7nm /Pd @.-e؍~Tjr J$I̒]lr]wzm/Do],?f (@2z&w\LU3)~$I(-ík+K9Yo3 P=^x4s^~$I9GJ)ˏ-[uwO&P @1?  >1VI$I5Y_; 6^F֗[Oα?ژ(@^~Q3b~$Ife22^J3>:=/m0P @1|t~Ԫ$IScS&_t)~7sAǿf (@2ڛ;7G?U**I$i:6Z[fxǦt ^ @2HT{`LSbkO U$IwQ*uh=?ʝ~Qjcy$cw!OM~$I'̒]lϏrߺLf^Z(@^joܿ~T̏V$IR[~+KvFw @2HT{ۮ$M 3 P=_g @͆2+I$=fI?]q]2R&oVf (@2z D?[*;J$IOy+ëVmW2Z OY @2HTO]qexي{%IG٥2ecSi碿B‚Uژ(@^Y)$Pׄ+I$|枱VFPi%",?e (@2z2Mn~l2.~$I}KwxXn]G!LWlay$c'3.$IR:( =?ʽ{_@ʮm6f (@2z2?GOʍ>sZ$ITgQ/ϟ_=1P @1ՓE?]*|J$./|sm[_&sKix:~1s 3 P=?4oG?_*=o$IRg2ܺoQ?=0P @1ՓmOF?_*7{%IT[UކC`lT}_ ?ke lˎ~Tn+I:+T/ϟ_S{hcy$c'[|\ӿ. Y$I=?7Ѷe2f Z=/e l[JD?a*{﯆,IE2ܺoQ/0wTm /Pd @Tܳ3 PG+IZg22[;6Y^yim /Pd @T#L&^I$=:++uwT=Oicy$c`ӟF?aj7 Y$I̒]lr]wzm/DK:_L 3 P='L%Ir2ܺoQ/:wژ(@^)5oiD?c*7i7K$Mس22[;6so"`u~Em /Pd @TzY3rͷ~$IR:+]z{U\2GJ;ߟژ(@^6g @ t%I4t.+uRIBg0P @1SwΫ1-0o$Ija)5?ػhK2)(nmc8(!m1Wo&+v4jb&L2"T 2I1Lʌ(2g~~j8gݯZ￲:V5c=2Eh/kay$c i1-P|Z͒$I_v{{KETD1hf @2HTsQme&],S߅f (@2у-Iֻ>/?V*2EWUߊf (@2F?~G%IT]?wʽPYtxwhky$chxmZ$I?[%{O*O(ELQ瀷ߓf (@2z'eGovݒ$My6{W22Z}C)M}"@~g (@2SX+am~$ISǫKďJ}E {yP]iky$cyiF<%z(vI_cg1YEiky$c7-1wKG<e4oO[3 PW) @K3 7 ]u8o =m /Pd @5_u7-=o$)wY`L;m /Pd @5oR~G\S$}я ;m /Pd @54#@K>nIr?G;Ƥ @2HT;{DhjW.IR}N3 PgcEj%ICOc2 @2HTYGhso$)o,cxw͹y$cnsڢjVK/c2` @2HT/Gh>~$I93\isy$cwʧ?o$)gM@`Lz'yisy$cGhxYy$%k&3t_oO3 P{ 6*M:-Jj>oQߞ6g (@2G-gDh.IR:Zy`=^~{ڜ(@^jbGi,8~I=?G7ƨZeisy$cq:-~I;ѧ qN3 P_XJݏ" w_4OLi`LG~wڞ(@^j\~xyK5bakN3 Pqe:{.~Ir4g 1o='=P @1ո}O?L _շ IDAT}u_ ;m /Pd @5]^qeFw_~$I9SY`L~wڞ(@^j5MTR$XU`L. ;m /Pd @5ΆJG!~I]% 17ᷧe YԿ2/IRc;Cᷧe Yg߈6ͨT;| $fQwߞg (@2k 6.M=-'H0IRk}ѧ 1 @2HT㮾=-S%IjoG2ƨZ @2HT?ͨ.Nۆ0IR;^{L%`\!P @1ո=-;/o$^}уߝ e MJ}$@?f $G1Ƥ!P @1UDό6T˷axR&0&{d (@2?Eh?~$Ic4'Cy$c:=@ 7~$I{F/ƨͿ =2 P ?m3jK$5W} =d /Pd @U}۹Zw⟇0IR{\`nɐ(@^*?P}7LԞgӥkoO @2HTQuh4,Nۆ1IR;j7r0F3K=2 PxR'@ Nt$M|-Ki4oO @2HTw^ho0I9' 1!d /Pd @eO6jF$i} 1pVɒ(@^*~Tg$i$\0Fë =Y2 PEV-yq) B/ cɮs .X~{d (@2nte6jR;&IܚnVQ =Y2 PE7hg@KB$Mf-geG??Y2 PE=;&I:=L0fCɒ(@^*jKKO[&I`HӔśߟ,e &я~ %wL4y .R` =2 PMBU{E?Zy2`[&I껾}5ѷ'Sy$cIw-=x[&IlTޣ 1~+'Qy$cIZM)Mh2I5ѧ 1,d /Pd @5)VhPY[&Iz_hi`z)P @1դ4l@[&I>KYwߟLe &~Xo$i2ݽ*,0f?2 PMJ.E?ڬj6LܢJt4goP @2HTD? Ze:90fwߟle &ᕇF? Zlt%LۚR~^ɖ(@^jO{&Ikxѧ1[}e (@2_$hyK$)7E"Ƭ-P @1դ)[9P @1U}ODG;I6z %[ߣe P+ 7~$I_wF~[=P @1U[Z0'tzmm$_+$pb-ʞ(@^- .?}o$i=ZT?>#ꟻ(% /Pd @Ֆ@"MR-{i}$[܂{=P @1U[mUhdH߆7IҺ0:{j=ʞ(@^M$Hef&MvUK_Rʠ}>ԟ)3 6I3 PyK ty_}$]o|2llͿ}!P @1U;Od okw6mx!h2 PEX oqgKiF'`?~!P @1U۪o>=̚}$I;F &@ IӐ(@^mWlfTο'IznZG}-d (@2j[^lHhx7Nuy_`4~%P @1Uk-ͰW] qVrF` ?!&MKy$c66@B V8IғvRFu`4-e X?~:$-ղ9IO,<0!#.MKy$c6V-ݲ|H$_[ii740 T˶MS(@^շ|HyefwN;Cg 1z4Me Z/D?7wN2~4Me ZK)Tef o$MsC/0A+?~)P @1Uk[Qi7 Tu47} ݃MӔ(@^ >" .z~i(E&Ũ.3KOӔ(@^p ɟ u4 8(0AF]~-P @1Uo=S `>4姀JҘvڶA'0AW~-P @1U}I3 7>~$i$ ?ߧi /Pd @^Hy2NjJ}$ 97j2 PAo~F$_Cihp|&M/dd (@2j} 7)M@bR-2IR[hW>ft7j3 Pehx1O . wˣ@U{ߨi /Pd @ ~J$/NۆR_~%i>ꟻ(kkE34P @149~jP;/,3 7 4uW):+oY~ @2HTSтK؏EI~4_\χ4=9P @1մ4?%oOˋ-~Asi* t{c]ӓ2 PMKݣ0ffuvyEmnFex͗NHyw%Ie EPY/MQ֣FHbx!wMO /Pd @5M)ELEFIZz  ޱmzjy$ci{TޒZU)e؋ zP/ ozjy$cj=M7RjWfoMov}g (@2I,NۆHIz[D]L~e q~vElQ. ξe _TJ&S :`w]\fl~;%%kƯG0Ee j+e4~VOkEOIIZEo=' )=x /Pd @5?8+ZoYYf ~Jjwղf0S}efwPϝ(@^jg7$PI]+뢿B Z @2HTޚ~TO>u|kiqWS{{o.P @1WN~$PIR2Du0#ڢ @2HTz^륾R-yq-4WPJ3` { /Pd @留%[ҟ~^;/,җSIM /Pd @'^Bs6Zu=49U+)E=@)Z߲ @2HTzޱ~AF]W]^~S%9J_K0ۨu /Pd @m>$`4[:1J wJ_Goz_-P @1~/G?I`M=瘝V-ݲ ;.+lTj6wR(@^J?{E?I^*iò+\ @+gwT(@^JO_/D?Ow]).ۅ]IOZu^qP)M5n-җSy$c*=}ծl0-~{%=,بNXi` ?!j25 IDAT P陫o;7xߗ_iZ2o`c~Wae NDݽt|M jK`^~<)4G̎/ ڰ @2HTz檥/)ePE?SX;,ofoygsfx7V(@^J㢟)o9Tl~t-ب`=gs{Zmpy$c*={ݣ(@ffu{,esK}w6̋f2p{  /Pd @hᦳ_Y&.K-ﯗOo&P @1*k:).3 6R[xu^ux): Ws(@^J]7G?U{*~+>K\g_-+*e4~0|,(kn2 Pi!hFexQ~-3uٷ'~0mwXs(@^JkךP @1֭ξo~Nͨ7Z:-KOMiUʠ~10Foߚ @2HTZF^tމEuK}OZͿ 㚟 @2HTZMFZ+w(3;(k~{OѽWE?hѰTl~5?e U_Vʠ| z [R_~|`7~5e ~ =&@>ͨw^4gl~۔މ+MR?Fy_y$c*_| p\vU+J}wfGjf/3~5e -ظ4`* kFo9_,{@z w @2HTZ.~0]~쯈v~yWӶ5GG2`z4R? h~3 PivRFu3Ԍ+KEk\ynᦥf^߻_1[Έs=P @16ֳ1OA{c4-ظt}Cܡ7^J&#R_Nмg (@2҆;Cᕇ ).ۅyAkю/*COkD2zOꁟ>Ee UQ uN,t{Gm狶VK{7 =f_1ן /P @1Ӣ30,MK?-}~,~A9&jWyz^qPﺸ4GkIwDc /Pd @{{30Fu=xko9 GW{U:{,<#sY|OL\go>YhtMefF>2 PiZO W؏Kf}J[\z'}tMWJ%q^YEv {ĻKkVgm\K^}df4ǣW L5^{5P @19_~@Y=ӴF^Y[ϙO(+-˾Tg^EGgZ9?s[DhAT_w.oy$c*]?o\1o3 Pin[S2kQoe 4uW`=b2 Pi[Q=pK c[߳($P @1~y2pcQLy$c*}ղJT`W~6W(@^J𚣢7:kj2H Pi~ =U(@^JUO`RSQly$c*_?>Ee 4-ܴ4Jߊg (@2?9~xyߣh22 Pi~VlSʰU? {MFy$c*ë~Ϩy2hCdd (@2~ϨͿ MNy$c* ;S4GKl;d (@2x})/ {MVy$c*ۣ<O Rmߛh2 Pi|'oM^y$c*jJD?{RAveߗh2 Pi /?0U=&3P @1[g_+i>0͚Q'df (@2o9#Slx ? /Pd @=Ow'Nwa+*6qRCڱ,q484$m+b3–X-bY` #H! s~kO hy?9Mj/~W~D(@dSe轈P|9ȌP)ş~𽈚P|9ȌP){jjw"j|@ 3@zW}:zcsG!j~@ 3@ǩ.#&fC(@fJ=19=F#r RlłR굢Gv8r R|= u~(|(@d_q[RPnUCP|9ȌP $zo(@fJͨLF/r Rs*!z$}F/r Rsd|deCP|9ȌPYUO= O=F3r R\;n@ 3@51#UO=QUש _@2Tj^݋0z4#{ѻ v@ 3@6G?z<*S{a t@ 3@fֽ0b _@2TjhLsG`T۩XxpNC#P|9ȌPu//# e((@fJ n^Xn=y2E@ 3@f]14\O0O@ 3@@C[֦֜w&r R]ѣhE1|wr /q*@G6/>=.6ܜZ3w*r h[ydso,_@ 3@mG+e@ 3@ѩwD 2P9ȗP8F9{z߲8~Ols /q*V>=6@uw[*SB _@2Tfg@#:r սѣP=Hj݄(@d4MH;0:K((@fJYF`.GhwlH@w_49ȗP8TOn+n5&3h|s /q*UOG`WU /hs /q*e왩z w (@fJչG R1u{(@dg :|,| 0r ROoJu=b0s /q*GUS=\,q*[q[Rt z+>Caߊ~ P̴տ1SkV>i0$@2:W1TG*O݁u_C 3)o _(JnoQDSwOz8L!7{f67Wx*>~g kC 3Œ/% ߍ7u|wwU7G(@f~8|(izY׿eq@zf~ @ds/%MK kE[ OjtqE?(@fW&|(i]?'z HT{ѡ/!r DŽ/%McJǢGmgW9L3×}Ro]yWw_G?(@fk _*JGVFe6| HF?(@fׄ/%MSߞRُAgmpO!r A/&_,JN@zۆTC@ѪwF?(@Z _,Jyz,;<_fLiЉ~6 P ~(~()eAKÿg9Pw—'= ?`~i'^C C;/%^ΔA()6oxiw߸0)0MdlFIͩD%h깇Sk>VmZ&@rVRk~ GI Yڼ&z2@^owi7kmѯ i sK(|(9unX<2]zߙ~NL#wYQR}~h(:&fKSQ}O i wNj}}QRs*{c碧Kł¿ե}?~RL3c? _>JjVKShXe?T_(@cD<ʯH/Q0=Aoqi*k֔*u(ieUOR=t]piܺ$i(<"|)u.w# |[5G74R`jRRR3}AmHű{KS]sK×YT1zL*{}¿TE097e?:4zJ.mib P1[uJrRRsܵ,zLliKu{K PqPI/[1 ޺>zRn6ޙZ ΖQ `LoY:}$UKֳ8¿aTwP/F?3(*8×[FO*yU:^w4hcEJI YzQ;sҐj/~WJuhc}—[{a)ѣ v`Y71#O|? @\iKIѣ ^Uiuj';ZVoY3a:ERR]⡫G%O~k74cLu@8 UR×[qGRg0saK] ×]缏T ~L+Yf~f4P~}LIͮөѣ ~dpײoei H O r T[7ּ}×ѯMզ RnUjoei ,`@1՗/5%5CS귣c~TwP74̺?h8ΥܔzW}:zT0^tX4ڧ=~h8;&f qSsG㿋!V}]/0SoN _vJjnqoLc3P_@xY[/<%5ٿR5WgKîwE?5FP^Q_zJjvk=\u5{f74:RUF?7FP^YO3Ԋ,IDAT&fˣ{( X{;Sݛ~nj:—[1ToY=LޜڧRw4̊!ՓOG?7FPvHԚ_2TR" : \ :sÿwaV,8 U>Q@aǾ&ܺ?=A]ΕY1oTm%0S/I{/G%5]E*F\ogÿo6wT>qcS`9`\&$̎wE*FTƅ߶0w*VS @%IыRI}/-zT0b/J-}Fkp .SJzٺ"zL0BʵoeYiX OD?522 ^ֿ16ݛJê8MxWS 3@m/Lg/Q%59{e ^Qu]*9VRS%U~jd(Sb4yeUpH[D)noIEJêsomw)S%{SRURj1@Jê{ٟow)Umy<I?Y=hL݋0[UJsJ@rugkjE@Nߨ0*9VE2ƄPR;iKWI jTN PoO!ozrS`8`H/_%5bڼ&z<ݹߥҔ7gԻ~NJU3@j8_/b%5R}1z<07=*MuEj 1QRcĞKYIͨsR4ܹ4&fJS=So) 1iU%'5~A+bX`}s\74U3UO(zE^y*i V_=r55gOi *.WR5~ZP”IŒ/n%w̬T=ykH`Uo~0)n3R⏧zg?(2~pZj-8 ~+)CR=)z"0EH7oJ[n MFͩ{gK]I1u|Jn8`7U>)N%NCWG?'xE@hهRO XJQJu=E5XKiWk/~g*~F=;"|+i].6?WJRgRJ4Z퇠~T,? OJ;ѯI>~BK0פ&4f='Rq[%}ꯤOu(#|6nZ'|XҐO5z -D{5SwRgS(S犿LG6|,ixqڼ&zS[O5b?KWT L9|vFjirbŲ_Nu{s_f~=R{ɻS/SO(-KR{eP):g} A'z?դfLJIli|i]Tݪ{'R0Sq/#j ;fceNJc7kE? QK5O3#M=+~q-i]ߣG تmHY2lީϦiH3u/Ի3SSyMJ?/U|Կ٩~5o>-zzVO.^Oߓ-kSTMnJUg[?mH1HIENDB`PNG  IHDRHHUG pHYs{RkIDATxylTEEz%FLHT4@#cA Z˶ ,*( *%$"XGҔ}oLڤ۝yݝ7ofJH$lN$! O@i!g 琉y  J0d'C-yk#_iSܿL=[ߢm>d6{éxvȩB2,zs3RK&@3}!0qۀYHC8@N H{wx swDӧt@7(9wY!b}cr=hC|-0è.Vk%wjFdžXmŋӒB7,u u\8\_Ғϑ7ik)[`\ b=Z<.) Sj(nw>UsHX@J@F,CIH!_f9s-d@LG< PF)YI O HF d" R R, >id@cYœ{ɀ;$! b o۾ H])uzS/PF-%_H {RC .W_0wܨ^v 8Ag, HMCwLjsE d%+ #- 'of<7Q5jYCQNv7\M_=`FwL|cȷ;%6[DQh+_&n e@ھ]' cנ kiY1tؕH-|= H[v瞀d>N5&I.Vc cdl~i:<ieWZĠG6Ic(HN쮒DZ`l\W)+RF[j @)_ EɛV sϦ@g]m!T!vֻc>Ӂ/ z9FS;$@7g!JbuGbLJl?xsGBR> HǦR{֍OLe!.A]:%{D:huo؏/WE1jz} c0|^=qۄV1C%Qh&:_! IEH(B@$mIENDB`PNG  IHDR XV pHYs{Rk IDATxieu}Tj#>5ơ3h;MMI$ffNg85PE1IQ@22((DyY (Zcb;묪so>/{O0sm Lht>h{yV)-B ;>hFkfi;fbh{Etyycctu StG =.zE 1]V>)F7)Vë̒w=Iog#{e l6d?`v*Z\w?K X{ctEٷD~ƶݓ םE4-0蟷g?ZS~vʾ&u}&e;E_ctMُ=hC[P<|{/=0:)P\Ztfm0M4=zeYo~@#=o_o)κGyC0J4}mqU跲0 m6^S?=~-eY([eߒS?JV"F\(ch E[z4u{CLߧJfMC[ٰu/O?ƥo9j3G$~u TİXTLa?|:(ZG5;(I|aR0=Q >&8pZǼ+bɾKWe/EI2ן4|ibh T~hma4u}wİ}"z'n{$p;.~B1`?Z3KqwDٷ*e41LifItOx_~J3`2 {?wEV,i e߭T(D)I?^{Ӣڈ0Q 3xU}]!4>#[)FMGctُJXL#G54`Yz_㈲ȾcrW~{$=j˟s1$L]_/?LƼ-@}m$=VC_o~\1ي"8k Ҹgd 0{ggJcI0 mhb9R!#[ 2h%}SEws#v-4hb ߍl&SlNIzk_}3 _.Z˟~@,5iQٷ- dxњY)IW{bS] mhA7Ca)~` .;T*Ysf" U4-PQo? RG[E?oE%i.uOx_Ġ93`u/O?5fߺ,/TR_) sbh Xh#WjJϾ7b4Ⱦu0E跧J\j(ܝJGknRS~?KUWC^*IsjE3gwϏ֞O?RS1fߺr9朗4=G'<&C[/EkŮRCA;`w#Z{>%U>?7e?:Q0Vmd+ը_5` }f*IsjFmُN цK/Hsskl?}0Ɔ85;}pC\IS3KbpͱُN-)H+5so[&DqeZ]IK+{~t0 mXt[ωֲh&44\m "{%ixqMُN-ش!Zk~0+5ee߶LW>WZwGE)dh _H?༕w-,{{%i/Y` hz_X)O[)P!I9b{])ch ~Q+5Qo[DhG$ͥF {ُN- l/H?Pѿ(`э8Z˟^,Is~l0E mXpS(UjB1[)5ƒ4~l0% mXP΍̒Wik(^- WȒ4:.b~l0 mX8x0Ukξc Ew+K\_&SJ?hƾOцKoWpt|i;$UQ̾[`Nz'0]Z\w| eh _6@U纟|GĨ}Gsߩ%}qh`0zDkgJZWFy8NڊOOkpL C[M5Ҹ^(%66h,IǖǪ%~ygh (z[YXb(,6ϖipgLC[EX6$<)Q {oKc9E`hTi\W l-I;_~T0A mao~p*cS(QuyV-IVwe?& 옢A?~p*[ݣ1eߡ`W-I̒wcc ah ~M1eQvξ=`N`{$=Z3* 0`t{O4NW}ʾ5`q 9zfĠ`݊DkLiN1ٷ&,r^{{$XO~D0 mnWJCoKH1h,M7{g?lRi\w%Kҏl(l~<plw?$ƤooKU {ě%\vP3`NRij([gߒ0wF{u~{3b~@*e^(;35$]f[Sܗh mmxRv3KctoGK3*]UGg?h0C[jQ)oE_^t}]$m{od?h0C[jk3RfϾ7,oEkCD{n^a?@CPE:"ޖ[ax򒴭цK4-/'@Tʪ3g)N/I~P9mRJ3Kc3oAh~+:2^T=mOC뷣RF ξ{֊]%Mq+v4-s6RB+,oAhKWf? h C[Pi?q Kח4m@]Y3~*-fUOo=ewSxa;?~ @MQDk~*-Z3Kbx)wLˢlwISWd?h C[xCPi1&VJ4-Bha m _?o(ٷLbObx;O@9韻"TZ<'ʭo9xCD{ϧHF7a m~*-xven05?4U .?@0'u/O?fj0]2Ǽ3L@;CO>j(Z+vI?މϾ`*[7F{g1~0T*ܝ~)-d/9V5f?hC[* o(SZVƫo3zS0@{ ch @Ǥ~J Co1`_U?/I?+4,y4-?މϾ2h,M?34ٕ[~ T}#|Y(o/ $Mv7f?hC[*u?|Jڊ]xe< :cO:JcOi>\>Gq Z3Iss4-ڇMNޗ}Ks0c&Me?hC[*xq4?(o)`.QtIp4-ZOi[s6\};5O?W4Q ?1@PfOiGglE+H<)@PҎ=-nhbI-uPQnސ};h5Ad4k4-Z˟~)mo} `p &#C[0ZȾ}R s$5?C[0XWG :ٷ0{qV%i3C[*j\+vo`ϙ?{ mJjZKȾm2Gפ?Hjnah @%C[5Qo(X@=W;P-K 5gDyC-,WOYffh @T2US^B,a/:*ٷ Ȋ.ֲ%$5+C[0ƽϏ)VHلfeh @T2X74F=/6yg-uPV\}Ɇ7~F!9P- m5uzEĠ}c{{*$5#C[0Ʋe;Gqٷ0&S,$}ah @%C[csfo ` ./Bgh @T2ոYڈQ?M1ΡK?4P- m5V-b^}[cњY!il3C[*j\W-~!i|3C[*j\ \}~!i<3C[*j,Zkߘ}; 1 Ic-uPV}oaz: mdh:|h}+ Sn#Z{>%lCxeh @T2Ujv➫o!i2C[**˳oɊatֿ6Cdh @T2UVC^1g@Ín0Z3K:$Gah @%C[44F.; ;$Eah @%C[e?ٗ>0A-wG{ϧyH: mdhŮsK#K0 J?-uPV̒~AeLa/:k_!)5C[0i}ltr3C[*jj(;g_~A$eh @T2b5CDk.g!r2C[*j1K">~")'C[0ݢrwL5>7\Dgh @T2B7ٗ90|&\Dgh @T2B=e}Ө,{[G$-nah @%C[-X+v/q`\e;埓HZ mJZξwI$-^ah @%C[-Du//o(;E{%'C[0mf_?0%'C[0/Q(:*Dgh @T2|^[[7f_?atig'>C[0m`\u?I -uPVUDK1\(.C[0楙QyY P?K`P- m5Np 0'喻)&C[0vݣl?})Y+~"ia2C[*jG~9k~"i3C[*jGb}6I-uPV; /a3DgW$oah @%C[mo} !NI?c4P- m]|RȾ|vXȷ䟵H mJڞ̾tEqњY~"i~2C[*ڪn&bξtMM?s4?P- mU7)nV~"is~ @T2UG5,/[yߤH mJs3KK`Ag0v(C[0Z?ʾ\g0v,C[0'EyC #g1;C[0RȾTb$mah @%C[U{(/U1F{祟Hھ mJjp`Q 8,LFeh @T2YQ?2X\HٌP- mx o8%H1I3C[*Ke}(3I2C[*m$HdH-uPVV;4et>Is: mdhhfi^}i-gHsah @%C[x?}YoO?4 mJ?!n;,h%6攡-uPV?\?Ͼ$RwH: mdhb(ܕ}I54 Gfh @T2տd_cwoHz mJV{ϧFٺ/rkŽFkfIY: mdhm IDAT]})4BHz mJj=ޖK~#3C[*jpQǼ+LGңgh @T2ګewSe(ŝ_K?בP- my+/AF~Wv$dah @%C魽QvξiI?-uPvz럻<hoO?P- mݢ<}4sy$hah @%C?e_z{[z$ mJW{ϧFٺ?[J?3C[*N_}e0Q:G)G3C[*NY+e`n>#Glah @%Cξ&RoL?dh @=T2۳/94 ? mJSf_n,πi: mdh;%,{g_nmx@Ҕgh @T2Ǿ;R|(:k_~$Msah @%ChtٗT\>,H mJ__ʾǰ}m4P- m'gd_fSepފ3!iZ3C[*Nv_QٗT)Fkϧ IӘ-uPv^yT%0o?8φi: mdh;#b;iTܺ1N՟GwꇣwDwF7EWG{G{gZY/Aaoo~5fN3usQ>roD1_ Pۣl3"i2C[*Nn$ߊbtf=pފ=7f}:ZvJ.TݣY+-_["F}ui: mdh;=1['}?Qo-)0|xv({[) PsMi2C[*Nf <EE_~K.ӈfFgKwbp|FG swi2C[*Nf~-2ʇo DhY&ݣ{obOH6(4eh @T2G=2(.W32Gh-;ԶSw1yv$%Ҕdh @T2F7}Yl?ψOhzZ=N˟# V+0Eן=D mJUgK""Puc lNPtֽ9ٗaˣs5${=ͳ!Uٺ?à!Mxah @%CiۯTn0 gZ|J Y+vgK yRĠ};`pފ҄gh @T2{;*e9u#Ԝګv[Ϟf)[G4)I: mdh;m+~Ahj~_K>ew&9C[0d4K xqG̏D{gЄb-0{ Mpah @%C~ˣ_E{Wt91Ȉ~+6GA mJͯ?f_F|g .':^@jmG;5G1ӿ/H-uPж-)/#Ze^utt|Kf7~=Qn+v~X1 M`ah @%Cfɾ`*w=z~8ګ}@S˟/I|;ŶA mJn3/!eoK ._M mw3Kw[ ^y(Z+@ mJͭ"Q%x;E{3?ykfݒ}TWҿH-uPж]}*zvt} 1s_Z?avS>ro]S7y: mdhfF&ϠGg?Ei18oEGB:O#4IP- mYS)R93^{缔Y{gC"am SctI: mdh̆ן}D(5z~8Z+vM|Ʃ!fߢ0_T1C[0mK{1e_:h÷}`lvi(7ߙ}\z`4)P- mWWeUwCNT=sGٷ0L5ګvܗ& C[0m*xњYY.5e0_{i2C[*6'~1F)7o/J̒({[oo8I-uPжY 84F([E~KXc/ѭ_;`t?kR3C[*6O@%mԏe뢽T퇣m;`bn:-3^jxah @%C{/_e9/S03[_=;)~fKM: mdhۜ7}Xm4:j5n{ڟE$78vP- mQ{gF {ٗ `HfVK~u/kh{I;-uPɡ}3ٗ bE{?%=J+vG,X33]jhah @%CfOb;.!NlTݶPy84+RS3C[*ڎ/k`L9g~$Z3K?%ͽ?;.~@et|ig mJٗ ~?%mgvkcP}?ǥfh @T2nɾL Euct{Og{oFۚh([Ek?åeh @T2:c%)?%ou/1kԴ mJ/X_[btُhwO얚-uPvY;/X4o -)W9R2C[*ڎo#ޔ}ytG?{%-~~7b~ X\63[jRah @%CmpAٗ,bY]Iyu>|{ُ#[ewSV>93[jJah @%C1mfi[7f_p2Oܕ^g틣xO&[S0ZjJah @%C{۲/ X0ews[IU{;.~DXm4ZjJah @%Clpaٗ,b>韵ƴU0:.Zj@ah @%C1lNQ˾4` .;(Z˟Y+iY:~5R2C[*ڎ_ݣߞ}YwMԬgmDYf? EΉ{EMl-uPv|M|韯YEE V1ocwꇣs{ mJc̒(7oȾ,`^n0{?;UR1d?`ޔ[7g~$G9Z+vM&)C[0x` .?$ZvNl4Q?5ԯF{?WI: mdh;^ .\}I)F̕*iΈA')?;.ewsϦ~JӘ-uPv*)tSI[ȷDےb}ߊ5f韕 mJSWd_-wEgk?O%M~9Ӥ,x^{l9bDI-uPv|ٗG}?IA!Pha0duNsL=2~9+7\}]W,w9 `ۏ-OՁ]i{cX~$?C[Jehz5@RH÷xJ^ w7{d4ڹ> ~$-.C[Jeh:c !4IkRowTRw^ʔC١ϧM_[_zskdڮFWfv!iU4UdžS:w◥)O[?C[Je :#_ 0o[_VU+~!4@Tu}ޘ;֥~$dh @ C[ mWAҤ2{~ͭWSIV@=~M "G4޽1 <6~[$5+C[Jeh_ע o5$ͻ5iK?:zhILRgIdv;lwK6>1U_hG(޸Q-is}l=G Id6F hrE۩OM{n(4-MoٖFipRooNdh @ C[ mc%[)Iwك_Hh᯦Lk? 㩷 P,C۸~7jS}өwʓo$-E-?CQH՗>&<% s~!^|0 6{~)௘A$-ewDJ8#yI5MnI`I7&s] m(ah @m7|o8/7yNhFn]M]׼. z<)[J3-Yq%/ Mn<7`ըJՁ]i{cXo5Ԛ m(ah @mL7o2H÷x}eonm*S`գRupOݒFW:|Vg$-S0 6ߊ~zYFWbm귧E,jf-iԛ[+I+-% m2COnj(I+]祺@G0ͪ4Ɵ/I3 .a m(ah @І'zh@~E]tJiG1@ȡTؕƻ7u៧2-Y+?fߞz>5.JRdq 7G4ٻ%|u?7% P,CەoM@ՃM~%)5i'XHizis}l=)NJR3-Y+FafU^{(INOgKٱϝJߟ%d9+ܦS@?PVY-?@KG4޽1 wK'IR3-Y+pˣyISjᎎOOoNw?oԵ m(ah @6:O[(IɍE\M2=K]F;ק&IZP,Cە:'( .|qU'{?U>rxk|pɩwʓ?$I%C[Jehm: Vc=JRCTV:+woLRg>I旡-% m2]_tPup\&5z/E|+97LnI`ICgh @ C[ mWɧtL=|4}^ &6rM4wY]5[#IZ m(ah @uJ߅?Ijl<9BG9HCWk^NNMO|$-k0 vt|J8$ !IR:WO=~3ٻ%vO'^HVG0 ve_GO @Wu^/o$OwjfnM.J[ڹ ՙ-% m2]/}4$ߙΨ:6p_4vrmzJ$9P,ChnME?5PM$ /c5XZTu}ޘ;Gy$5;C[Jeh .xa3#IR޲-?{d4ڹ> tSlKڕ-% m2]`9ֆ=Iju>5RG>4lfץᶓ}B"P,kgfU%7OCwN4c)^%Id._~fZ_}$KMn8+BGSui{cXg|gKIo0 vy'OӞ~$S4;'VƸ{`h4zRͭs(Iߐ-% m2]ކWBrJ.6c)ճ3Kk6M-чC\p\7IJ2-Y3o&}S)EJՁ]i{cnym:>ϕ$Id.oW?ҟ u6f~9GSupϱXg<3ϐ$Iː-% m2]֤zHR>$IiRggjr7OnI`I~ $3P,CkpF?/-6Go$[M>wAYfU{4?/N Os!IRT0 v;>~$ISG}ȡTؕƻ7uw$ieh @ C[ m/ e1` $/6|E_Z={35=Y_$ m(ah @5s @ Mpi$`$ݚ&{iԛ[u-IR2-Y'4F?/mSMRsߓёkA̪4ƟߙFWF% _Ò$!C[Je:i& IDATh< .ziB~$n`JՁ]i{cX*IR[3-YHK8IR ǥٽD_ ՃSuSJ3u)IR2-Y[.~ZZM4`DMO+?h4zRͭ $P,Civ碟ny}$Ϳ-ѧVϾ5%i뿤E/%IZP,Rpp\J~"oO57N4o>r_ a#Ru`Wޘ;֥¿$IR>C[JehB`)$^}Bzt$UMģS $I d.}j"cג֤ ѧi4?aI$P,ÝogE&IZx$Y}N:~+Fk^NNSu!I/C[JehUw]D=z,O{Zm$-o>)Q9x4ܱ.OFKd.}u @KLn8+I_ ?}VZ>|"M>9 w$Id.m;IhY>/Iտ}Y=7.H`ͭ WI2-YK]?Du&IZ6f}^teiNHm7$Id.m^W5I6|OEU>r_JpǺ?o%I-% m2]o,IhCw&IZ.Ǐ4ٻ%vO'$IjW0 vi5Ih~$IMߟt:a6M@ץE/$$i3-YKڔƽ'q~b]$-[Ͼ9N]_JvG~' .;I%IR2-YKWt&IZOՁ]i{cXD$IҪd.]_pǿ io}mzxI[h4zR??I)C[Jeht? @GK Oih?KN5ICO.J6 6K$iP,C%m;pV=$\+~1ȡTؕ׽! z"I m(ah @u>b%cͭI؝ƷFKK_Og IP,C%jnmJ~s`3IҊ7|?[RO>&{I+_>/$IJdh @ C[ mc|$)Ջ;"*O}5Km'o %I-% m2]_4Y]~$I1 f#Ru`Wޘ_z IZ2-YKÿ4Xo$)koD=|4U gu3J$ m(ah @4{~S`N-$?S UoHKr}$I-% m2]/_4U]Y~$I$IjC0 vijSP{n c$I$%C[JehfUSP(I$IԒ m(ah @\g[_~$I$IjK0 vgf~$I$IjS0 v{}3PϾ)I$IԦ m(ah @|E?# 5;&I$IR2-Y@M)wL$I6eh @ C[ m;.I$IԶ m(ah @"p\J8h{$I$eP,C?yO@C .|q$I$mP,C5|OF?! T?ԛ[~$I$Ij[0 vq>'_2I$I m(ah @|O@?7L$I6fh @ C[ mM.~Bh𖗄0I$Iژ-% m2]\o~BI Dž0I$Iژ-% m2]\wG?! Sy]$I$P,CEḔf'aƻ70I$IZ-% m2]x;h0I$Iښ-% m2]x_|4M]o$I$Imd.ѕ&hᯄ/I$Iڜ-% m2]xk h/~I$I m(ah @›|4~$I$Ijs0 v߰D? 3%I$IR3-Y ov@O?1~I$I m(ah @«7h{o$I$Imd.)UA;_$I$l4;$I$I]d66zl4ޛo$I$Idږ?; .vI$Iԥ m(ah @mYsd4W.I$I-% m2-kpዣ %I$IR2-Ye Ϣ |%I$IR2-Ye /O@{C$I$KP,C۲FW:h ]$I$u)C[Jeh[胯~2dׄ.I$I-% m2-k߉~2dt ]$I$u)C[Jeh[3h ]$I$u)C[Jeh[ӧE? 2_.I$I-% m2-kwK _~$I$IR0 ж𛴷#h[q$I$KP,Co~'A[~ vI$Iԥ m(ah @mYՁ]O@yN$I$KP,C۲~23o$I$I]dږUd4H K$I.eh @ C[ m˚{s Ӟ~$I$IR0 ж7d4Ho]$I$u)C[Jeh[/G? %I$IR2-YeՏd4Ho㷅.I$I-% m2-}3hކo$I$I]dږU~2$nI$IԵ m(ah @mYG?M1$I$I]d4&hj$I$IX0 ж O~..I$I:-% m2-hE?MRo$I$Idtʓ ͭ_$I$u(C[Jeh[ЩO~. K$Ieh @ C[ m_'h)O _$I$u)C[Jeh;=-hަ$I$I]dο 9У$I$I]dο'F? %I$IR2-Y3 9CK$I.eh @ C[ m_gG? ?YK$I.eh @ C[ m_~./I$I-% m2s\4M ~I$Iԥ m(ah @@ .xa$I$KP,C?G? 3x? _$I$u)C[Jeh;Pb_$I$u)C[Jeh;[\4ҟ _$I$u)C[Jeh;Ps0w%I$IR2-Yo@ÌK$I.eh @ C[ m\4 _$I$u)C[Jeh;8h~$I$IR0 v .xas0^$I$KP,C7a%I$IR2-Yo~.f3$I$I]dο9ύ~.fr[$I$I]dοYώ~.fzێ%I$IR2-Y@Tw\~$I$IR0 vO{Zs0W?~$I$IR0 жMG? 3;tk$I$CP,Cۂ6>1hك__$I$u(C[Jeh[ܚaǿ$I$IP0 ж4F?M2.I$I-% m2-` J$I$\0 zX0'/I$I-% m2-?d4L _$I$u%C[Jeh[V7 \%I$IRW2-YeՏd4ҟ _$I$u%C[Jeh[VW ߆/I$I-% m2-k /I$I-% m2-kvx0O̅/I$I-% m2-kv߾'a&}s$I$+P,C۲fwq0} _$I$u%C[Jeh[VO@T%I$IRW2-YeU~2oC_$I$u%C[Jeh[Mۯ~2f$I$I]d~mO@$I$I]dږ5웣 g76I$Iԅ m(ah @mYOd4Po$I$I]dږ5~2h7L$I.dh @ C[ mw ^7L$I.dh @ C[ m}G? 4z߯0I$I-% m2-k_~2h~$I$IB0 жd43g0I$I-% m2-kΟ~2hKo$I$I]dږ5x?~257L$I.dh @ C[ mCO@~$I$IB0 ж9ύ~2~&I$IR2-Ye7d4Q5N5wL$Igh @ C[ m ;IO@C7?=I$I m(ah @myD? 48o$I$ImdږW~6hΟ a$I$=C[Jeh[^ؽ@7L$Igh @ C[ m˛l4ׇ0I$Iڞ-% m2-:xC@[o$I$ImdږWqU@a$I$=C[Jeho~a{@0I$Iڞ-% m2-ory@Տ~=I$I m(ah @myOgIͭ c$I$9C[Jeh[5h c$I$9C[Jeh[}l4c$I$9C[Jeh[𲟍~6jx$I$Imdږ7xۏD? 57$I$Imdږ7x?~6j71I$Iڜ-% m2-3 ~;&I$IR3-Y hq)u@՝c$I$8C[Jeh#O@;yG $I$P,CۅU?&&I$IR3-Y kv?#I$I m(ah @ª>hE?~$I$Ijk0 v߬}oPw|$I$P,C~E? 5w$I$Imd.gN~:jrywL$Ifh @ C[ m?~:jg$I$P,Cۅ5ڹ>hٽ1I$Iښ-% m2]X~:c$I$5C[Jeh(hNMLJ2I$Iژ-% m2]X3t4`o$I$Imd. ǥ4nE-$I$P,CۅWG? 5 c$I$1C[JehfbPO1I$I m(ah @«>hm;$I$Imd.]|4Tφ1I$Iژ-% m2]xϋ~>~;&I$IR3-Y o|룟t|-$I$mP,Cۅ7G? 6[&I$IR2-Y oxF? 6UL$Ieh @ C[ m-/~>l|2I$Iږ-% m2]x+h-L$Ieh @ C[ mц'TϢ슿e$I$,C[JehO@Cc$I$-C[Jeh`A&ԛ[~$I$IjS0 vqU_4Xg2I$Iڔ-% m2]7mo" hᶓo$I$Imd.ɍF?! 6ڹ>I$IԦ m(ah @i IDAT~$I$IjS0 vqKO@M]~$I$IjS0 vq .'~$I$IjS0 vq'[&I$IR2-Ylq)ͦ@O{Z=$I$%P,CW?zw3`^~$I$IjK0 v46I$IԖ m(ah @ok[&I$IR[ZJeh&74t߻o$I$Imd.4?e$I$%C[JehFW:h`-$I$-P,C7e@7~$I$IjC0 vyN3pH=$I$ P,C%hq)ͦO @L$Idh @ C[ m{|[&I$IR2-YK?~Jlzo$I$Im?yХe}j\@ nC4ĉ5Ac2N2IXAr0$Vq[eSo/4*ȒF7Yd',vGQfdG֦޳)hα{3I$I-9 mH2Oc)h~$I$Ijz0 v<O @9(I$I mah @{џvn-$I$$C5z @#I$I mah @ @W3I$I-9 mH2_GDN}nL$I&gh @C[ mW/FNs$I$IM$ڎ-(K~$I$Ijr0 v|zw?:1I$I mah @j%sp~$I$Ijr0 vUџrGo$I$IM$ڎIhցo g$I$55C[rdh;_rf':a=$I$$CֿO @uL=$I$$C;GR$I$IM$ڎ=?) 7{&I$IRS3 -I};?) W=yw=$I$$C1b纮 @UgIM$I$$CW=HgG;I$I mah @ @uOd=$I$$C "DV{&I$IR3 -IџzN=$I$$C=c @Íi=$I$$C^{gFzqūo$I$IM$ڎ֪GV >wo$I$IM$N)pg$I$5-C[rdh;F4\$I$IM$N藹743$I$IM$NK?- 7z{&I$IR2 -I{'?-M7ԋw i$I$5)C[rdh;O @G+I$IԤ mah @dj%P~$I$IjR0 vrUF^Ŋ{&I$IR2 -Ikxߵџl<=I$IԤ mah @?/ 7z{&I$IR2 -IwW?/M7׋^~$I$IjJ0 vruy(@ i$I$5%C[rdh;G @yM$I$)$C uUEb&I$IRC2 -IzO @ o;7I$IԔ mah @dsU''g$I$5%C[rdh;_[џo$I$IM$N_}{o$I$IM$N=?1&I$IR2 -ImџFM$I$ $C C][џ&I$IR2 -IoџZ3I$I-9 mH2/voџ5I$I4$C׻|Yg8I$I4$C] @z]M$I$i3 -I}Ļ?3&I$IҬgh @C[ mz447M$I$NѦ;?5M[vi$I$r0 v: o??SP귅4I$If9C[rdh;(@䏆4I$If9C[rdh;gUKWM$I$i3 -IөfO @7 i$I$r0 v:V&SPc4I$If9C[rdh;4hX/9I$I4$C5 @7M$IY$N?7&I$IҬfh @C[ mW(@4I$If5C[rdh;:'I{i$I$j0 vz @zqaI]$I$i3 -Iӭj=(@됷4I$If1C[rdh;݆\(@䏆4I$If1C[rdh;돌wBM$I$i3 -Iӭw`&I$I,fh @C[ m[[(艟4I$If1C[rdh;Z6PjT}u]$I$i2 -Iӯџ~$I$I mah @yqgs?~$I$I mah @_spg G4I$If-C[rdh;g~*P}׆4I$If-C[rdh;@S’&I$I,eh @C[ mZs]WO@Z$I$I mah @mLMwFz 9c7M$IY$4O@W,i$I$R0 6Ez 0&I$I,eh @C[ mcgџT i$I$R0 6 wM$IY$u=E~ 9wM$I$5z@z})I$I4+$C_tJ׆4I$If%C[rdhWD~ 0ztcM$I$iV2 -IquO??% ;5I$If!C[rdhW렷D~ >$I$I-9 mH2j=(@ i$I$B0 6WD? 0o4I$If!C[rdh&I$I,dh @C[ mc'@ zq$I$I$CG; Pa5I$I3 -I-߱g@$I$I $7z'9(I$I-9 mH2opwuiM$I$):C[rdh_{ (@z"I$I-9 mH2sh&I$IRd0 6ցo~sG$I$I$C٨z@z/ i$I$Efh @C[ mg]D? 0&I$IRd0 v6_spS{o$I$I$C٨{>OBV!I$I-9 mH2GvS>~$I$I$H^Q^sK!I$I-9 mH2F(}$I$I$N(h]7M$I mah @ԻTUuwM$I mah @9&I$IRD0 vvj/[`{.r]$I$)"C[rdh;[6$(So$I$I$Cj'@F~$I$I$VK$(AUխ5I$I-9 mH2:'}(IPq k$I$M;C[rdh;[5IPޅ_k$I$M;C[rdh;{UOyP#74I$I-9 mH2~`4&I$I42 -I[OG? 9v&I$I42 -I[wG? ѻ$I$I$p^Qv5I$I-9 mH2F~"`m7M$Iidh @C[ mg#%r&I$IҤ3 -I]~"? k$I$M:C[rdh;۵xW~$I$It0 v[-F? 0y]]$I$i$Coxߵ6~$I$It0 v_g@ nz}]$I$i$Cٯ{>BtN@]$I$i$Cٯ}nB.J]$I$i$CC]uT(3$I$I$6=WE? P&I$I$3 -Iͨ!OB5I$I4 mah @m3@!:wM$IIeh @C[ mQзG? ѻ|i]$I$iR$Cۆڛ vn]$I$iB$C4eTO?~$I$IT0 ж9@!Z9I$I4 mah @ms+Pws]$I$i$CZB/I$I4 mah @m~2`x7M$IIdh @C[ mՖal^\X~$I$Iw0 жYZd(D~$I$Iw0 жYuNXk$I$;C[rdh۬ZZ k$I$;C[rdhۼ~6`xu7M$Iqgh @C[ mF?Jo$I2 -I6ͫg@!G;I$I4 mah @mg@!~&I$I4 mah @mjg@!?<.I$I4 mah @m3~`o i$I$3C[rdh̆t(hX}u]$I$i\$Cfֻl!Pq k$I$+C[rdh:'}(P_k$I$+C[rdhZt('5I$Iƕ-9 mH2mn{;I$I4 mah @msl<#P5I$IƑ-9 mH2mnK|(DgwM$Iqdh @C[ m[D? ѿby]$I$i$Cu]UO I$I4 mah @mm+ PD$I$I$Cf7y]o k$I$mo0 ж.RS)I$I-9 mH2-;($I$I$C=g@ n&I$IRN0 ж~Vs$I$I9$C B._~$I$I$ږWݢqA]$I$)'C[rdh[` Kꪳ9iP3w%I$I$C2@!_wM$Im$ږYUO BtO;I$I$C2@!~$I$I mah @mzs65I$I5C[rdh[n/~^`دWl IDAT*I$I-$CrrVck$I$mK0 жzC~$I$Iږ mah @mug5I$I%C[rdh[nE]W'@ k$I$mK0 жF(D~$I$IJeh @C[ mnx]$I$)-9 mH2-y~bݡwM$IT0 жGnև5I$IR$C[%;6I$I-9 mH2-G?3 ^&I$I2 -I׿ B.b]$I$ik$C랶w35I$I-9 mH2-#Pꩇ$I$I[$A KxS$I$Iz mah @|4@! k$I$X0 v>],P$I$I/-9 mH2:'}(Pׇ5I$I^,C[rdh;]]WUsn|&I$I eh @C[ mѦ;h=I$IB$Cip B.B]$I$2 -ISE?7 1ɩwM$I$Oc(D$I$I/-9 mH2X׃n$I$Iz^0 v=!P$I$I$WGD?9 ѿ&I$I3 -IUOF?9 oIk$I$=?C[rdh;_}{~b&I$Is3 -Is’j=(D6I$I-9 mH2w^(D5I$I-9 mH2W~vbxwM$Ifh @C[ m=ZOԋ Ko$I$Ifh @C[ m֪uUE?= >7o$I$Ifh @C[ mɟE?= =$I$Ifh @C[ mMD?= 1qwM$Ig3 -IYG?= 1z&I$Iҳ$CORTUZ&I$IҖ mah @휶|pm$I$L$o(DUwM$I-$C@!\~$I$Iڒ-9 mH2ߺgEvM$I$C[rdh;iM$I$C[rdh;-,OB.|m$I$}0 vuI[Cf]$I$$w+~z&I$I-9 mH2:k?(H됷6I$I|gh @C[ m* Pi{6I$I|gh @C[ mU=yw3G5I$I|gh @C[ m5y]38I$I;C[rdhޅ_~խ m$I$ڪstNPm$I$o0 Vwa?)PU+o$I$in3 -I"su]$I$o0 V[o8:)PA^\cm$I$g0 V[@A&I$I mah @>l@Az&I$I mah @ia"9P6I$I\fh @C[ mlû.~j?#I$I/C[rdhg_29P m$I$:'49P5I$I/C[rdhgkks Om$I$U~bMk$I$ ~rj -I$I+C[rdhֻOtODm$I$W0 VϭsO7~$I$I-9 mH2z؏~bMM$I4W$C[=C7D?KJQ m$I$7,(HgM$I4?$C[=~&I$I mah @_ݢ%{Mm$I$O0 V_ Kꪳ9iPA^\&I$I mah @^]F?M 6I$I|dh @C[ mBZ4(HM$I4$C[P?4(g6I$I|dh @C[ mB5iP~^\&I$I*?C[rdh|O 5 m$I3 -Iz?95yPgm$I$-9 mH2Ջջ I$I$G Uҗ7I$IR$C[hwa?P!I$I$jk!Pޅ_m$I3 -IZ GG?Q 2&I$I*;C[rdh=/(ڛŅ$I$ mah @Vݢ(i[M$ITn0 V[maI]u6G?S ;M$ITl0 Vw]L(uM$ITn0 VW~z&I$I*7C[rdhT?L(Lз7I$IR$C[jtt}$IYrsŸԽKZ9(SB0 VR @A?>)I$I[};ԃGnjV=zK mah @뢟*6~$I$i-,ۇf=/#zJO. C[rdhmw*io$I$Tw~]v^]9z%dh @C[ m-u#P o$IRjg~_ֻs'գG7礪9 mah @;\(Ȗ~$I$)җQwا_zMn?o$C[mkn~M$I_kozfT;-9 mH2նpts0o o$I{TYwzxyuz<Ǥzqū4=C[?݋_u}r8Z{FcisR{sz㴢Nzjk @MP $H@1=\~ JdZ/ Rz}4qazy}$IԎLiieʷmN(;ꞡ-UPVZ礷E?4UM$IRo,;4RG%oW mR않G)~0I$I}ْCRwլ44ں!A'U7{Tah @)C[Uitя, 9-M$IR}*uO_ꯟF[֦b$eϸP- mUF?4L~$I$i HiieʷmN(Ru5* m(eh*uG~+M$I4wYvh9< 6.MRStO5* m(eh*e_07I$I3_]5+K/KiEd,tOnꞡ-UPVU+7a:KY}$I4}eN̨vTL<ǐ5}=C[06muc @.D}$I4E-8 uWfᦕ)߶9cGmV0a3 C[Jڪj~lhɿ}$I$FsIeޚ`4ں!Q?[5* m(ehuV;amib^7N$IK-9$uWJRdhޅ\ mRS ]f`8I$Iϖ3~fT{TdEf{Tah @)C[N7E?4L_7I${Y#ᦕ)߶9cB+/:"yyTah @)C[NN~th}$IV4wQ4ظ4nHi؋#CV|攊eKIHKh놔说[>=C[09{=Q;'IvWJhTdGu)3YX3 C[Jj*uI @'Iز~3/tT诩0=C[0e`$IjYsMeޚ`Ҕ?xSJEfŚgh @2T]oex41g;'Iih^w`I)ﺔ诠nxϚgh @2T-zUJE8@J$IҞ]5+K-kS=Uk3 C[Jj#q'Ije ^+Kupʔojc/u* m(ehjxя3 47o$I^βCSoiqi)|5jkpu3 C[Jj]&t$I)[rHꮚWF[74Ȣ1B [=C[0E @CuO{o$Ijc٢WKhTL<op~3 C[JjʚO*;ih򧥅9I]qXꯛV|攊" ?j-UPVS+i('IԨ:M5ƥiuCJ~>`rhψgh @2T6G&*;'ITײ%Y~^}YJ,"W-̨{Tah @)C[Me37zI$IC٢SwaɧhTLl*T0ϑgh @2T-~]# @C o9#I$] xfTnvnZmw6ZR mR'~hbib^wN$)βCSoiqimݐҨ5 b?oj-UPVS3k_ s$I3U]5knte)'3ϟgh @2T_E?4T~$IlԿSiem*&E/Ϥgh @2T;kjo9I=nR男iieʷmN(jc?j-UPVS޼4D?4Ѡ&['I'u>S?OM)oU_Ϯgh @2t4zu @CuO_$Iz%Y~^mYO@_?ꞡ-UPV`ñя6 5zI$I,[xP8,9*v<U h1P- m5я6 ?|k$I-lRg١wpʔoۜRQD5w?j-UPV2`ZEʎ['I}ծ9< 6.MR-;?k-UPVUo? s$YYjVꯟF[֦=bGџu* m(ehjxn>7Iz-<(uWfb;jYY mRxPEGH,uz|, 7L)yW4??k-UPHEUg;o{ꯇ:I4^eǿ) ) _Y*Ӻgh @2մuSqjpQN$-9$uWJhTtz0%&wgl3 C[Jj:.os$ifWNM+S"fsG=C[0'F?4UQIvѷN$Mqs{kO|攊<ɖ!P- m5wя8 ;N$YqiqimݐҰ Tvԫ?랡-UPVYvqlxN$UvWJhTdG;{Tah @)C[Mwŏ~h=M'I-<0uWfᦕ01ggh @2t7,W$7uzkO|攊߄ mnW IDATR'1~$IjjVꯟF[֦"{,4V&dh @2մ7FG*-~]$e L/f_4TK*œ߂&dh @2L4`~$I]^:_xG4o}_` NmP- m5 =1Qu${ْCRwլ44ں!A'~xMhBTah @)C[D(QSHe^/K-kS=};ׅߐ&dh @2JLG~7$Ie ^+Kupʔo}M+M* m(eh~O@ l$iڛo,;4RGg)2qyi@Tah @)C[T[WE?4XN.[rHꮚWF[74ȢO.hӄ mRz~"q:'%Ie^/K-kS1hi`/{Ԅ mR:_tD$iZp@8,NM+SmsJE}J6yoT2 C[Jjƚw*OE?4;I^%J#&cwޟߪ&dh @2L6G& v{'Iҋw]`uᷪ P- m5/pw$XcwDJXߪ&dh @2L=_E?43$I/VS |UM* m(ehm)+&Msy$@i؋>ҷߪ&dh @2L?xSc@u+I}"s1W * m(ehn\(I˖}"s_~-UPV3]o{.;N\_>|~-UPV3]vG?@_y$d>DjJTah @)C[ET<5f;I~;<0Ɗߪdh @2UD|%F\~$Iziy`|;V5%C[0"?G?4]>J?~$I/yQjJTah @)C[E9ע}Z#7O`qѧ16[Ք mR i>>pϋy$}ckUM* m(ehFw_t,ME͓$iѝ/#c߅ߪdh @2UTZ{W~?V5%C[0R>~hbb[wݓ$>#V5%C[0" S=I]sK)P- mG`q7O&SRů WM* m(ehz_ѯ-?qW͓$i>"Os WM* m(ehȲ e~$I#ѧ1Vdߪ&eh @2Utŏ~ he~$I駣O!c,[դ mRnx9IGBh[դ mR~$Il clNDߪ&eh @2UtS_'Ijgߎ>Mߪ&eh @2UxsMEG@ _$Ig16[դ mRFw]*E~$I-ȗTW1_߫eh @28Կ3ѯ-ѿ'IjWo>9.^5)C[0ơ~h {v=>6}-UPVcT6(-yC$ޅ~7߫&eh @2ո4[ѯ-_=IR{\80&~-UPVѯ-1;$= o;;0ƊᷪiP- m5.uO{o@[yʖ~$I(-V5-C[0ƦHiԏ~%hޅ}VTLl>{]ߪeh @285ѯ-1'Ij~S*rzjZTah @)C[SGE>L׆>IR|17rQjZTah @)C[Sݕ&Ez~"I]?>w~-UPVckUak@K2I[ c{߫eh @2ո?pck@[yʎ'Ijn>|iTah @)C[[k~-hEG>IRsN`eK~-UPV}$59{4D:Y>JsY * m(ehq+;;7̔ ~$I+;F8\P- m5̤~$Iͫ>qU3 C[Jj\,E&G$5ş>qі U3 C[Jj@@tr$5gF7`IP- m5e_RQDOԬGn>oE-^51C[0Ƶ-ѯ-?qw$5y4G7\߬fh @2ո6qy@tNy{$5EY&EjbTah @)C[ks$e|6IQoG5-:8f51C[0Ƶ؟~=hb#ib7PT>k=^55C[0ƹb_Z{o?IRuII`~-UPVӢ_ZfxOTGOcnxyP- m5_fl7PT߲}5 YM* m(ehq BoGo$P)_ mR~Mhݗ?IR}\{B)mjjTah @)C[{6Ec>JD_2j mRz~<5M $հԟ>cĂVC3 C[Jjʷ~%Is}bb[jrTah @)C[}sJŎG_ZsAIR9ׇ߬&gh @2U0(IWÛ}moVRCB?Qw%IRǿ}UoV3 C[JuNW;(IGْC5ڟ߭&gh @2U]*~@@ z;Cg xwjrTah @)C[եgF.Q>Lْ7AI7@MdG&n59C[0R?~]h/' (:O߬gh @2U]> ѯ -?vgW-$oQNȣO50wP- mUD2TAI=ѧ  mRSÛR[Nmp ѧ _ mRSs$)[xP-$g#ߍTD [M* m(eh:)Ek@K[(IcΟSe~-UPVu+v{k@Km ?>QE>L ]M* m(eh5ѯ -?ʘ]?vgjCn3UPVu?~mh 'BI5wTt>OhՂ mR[QNȣ_Z=CIxY@ 6~ڐ-UPVu,W][(IW}~ڐ-UPVul@MP4]} ]m* m(eh:oG:\g;$)קT' .~!C[0X)ѯ-6{(IwǢ5Rt߮dh @2U]{U@ :);5P讋52Ֆ mRk>{(I)[t߲@%?~ڒ-UPVuѯ-?qWWM$|qfz|,~%C[0j}R}2座(I x]-Tah @)C[չ_~hȗt N"e a-* m(eh:__!ڮSķDI]5+P3߯6eh @2Uѯuo$izff&+SjSTah @)C[սb=ѯ-7óEDI TwDjfp֢ mR{WDF~%I_Gjw߰6eh @2U`kx41w(IFf:K~ڔ-UPVu/;5)y{EI-~]J0P77P- mՄo~ "&J}jo߰eh @2U\8U:(Io>3oX2 C[Jڪ uOWѯ4ܴ2.JҷFj cm* m(ehFtSODNhBm$MiD_jj/G߱eh @2USuq; =1.Jybb[yůe-* m(ehԿ v*;Rvԫo$ij`i=~ژ-UPVM տ|Nm$MM>+{߱6fh @2U*a+;ibQguNxsJE}Ve em* m(eh&5qE+(Iڳ>'X em* m(eh&;_)xV41w(I헊m*{ mRjR٢SʇѯJ}Ɔ='5C[0VDV0>Jҿ>\O߳fh @2U|ѯɿ}ښ-UPVkީjstz$R,">YQl7P- mĆ~969{HIRyWD j.tK=ksTah @)C[5޹~ygn$tץ4D jn7P- mIJů^;C4 }.h7P- mo~yfHI -xe*ǢO ]qX]ksTah @)C[5_/x契9{II_g&GibwP- mԺ';CwR?v@~ڞ-UPVm>w0I}&<Û~ڞ-UPCMns_1xA ?~'%Iϔ-<('O ;Oo[3 C[Jڪ|$Tg)IMo)߶9#wN;3 C[Jڪ-(uTx$e  _{(Rvԫ* m(eh~ʣo$5lkS=Q@nsqTah @)C[7FnPnO~7% 7}9S޸"'n-PVm*߶9R/ Դ_wZo>~ mRjSDrKz|(nJRc:)tKG; 9Nfh @2U~7_9%lS4X[fh @2UO*Ǣ_;%'NIyoMi؍H9+P- mնVFvk`Tah @)C[%~ѽW9{QI71 @ \ gh @2U[vKҿ 4nuz_ 3z mRjs~,S;*IR_LEOg$~P- mW/~`OܕRI ȟNCD,27@hTah @)C[ΊwGۆ7.ӣ?hDŽ@C[*0ZݜSv[o$ջT z mRj{Ûn+Sv$tSޞҰ1 @ibP/-UPVm{DGO 4SeG:O @KV-Kgh @2U뛿*;_E#TIF^ @/{* m IDAT(eh+Ms_Ecs?~S%iZWnZq @u>+7Q/-UPV[WOhKwU\wŏ蛨* m(eh+T2A'u=?ݝw-JTT7QP- mg}{9{VIzJ^+Y~U-UPVz޹~` JTTL< ))[x`mTyTah @)C[陲E&Ez?~_%iOʎٔ?OTiov-C[0Fw~%` :wWIڝEJCDv-C[0z_WTS 7V-<( YvhԮeh @2~\vkRʇѯ%LlwVv=ߊ(7Fj3 C[JJmteѯ%L=WyYIzFw|##gpwR-UPVzn ?ZzfWl>is?*uW͊ mRsˎٔQ bpőV^pd{HxanXp@.gh @2ޫ_M6l3`8^R[P- m_7;S䩷{+IO;E*K7S2 C[JJ/;R*O>JZ܂ˢ? Tv?-UPVz6F0=}7WRʎ~Mv %nzTah @)C[酛x==wWR{ʎy}nsogh @2^lR*W]al+iFwE.|W離gh @2^=ߊ~E`f o^IͭHɿ}?{P- mw'_Q9ƶҠ) ^~C{P- m/[ڔak 3H/,!+/RQD@eڭ mRK7fְg?K{wt]y:+!IXG (ʨ딈 "%0ðL3HYHȞ:,$!+$: dOȾ['N~u}1\^U}~|]bx Ih-!T۔-uPVzzgY1wڇ?%5bte7lGj3C[*J/^{sfN1 'ٟŒUF=7lNLնgh @T2~nQeobIͨw" KʹP-<Kﲏ*\uh,iB[k :$y1VmWah @%C[i+Z҈~+@mgGkn˒&o⑫(7ݯ| Uۗ-uPVں?8-@E{W.K'? ScЉ֊?c}P- mko3"nOlؒbpŁe}%~N笶;C[0-5sG&BKϒ^7+!X?Y: mdh+m}fYesta糤1xQdD}?sP- m=G&˨3?-iakj~2C[*J5ZS>0qJiJ(;Xpݓߟ: md!kp!&ˣOVK&F}XݍZk'C[0TQ>01L-^>e+fx`[ah @%C[~œd]\^T絤u;F^}ua_ah @%C[~?}t` o<1ZwKܖ-i/]1g_0vek}yy: mdh+կ}#"+6:)[?_+򹇳 H3ǚ mJҶ5z;aЉEߒ_u~ :z7C[0m 2hpik|y jn|!!l 3C[*J>P0Nzqi&[sd̾ `b y: mdh+m{[N>H[?˥h('j{ah @%C[i# gzkޕy.Ms/(&D*3Z -uPVڎec 6hui meZ mJ5aߊKtvu޸6ejleޘ٭: mdh+m_/J1Q0=r7r}Mg4m8/@x.C[0/lQSv6DxQtOz_/@#Z{g,C[0Ⴔ?S(8T*;z_wZCgڲ]~^Mmxu-hah @%C[i~uAqVuZ mJ9GfVs d z=xy0'C[04^}`EW\ ݓh}\`NpKah @%C[i~2=*s[bn([볏̤\3Ɠ-uPVګt6F޸6:z :Gr .[wfykƗ-uPV7}P#}&*MawQKx??+hlP- mw6b=d5GF? (%g5C[0-^7#ߖ3Q{ˢ{ʟ5Q# Tfh @T2K7PSԭѿtit{K>{/[oW)?%;2-1__tR1fDeC~6geh @T2>X{n?'c#6g%9M=?~ ίGsl}l mJZC>@S Q#Fw3|1_;c=sۢk&Esukt׼+zg|$sCgFQn~"?a`N`@J: mdh+ş>4 XOύkbpŁѿsѿ;si oQxy?vO޹9e/L <;,78[hG]SEb 0CSah @%xjc4lE3C[*JkxG`:hgh @T2Wwfy/8gh22C[*Jxc0u:Ǽ3G-uPVo &Lk|49P- m^GĠ}F: mdh+ 'd}Pn|0ZKvJdh @T2__>Sߦh2C[*J9|?4ZU{h2C[*J9HhUh2C[*JI-9;,sx4qP- m.ɾit9o; mJR^}_1f_oh23C[*J o8!ht4P- m:GR5(3>: mdh+7zMEk.9 mJR~>}4B#-G-uPVsg_</Dgh @T2&Wu0.Mgh @T2&=#+`2[Uo8 mJ4+`" .? F: mdh+MN~>,2E{'F: mdh+MV.;&clԜ mJd=(F9Mo6jNah @%C[iZ('nʾ&kԨ mJ;W@oKQ2C[*Jҝ| 莯ӨqP- mɬf_:z-uPV+_ewcbtߥ3jfah @%C[ir?H]53C[04a7у˨P- mnxk`_o2jnah @%C[ise}UKc mJ7WXt5;C[04uWuA;-uPVjFWe_ sP- mf;O 3MGah @%C[!-1gξ2_YFȷ翿h*2C[*Jͩw̾2ݖad'C[0Ԡ S9]45P- mf?/ y3MWah @%C[a-5;:_1Ρ?ޢ: mdh+5}ul ǧh2C[*J lnQn~2v^wM]ah @%C[/tW: mdh+5GZ}Vv7F{W濯h*3C[*Jͭ粯wMoah @%C[W<Άk`?廥hz3C[*Jnpيk`h{;C[0ګ)*T9:g0 E-uPVW|!:xae#ߞ~: mdh+MG}_eoSO o8!D-uPV'JdžhwNah @%C[izj#Άk f: mdh+MW.ZS% mJҔb(7?}DO濕h2C[*JWɾZW<~CN: mdh+Ma^sg_/*~H4P- mȾ^5nah @%C[iJ[sޛ}fЎfh @T2ޙ;bӿo" mJd(-fDh-{If:C[04NkS$-D2C[*JSEQ%5kh᫢x ]gJ4SR^/LĨ}FȷcH[KO bh @֪=>%6`u_H[˳ bh @־?))>1:&Ph=BڊG>64-Z]ç*:&MYFw[Hu*; TjOIВxW0Af!լ<}thC[*~gçɨ{oGj VKv(@Ps?~J}-=R&0TOISE[Whx7 i[@P)i_ HRnz,ګL }hC[*)iZ(7ztO i}/ cwEIDATh @NK4yuO~$inc@Pi鏟&]g_Q=#ixG 1Ry}㧤ɬs~5A?Nk ch ViPI`W7M;D[ 1`x{#ǢX5,r^Wu~Sq m*3>*irk X ݓ8Aziq m*H4-^e_U<^{L4O cޒ}h(C[Z?J_̾m4zh-1Az~2hPlO Ԍ7;mP7G7-H*-[mM鏡Q{WFZ}m5x=}h(C[^1ʗ?JjF[99|5=AZ:5x`=鏢ދ-`+?:/d%H QOg1Z(*9u~Sİ}u/,=B5S@PKcZ(aTRs_ x+J?WD 3ῐ8*A-%n;Pj4-#qTR^{LޙM/"F@Mڇ|#f^GϾ^{l[G )`h 6{E#=}̼≛|wi=.0 m&N$̆7}*sϥH ]7g7-۬so?Jj^U򹇳0I3?6 e7-lpRIͬ{#227i,-%#0`;ZgF6Kٷ̌[8#1`GSIͬQ>P5ӯߊaoI U٧)bh v36nQéf=#2*;coҸ{G)ch vSImxL_N/ѽ>vLC[+O%5ʗE NZҸvzy>_?Jjn5yTv6D7sSy1GTInpWLחY狿/r m7/jcb('*_Ҙsa`J0ow31UR~w~mFŋҿK{oe=-so?Jjv+}@#ʗx3`^ X*-5o̾QަҘ3`uOP㪤fA;:f(Ҹk|Y>L9C[]ؼlGVIͮȾY=^hn 0`A.Y* ojumt﷢dҸ 0 mXvxCcfQ>hp_W]{Kvk 33WI]e}ds/o2_'bh GWIon &GYD?M.e9sCsC[T^*-9G}D_RFKv᫲ 37XIsV7ŋҿK *0 m+O=te\ʨ{oEc 2`򹇳!3=z}l^sf^G=}ؔM9mɥ} aUʃf%5~?l(F=ť>8C[Ʈ{'g%5wu _~e} q_#ޞH+-^;}^sto)Qes1C[rk%5=pnt%Zswo)orfy鏶]_t47wRF/≛!C[R ~pzlܢ[Iͮ}([OE][Jiٮ1c-7}s̿J-tS-w_?Jjv+v[360'Qk)%;fBxALt%5!{G{>FocRJO! mE3>+Npm/]}ZJiN1qmeh d)F=?Jjt}V4Gk՞ƒȔe__̐J.,bx敡-Vv0 mhe?&KjHwѝȾb+=g42`j%GeIͨj(3` =6Z!# RZ{#ɯsFݘ}s0E?85ZKvL+-d{/>n0LbC9Β&̍`{F]WZ:WQ -Smxף}В&}]p/ҿJ ݢ/0 m~A<8Z4 _}[P#WG{ҿJ 2=D14̌l.tl^jIҝctﷲ*xh5e-iT>bS%Koۇo̾h-!24_}M/]eUlzr7ܶV"[OF#Wxh+{4u^&b>Z0q myEos =&ڇlɨsGݘ}=0'nlګ^s?ce)hQ o;':'76/![Rn/b4Ⱦ0Fjt^S$7%b>Ne+u-)Y(+ Q@@ѓF%?K{Kf_CLb'ҿJ[Ӗ޹-_)@*>xE.hrIkxo O}_Tz#~1U o:9>20U m`5DDk^;螋O}_TҊݣsF} m`>e#}9goݼxwIV{ˣx1*-xwRF/?/JtaD ,7o-Ff-,~'ǮG?h/ij'|1)77#kO:gkW(F xa9 XlIENDB`PNG  IHDR6 pHYs{Rk IDATxyu}K4[tt4u3Q$Ѩ9ٜNb&椪7@E () `444OFiD` 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$d 2@BH  !$dJJ-c^__iHj+٭ї#6wJsSŸ;%%n=K76ڿRo=G`*n*O+_j_4+pK1R=S2lֱ]:_ҿR?|OĩeFsz??F5~IE :e| `?Tkv /-9}?uҹp4|TW(KdpyZ2yTivEiҽxuyY.st.Z]j_dijJ鵢/S@Dws·KK?0w{?e&i+G__jV|*IOǷw.-ۢlN;;w)7xIR`kO*ժßS%I]QZǿ?~,Wn='P|,`pL)i﹥{e˃0xρNXWT;?Jvfei2Ʋ\w]]Z_7%i;]v@ }S[$Mg+J,{/٥%Mfw(+IPJ7v)v/-ձї1Sͽg%i1ک`U3tҹhڪKG_LŶnҹhU)Vb.N)/ "Mkw)OVa[IEYzITn-Ͼ1/4ͭޥ n<3r`ՃΕ:|{f9 z;Kf@D_dkg~'yWFպ=J[Ώh]W1^֬, gG_$3l?TZG:WfFW7i3=@]fe_}u%ifmzLPoTZ'5XJsVe @rÇ(_,I3}-u2 &~pf?T)Ekv-[}YL4q#)a ~zytȟo[R|?;W\,I3#nʉHDߋ2[/X7W;?KkRz2&n}]zq3o>7`_{OzQ]f.,^O ÒҴz2+ї6]qd$͌ 6/dbU_Qjᗣ/mxE3̒43~yǗI1@ RjҿK~pX:Y$͌5+K$t? Rfw(ziJ7?CK̘ݡt{2~i?)S;"LagKigiIC0w%e\-w{?OKR5ƺ]FMջt%`껮*uO ju/;h u]g|0-e{̒^0J+ժŸ%Gw_O_du%`\?&[q6=99duN)R]0V]GzpnwX)Ydwj@a?ß%cͽZ &qo) Ko-Ͼ1[1K= 6^U{3LR8/]5l>PZ<\1;Y\1;K):<)SO2l?K&Q}wKfgrIXO9¿iR< 7>&Z/?KR5VT}k:5'äD5~zfԗ*L >j5{nl`pMZJ#kQ^0}ui%if|{~4zm7IJsGv4vᯊ^ս9t_5C_Q]pm%ifLٵ n_PP1#%Fqi@:/-]Ÿ%S#s)d ugk|Q7ERzW.I^n29fHY|ݥ # Y j\YY; FTo~iMTg~+¿ RZ ۛu1r3lzIToc7 5|ankQ2,W7^O j 5n?@R{j/M{ͽ^껯] 2|S-)m >@Էz2E xѻtg}ICkv--0RͮinvE]c?%ifZǼ>޷^ P8l@fFWvh;_4ͮ(X{`Q^fe$͌ջz ߏ)G^XGHR5ºҟ149x@HR5>^kqpR)qo.} fi}?HR5zל{/Bj6[`o/O<+@>-A|a!MSͽV{`T.3IRosiZc|8ޛ#Խh6Af_,lh'/^zrIQ֥7%HRZl`Vis~ ?Sj zU Ҵ>Kt}ʴ7f5{KA/.qƨ{G$ZD_@]W;hikR{߇4%AE4mzWbov2ጥxpm3$ifa.;`0J^UKX"N?oj{6 N=%J\RTgsIҚ]K鵞x*Mp^VKX*NiT-O@缿 Ҥ@~̟DCHRu/yy_4Ư, H g4}yuRͮ$ֽxRuN{_y$U{΍>K5 åu%$ڎM{|_4i5Jv I~ qDvR}M `Bwx$l[31_u{8i?27 o?jj8 )ITE&̰4}Ny$UOֺ=G Na҄וD&3,$چ[6>z\8I3pm' 9gT=I_u()ep# 6>\ZZ$<~+xK*o/-ժ1$z#?j./J}K֡o 2$z:#?柆 ){a7J׆iHRG~\5}+IailKv IytC^ϪFo/H}C,ӫC6$ϩF{ſ ) ,pXǽ9Ck2c9_`[6> ?됤_5iNiIo8=Cf ?bl%LNlj4|M o ۛ?r8CF?̓5HKQsauo 熟HR57l8gRy/F{;<`\:y9e`giu/hXJ營HZ9jS_4ZGF)nX&?|ϣFfeUsSJ}}`|"˶-_YԨfWi\>~,CsF$50/FG/{= nJƲԵyIvDewHj, K;@V'My2(mo}oxDړK$5UuoR>&&nR?pK n*}~", JWFWLJHj, JU?<3sI~-o'5rgiI`9nmާT$}>úsI4{Y)f-`՛֗jN+)3h]Q_}X>ERɘ@S]G,NYJ9F Z{ IDATѷhE|^YF VTWFߛF};\$L4.Y}OM]$5d:ե zd}I44]YY{G=(## FRɐ@SUocUuUV~#145u+8@vs:,FRc3h:ZKa`I ;[K=d$iw._ZTg:U \%>f$56&U;z!o/պ=h$i{Ǣz+FRc*3hbkRz{,@~}iYed6 n4 07~%FR Ⱥ|8 0Q'=FRc2hj2lL[Jfeٍd5S=#g7S@ULOMh3Igauo}`p|9Td_B` }r$5&>&g8w]]g:@ݽ?Q}`tsIe3(޷_Lߥg;@xu)u?~ 0z~#1תJi}}`z:<$fPXݯ]-` ~|q9DfPH[퇢)tI?<%pmZkDeВ>-Dt$GRc2hi[K}?Hg\xV2)u/^}/HC$5&&A/*׌5֡/ ?Ԙ ZΎ׿s I%};}FׇIjg[{>Qqyfw?T"3h.ts!I k_>RY~>$@cm{߄IjejR5l=X<3HR#$ӪK}58ewفgEJDY0g-C^~^$4R6מ~f$4z261~n$4ZzE)^- 3#I%6{??X Y} w_[HK@ivE7 |]gIRdH{۠R)ѷ#ƠwőgO#movE&^8 zuKϠ$Qe69ѷ!ƨgP#mkΥُAS=(^%"Y?8>,JRc$ٵ }`/?T@OZW}&LJRc]ҠW8lJRYL=a&v@GMIj,*7Fk0A/?T@[GfϨ$5@ݚe{ ?<ڲ<.TEcsl$c؉ƶc:Ai;vDFPŤ2 3HA @1XX EAQg!s}|իW:}}O$IX^VY"I$I Խp* {J,y󟕊n-$I$IB<_f'>cE$I$I{3+ {,pkL$I$IR4RgW@z2,x'$I$I`?'뮍%$I$I`E3, m. >$I$I*\gX@,x3D$I$IhmL~dց$I$I:g}=, 6C!I$I hK[g 5~kJE=;$I$I4!O\=! R꣣g$I$I&b-1Z@,j.) z3C$I$IVmޥF I$I$M`m|KS6g$I$I&ց ?_:gDIT<6 . ~|q|f]sOZz=R%?r~xu泆 7ݸ ߒ$I7~d@]-xv*;zFH$Ӡa/IOJKCOaZ)u)ᅩ13'+UR?Mc?:}9u8.?(_>\}џ$IW[ϺX,j}$I]ژkWGyRϦLͥHN3[_)/ÿ2˂ٿ(]vH$UޕdPS $Ih?86wѩ{}ߦ~oQSVj>c{)ÿ~$I M.Oϲ/g$I z/VOu|ߑ&]KR:o *A?mIT}#}~@ ދ+I4Կ}E}x=wGƢOs]H$N#;8H?fxCJ z$H)tg_{|:)_w~Ƃ_9{ntz*ڛH)sw,j=g$I4fw:廼&=`3߳0]#J$=݊A; ɷTt$iRSvi'}6o89nN$M`4@  I&~wx?{w|8撝[ַ,u/YF$I2@eP3s`3@$Ub-j>c)/T+|}?UITG}$H,jb$IU/O>^„X:éë$I~ g, _R_$U..; Xw&[SOgT yK \*@fPMiЏ~K},I>VF&WΊƽ%IR]}t YA;F?%IҘ+}x_>Br=J($IRT^wyu \`-xO%IWl\_KsR}S!ItkE?%I+ցuΩ'$Icק­EQcSg$I*A?o8%ɻO$IҘjw 0,XsF?%IRx% πef:l4?V$i wR8Sw~xItwR?L!&IFX?FMYLE ,I&ٻ;g~-_^cI5FIԿw hԔ[U$M^;/Kc?>Z? 2GQ$Y1HnπF YL+$isRoղ-P }*DtJ^k;̭ )R*$Iz]{wzET-SϤ{\%IӬh=EĿ_zBD?%ITl%uNBj,|N{L|Sw|%IӨШ i3T4E?%Ic4^oRs%ISlp13'5b0eG}4Y.I~=W?žö$MhC>.2O~Kh:~ F y/t-$IU{4j`仼:A?9.IR 7:hԿ{IEjwhԄ=$ )Djl^23'Ol*ڛ$i3^W̭ i13' Q[ZVlsxؘw|צ-gG?$I4Ϸ{~4j`J4W[S%ûȣk?$Ixs^4-IR}*ԻoG7$IW/@,-SѼ?-IR->o3iD?:$Ic4{E̝nS}_E?%I=~rx=']WF?F$IԻhL9 )п$I[+w%e0l5YK$Un3;(=N/ ǵ$IS=~=|lz "Ii7S`uNBsZhnH?R.N5F?j$I{n;:npӒ$MU/ {f^$bؑ$xO̝N|$ij*6ܚZ| |:Ch?$>*S`uΞ~>K4E?=/|11 .i$IR}wReИBlnuYtWjmL.םX$uhL! ף˒$MtkI/ @I32 I4ފ 0wXL ˒$MdE~xw,}S4W$ծ!)c0o~&K4qo>+;"|xGcKZտwhL mcI&A/uΙO'%W+`$էA/;2S`u8q,ID%w70?!I4:gτhL 4g$IQ|/{fZH$^טsi$Iq_I93sWI:N ]K3XPswl`:OQ$^+ XṁƔ0KǮ)_y La($IhOuSRg?ҷgyhL 緣͒$UުScIE{SOtg_|x2=E5`0A.~VKTs澿OAI*쒼]{jɔ ~~KTƽ3 |}Pz4=S15fh o!q.IRqQ9 [s_OŃk$]yhgV~! 9ߣ$U SK3I)C6,&DE|I*Q|/PIME?&%IzJY{u_|WV {,&@)9 IRx O|XHߠViM1EYLGIb+?d+$IJsw1퇹c07='$IN?>ߤ,뢟 sS_>,@=/~'zvHRyh-h[~J`rN~qjdbPq>=K$I ?OGsNEG$i퟽ʧFIojÿh$i+4XC9勩Ƃg4 8U63ǗIjW=k30@Zo&$=VŦRs:l۔dSšN$ig0()IwE{Sz^^SjW)3 Ȧ@u]=$I[Ec]j 0J$E?jkWE)IRѸ75 0D?v%I#j*U>g|%;5n>wz|y$|/P/3sRc7{4~}4 jE1Iris c7YяaIfVtJW|Ozm$^;z_/& 2i,Iz{".o ë*̝LU4hmw$A?XT<6,I{g99Q j.'I*oRE[hΔ觳$բ.o8%uΙZ9! ꞻ zJ4:gτZiA#ZN#o_+wOc?{iE|YT#RԻ9 PU RISlOuSCS/ֲw-ß`oK/$izx<3sRE?%i"ro?@Y,*u䇣g$I7皔o9 Py J5E?%RԿɭoYw|I`dޥFUIJKo 0)%F?%)~7 ̽saP1o$WZq|4?^;).I㿷ß)bP!n=z%I*I яqIݽm;g-@cYT!$IRg+]qp\5Ns>|ؿeTF YTHow$I41 0lkWE?%so?@* ƺ-Inv;*~L|פqo]νiXTDs7GpI~~j 0mfXIw5 :[j/&@,*sg$IOsg*3/1/i+RSR|ß}dO@E9&zKv~j{FLZ3[gE?%MӽW"Y@*@U/ISnn|WT)/TY@6,88C'נK>CxXh4 ~Ʊ6Gѯ"$=+v < ZIڲ"DͮxoFP~^%cB]ŦRs:lG? S,wITa=??+ ^=*<{WDgbI6GN_s7kE iw`Խd>S M* ͅѯ4$m^Fw~UuNrԐ&H7ScV?(@9sg'gfԿ!U@|{Hu`73= IDAT<$mVo[pS6G{@$If:s'sEiyy]ojwb4=#g,V7H'3qWl3_:g|eWωbظ&]Iǯ(Rs 'wT Gqoaۦ|~$1QsZ=TBп}W/[@V c9g^{$I?` 1E`^Q'{oթjXQ_%I'C N/D"=Nņ[RCS/ֲwƂga0Fņ[%IzTEc]j,:|Fhf _\{_H`L힟RQDOJ:g k.~oԱ~)Iң6Sg$0{͌FTw uW8X}$UGc7g+]Obϧ澿/Ւ.; 5TGw#9i*q]{\:׿Fc2瞒$U]WF*hipcM?O|_ `/f03sR*I#t|GsVi_*tNbj{@B,FmfON%I IF&FhTR˫?a>eIQ LJo݀wR}ܧRs7`n9,F݋$IY~05n>L?^LtWZn `XXJ{Q$ֻwIϟ@|O]4i,Fzq$Izrdkǝ5EԿ}E=dj ?o$)"_?9z&07p`Ի9K_c|6)E쩏$V>Me~`K}#I`n=YP}#Iy17l>l,FssIR]sL<#ԻsIRko!U>:7|C a0BEsCя$o=/|Y ɷA$uZ<0#\sIRk.}G<0#>#>WXH>$ոGB e0"KFHj\ @`$I廾6|Y( 1GTӊ A g0 3[kEHjZoB E|WEHj\φB g0oIRkY@ODHjZ0.zY8 IRMprJ{EHjZ笯A  Q|ן}#Ii>,F`p?9d`0E>GTÊn @Ve[UJE}$IaA U@ɚ? O(YEHjZA ?/~Yʰ(Y̯FHjXX>R,J]{$o;?|YXwg@ֽdi J(g@93*d7FIjX@  π$I5,3*L }#Ia̜9*(Qπ$I5ldcPֲwGIjX@  H$u/X>r,J>sg@6;g U@:̋>$հ!@V9%# HTÚ1|YXwՑg@U`dcPy@U<6|Y%Yhp@5ceJ(Qs IR>6|Y%Y(u@սxddP|6g@9{n J(Iπ$I5}߇@ $ 4# HTZm>,J:g@6@VI%i3 IR wzE J(I>$խH @VI%@U@VY%鞷]9$fn @VY%^W9$f <|YeYâρ$I5*򆓣ρ$I5dePys IR]deP=DIjVw*$5@9*$E~_9$fu>|YeY$;@>* >$հQ@* ;( HTZdeP|DIjX@ , 4|S$5deP~>$հ^o @VY%h3 IR k~?@ , P$;"|YeY>$հ|@ , t$5l>,JYg@֘dePi_>$հ̜dePΙ_>$խ@Vi%螻 HTdfPK$Iu@Vi%^c IR*K>$լ)|YYw@U47? 4 >*HT|}J(Aρ$I5h @Vie|ן}$IYh< 2>O>$,4@gFIjV~0|YY!zn9$nu* $Iu @Vi%ܱ2HTdfPK$Iu(U@ w]} $Ia93*{>$հƼg@ ,  . HT @VY%{}$勶 @VY%! HT_>,J0Xc$;*|YeY@Qo@VY%$E-3*~}$Ia>,J` Iu@ ,  ) HTZ| |YeY@Q눿@VY%$E_@ , IRD?>,J03 IR ,dePWEIjX @VY%yY$u]>,J0g@ֽ3*g@ֻdePƇxg@[dePƇxg@6;g U@ DIj3*π$I5lnu ʲ(Acπ$I5xG ʲ(A#π$I5hm @VY%]yh$Ԙ"|Y%YwG@o9ddP%K$I5-Us*}#Iiͽ+|Y%Y{n?:s* DHjZA $ t.GT'CJ(A?9s*}#Ii;A $ tNIRM]~`J(Ag$I5 s*6GT_>,J>?6XwmJ(A?>$մ⡻ U@ ZIR]wScfN,ʱ(AsEHj\g!U@ 1GT^> r,JIRkYdcP|DHj\눿 @V9eIRkY(I굣$I5s9dcPy$u/Y>r,JRl\}#Iik @V9%{]$\>r,J2X*GT>r, o=/GTӊ9dcPy)?XYdbPGGHj\g!U@Iz}#Iq~/|YXrIRkYdbPw>$ոI @V)%IR랷(|YX}g~$I5nhg!U@IG,GT7> R,J:g?7YdbPҷGHj\> R,JIRk,zn<ʰ(I }$I57C IiЋ>$ո@ IRkYdaP}?>$ո> 2,J4g?׽*`$I9&|YeXwg?_sQ,ʰ(Q⽣~$I5xYdaPy~$IuMy@V %IRw~U<J(QOEHj^kٻ!U@Z(GT|"|Y%X?>$ռΙ_ @V %jsIR]o<J(Q+}$I5*L >$ռHU`P)GTC*d~}#Iy/ @>!(Yo>:/!(Y}}$I5s!(Yy>׽pyd,J>>׻yd,J:/}$I5oyd,J]>W!(Y}$IJv@l}#IRjH#Pt>$ռ֑@`}#IyK<PP\}#Iy݋@`GHj^!ޥFHj` BY@>k3X@g?FH]^>,3IR? @`Z}#IRjda,F7DH. @`=7G3HQ,Fhn>$ռ!=WGHj^XꃽsIR+/&|&Y ?G3BXHyg>$Q @`D:G9k3BXH}#IR]~PL#7|$IJWD a0"m|$IJCD a0BEkc$I)3`\}#IRj.}{LÇ+IRddcg0B˾}#IR=7|&YPg>$ޕD ; jwg>$+g"3IR@6v#Mg>$ wxa\|EH4E + +FH|"|&XY`3IR3`MGHzW>l,FjY$Iip3`:g~-G:Ԙ>ll,F}>$iX˫"5I~\|/GH4s?E  1wY>ll,`3IRg"8>N>$)@66c0{$IEm>l,,Ơ>$iXs"py$I|"|.XXAsEH4{dca0/>$iXE  1)ZDHw_>l,,dpg>$kƼgE 9 1]{\$I~5|.YI]{$I:O"tNBy$I:d#g0&oYy$Iz>l,ƤoDH4d#g0. N(|$IJEsC\ҨYQg>$ wd#e0{ͅ=$ kd#e0F+>$iX/E ) 1Iu/Y>l,ƨ}Ǣ{$Iֿd#e0Fͽ}#IҰ"_>l,isS*3I_?4*cVl3Ga>ld,v~y$I:?>ld,Ƭwٷ{$Iֽxd#c0f3=Ga[ @62c:=$ +'|.XYsߌ>$_>l$,m)IQPl\}#IҰI @6-gGH4rd#a{I."@9GaCwE  ?}#I#_>t{zY$I:g# -S{$I9KHeRl%GaU" ꃿI p IDATA\Y#GaE{Sj @V* >}#I#廾.|6Y,xOY$I:Je$_Isg# P}#IҰUGE +@䇿I :|.Y,.; GwScJc>ٻx'MQSiu|,V֪:?3Te.ZGֶj&!a_4! d-,|=x5sx>\vg#P1P]$Ig|*|6czoFHԫu Hy}#I҆:w?|X>zK}$I֭@eXkzj}$I/eyuKg#Pϋ$WwF2#,5ND]$Iul*3 X7GHԫuݒTf@;y}#I҆:0~6Lݧ~}#I҆3y>ʴY GHԫzkg#P6 кjIzOhl*f0g.G^F2mv;z$IվT`T4ϳ,G rT`@d<}#I eݼ%LIzՖ3|6i}#IRy@eZ,DDHԫjil*b0 jK}#IRϮ @eZ,łێ$iCYc}FG * }IzU~]l*Sf0@w}#IR)>ʔY z$I56g#P2 8Ϣz$IչT`yC]$IuF2edʔX A$icZm>ʤY 9yV6G^%o@>Ykz$I83LjpT]$IZ>ʤY E}#IRF2i~GH+=>ʤY .GT&`@eϭ$WF2)sz$IպbAl*b0ZW}#IR]F2)qGH+{gLIT&`P͛j]$Iǽ?~>DY ?$W>ʄY GGHԫg#P0 ּw=$ꮽ3|6 `}#Iƺ<T&`U5ϳ,G^# |> p3FHԫqg#P ׹Iz|Dl*b0Z+FHԫT&`5Nx]$IkU4on|*[e0jz$I꫶Ml.ϚGHԫ|[c0?6G^kFUC#z$IyT`4/b]$Iƞ{.z>-v$!o@e,]ۉ$WOG  !}Iz98|6-[O$WgT`H4/Z]$Is~0 6 !Q?w=$U#P, !QW<ˢz$I8lɞy(G^@e,Hsz$Iyli^>/G^Ym]FGIC~Gz$Iz#P$ !R=<$8#P$ !=x]$IZ?'|6M2VDHkl.EFIC}z$IU @e,L?$!|>q,L;$-|>q,8Cu!w=$ʞ<|6q,PEHWׄG`{I2p,݈$Wʽ#" !}w=$ܷ"|6>CIze4:'|> !8z$Iz#PR~$ijX ysU$W# !w=$ꬾ"|6 !ֺnI]$Isy.|> ,X}#IR_ŻG-yS=$I}5t|*X >G^}'~> !yIzu:|6 ,\Gߎ$icjm>{kYAv#PvŻEHWυGb0FYIz?,~>@tV_}#IRg#P(DHv=OwPv 8W=$U[eױ~oV=$I}5eױ(/>}#IR #\:_}#IR#7F(@1~O]$I`, qǣz$Iv;#(A$_J@6G^[N J@:^}#IRwFH%fP z$IXս^> @OXU$I}Տ{|TRR=7y$Iy7#(lw=$yNlTRӹIz-g#(z$I꫺GH%dP0>}#IR_S4|>@*! DHWʽ#(5w=$YlTBԹIzeg4]|T2H]$I}> @O/<$Xd, +y$Iuݒd, *{Izu\> @A8+GyZS|T"ռz$IvGH%bPP?}#IR_ w|T"Uk<ϲIzo>>|>@* >}_]$IkJڷ}#IƲn^]$, yWz$I~GH%aP`v$oGH%aPd vN+G^;G) >rS]$Ig> @|D]$I}U, q_FHW? JjK}#IR_> @эngz$IY}E|(I>OGHgP$ڡo } @It:7Gu;yu#(eߊ$> @Iԏ@=$I}5W|#|>@*0 kgIzu<'|>@*0 >qw]$IFHfP"[N$ D~)G}<|>@*( {Ij]}@|TPe2 @ɴ[}#IR_o dg}&G!|>@* -{Ijt\|T@e3:'ϪOEHԫ#cPBVDH,˫{<|>@* j\}#IR_> @ Oh=$I}5/`,JEHW #(왇z$IꕥRXT3z$Iz#(%_$Y a=$I}?4|>@* ZKww=$>rc|(cFHn{Â:z>@* kxtU$I}Տy_|T%8<$\ ,J-<$չ ,l@* k{Ij]$|>@* {fAA RXg?}#I:<iYw0GG'|>@rFHW󒯅GHC~ŸDHWs#!g@^yuz$I5i#!g'$A o91Gg|*|>@blмK<$պiYAߏ$UwV-GuZyE3F=ݟ_}#IR_> ) zZ.$%> ) zgE=$I}<;|>@RԾ[<$=x|4,htNU$02|,ӹ{Ij,l|4,Ӽ|~=$I}|D|4,S?DHW[#!d@.ϳ,Geݼ׮3Ґ`S?$  rr=$I}X>  i~DHW#!c8#}#IR_Y<>|F@"`@"lR%<$վiXI>}#IR_3GHCM}<$zg$!aɳS<$83F[$iPj;Ґ`ZW}#IR_5#!afտ{Ig$!`fU<ϲI3`O}#IR_K>  }<$չiXE͋.Gں< [T[{IU; 3Ҁ`F=$I}5 #>|C=$I}o>!|>@plUây$IҀ`$i\=|F@`lUmnw<$q'g$f֍ɳں{Ij]{Het[}#IR_Gn Z(G׮3Ҁ`B'}$GqO`4,꾯$i\ g$eeVGHWgi@Y0aN$V-Ow ּ<$3`jG}#IҸS4,;y}#IR_΋02x,#7FHWV}2Osg$cV-$i\%o XG$Ij iX0)C}#IҸڷ|7|F@0L<$l #Ii=$I iX0ix$IWOHHI;Iպ iX0i}_}#IҸ$|F@ L/[$iʺyu_ SҾkIU?HH)i^;Iպ i@X0%v$i\݇>#  fyiFH_W4~NH< ȍ<$~g$`V-$i\+SXG$I' `FYm]5$IGsFbY0-VDH4g$`LKk;Iy3R0 ~Gx$I_;IH,꾯$iՎ=|N@ deVGH4># `ڷ}#IҸ:^># `ښ}$Ii9 )V[;I6YIHA,;y}#IҸ9 1y/[N̫:HX0#}#IҸ:w>#xAu7ND޺vqyϺ3[) f<$d;ωCn䭫3ؓASX0c:$M0^ᲿysyV}r~8S`,1 ID-}K(3Yυ`ƌm%IĚ5|N ԻN>h5/bHX0c2$iu>?|NĽ_͇!.3*[:$i\Y<͛>'fZu?D>5/Vg* fTӢ I6YIiYw,/Jcc4xX,Q͋>$i5s`{S>f^ZW>R,̨ڲwE$m=Iۿ)/wgwHcZs7,kӼg%Pzսv})wF4o<&M* f\ I6Y툷Idw})F׺BM\9 X wpX,q{D$mνI7S=C*3W[[Y!I&˚oY puV_93otNE$mڲwJ`y?ϯo?R,̊}+ I6YoI`?wƹoXw%ϻo]JYFYZ0$iu$|NnS>^$#~҇ I6];J`UwǞLxoIcB6 @f؞/kG7/})y$>qwHX0kuD$mF$0=Ճ_76o]8 Y5#]$ jS{3o_ټ}2k}xsCZ4|V0<8׬5և`vɳںCM}Y n*Sj߁T0̺}+I6[ׄJw7<#EnHck\}tHgY λ+#bC־fV-,N* f]uWF$ml#f'?fKSnwFJb6{ $iyC.|wUƞ{ m}g$Iyg%3v_7~`{#a6ѼI6[sg%S>nJ[cT le>;$IlYm] GuW?V.;]3$Of`}H: ?=/\սv o^>?}A'?JŪ{ mzkIX x_ֵjGm*{cD6\] ymkOT*]Y`X,ئw}Hٺk lw7+)i3eugF* >G$IbsW`w!->֞/N+,$io=5~^u O脟-#b6}D-%[x)3%pGϚT0ls>K$Ibc?6=/ʬe?xGDI۠5O* Y>K$IbK>/JûٟşI#b6WoE%$m+%@io7?Iuϩb ݓ$ tf^]y Pwk?IO~n З$iC`({3Ǣ?IO~ DoE'$mIkymٻErr}$wşo#b@q)<$iu>/Ey_Ҭ}']* b,%ϻ3E-V=53 ?I*I5ׇ`,3ѓ$ik`6Uzy^??%}~4#ys1a?>2L$io?#|^̘;%o}>orb]{Gg\k:) 4\"Ij4o 03ף?^Iunٙ 0C}HG;|fLS$iҵo=5/ /l޾aw%֪ݑb ؏&J4eن@9}hjџ$iѷT0'$I[| w%֕{ͩ`,UkW?(I"*` _n|$I}5/~^ \wg$I[l֧ysg&0|=3;7IzK7}Hj>3~ʧu~헤i ?SXqD-$m{L ^uWһOFL4vO}Χ \7G-$mU3ض/I۶Y ?SXot_$Ij>>3~I Z(|$irr&nz"c$iՏ{Hc@E6vY0t]n1˛S޾<{ V?=s$ϯyE1$mڑ>7_x[_7wͻ4Ֆ%~]g$I[uł eS>cKUh IfIchxt#IV>rc2k^?ys7$I+!'qI^~#|n@,o91﮽3TgHX00jy}#I҄j7sּymk睇N3zKkgHX08FNIPԹ C»=XJd@u^Y#Ieʞ/0h/Ij' c,(K}H4PPwkͻ mx,(v>k$IPUK&nDcIRo$Ijٳ?t5zJ ^s]* NgD7$Ma>7`[Ō$fOw,8>o$IP˾>7`[ڒٮuݒy S?F7$M~>7`<*I,׺r7R< >,>s$IzY7kfSuWEO\IR jzKd@>yO#I҄j,#|nlq+I*A6|` o:6̑$iBo?#|nl-{g$ƙ>RY0e#I҄ifK?zJJPϼT@ $?b*I |vliQ+I*A>RY0FYsG պ yG$ չsG =uм|~$>RY0+}H4j-|vlh]X$` U?=$Iraо1+I*xYc}KeZS$ImfAg1+I*xٺ]*( ZF?$M 0Ӻk]*|ޥ`>0$i5/j#VT:^>RAY0i#I҄RAY0IV-O w 0~MnFϼTP ?`~$I]uWϼTP .I0U? #UTRAY0Ǽ/($iRV>?`FTIR.ay}I4Ӽ3j *S٬]3o,ݟ_}I4aQ*I*A y,>$IT떄OԾcyKfШHI5n_fj,#zJJP3/Cy֍>$ITv0EQIR jzKfP>~[$IҤj]sph||$Y y,*UK$I&U4:'|duVT?g^*0 JOEI$Mo0Y3EPIR --|`Tg$Iu~3&eymGPIR .zi). N%I&Unuɨ)I*AYc}Kg$IXm[g(LTDNIR >yOKgi&I&]ʽg(LT/ENIR ꬾ"|楂`ԾII{ Os(LD%ѣSTڷ|7|楂`(e>$It#>C`":_=6%I%u~3/C}$IuA3&"{gcST}%|楂`(5/r$IҤ 4]-yuǦ$5Nx)6 Rߋ>$IRc>G`KjK=.%I%]s/it<=}FI4ZQ؂T=s/Cs(I&]Ӽ(lNRT,O v {,Z_>$IR$|o?#zTJ``hՎsJ)վ9 }Q)I*AGoy,^ϳJI5ӂg)=_N$gϽ_$ [S>>GՎx{$5ϽT }VI4ڷ>G5)I*I >R X0j}VI4)O w Z.T?#s/$ q3"~/^=%I%Ms/CsߊJ)5A,z/ʪOEGIRI.|IK%`k^J^>K`LDOFIRIJW;j3K)?RS?ccQTkVϽT ;lE$ cGo0 +z,JJR^* s$ISvR}$i[s/м_-I\g)%7:'jG$$5B) ~{-I\<͛>O(ݢǡ$DO`K%a@1$ u?O(FBIR-ٗJڮGAIRI7RǂU>$IrVSJv#PT?99|P:_}I4n^=ri^PTZW>RXP(K}I4 Kދǟ$D5/R;g$I*{S(ysl$_) sLiU?3RcOT,.|IK%b@t ($iZo=%|PCؓ$5/Ӽg$Iӫ]ϫ{JL:w=$I%g_* vEe$M;|Ppsdȓ$֪o\,(Dy&IҴ>rSLjn$E_ d,(gFg$MҷTyעG$dO`K%c@!5Li׺ @q,IҶzk_* 3I]V{:O v]݈u2ժit8R.VܚcMi83⩟'I*Yn ,(-'Fk$MCWTu#NT~ggK%d@a5\&IҌT;w*}MTZ+ϿTBVDk$HUK*Q=7G$y޴B>}_&IҴE/ C/F6IR JBk߰,l$iFj @1t8zIJXug`*! qGm$HGo ˗݈k$|Ъjg3N8D3IR wI L%e@u1$iFj|B\`o?3zIJXg`*) }8IfVmOEVԂ>zIJXcsp,(q)$ij~g+é~҇ǘ$Ֆ5|j9'IҌ=P͍ MF1IR7ETRBG$I3V>[2Yz"zIJXwsp,(%}I4cu2|0\Q$mTbBm[:If=_]ּ[s00:'Ϟ,$ijt\|`8,9D.IRIY8R^;. _QfQ@QDp/ *\@}E>=ݙ 78k{3V4~BJe=bC~;|N{] MSmG}0P't3V4~/\=feۅiki#P)eJ$QsH媥 )V>$~*Yhj7}uV$Oc>=rݛO Yho{ѓ ):kP5 Ma32[}w$b"5𙨚uߌ>`y$|Jbk_0z"0zE3Q5 Mg͓>} PΟ>g%I_@3Q|Tg! \?>k%I15Qs3Q~ڊWG0>g%I1u~:3Q>7д}1r)m$A8sQ~/,iV4:7=~j,4x`ZC$ ֹ=nIGlT,4ޗ \y_m>o%ICjsc-e{D0T~ @[3buQeqE0Te< >s%ICx `Z~-~JZ/Fx>U{ZRpwGx(|JW0JTzjR3}!|k_s̕$ ֙=Viʔ<|F,ٵ3ϼ+IW-*4;ΎJ= 鉊o>'`:W>s%IV/Exy33Rgd =Q$ _I=>w%IWRi8sRgd =Qߎ>'`$:7>w%IW{%I_纣< =kSjFy_^IUWS*ϪygjϚ/gLއH u]rI5M]TٟCXHO3F}юWY5*W>+U[c>7`t: WnG~=-`zQ>/֔ߪsF IDATsqW쵾c֪ujk@z>;` |J^kSje#֪gjk@zڗ}vHߞy[`Iս֪la =>?`Z~-|K~Z󄿌 N 5 ٚMJz ծ|aI_ˢS 5 i uo=- D isKM֚3B4Xi~oTѣ֩lN-gjk@ZCN/T>Y,ISܭR cK3gҺRˢRѾsX%;GZg}9|v,:+g)(8X{(}z:Ro>K Lno$I#w}z+GR6Y UmYHx3´/#|KR\sdqsӉS@ZGއ4otocIjo?'=li_W:[g*6\6,IU+_Tfˣy`=>GU[,u5Y*W?}@wɒTffgDʕQ@Z:W}@Lo,IU>`tFUm֣>[ \ji(|.KҤ8wS*::lɟ w4oT6WE{˷$MpN?_w{me ϒ4)5'TI<3U @ڀ\}\yPlI[Sese _ =WU۠, uD0V'}:|>K8׻(_2L'? mpj Oծ~ ђ4*u h7?[64 i+"{ek`-Ic̬Թ#҆f m`s}p\+zNKҸԾ`^ S~0e3W68 iw} cӒ45 o @t92|QYHQsOY7?>%)!R}"@5Fe mD=lJ>%)^oMe|sV@ڈ{%U>vO$|^K(w}M*[}u\>gU,xVS6wy-I(xugj/!ֹ ْ4E/N򛣏\~ mtFVW_{y̖asXzUQ CSzzfOv&T<|{9 cu߇lIxM%D0TJ /)WtS[>%i`ʚYUڔ,M~aekunFnI+]0 ݅^M@ڔff%1L2$~[,y{y)Dgj/#<QZ_>%iC(_}ȴ&g mb}D)7廾&|KT,>&g mj3rg2Lb)_9.I(R&T3Xd ox[jDqIZS=ߒ}\ȵ/>UHs&R/|a,^}w2[}L@~>UHҀ*3l7$[c>R;> D=)>UHҀj_8|e i\jŔ"X0>UXҀ&|0n:W}@!?47G0ъnM. 钦|S3@lYe i{xC\4廿 y +ͪ 4 is*\y.5}_*<>>UhҀ+]}V@e~~vIlfVj󕔊NQclLټ \{}^@u8#]Rul:7}\LVmYHCxTg6TGMS?>%M~~5}XjYPqg6TNo=%Mf͓>R}x4SZg Y_>:[zImRâ/kNJ@B.J,ng|{I_}_KCD[0'UVm(YHC{g7TVy/iLEjՔ &v4,!:orݩ[g*# &FSjC@R◤mGPieHj{s_43+' y'ҰXT!+:w}Mu~ilrՆ4zT`4:W[I#lfVjשl>`"uV`jt,廼*9W뭩{L 5 iu>,,RƑ@ҐMj?7N3VW @r~7<S}N),{b=' T-4`6,a7Y*[}Tynw~EITkSS = i/^}*|@F4w:㋩l>JRR6gY4,Tuz+HmßHZffo>:?+~+" iDK>`+JC@Қ*7ogj#@Q3)lz2u<(e;<7[SOgU~.z6,NgQ^'}:4-s}:Ń7?PmYHll>5=9 RE}.l~}FesF4:}kmJ9yT]_Lym|KŸ6,8{`=H͓?Ÿ?HX}7U/xO~ȳF̬T;S8CHR}wǤTtS4TyR@Dyn#lVy`L-3(: )}PSYD*Թh,=QSy\, E]ß7Ts~`S7_Ss )m~<(N#>ZHRP>}i}7?mRJҫy(jaYHW {٩qŸgHRS\qWC Fw|As ²PMŲR;KmßsHS`<ө{)eCDŽ?P-4 )bѳ2{(/\_CzFsLoԹ[)`Ga ,ZC,F_Y<)EsMqG$u<(G0$S6gJYH 0=If|W?t/x~js l~#оh g AcPYK$ Mz߻O,L=|D,1qG X\:Яjk:_SR*:@g?/Qm,ơY\qWlD?:~>i -_JDc͏?OQm,Ƥsg0zڹxks7w8RũXzumQ,1)~֮ͧ)/ 4gT]u?m{/`Z?Q,1l,Rq}+³y[?Ѧ0K;Mekuw0I4M֟D `R Zg}9+ǣh;"5Dj`OэN&XŸߨ6VYHԜ}x0Ww8+Cߗ?י[Χsѩ\qw P1?G@Zω@T,.u:$5R}w-!q9_IM÷'`oK̬AUxt4RԹ{%/|aI*_8uRSR?/ L֙H@:7=3)Vz u0u80RjT)eE/BOsSoSY_OSznI@GAxǖ=εH GQ/~i jf[yGjyg{g[ 0:JiƱYxT guLPyq{S}woH.jg __/OO}8DOZ|5/)u<(unN. RmƼ=N3k RmƼ|S\=S#~og M@)=W6YHP}Tѳ1֟W6YHRo t+Wܝ9U6YHR7zu?S61YHҜ^Sx,;J@T,IlfV*=z0dS6Y}$f Mh39z0d>~f Mh秲2z0$劻R6g{(&6 ikp94'&: iƔ"z0`e)'&: i~F<`Zg}9I@0z0@e?F;6YHXzU\`@Z oRYHy_D%|ыTDRy*3z<-I*YH=fwye=j@JMep`#u80IJYH}s QtSo _RRYH*_Ҕq\{Tݒj@X+Wl|sj@X &CCTdRtR`}t)uIU2 xw`=/?.If U=G/֦H. GRYHqGGkwHU: JkzίCRrRkWѣ gѾt#*TnwG3|KT~>z6YHUoV|@Jle3 6uYHSVy3`4;!զ2 iw'0|ݻ/Rmjŋg@E զ6 i (#:~@=zTW_~@~>v=zTR]4/z," _~#u--_T6WEDJi{)ԾxQL{R6o;)'~*Gʞ@Rj7;z6LbU),Gʞ@Rwx^*3`re{){JRXkߑ69\y_8esUw~y4YHz機uHٳd 鿚e*3zfL;R6o{i3'}&znLQ ϑ5d <=;^rk@3j 0޺T8R,$=Yx1 0ڗ#^{c\`l~#e@.4zI @)eLO~{)[,$΍GUP~Hzf i廿.N3zkh)ۀ,$e{DWPe)4RYHZgS?=g4xm`֫Y_!w~7#ekVxy 0Zzw}݌4{ó5 0Rs~'#eofV{YbM)e4{A5 0|e7.F6WXHZﺷ|;z Uʃ`l}alH{%n;z E-OH&󮭞u#irjhY 0?~"eXzu{/F/~I*GcsQff߽H*}]84YjLN#տ;)P#?kײ_Hno:+-Uo=HG}(z6lS6g)Ts6O,ߵA&mGhio cG}8 4xC=&Q{~"e[5NL$irk_0tPl+R6g)pyy¿ ImSؒЁ oUكy_>^k]8 45Й !Zg} Zcÿ I_ C7(&es K!չ'k{I{-:֪J}~"eC{O~׊UAQ{pi7~"eCx'kY=/J/>CsY\*mR*O_{- TYo/ߛHِO/y&"l:N4{5Og.ZIئ,f:z/T?ʦ|s_jչꐨWV~O"e#{\IVrQYw$R6lg.z%U 1RoߍHx</PRQwEIDAT`ʕ{)a3@E_ڔZ٨<025bgM__s%_j:+jp) \t ns "%U9[kF<iSYT}"eu/Z.B%UL->,{н/TRulʕjS䒔!;ÿ`IխqF4iP6K 󐲠O_'6 T|gس@Y7VϺzz.:a=*{ ) ._: _N+e;nTZ|eHO*\yp}AKm[! i ,u\:@ޘgH+߼ oI]sJZYR65}z=lָ?u֗t扟 1sћh_uXD=9P!fG.L@j> XȪM)=5x&BƤ㧶_@֙ RzjRx|p bղz0IS?&\lR6F?k8@IS̬Խ >V^]^7!l݇Vl4=B*6`&TNYfoCj=**ij:: wR6f^c_+sЭnLεGCHǯoj=~1,i@5_y 1/TtG(+RpIU?L,7S?_~ ecX 7 %M_I0fNj;)Ú}|bHE~-/@Ҕ5oT~`NB`48 R6ud,z;S+$M_klv=xw}iޚʡ> zVۦq,R㘏Hdz| SȏP}7%M_iS`Z;)nw?=1/S<<\Rf6Kq [ʞ̬Tt8@OS%*_Fy0T??KT`Թ4 rSX=SRkp#On8U?R4)vnw>*"u:/m]n0o3Y 'o<1e>a\(}@EҸTͩ4&bSz0ՏP?V뭩l<}@LM!~sH3R+Kjb}eZV&_R%k|)Ei!Zg}9gsiT,>MZ`:1\RP?nMU4 .%Տ,SSzYCӹ餔ZMg~/u\2 oIը~O'tonn4?u(M-^$iknӽ:gnidlhsq&\LQǦ|ϷI蚧~>D~MOߞQO[NMC 'ibk_84MY)🱥aWm}Il:Oѽ8i-ÿ %MX3Rc1(;qJ/x~j~oSF?-~H+J>)iUu^{R6A77vF*[jcgjOYrYj7)߰ƾ|X~s{.U/MwtRJzClYrgtrj]0?5Nd[X=>Iíuѧ<TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT{v@0jA @ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ A $ H@ Asdn?`IENDB`PNG  IHDR TQ pHYs{Rk IDATxyee}k PD "&1FMnbnOIkcsM<ɍ7ͮ*D! H'J# HH_PPtխ5w&7ߵggs//_~Z0>a zo:#Dߋ7EkDߟ&AuOa/P9:Ǽ=nG_0:;,QGnS?`S+'2#:Z˟u~AuwcW9G-쿧W9܁̍AU1]<'3Z{=7,i]~?~#IzV1z\l;*=z{Z=Z)fEsdV&Q$Բݢ}/EU1ZO@T|a?߸0mTpVxZs >* 0qֺhIvU~qh9h*0w}nZ117 d>c@k9Ocp9|*` \.Z$*i~Z ī7[%iek?- 2lU: RIZbԨ7ՁL$Ǩz4 0ç1Z{m`=?~H4Ɩ=;:g_U gs-MI Vϋco 5z䶨}Y=$i~~kU# 2&Ψ?w*%-lվ/Ѻe[%EyW9赲?9  [~s֊=WF؝ٯ"FylD1lA0whCڇ&k_G|Zg$i[gt/YlXL *\ͳJEDIi?cQo?rT{~$IZXu~;0'U@yF_u!hJ<]GknIjGEu'`TEyYT>()oz$6z^~$IZ#{l7* F?̢􃟤:Ǽ=ꮿP'Ekf%I6h6 l3*],ZKؓԈ:ǽ#_eA+Jc$-|^GKFٟ"dP4k: ;IͩsGۜz`zk]$)ꨟ_lA5\TzQ ^&A0VGkf>Qo/u@F>/ϳ$IͩZG |)L*`LcE%IͭpO 1KZ{/IRsV>oƠ u7SIjժ[_WLEk._f;ẛ?Q0vX3êAFܐ`B;0IRjhٟ(pUh-5@$-{V | ߅IUubim' (Aw]e$5ό~]0 F$I:1lJ2oDk$5%O-f&vWLݘ$QՈa?+Ƞ fQ􃏤7S n89u7j̿#$5'2Ƞ 6vTGlGRYVgbu_js$IeTO􃎤fo+m]$I j1OP*)>$#.~U7 :2LԬvCfBT[eݚ)#W|H;$5_keTOjh3`#u>[EwߡIU?B0X7h$5qtVhwifտOpUIͭ}f/FߩI]cO`U_s\!FRck7?m6h-%nMԜ*FqITaZ}IͬeQ+Uۭ߯IU< eP|˰귤\$5jsco*as:MԠfs?O@TԽd&"--w>5s3G#&IjLժh_(a Y;X$5Ż_S0u롨{7IRc;ٟ'a ~'C~4"R0Vojs$IiՏg1{P$5嫲_Q0/7$Iͨ1j< aPSn Z=ٯ(WϮH$54 aPl4j[&WwEo)_u8>NԐfv=_: `PS%WDW,~;G)^NԌGTtΠ hkf>UQe`A՛FIQ?M@2*R􃈤fU=r[ R&Z˞~O'IʯZu6dDU0[pf􃈤Y1Kٯ'H5h,ʿ$׽_?K@"*6uߖ~Ԡ[~;@#.;;IR~v{?K@*2N?|HjT+~5@sԣkvgYW HbPdЋ?~ԜzdqꑨܧKfv7fU0EWԘ룵Yx`Tw8$51otLhOJ˓$5TݐIAL6$5WFZZ";=IRn(s,0**Z,!)j1zc؏α?~'I-U7fdPS[yY+ SoZվ/Ϳ$=O?G2I7EkH?`HopQo$(/Ek|<=F Ġ &\]oٯ#(^N$ջ߳?E1 W IuO}wD=~Dgw~U/跳?E0 6ƅ I~:kEצIr\/ `O_uWLC7G9w}?C0 5|h,J?PHʩkj&S%I9 BggU0􃄤fv-f`@I҂=ٟ `T$t r~La?:G-NP)$z0 `o<5!) Ro7U#gI7 ALq~m/:`a qafvJ#$-\%#*0GomV[_A0z̤J;hýٟ`T], iA?'F\V/HHTտ0O `TzmA6(7l6?>/ɿ7$-Hc>* u7$-lϮ~fx祳*P-9ֺO0 `t/C{#:|~(IZ_96* I?0HZG)~Od43Psguy`PbuI SEQo7lEV0>Q4-50fU0!z.?,H;/~`xgx{EIҼ6O0fU0!G5 i zK$i~] 0fU0Fգ& i~gٯ`{>-I\cfP)I[7Dٯ`jyjfQԛcdPs$[>/zW 0~(I7Ƞ J7EkՋ%Oݟ~c_9JȠ 7|Áٯ`\U?c벿2TA_96p i~ٯ`Fe?J❣mcbPÁ^3n+/8R4w.A:5IZg~󥮣L$cbP̢􃁤1x~QguHT}$iluO 0&UP $gWdZ2b$MP^iĠ ֽdI@zjPH$"U*(Xc(4^1+)3FïK$gY10Up@ZM+H2Z{]<#R47Y J<+#(@*%IsO 0UP=W$ͽ~MP_H$ͭE տÀ>'# kKIҎ>ٟ` PO} 0 iǫVcwfJ\KIҎWO 0UP~;0 iYÛ~ =1%I;P3BUdA@Ҏջٯ}i]$iWJ|UP֊=7G ٯᆷ_44%I/dF92j^w+(D~)I7 Ƞ 4ClfQ o>;dЉ?)Iڮ_<$ ̑Ahp9IW~uwu<=S.0GUPWM?Hګ1g:B/[~)Iz|#*(P}j^wk(Y=α?~)Iڶg'̑A7 iYÛ~e~쎨{OIS=ٟ ` @ޓ~.0AW~)Iz:'3̑A}o$mo_OI0GUPoO?Hz{DW0MGy'}?TA* prk`OL$=y^Ƞ T$=qݳ*Lɿ~*Izڇdg#*(Puk?uos+Zg${'|UPH?He)2QI>⧲?TAZ4 ;Cٯ` Լ |UP$} W0CQzQ=$[xc#*(Pk$=^ˢ~-Slpwo>Mٟ` @URC)w|&;T4AϠ dP%5:Uo~ {ߛJ `TA ګ1gipw$*UP *)ώ_~| *ISAϠ dP%67^ߗ~*IӜAϠ dP%9uxR/8.U9*(AȠJʩZ¨7? غzc~.NU5*(AȠJix˹ُ?6=h--^U1*(AȠJZM]~*IӘAϠ dP%-l^uos}Fh;VI |UP *i[K\f9Z%i2TA G`NzVI |UP *iaj~#07*_~*IӒAϠ dP%-@˟Gs]%iJ2TA ُ:XuNWI |UP *i~~ƪ޴6$wUP>*(A4U{{sy!4TA @U5G`ԣh~s]$MrUP>*(A4?uN`ލJ~'+IAϠ dP%jQo\x,'ߟ~/+IAϠ dP% 'g? njHI̠ gP2[cX,>~?+IAϠ dP%jD E~O+IAϠ dP%W~jsj%i2TA =gt~_+IAϠ dP%Oe?Fh{[I |UP *i n:=Qh}WEkw4 TA @Uُ1@4 TA @UҎWxn~njOǕ3TA opُ0@c n<5WJϠ gP2vQُ0@u\I*9*(AȠJځ?;~|omZk$AϠ dP%m+~tѻTjUP>*(A}~kD=~tѯ:TbUP>*(A-mS}7+IfP3TI^e?{^I*-*(AȠJڶڇ>b~d5Zh-yz}$AϠ dP%mCwd?}JRATA @US׻ُ*DeTm IDATJUP>*(A_ke?cpwTJUP>*(Afd?s% |UP *~/Q4Z{m~,IMϠ gP2jD~,XOe]$5=*(AȠJz7xL.{KR3TA - /~',IMΠ gP2jݣpo 0hwÒ |UP *;_yxc 0U~7,IM͠ gP2UEԣ`tNxg$51*(AȠJ~$oDk3%aTA @U>ُ#T]bIjZUP>*(AGVwGwƒԤ |UP *i1G;cIjRUP>*(AG91࿌ЏKRS2TA 4-5Fߚm_;+XAϠ dPi%ُ Osϥ!KR2TA 4zUĠFk̢dIΠ gP2Ҵ6wɒAϠ dPi{d?z*(AAt;C%)+*(AȠJd?rla/H$edP3TiZُ;hp̒AϠ dPh3bُs9m͒TA @UzG 9rf9KBfP3TiҫV(ΆG 1{ΒTA @U_961`L]%i2TA 4ɵCD=~~,I AϠ dPInxُcVjwВTA @UԺQ<~{hIZ |UP *Mdvzُe؋AʿyΠ gP2$ֿtY<hI |UP *MZ/跳-[=_~/-IAϠ dPIkp ُ dxҒ4TA @Uڇ~H`zzK$WUP>*(A&e?R,OK|eP3TiRkُI:ǽ#Z#*(AȠJN1Z{m@њ+5(ZƜAϠ dPI{{%uN|W}$;*(AȠJŷl7ܛ(l ZƘAϠ dP]ُ =%iTA @U*j n~h#Ek.ג4 |UP *\ó!HqeP3Tڇ&b~hz=Zk=$#*(AȠJ6dzcK82TA Tn=^ߗ~-Is͠ gP2R o(zK}$5*(AȠJ9 PwGr{mIKUP>*(AJkxُ vE$%*(AȠJ%97JkEϋ%iG3TA TL3bG88[v0*(AȠJ=J4D%iG2TA TDw_~\(%i2TA TBOe@Ɇ|e}$moUP>*(AߒgD؝ُ [$AϠ dP׻&R% |UP *5js`c[$AϠ dP&׻ُoTXUP>*(AgGZ0aWοm̠ gP2RS}&TC-TA @UjdK&#%i2TA z| `-U ɠ gP2R#; &\#%)2TA Դz/` Q{qIZUP>*(A]޸&`Jthݸ$m%*(AȠJMwf?LA'}_~?.IOAϠ dPƴQ;`?o$=IUP>*(AR~FVT{ \(*(AȠJTݙ80.˿+'Ƞ gP2RG)Vj%3TA N1zG)׻_%2TA ]~ ꑨ?'\=*(AȠJٍRczC$}{UP>*(A2Kُ|Sim>3\+*(AȠJ GCI?ʠ gP2RV^Qُ|;x{tIڒAϠ dP7O{ߣKҖ |UP *eTA?<7DkfQ}$TA @Uhp}ت LO$*(AȠJ ]ϋ#}ت]MS$*(AȠJ ]U?MG5^]tgP3Ti!=Ά{&Û?~.i3TA .@<l?~.iz3TA `-9f@9F]/gSbpQ]G>S߽Noo?Aw n:-;/_=MLͿc4TA @UZ'N;,~cw+F]:.y;{F|}ODˣxV0ڇhzKtN̒w o9'Fk"Q ٳ䒦2*(AȠJ gxQ+w^N-Os&:'=i-yFzUt>Kcxn=9n+?gK |UP *-Dz_h1ܾ_ <=]jՊ=gfLa;zֈ0V>/,-i٠|UP *-DOQ7DãwfGS̢Tth>1ۏfxEf4uTA @U@ԝzpՑ;F瘟mIf=?W{ѿ|#%Pi}>4]TA @UcïK=:'zT`Xcjfhuqp1z?nLY?K |UP *k˞uH9S~tZ.o矇U^S?Wn`B}͟TA @U϶0v*w]fT$U'1渨7ݟS pϻ'*(AȠJ"U8cQo\Oy#ŻwU\^ 9w|&b`;/M?J |UP *Wޙ @ '"*lɫZ?guy 4{4l+i3TA 4_ oT77Pi[Kt>!Q;qO?J |UP *G[%XԣoߎG>_u,J?JUF3KbO M6Fu_%M~UP>*(AaF4{N+Z[UzfEEKFZ@[~iUgP3Ti--?db wjSYNt.mjUIAϠ dPq=dXd˰~p=Q{T 95Wf?r4@S;*i3TA 4F]c 73o>J Y7+FG$cwDkgSIAϠ dPq^irDuۢ5S9Tnod=xc @~3L*ir3TA 4ם# <1Vmga?` 4*ir3TA 4_1dH0Fug3FTvV]23;F`3̠ gP2Ҹ]ga4G?g3[ikO7hcϞ&2*(AȠJcif#92z/U/?_JN9ctUُ;ߞKNIAϠ dPq9]?hgJirn+1]/gMIAϠ dPq4eU]ˢ{ƟDk3ϒ4^31(sʠ gP2\yh S[}}!%}gC_?[Li~4YTA @Uk,1`+F_ݳe%m~,7>(+ϕ&+*(AȠJsjfQ=6͎2:ό7iNʴO;g)%MNUP>*(AR磿# 7 >/I?+J{~#Fޔj`; ?1,)ir2TA 47# ?mY?i);~Ƞ gP2ҎVA7G`m`}O1g%sKwz86_4 )i"2TA m A=-F %-|Պ=C"F[QEk3ϏϠ gP2Ҏ6Z_2+FW%>1Z7[=ύϠ gP2Ҏ>gtǰNAN?JjX3{g33TA #m,= .VmmJi4vJt:k휜kP `T.Q!b P T-oK[Qy{?k=w+g==YP$DfP%ϠJJA{J;t%I񠌮}S>:K)&Ih|%w"A?*)aU^l%If\7[oHl2K8$IjtV~|C++-MOIhp߀@*UR TxLv\T%Ir|߶{7oϗv?I%ImA?*)aU|#SSdT%Iu܊뿽Lvn*I4aP%ϠJJAL%Im[w}_LJ$Mm΍4 TI 3ig*ITe*5~ ~~!G$It6  TI 3'*IT]mepoj[]+I4 {JʟA0*ůy$Iҿ4=9w?>uV_I[HJʟA0*fg$IRV*`- ,^cI;A?*)aU<[8yJ$Uͥ{gzgcY$ijoA?*)aU;o1LWJ$?g:^UR To-+;$IҒ6޶tO|Z-P-?TGQ.I-t@ TI 3_[ $IR;x . Civo.IɰtW?/dP%ϠJJA7G?KI%[{L0-'?L>$I)~uP'*)UR *s/D?KI%Ϊ/i32$Ij⿣TI3fPW3OR$6^~wLeee>'$IR1cP%ϠJJA_iɷF?IIV` 7q)$ǿ$IRյ>vbA?*)aUeO$Mmۮ(ݓs̘~0c@$F22nM\[׀TI3fPŗyIs$I:mm]]:s[jkP$ij/'cKgA?*)aU|hQ$=ߕ?Y $IvϮ2ٱ ̗{ʳo0`:TI3fPŗ5%Io,?"$It CΫ}uEǕo-`zTI3fPł[~0)J${+Ӟ~coS=FTH$=&^ןS_g|< TI 3bpˊ(It@zqzj}c> Imp Yyd6*)UR Xܻ-)J$=ڶ.eX;?=$IҌU&;6߰tOyvTI3fPED?CI'xPv]Kџ"$iFjWU;_^K=xTI3fP %Ipm?'o*o$I4d}-eů TI 3bg(Ij[zo{ '(CX$Iɿo|%e_wl<28P TI 3m+D?CInᷙ]F/$)xjcSn/ Ko e&*)UR fߏ~$I]O 8{_nj$s IDATIH2_Y`TI3fP5&]%I=wQ$I3\3.em}\[{L~D3gP%%̠jzj)n$Iz-|CgwU/EH%񭗔Jݱ:A?*)aU%I$=ƷtV~C4zg?~$Is_n/ };~0gP%%̠jv>'IpyAs~a'cH$g`O|euuJ~WdfP%ϠJJAj+I$}F:ۘ `R&#IX5^/~u_0*)UR fS-?$IaMlR6cI$mioްo,IRU&;6[:Lq3gP%%̠jo0I$f1Gf ]$UY]&]Q+џ<9UR T͘g'IUMv\^:+Hyy0Ibv䮏o(+3 gP%ϠJJAlYuΒ$I55Yyd@>7iGI45ܻ? ?J-?h?8 TI 3-~r$IRs? ȫ.e2H$U&;6ҿe]bTI3fP5[{>$Ik5EG[:$I\Lv^]F[W{s?_A?*)aUc?f$IJ=ctݚ7I_ξ5gů(3_9 @ TI 3w&ITʨWz$6`ʬ8tk$IfRx2|B;t @*UR T͎$IҬ6_ Nݓ^1N4õ{v-|[KΉ> TI 3CwF?7I4 g7ӭ{KI45f etݚ2x|=t斅0 TI 3 M$I Co"f=-OfRo)^zQ8, eP%ϠJJAl$Iњ/(ݓݜ,ѧΊ$%ݳk/ S_ɠJʟA0~j$ik{.~p=l?Lvn8$UT;xLv^.:tW?/ *)UR _ݱL$b͸[]}o$`Qivo/)ǗcJgnYg/*)UR +$IWI Kfo2{CSlJʟA0)R&'&If 7Hetݛ?>%i|/{[}3_2gP%%̠jz/xY$I3P;[zo'?F%i:jƥٽ/^Szk)C0gP%%̠jz>vR$I3W=D]?Q*Ij*[/)'cKg?`TI3fP5~$Il|;ox2q*IULvl*-ayM?`TI3fP5VUx$IhIvϮ2ٱ ̗/+UG? TI 3$I~)txHzߥ7,/Ӟ1gP%%̠jzLvn~N$i ܾ9Z jIӨo UR TMe$IR`{5-T}_ݷuX*UR TM뢟$IJ쏾i W:[&캡[S/ǔܲTI3fP5{o~J$)qJħ4I_ʸ1.宙[?(^T:+ &UR TMUO]{$IOoHhEKjYƷ^RO<UR T[g$Iٵ8Ўi 澛?Υ*k.~5W]t\>:Y TI 3oH$%nȬ+m?ҥ&^ןS/ǔܲ>A?*)aUo0I]:+g .-iCw__w 2gP%%̠*K$IR{u-Ӡ{3FWdǦ22_)g`TI3fP[gҶH$%}xg~\wI.~:/]}t?[ΠJʟA0|$IIo6ۮQivo/)ǗcJgjUR T6뢟$IJX}tN L/,eԍmmSݟ)QxR TI 3m|OH$%leE_~R {vɎMee7,/SOA?*)aU5$IR=Z[?5CG+SJ//ӿ5*)UR _.I?}cӮR6c_X3.em}\[{L8x TI 3ʫG$ek2*7|G`|џ^۔;S+Jg)oeP%ϠJJAU^+$Hd-n ůbo{dǦ22_fTI3fPuG$%kTp~?Uipo켺[S}YcP%ϠJJAU^~>$)Q[9++Df}_ݷ;ť3wH *)UR ZqX)~$IWoA. UƷ^8;tV=5A?*)aU9OG$%}Yqh js@vϽecSn/ K焿7A?*)aU9 .#I5fY Qʰ}IΫ5e[{L`TI3fP7D?IvtOzFnxEڟ&캡>uvwKo!cP%ϠJJAUN;~:$)I }tVQ> j| p wΏ# TISA0$IJR-?~ kѧS{/# {ʳ<*)UR g#I4 &w~$D2yu] 6_zk)e/*)UR F$%ip+ozQ)m}&Lg͸4__wl?%sx2 TI 3gxşF?Iv}*5Sa*j}[KΪ͠JʟA0|ƟF$%hk~^iF jWOmX^}s TI 3gsk$I6{  ?/zv3p0 TI 3ʧ=l$IRMH|ZڇwF 5^֗JݱA?*)aUtO'#I4Uw .2k{vɎMΪwTI3fP¿h$IzG$d1LL]2yum]]iύ1gP%%̠*F?ITy Yǯe*u9 .~e40gP%%̠*뢟$I~,f3-j&ٽ/'cKg=42gP%%̠*F?ITq+RqvϮ2ٱ 꾓 *)UR riG?ITq.^2eUJw̠JʟA0<ks$I5׶{ o- ;K{?zer5et,7~WW3gP%%̠*y?\$IR5\~Oc'caRx2|B;tV TI 3cpD?ITq 0}ONv6h*p|oX^<+? TI 3ct͙E$Z,~=pΫ5epqaP%ϠJJAU\$IRMH ~Ѿ2x|=t8( TI 3ʣ?G?ITi:V%/CwYyd}1gP%%̠*KiE$X3.S)^e*ݓ ʠJʟA0zk/HJܹ%V*)UR r_OE$UD*aP%ϠJJAUeS$I= ppTI3fPuOE$UXsw pTI3fP䮫$IGW)cP%ϠJJAU$I/SǠJʟA0uO|Z3$I>ҙ[~A?*)aU凢$I2gP%%̠~wA?*)aUm]<$IR-MXZUR Tk~${o MgP%ϠJJAU&;F?ITI MgP%ϠJJAUڇ~$(6A?*)aU;0yHJ?'3gP%%̠NGG? ITK͸tV=5>A?*)aUu!I*aP%ϠJJAUG? ITI헆&@ *)UR 4$IN MUR Ti!I*ipo&@ *)UR 4YOC$UR?~1 TI 33~$ڦtV=56bTI3fPUF? ITA̓w%@*)UR >!I*hrw ǠJʟA0:Q7iH ]cP%ϠJJAU}'=#YHJo A?*)aU$Iy?~q TI 3J$-= ǠJʟA0 .~e$I5ԌKga ǠJʟA0 76YH j3.bTI3fPUN~$&wn KXUR l IDATTg$I oKXUR Tgg!I*hx߅%@,*)UR 3Ǣ$I KXUR Tէg!I*w ˠJʟA0{~$eP%ϠJJAUe斕2E? I]۔Ίo A?*)aUu'!I*{]3gP%%̠.7}O$Iws]3gP%%̠.s~|WMàJʟA0J-+m$I yA?*)aUXydS$I6`P%ϠJJAU?$Ie M:TI3fPU<)HJ~/oUR Ta?~ $[oUR Ta鏣$I5g&@ TI 3?~ $ׯ M:TI3fPU^$IR%o(6`P%ϠJJAUOA$U&@ TI 3`D?ITI M:TI3fPU~ $o M:TI3fPUů~ $ڇ M:TI3fPU=)HJj{&@ TI 3C]$IR-5A?*)aUuoX$IREuV~ TI 3C9)H>:>TI3fPU:)HgP%ϠJJAUz$)HZ$ ϠJʟA0: I*υ'@<*)UR [OA$U A?*)aUu{$I~ TI 3C !)H^ ϠJʟA0:tW?/)H]sF}3gP%%̠S$IREo >TI3fPUUGE?ITQ'@8*)UR * I*jr5 ΠJʟA0zf$IR%5_~ TI 3Gv$I;6gΟvP\PQ)2LdjmUK[QZu:"c[E''IHY!Ȣl$@Bd焄B +1 9IoP$gy]9>?333jǴ@s$I4͖֕'@-*)?*)0vL9Hlt333j۪$Ij?Z~ 1A$5ԣ(OZUR~UR`U IO>jTITITc~$gN}233jV?IP>jTITITc3$Ij'@-*)?*)0v?9H} PˠJϠJ ̠kR$IRCoyO}233jë$IjW'@-*)?*)0v /P$IRCMY~ 1A$`>jTITITcpk$IjFTITITW?IX#S~u ;eA$5VFTITITw/W?IXFTITIT֟~$羦FTITIT{̿~$_~u 9$IjǗ(@*)?*)0vt6>9H|N133j'fi$I 57 PƠJϠJ ̠-r$I 5ycP%gP%fPՖ?[$$IRCMAAAU[&_t$I|(@ *)?*)0L'!I{soAAAU[w^R$$IRcNzQ033js$IjoAAAU[FןT$$IRc .~}033jGT? IXë.QUR~UR`Um\IHݴFjTITITe?~$&w_]~5 ?OB$5oAAAU[zIHgK{)333jKV? I`CN֞AAAU[o'!I{O)333jK?\$$IRN}I=*)?*)0tzZ$I ?5w n6$Ije)333jϴ`$I5X{UR~UR`U|B$5o`TITITgrG$Ij>U~kϠJϠJ ̠=.~$m7 3g!Isw)233jpB$5X)233jW,$IRNyq-*)?*)0g!IN֖AAAU{gYH^qH-*)?*)0Ng!IlS`mTITIT~$[*SeP%gP%fP՞?X,$IRMN֖AAAU6|K$I-6ϖr*)?*)06OC$5XM?R~kǠJϠJ ̠Mm[$Ijމ/,ScP%gP%fPզ~$~N֎AAAUƷiH|`TITITit۪$IjGo;X;UR~UR`Um^v`Ӑ$I 6;X;UR~UR`UmOC$5[`TITIT+$IjaN֎AAAUz'BӐ$I9 6 =yOC$5Z*033jSgӫ$Ij//UaP%gP%fPծٰ[<$IR .;XUR~UR`U>yH^{\ *)?*)0vMyH~a *)?*)0vo=yHvB$I-6ϖ*UgP%gP%fPծ$Ij]~ϠJϠJ ̠] ^W<$IRNO ?C$5ZP~ϠJϠJ ̠]_X<$IR /;VVAAAUGx$I6ĩ C$5o`TITITm6W?I`/~NVAAAUۦ]D$IRu[X]UR~UR`Um{]$I}O*233j $Ijީ/-UeP%gP%fPն'U?Ih VVAAAUۆ\D$IR ?rl.*)?*)0 {m$I6[X]UR~UR`Um'"Imo`uTITIT{ܾOD$ڰ;[^ZW~ǠJϠJ ̠m7|o$I 9Y z n6$Ijމ/WUcP%gP%fPվɃ\L$IRG z 7rY3$I6[X=UR~UR`U}D$5so`TITITox$Ij>Y~ǠJϠJ ̠}HVvgK{+033j_ߨ~&$:o|v*)?*)0uA3$I ;`uTITIT~&$q*)?*)0KfQHF~M * 2LYT$IRo=VVAAAUg~*$&R~àJϠJ ̠*V?Ijly`TITITe^yhS$I yӏ+3330uOE$5\s<*)?*)0 ^VT$IR {m<*)?*)0 %ID 7U~+wB)?*)0 CYT$IRÍo^VAAAUu٨_\$IRM^VAAAU-E$x8[ r^Y\$IRu|N,*)?*)0O~.$z^VAAAUᕇU?Ip ^VAAAUy~.$F{XYUR~UR`U97>$Ixe rt٧Hn^VAAAU 2MOF$5\gw,133/OH$=^ݷL*)?*)0,~2$g^VAAAUэU?Ip.WcP%gP%fPex'#Int9 r GOF$57+133;$Ij`~XUR~UR`UY:Gh$I=7 2 ¬{6$Ij;fVAAAUC~6$e *)?*)0<-U?IpP~+àJϠJ ̠*$Ij֫`eTITIT|hH._~+àJϠJ ̠*OU?IxCfAAAUH{^Y=gP%gP%fPsس$IjfAAAUu٨Wt$IR *)?*)0\K7T?Ix3fvAAAU$Ij%,333}T?IxOfvAAAUU|$IRM>}UR~UR`U٦/T?!Irly7 { M IO*)?*)0lN~B$fvAAAU I|hfvAAAU^U$IRn{c*)?*)0l Ig.[]gP%gP%fPoU?#IxݣW~ΠJϠJ ̠*xUH$5^ﴗ,3337g$Io-Y]gP%gP%fPo~F$F8fvAAAUU$IRMx:*)?*)0|ݷT3$I7Ζ?nvAAA8[g)I%UR~UR`UaȽOI$5^,133-U?%IxK֗,133^$IRnT~ƠJϠJ ̠j> .$Ior7 k Cߨ~J$&O-[gP%gP%fP5>)I[~;ϠJϠJ ̠jNlxʗ~uB$iUR~UR`UcI$5o`TITIT͏U?'Ix/,YgP%gP%fP5?WV$IRMfvAAA$I sw-133ݷls$IN9UR~UR`U;$I hpޟ-133/U?)Ixk/YcP%gP%fP5_w^R$IR㍷^Y~;ǠJϠJ ̠j =IIƛ-/+[333/II:PAAA|OJ$;W` KgU?)Iࢿ*[333?J$5So` k$Ij}/Y333?S$I7ϖ]~O̠JϠJ ̠j .g%IO<1*)?*)0;J$?w OU?+ITITIT͡{f~Ӓ$I7=w 7U?-Ixm[oTITITͧM$Ijt9iw $I +[gP%gP%fP5gnӒ$I {m<>*)?*)0=n%I]x|UR~UR`Usoͦ%Ior5w T?/Iz^w U?/IP-c333_ë~^$)([fP%gP%fP5%I^vP<6*)?*)0=K$4xlUR~UR`Us쀧fq$I7}xLUR~UR`UmOW?1IP*[ofP%gP%fP5F7S$IR@_X~̠JϠJ ̠j /=InAAA|'&I}fUR~UR`U{󫟘$I hruw gQIvgT_ǠJϠJ ̠jM>{c3$Iu٧nAAAxZ3$IzUR~UR`Uo[$IR@+)[gP%gP%fP5zIƷnAAAL$4}zUR~UR`U `il^$IR@CQAAAbsMS$IN**)?*)00؉OM$4/ ãG%IvX~_eP%gP%fPz+OM$4**)?*)09OM$%4̖7[^ګvEdP%gP%fPoO$= ,"*)?*)0vfI$I|e ȠJϠJ ̠jM JWZ~"233Zlή~$)?nEdP%gP%fP~$)iwlyi]ƠJϠJ ̠jN'(IBGoX4UR~UR`U$I;S*]`TITIT-uig(I^~p ƠJϠJ ̠g~$)-h n>JX4UR~UR`U~u3$I!uAAA7d3$I!N{YĠJϠJ ̠{f^S$I /;vbP%gP%fPţ&~)JƷ]P~"133QV%IR@/~nEbP%gP%fPţ羦)J:=vEaP%gP%fPţoOQ${篗.( :MFQ$4dAAA_1MQ$4AAA_1Q$4}AAA_1U?GIRg. I/~$))/.]`TITITOͦ')I|oXUR~UR`U|;$I h|XUR~UR`U|MgW?IIw ,*)?*)0*W$%IRH7|oΠJϠJ ̠{ǯU?IIRKΠJϠJ ̠9$I i)]`TITIT_l$InT~333o_$IMY~333 /X,%IRBsw.0 F3~YJz'r̠JϠJ ̠o9Ǫ$I ip_.0 &Kf)I}AAAe)InR~<333 7Y4%IRHCQ~2337W4%IRHS~vyeP%gP%fPcOӔ$I! > +*)?*)0*^i{$IoyOsʠJϠJ ̠3ze$IMnyeP%gP%fPn>yJ:@ȠJϠJ ̠ߴ_$I!N}IȠJϠJ ̠=f)IB^vydP%gP%fPZk6o~$)m.0 x"WV?QItAAAOd'*IB *)?*)0*H~OT$;7o7UR~UR`U<1T?QIo7UR~UR`UT$4AAA;l^T%IR@-.0G WV?UIдȗշ *)?*)0*vpOU$=oUR~UR`U$I ѻvyaP%gP%fPOS$I! 7U~033b,5W?WIxU *)?*)0*vxU$%4̖]~<033bg 7Y\%IRH7DJϠJ ̠ߴ_s$I! *)?*)0*vV}$I ix[oUR~UR`U촥f'+IsMsJϠJ ̠]1OV$%4ϖ7Tt%IRHS_R~@**)?*)0*vG_~$)e.ʠJϠJ ̠9gJw\T~@**)?*)0*vtۖ+Iv-/+] AAAkwU?_IRS~@"*)?*)0*vࢿ~$)Y[~@"*)?*)0*vWU?_IpQ $233bwul:~’$)]oHdP%gP%fPŞK$I \~@*)?*)0*wT?aIR}oHcP%gP%fPŞ\',IB 133bOtOX$4؉ 133bll<~ƒ$)go] AAA{jr X$%4:~{I S^%IRH_X~@*)?*)0*TK? $133bOu۷KF)KƷvUR~UR`Uui,Ivۡ~UR~UR`UV?gIR+] AAA+ex,IB; $033bkY$4TITITR:<9K&wvUR~UR`U;$IJhԟ-oxJ333b%>yF$I!uߕ.:*)?*)0*VIKvTITITz'|$I!>qj333bEl<~֒$)Ƀw.8*)?*)0*V$IJh:uyF-333b>g-IBZfP%gP%fPJ珪$I ixZfP%gP%fPJ'$I i.2*)?*)0*V^i{Ӗ$IM{͖/(*)?*)0*V3W?mIR.**)?*)0*Vë$I .**)?*)0*VCWT?mI𚷔.**)?*)0*VC?\%IRH{+]UUR~UR`Ucޣ[Z4鐤 k&CfMHT X3dԔ@HW+[/*dc,Ȳ/±6 |"c &"ߍϾ:G!:G:g?{`爏u$IJP[O}IȠJʟA0*KUoI7.0 TI 3bt_?ޒ$)I/ƑA?*)aU,֧'-IԻƑA?*)aU,ƺWR ?$)A3.0 TI 3b1 vG\$%qχ.0n TI 3b1\$IIj] *)UR XLϿ'#.IԽ~]ƠJʟA0*S߈K$RƠJʟA0*)/.׎KUc#UR T߻5c.Iܸ4vqbP%ϠJJA{YsI ]`TI3fPbko{G\$%w *)UR Xl͏sI#{o! IDAT'UR TVS3uIAL91~1aP%ϠJJAпKuIyo ]`\TI3fP(t?-.IԹ *)UR oK$yE JʟA0*Fq櫢?$)I.0. TI 3bTgK$5>K *)UR ޾mwI~80gP%%̠Q\菻$IJRwƁA?*)aUJSq$II\$IR/p TI 3"޾ˣ$IJT? _hTI3fPEk\$IRz{. _hTI3fPEF?I8ZUR TƩ/-eЋ~2$)QA?*)aUd2x'#Iվ8UR TIMOF$%{  *)UR Ȥ}Ż$IJn}0gP%%̠L_d$IRAi{E GʠJʟA0*RYulE?I֖ߋaTI3fPE6{wF?I/p TI 3" gD?I7/p TI 3"o~6$)Sv>o8UR TMcg#Iڼ,#aP%ϠJJAU>t$IR:_A?*)aUdwyӑ$I  *)UR Ȩs$IJT~L>.2gP%%̠Z)Hd5yC eP%ϠJJA)R#Iչ7 ̓A?*)aUd5x#I߆/0_UR TUMG$%j>UW~|TI3fPEV+|$IRg>0gP%%̠_|$IR:àJʟA0*ZulE?!I]00UR TYޝOH$%zàJʟA0*2pz$Ijn'7 ̕A?*)aUdֺmOH$%G seP%ϠJJA5/~B$)Y=00WUR T]H$%jv_` TI 3"޾ˣ$IJVÿ~\TI3fPEvk$IRV00UR T]7E?#I00UR Tީ/-eЋ~J$)Q'TI3fPE $IR_~TI3fPEn=7)Id/}{ cP%ϠJJAuо]OI$%{7 A?*)aUAs뢟$IJ౽7 A?*)aUªcK~.9ILUUi(kNaTI3fPE]$IRZ-ǗƥmEݶ +ճ TI 3.7$IR_h 뗔%' `W)H|*?'gP%ϠJJAuѺI$%k7 BZ[Ω߿T'#FvϠJʟA0*Â$IҼKc{ȣoyE{lUDŽwb8*)UR $IJ̿}Ǘƥm۶gFP )/PUR TQ'}G?)IM axfUJ6oUR TQ'k$IR~qfSS{O gP%ϠJJAu:MOJ$e cjyYim^V:;Vޞ-epp_|ΠJʟA0*jԗ2E?+IoczX}|in\ZV e e\k~ʠJʟA0*fȞg%Io %{㙥`W)fT_gpUR TQ7[ύ~V$)YG aXҺͥso/%{<+TI3fPEݴxg$I٪81Ysbim^V:;Vޞ-epp!ԭϚ TI 3n_$IR Js޶two82  eP%ϠJJAR~Z$)Yݯmch_RZ[}|nLjQ gP%ϠJJAuԿwgӒ$I<7^c}~o/?ڗIF gP%ϠJJAuԽ%IUUqυ1QXsԎgK73~r+ʠJʟA0*u[$IJY}\in\ZV `W)N/oPUR TQG3_$IRº|"^XcںtvN=_*3G s_opUR TQWճD?/Io0Jc}~o/?6mf8*)UR ˢ$IVUMw LJ7ΎgK73FS3? eP%ϠJJAuչ}K$%}ǕƥmEPvkGqD? eP%ϠJJAu:MK$%w'%uy:OGw3gP%%̠: zOL$%kķHڼЯ{Y,|͡?a8*)UR #{$IJXckS'}Wl)Ju^yb(*)UR V$i/ww ǕY/+Yz~ z)nZ1A?*)aUw$Iw;4/)KgT^?kgGg TI 3faI6xw BcIyYXYz{/+FX׿!TI3fPE:Tg$IJXCB:a_Dn_۳ +D|)PUR TQw{$IRV1pV{hԿ/TI3fPEݵ.~k3$I } Xڼtv}E)3pUR TQw3_$IRҚ[ CoۊһmSWJ5Y5j? eP%ϠJJA`o$Io,`~u_Kw?^+cռn 3A?*)aULˢ$IJ }PTk9UdšΠJʟA0*&A꿌~j$)a3=[k_^ZΎgK7^i gP%ϠJJAuoF?5I'Y-@2/͍KK{ۊһmSWJ5Wzf>o TI 3b"R&I67]2k_rrPvmF8+͹TI3fPŤ<'I;O./S{OD*U'ΠJʟA0*&Es$IXgLOT-5ּ6/++KoϖCOY53gP%%̠IѾM$%uޛoKs޶bW j#U eP%ϠJJAbaI#SoWuo<*یS zpUR T11VS3ON$%loXc+J7Ω߿T'ԔƦQ3gP%%̠IҿON$e-5/ e8ZΎgKS4U-TI3fP$^Z$IIkm[ܸ(KRU5 eP%ϠJJAu[$IJZ2~Iim]^79K㢔Lf8*)UR $3~.I ~LƺWo.S{PeU TI 3bT>$IRƪ4[֜XZΎgK7sm `(*)UR 4E?;I%'2>47.-m+JwC߉O eP%ϠJJAs_F?;Iޭ24>ҾߖW?ZTJ㝤۠u TI 3bҴg'I6x[`5̡_wJRMQN¿v0A?*)aULS_:Á$Iґ/3`͉k]dt$cϠJʟA0*&;$IJZw2#ܸ(Jma(*)UR D[>$IRzw^~,%uy:ZD8&i:χa8*)UR D3$IґT=h^uL=PޡԷ?_ǣ4ªs_ΠJʟA0*&Qc$IRgZ=pDN(sP:;Vޞ-epp_)Uc_ʠJʟA0*&Ҫc[V$\{pVWJRz$YUW eP%ϠJJAE??I׆2?~Iim]~W>H᪦b8*)UR T/'IkS_~ڼЯ{Y,'%IIH43gP%%̠I:$IJ\낷3:ЯݥgKWJUEX$&U}/CTI3fPŤj}y)~$II`=S#)m+Jw?^;G I5z{ gP%ϠJJAl]OP$%m _cںtvNj>㎤ z gP%ϠJJAwۦ'(IVUG=X{Rim^V:;V2x gP%ϠJJA};$IJ̯g15uBin\ZW{v<58jc$X'5 TI 3b5?A{ IDAT'(Isa=G^3/]two(J鵢d95x[_CΠJʟA0*&ڪcJ|:JU?6{O4H女so/UO$鈛2A?*)aULD?CIٿ~奵yYX91DZpUR T1f-2I#s`>47.}6-D!I=_ʠJʟA0*&]2J6W/9two(J鵢Đ7x gP%ϠJJA-3ItZeԗ4Sgj<ӄ$En pUR ToE?EIo ghyYim^V:;Vޞ-~u$< gP%ϠJJA8?)Juw}0ܸ}3H/IsM_ʠJʟA0*xQi_(I7x{&W/9yvYJ5z}Mdj_RZ[}|n#<$y+ TI 3ֽg)I׹7 X3~uߵ(K5}0$%ΠJʟA0*a,%IR iJ7Zޞ-epp_)U}JjP1A?*)aUg\$IwJcZ}\in\ZV `W)v+Ii {CTI3fP?z)I׺7 94/)Kgԡ_z&$MP  TI 3D?MIޭ i?'e~uJcѧ$ikΠJʟA0*q!iJU>~l< S{}TU*I53 PUR Tk?G?MITm]>47.-m+Jw?^;$$5z}Q2gP%%̠ ^ tS$%s{EcںtvNj>}~JtD5?WΠJʟA0*xa<%IR|15֞TZ}{/+F$-X gP%ϠJJAM~$){viyY]}.J¿G3A?*)aUU=D%IR i&Qc+J낷Ηs↑T$4$iw¿gsxUR TO{i$I5ំ5vʋK(ϿZO|>%I9,*)UR 'XD%IR \w @4>޶two(J鵢O>IRV=}ouϠJʟA0*ɚ!JԿ+w @VKJk9Udy'IRm<A?*)aU0Ky>J z k}yim^6l[3$IտA?*)aU0\ޝT$ՠokKs_׻mSWJ5>$If2gP%%̠ ^&Jsa]ڗ\7]t'$I_΋oϠJʟA0*w$IAU2`T女sjoOFc$3gP%%̠ k=A?Jڼ,Xh5/s:;Vޞ-~u$IJQ3o ϠJʟA0*8cwE?UIT7~Ǘƥm<|{) ̒$IGX) TI 3*Ij౽w g]t'$IZ:{3gP%%̠ }D?UIT iuukKkKz&t$I:}pxUR T5>E?UIT:oһ3ѧ$Iq3c3gP%%̠ z{U$ՠwk^̝"I&֧3gP%%̠ 榷*IP]k_~C7G_J$i53gP%%̠ 󅿈~$&.~[mO|;L$I#_ A8<*)UR `n$II m~Tcg$Iq3~6 TI 39:n#JT}2Ē$i>7gP%ϠJJA]뢟$II3}N}Iy$IF]0'UR Tu?-J9~7K#I4oƠJʟA0*օd%IRM|in\}I7x9jUR T5N{Tg+IPUW73}I7x9jUR T ~$&`[ɫu7scP%ϠJJAOMV$դw~h_O#I4 A*)UR `~l%IR]KcI @ }I׻1gP%%̠ _~$F/7 @Ӣ"I47A*)UR `?t%IRM}wH$ε~07UR T+IjRzLOT}L6,$I#}ŻoƠJʟA0*~$F.xK}L7ED$iĵ.1gP%%̠ yoD?]IT7~mwO"I4⚛~07UR T:n#JT=2XUH$~5an TI 3#?pc$I5jƢ`ű>$I҈k{EœTI3fPG{W$ըuk`25/>$IҨmىTI3fPGuy$I5jLͳ-$I#zykUR TiJ$IZК<; $I#npp_ TI3fPGn$IQ2&O{; I4]~0wUR T~^$I5$)';3gP%%̠ )/.׊~ʒ$FU/sI45>l$eP%%̠ ^$IY~׺g$I ȿȕA?*)aUp7~ʒ$f~G=$iu7cP%ϠJJAOY$լl;gF=$iUA*)UR 5N{T,IjVk sz4$I#noǠJʟA0*X~Β$f8?m[OI4z ̏A?*)aU07%IRͪO>y$I҈~mc TI3fP }ۣ$IaONԚOIP0/UR Th_%IR ݶ)yOIP{;yTI3fP g=OZ$լD^}|OkSG$:ǠJʟA0*X8_%IR k}~:O#Ij~wcP%ϠJJA,~Ғ$uo>;{GIPcIwcP%ϠJJA,G%IKV=h^}\KWD9$iuoϠJʟA0*XX~֒$;#_>q$I҈<3gP%%̠ VoZ$հW?~5R>q$I҈w]¼TI3fP ?~֒$U>8|F:@=4>IP!̟A?*)aUgZ$I5ͯJ}H>~0UR T[ulOE?mITú7OIP ~0UR TsO[$հj2[ȯѧ$I }wgP%ϠJJA,ε%IRMk][ȯ5g$I yYTI3fP O[$մ59}HٻhKV@dRDDD]" N"(*2V*IB2bB22d"I a{?ϯ9Ȑ~k~W߾朗! ?*HȠJC+-eЎPXZ+w$IRV=>kIZ}-Π 3 4o`Ju[G$孳 @~hAgP TIipo`J ;6֑$Iy ;Dˠ 3 =io w$IR/fug!Z\UA$dP%U(eԏTߍw$IRʆ7}~hqTA~UA4F_,GRÛ>~HU} C ?*HȠJ_vհ[;%IfTK;}AgP TI{FSw;$)We̮ao E䆃YeP TIcl3J)5ZwF#IR;' o-.*Ϡ 2[u? J{;$)O`հo~hqTA~UA4cLi w$IRFw\}C ?*HȠJoݣcL;$)Ou{C~~gPTABUxk `,꺴|E#I_{K/ o->*Ϡ 2_u?$Ij~ݣ}A[-gPTABU\:GbՆu$Ij~s9lNzO-gPTABUk?b-$Inx' {țo->*Ϡ 2_{gR )6|G$5z]' %᷈AgP TIw`խKkŶ7$Ijf]_}QҚ*3 !*i2 .]L1~Hf=7O Ha]--ˠ 3 =]?xB#IO Kg"ڲ ?*HȠJL흾j#LawzN#IHfʃomYUA$dP%Mޫ);7$IjXsJj(*Ϡ 2&=)7G$5οp3 !*iruy`uiG$5I}:1іePTABUj=T{`H#I} P{#ڲ ?*HȠJl}DSpk#ISu *e,*Ϡ 2&=9迅=$zz)^i֯GTA~UA4ٺǼ++ {$IR|}F~h3 !*iw|V)A>0å᷏$I4W3myUA$dP%ME3w{IO P# ?*HȠJ|vf I؊mK鷢O Pз$ ?*HȠJ|#̂.^~H:\5kDKpTAzUAKv0hG$?矣O P}8dPTABURL`G-[>$i֝}{>~hi2 !*)ˣ=᷏$Ip˷.uwc~DKAgP TI1u??=9$IsOE @ IDAgP TIAضǢ` I4g];7&*Ϡ 2}3O0#g}#I&~ I4TA~UAW~Q_~H rRTW 7A]%ɠ 3 $uzc#I__>;`Cw$Z$Ϡ 2[u;E?^up#I= ItTA~UAS`FJ{g?$i_` >7.*Ϡ 2b70Cz_$I_5/>7+*Ϡ 2bg!ׇ?$i|N@4@_ KtTA~UAܲR?vS̐o$IX=)ۋ-]UA$dP%7!/~H1|Rw}jޣ 1wm%ˠ 3 z}0)fɰWڻ $IK[琟2*.yUA$dP%뇢`P $IE;E@ x]͠ 3 fTo+9fH/$MYO /A6 IDATKTA~UAԌW3{į@$iih~ho=*HϠ 2Q?~3\{r $I9}Z 5᷉6*Ϡ 2Q{RWO0KaiyI$IG_@ :|DKAgP TIͩʵO0c/$IҖ5?.u}V PwumϠ 3 4d'1#m IUI4o-}UA$dP%5o~oA$in;'MTA~UAԠVn&itEw$IZT흞Sh}N =-}UA$dP%5+U)a;H$m~8 -}UA$dP%5Y,3hxw$IF7}F Q?@mdPTABURgE^i~Q-$I6.eЉ" ƓAgP TI knY[룟`ϛ$I&; O4 ?*HȠJj^~4?n.$I AzDɠ 3 ;Ϣ`FNzO-$IRWѧ ~h<TA~UAԼk^43[H$=u?}6MR Kk7ƓAgP TIͬpk̨!?~ I'zhjMƗAgP TIlp07~ I'OD @ o8>F?*HϠ 2Y~YU K{$I7dkh Q4 ?*HȠJjf/3" .Y~IinR?|w4LߌS4 ?*HȠJjn/_D3n,~Io{[{\Zs/*Ϡ 2[7G? V<-&$I_sJOaFw]~hTA~UAoS#0z/&$I h S4 ?*HȠJjvN~&Vm $Iwjhi~hTA~UAzgqݏ;&$i 'P~2Vx3 !*ٵwY3̸χD$z뎍> &vKkŶ᷊ƛAgP TIͯzqݏ|M$IҬy Uw.V3 !* >WS̸ѭD$jC)4s*UA$dP%5o~*YWץ"IfjMїPOIgPTABURVn_ʠ\3nxw$I3VF@u}mgPTABURFΌ~.Y7?~I4K מ} U+[+UA$dP%E?exAw$IR{WR?yqdPTABUR:&᷑$I?\GdPTABURn~2E$M{흿w< ~h2TA~UA~2JK{ $I['>p^~h2TA~UAG`OEF$Mm++_>\ZsM$*Ϡ 2Y@)^iyi}$I4;џ@Ín;7f2 !*)W;/~6 >om$I5TF 7xEˠ 3 \g^Hi{̻?zEˠ 3 \uxC $IFw\$M.*Ϡ 25ԏ~%Rۋo$I?$P [4;Ѡ 3 | =2G$MC/$0?M6*Ϡ 2;F?e4(~(F$)s$1`e ߊUA$dP%嫽JF7 ;&F$)s΍8᷋&AgP TI9\_tIuys'9H{M6*Ϡ 2r?ߢo1In?/cHoM>*Ϡ 2r9 w;ILT^sxgPTABUR斕{o1;ID HwM>*Ϡ 26';t;I TFϠ 3 u?';T__Zs[J$5ѝEl.FϠ 3 Rg;N[I76O0ɠ 3 ܍tV3.U$Ijd˷)?dgS ?*HȠJ]?w3~$V$btys ?*HȠJ]{WD?#?Vڻ8^$IwzN?lZ}- ?*HȠJ_O ^sx$IR\G3˟ cAgP TI\&)x|uU:{I& ]`s .-Q\UA$dP%{['h疅L$E7\{r2T eAgP TISmJ<3IX7R@Fu]ڻ Q-iPTABUt4 QZ+$I inY2Hpk= ?*HȠJz'qss$IRDS1 $6{FTA~UA4wy~)(IxBu^II!cHwofPTABUT}y7~3I4Ɇ $7b3 !*iz')uyW$I$R:Hl7]斅5͠ 3 sOF?)OmrIrR=xs.gPTABU5ԏ<;N$+?n)?gPTABUt5g {o'IQgYR~(>*Ϡ 2~V6΋~f$IҒ6n??cuZu} ?*HȠJVnWޣO &$IKXESbti᷍AgP TIpO &JiIEnoxD oԌ ?*HȠJz'7idë $IZF|:c"^~ߨTA~UA4}wRaɺG#$iK}/?N)R֗ܲGȠ 3 ltDž &riJ=q L Dž8jNUA$dP%Mg3.y,~CI-ߦTw_1 Li1TA~UA4`u+w$ISOP` ;Gɠ 3 魺'`,;$iSSrfePTABU6p'` .'$)[}֯o5**Ϡ 2΁?l*ݏ[J'kp~џG᷎AgP TISܲR?rO3?"Ijfݣ~T{;jVUA$dP%Mw,co)I?PI`JU~yTA~UA4ug`z'a=%I7Z]2bV8Q2 !*i[mE/$I*+h\~yTA~UA4 o8.X]o*Il7[ƪJ{ {Լ ?*HȠJz'ASE~$$n^WʠqL꾫53*Ϡ 2NSʨ,hP:1$^] ? 0tMffPTABUl4`*]~WIfee@`Ft|{FfPTABUl?-6}[IfgOG0+AgP TIQ{ROᷕ$iRa0#DfPTABUT{ea ᷕ$iznfH̿ ?*HȠJg8Xcn~_I./nfLg ?*HȠJ{"X2;.([X)j8`TA~UA4[U_,;W)in2\{RG0W TA~UA4[ϛ~vN]~cI7dO5`Fu~g-fgPTABUl5wʠS:t%I[?4fհ[Z~TA~UA4{U,z] ,IRQ? Q/~&R3 !*i\CFw^\Z+ $IyRwfX ?*HȠJ:>5ZuzUJG0oHϠ 3 ٬ڰ.~kI]{KK,`~)GUA$dP%fKVG??Q Kȷ[f^}?}o#Ƞ 3 ٬џ~~Ʀ=Z:!$5N)WX?ҦfPTABUҌ6~Ʀ~+]F٥'tJko$Ƞ 3 mٽ T;?7$etEK0?o$ɠ 3 ٭{ț yqi.$ie#o?$ɠ 3 nnR?z_30v?'/Id[mtJwh[Ii2 !*i\308$Mۗ-ՃJJAgP TI]_~&K4vxf}5l{I2 !*i[u[F?E?oo0IjR}y I2 !*Ië~&K` K/DYw2hGl~W)wUA$dP%\C(?~IL|2d° ޯ:*Ϡ 2u q~knY&I^{E?KZ6R ?*HȠJU=pC8/]Z+ $iZSxgsd"DTA~UAǫG'F$M[>Xʰ,xTA~UAǫ+K' {>'o6I;|w^wlwZ ?*HȠJU{UXՃ?~IR:TF?c1쿇[ ?*HȠJ~~9'6IX)nS06C~si:2 !*IOT{O=ZGZ&IYj2`/[^ ?*HȠJғ5g Q/o7Ijzԏj}o/MOUA$dP%@.o8Ij\++KVRWO5Dt~S ɠ 3 $=Y/Z l Ǘ8IjJ~T_<LLҚ[~iz2 !*IOKgE?UT]Sڻ,ЖoSga/YŻb ?*HȠJS;=O@:A-:X2)+*Ϡ 2R~JIҤ[W=xKMˠ 3 $mJ/\5tAM'IsJuUO.@2M_UA$dP%iS+@j;/.ݾ?%o3եT \gWg ?*HȠJ&5U'Hn=0T$iRo+yh꾫3MgUA$dP%iSS5ljTKi- $i׼ מ4Ji ?*HȠJҦ',1ZwFiO6-BK4K]/4TA~UAͩg `jԭ .+ƓM{/jMO'@#8^fPTABU6_Y 2^ %֓ǫ+Ӣ_KF/6MoUA$dP%isjRQ0u+}_~I9ep {O$@UC]c͠ 3 $mn΍~Ӱ[go~IVl[z}pϒF_L Π 3 $mntLKg $^ݏTn~R}O8MwUA$dP%iᙥ?|L7J2 aw4 ?*HȠJb^wL0F_tOt9 e Mt ?*HȠJb `vepNw?\7WJ]EpNӟAgP TIZTs[{0R?t°=(ë.F?i՝o]J5` Տ_Z˷ 35TA~UAοD?mQuեwKkgߞRS2^KVߛ ?*HȠJR K7ߠRD^Ug}j# 8uSAgP TIG[O~jíᷨ4:vqa *TA~UAqoE?oD;J{ߥҖ٥.ë?VG `z'~M*TA~UA|R?v@jgMiU?-eԏI wܭO O%*Ϡ 24~;>ߪ7^;J=?-4࢝oUi>*Ϡ 24:&Q_Q:6n { ,iꪴxy*TT0 $E?s4\a]\{?}jj= a`J F~JAgP TIgSIUF[gtҚ[~*_@5҅?9 {;Z?3 !*IcmKy( JYk^ߪymU:N@^sxٟ`\3o]ePTABU򽣟:D#~jgWߺ|]?w2٥>%S߽7gPTABU]g_0'Y*CwWKW{1^//O+_Gi77gPTABU& ;fA5*7~~-|Z}=hJg/iŻѺ3J407KߖAgP TID~?`GV\7_Ke7;wJeR=xK)0X=-wmTA~UAin~R2Q.|:xi.~܊mKt~gepeJ 6h5,-*Ϡ 24SR?tG~~^sx響N~o~7[-:mgξ-ݣQz} .ܱ ptymSd?omq2 !*I+6{Juet˧ʃ|]SQfK{V9n[{t>3 w~kO,7Px[sos2 !*Ilg&>𛛪{*)O\Në.K,.Oo|Gw~]G; QB'wga;lO.+.=J^ϥ'ʠ 3 $MM9ÿ?(*Ϡ 24іo]wE?}Υ'ɠ 3 $Mˣ>X䟄o.=YUA$dP%iҵwRFW?@i>{s2 !*I od˥ʠ 3 $E=W?f٠Sڻ{pi1TA~UA9 O"Sht۹߁K͠ 3 $5]D?L [ZlUA$dP%Ig)RmXWZs[--6*Ϡ 2ԨoSꇿ40%zᆬ-Ƞ 3 $5~c֪-mIUA$dP%iw~n)V@r>TA~UA&6J{g-miUA$dP%uR: +ÿ떖"*Ϡ 2FDQUڻT=pNȠ 3 $elp@c3jiTA~UAwy^)V @꾫KknYw$2 !*IY|'ݣ~-;jiRTA~UA|e)(`/~ZdUA$dP%)sõ'E?LP_nZdUA$dP%)sL3 4{iiTA~UA()`%;iiTA~UAuyWS n;'h)"*Ϡ 2e1 ?*HȠJ4;Sd ?*HȠJT4U1I` :1{h)(*Ϡ 24-NzO |jmN'eTqiZj2ӺԎSsjLVnNӞũ& .3 AA("E@YA=|$Z$zWh`Fh_YJAT* UV4 AT*IkQ>vwx`g :QzYYTA9 rP%.px`'׬H3KӒ*>UPA$ղ%{E *XoYTA9 rP%.H`.?eirP *AvQ6dYSh-yF~YTA9 rP%Oc=Ҵ AT*IuX(G-Oct750},M[TA9T=jxߚO1UP}TI{Ų}<=nxK5UP}TIjB5+-Od4I#KӚ*>UPA$5bODٛoC9UP}TIjJ+We\~!/MKӜ*>UPA$5bnKwҴ AT*IMc([X49sPJR*=7#٣z|(}g,U!UP}TIjZ1{4Zh-3}_,U!UP}TIj\ X^XHTA9z~8{4KwRrP *AFx(7ޙ=e4Q#**>UPA$5=aaj9sPJRc]oPb>ab9sPJR~_h-5 {',U1UP}TIjt3hwG1@v>6}',U0UP}TIjzߝ=,s›wRUsP *A$-ѽWgcZ|3;`9sPJDԷgc){sQTTA9 rP%IyyH*>UPA$i[ߘ=jcZݯTTA9 rP%I?jxۗ2@-tN{gWCTA9Deh_IJuAT* U n\=k؏NJuAT* U"bԿrUWSTA9׿ P9܃Q,q AT*Iz|}l?=*{RrP *A$=q>=*cxW50}+-UP}TIғx=r{~nxu^WaTA9'c`.MJuAT* U,=kG5=|k앿ϕj*>UPA$ke=OYF䷦q: AT*IzSgp[9sPJᯊG6(ۏD[9sPJGgl=gԄTA9 rP%IWQv7emtûDkfaVjBTA9wG6@a/GRAT*Iځxfݓ=,W+5ΉoATPkT b=Ԥ:=G'UPA^J5[v:~GVjXޙ̓*֪?$juN K lnVjb3~?'UPAaJHRza%ΣQĺߗ=yrPTTG:b_d=ϳG0Oc~9 IU10Q;.}z4{ *}TՊώr٣`"\]n>UPAޕ*erמ= yrP9gG$U1kM8᝗S4q̓*E>aH^+ڟݫ1'UPA5?$ 0 >sn <9 G$աb,~=exע5[U҂v3̓*/?$&?'MQ/ɞ 8 wMC@jNh) ?g:ǿ1{,c *loLHR,;}?'MYݳߟ=1pPZǀ$թ;{enUҏ׻d&{:c *8TC^eo.{l&}* 9){<c *}TzcxxZ{FkvQNU*ڵx=|Kxrn/*,9{Jc *O?$u>z}$}*+*kT׆=?{0Q Iut'=Z>SIO^ٓUPa[~ed@Zc쟾7 n:;{Tc *}Txf={L%=mwe `LTAu/MHRQ4\(VDTSWq*T7=*˭3{O*#UPaњY8:W(;f|W#}>*{dc *8Tz|({ 3zhkuc#UPqsOHR-F|={M1FF%mWDٓ#UPqo@&/!`}owgkATԔk@ ZgC%m9+hG$5b鳣|T~$C~2}*i*7ޑ=>1sP5?$)u>T?L߁Jڱڇ|&A Ԥ7@ =5})i}o0FM17{cARqЋlo@Mbswvg`TAMOxscATG?PatNxSSҎW,'b͞"8}ueAyY*NI;U=B qP51|$5a跳?@EmGENI;/e`BTAGhջP$})i*V7xf6J9Χߑ4Ydv1UPs^>"FO .]4f[G 9+(/!I _`†=?Z3#%/ A4@S$2z(=7)i|-3ʍwf *h0_>"0feo.G&})i@x8_FC z_O0Ne3GQҘ[W͞0@UQG6!IMovQ ZW%ޗ6{TA n>7!IZš)K#읣V|aGG A4IYFqHHD?*P>zW+~"}(i u|9޽6"IZ,;cЉ'%}(iy}h=ed:ߗ$-bQ>vOgA[~}~QYûd` 8=v_$):md#&Sw{G 0%TAC._ $maٟ`; *ZL)JŲF1L UTn$iA<#F2O[/'JHkO3qP 6$i[#_1d'2G7%Mo(ILUpߟ@$mſ,OHJP; 0eTAÍZ?֊?T$IњY[i#w&Vò 0Tѿ$i[DO/}h74:'fh=j) ت},muNriFmXŲ}&S|(;{SAhZ$i[+4@c Q=5\wn*\sSx$-kG4@ [|PIL9U$i[š?ewS?N J\#٣rFqk2mu|OfENP*>;Fݜ=j pP'Z3%M1\wn*Aל$mca]jkt5[p@IwDzG P!'=6m|Pn~ U?4:-b47@8ܰސ$m{Οe^Eݟ>UQ7fObTOih$i[kO4@=etW7}'ir+ܖ=m rPIgޫG PQҿᬘ$iۯ'n4@e n\Cm3gTۭǏ$ikqg*i+d٣8U$i[kN,@9KI\['|9vhNCH/ P Xf&T;WD7?$I }r:4GoJIROu!զ$8\a2fHIR_}tvpݹњ=}&i+_+OA0o_LIRc][=` 4ZK߫Iw3ekCXxJkG<$ ÷fOxJ{FiW?8 TSgpוQG$5ᯊ1{NIߣIGWoD=R*`: [2ȓ9#F?f8E3I?){0UT{>=I{ >=MFNߛIڹGB o0{4U+_hǟ$չ7>= ʹ}+evb cOE٣`^T+w;YAIeK= V7F$PŊGepPTscn TehúQ@M>wdbQv7grPT}ڻVIҘ+}E< }wcb [!APy7DwX%Ic}F@Z9-;1IO_? ߌJTQ;5Vs›waI)\`g 4*vs{?.%.@ޜ?>{\r=5+uЋT8&{P7bo}I7,ogFsP_oq*6{ wQ4.z>5ѿlIȞSA( D֊?L%JK7S}-GTE1z0uT4EƳ}g?X% d͞T?'x[_pP+b;YYIT7fOnߎ9}%5WD WGy4{T*e>3 Z˟ȕis[" @NTfE_G*A cxѻ(>17[CX(GٓJS-}%ծ{D_n~ۿewsO<@m8N[Ֆ? ?D7ܒ˒Xgf٠Sߞǒ*(~Itctѻc11za?'TaoڡY(zm]XC1h4Y}%|aֶV'ek[ޥ|~q5bIh,U>z_Ft/htN(y}~ Iifa ?={@Eg/;IENDB`PNG  IHDR<q pHYs{Rk fIDATxyCD"QH{5 5ODW5n_ƤG.˘إfaz;$o8S,cu6Ir냳I`-z5VQ?rY_뱆}nNqpIM{=! ?!eѹ"?zK EH_U(XsD9%Ԅo)XNѹ!ȧ$1[erew8ׂ{؛K<S9s_A N !wx.(k֊\H+869iw } *JZ߰TX+NK$9YL>581YXrA+hIQqAEܣ[Ċe'~PM_E^DgʪqVaSAbO;;cFIYAX~Ns1mIenJ-#vu&d E\kZJp0<(L&Ug|oKϟX8I8 :~5dgVs`5u{Ћn) V%Ȏ{bhOjun/q.r79XqoT,cg'ҰhETGH L,cԏAvQI5.iIuBZ/<,XCvlyщ`)T7S& XIAvɤ`R ,L L,{d}g nPL,ܨ :,9/L L,B})<,Xxqx轿%<,y0T8 {V `e1UxB)X0-@vC' dٷ\xB)X0S~ iDž' /QYOӲ,-Hb' 0#9YZE ;ޥ“J7\N* &1P(o`ዥ֓LgAxb,!z#N,a0ȎwjYCePW-C#Xx meqt=0r`jY)eq\-#%tk|[x,ÆYt,d)ֈ7١BXz_3g? ÷6.;ci7@9jDx9^/?+G&ԩ^ 4 QXg|*%SV oDMt6hsʩqItbaxq߰9EjNъec'@+l"s $.ky6B8Ub4\,՗y/G˴q[d?"XB['&=VɌG |osGPMk.xi3g>36.3ڞm؄|7YEY-2ܭ\rc1-xMOZ[]EmAcg>T\*y8ׂVpm8m[5}VHU#ȇ;ytl{|7}ZӞMZs94LK8 pLe+&6,{İ%CŘN-]KQ<:1cWruL=;Samc\ܿ|7      :OWUzIENDB`{ "name": "Contao Manager", "short_name": "Contao Manager", "description": "The official tool to manage a Contao Open Source CMS installation.", "dir": "auto", "display": "standalone", "orientation": "any", "start_url": "/", "background_color": "#ffffff", "theme_color": "#ffffff", "icons": [ { "src": "android-chrome-36x36.png", "sizes": "36x36", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-48x48.png", "sizes": "48x48", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-72x72.png", "sizes": "72x72", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-96x96.png", "sizes": "96x96", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-144x144.png", "sizes": "144x144", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-256x256.png", "sizes": "256x256", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-384x384.png", "sizes": "384x384", "type": "image/png", "purpose": "any" }, { "src": "android-chrome-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" } ] }PNG  IHDR  YŨ pHYs{Rk IDATxyeu}}58^[Qُ=:C1}/3إjny.? mGS%M;=+zGU /;2p.5(btq;Rb]|H0S[N(ivZMt^rH ُAh-]Lύ޺6lI1ٷ#Lx{YkD[~@&(=URri|ٷ%L_^f#J݊}_ eG".`-Mh=_Ce߭lY;OJ#3de?* .3gtQ|W +z'}"Rb.~T3`fǢ3?=T6G G',(]vu˾uX"]EG%iS*(ߒc T^zDtVo~,ޯso ?9^*IώMgg?:`Az>RK~Wpg @FgO%iZu /=< ^A_KzdܲTIڤ5ُNh`V*{K-EQ=xK :]U6q#g?>]Z>O?T_o_&IUEzv;a6.RE KmX(:`;-ﮒ9zwhb @k^H? TsuxLUﰒ9uQ/ `V(;F+6U(8 wD/J=m` +kVI1;ٷ/-R}?Lͨw"q#.ptC_U|bV @ trtVln+IQd?>q0F~{Vr_s| @.:(V6g?>102z>~+1)08s%is[KGe D2WjSsbtٷ.Ӣﻒ9&F7Gd +LJ釻RG 7JT]_c D_A>ԕٷ.S>ݽ^+IS#E#~.,/J?̕TgߺLjMX,ISoS v 8_yK!ԦzGs6|b$mN1 `?o6;~ ^_$mVd?>`.F7[J-﫣ϾuAG{$mNݽ_1(` @@tv{AԖ{iTߝ}0QcIڜ'C v;釵R[*vZSm dIӳ8] /=_}lc)b 釧Rfoe߆0'|4=_6y `Q|WOz5*oC~t[UOD.J?8zoC*ES%xsˣ=H`JʯJ ;B^} T]zX$o<3q0~h*-ysbtZ ik)a @cK?4ɟ̾` :$nޝ$`JhU[JKYߏ> FgVf^`JLXܨ6ܑ}L:L@ҌbQ?10%JKՊ-c|ٷ̞r/l@LVsUS)` @#ocaT #U=pC;Bk|7L]釥R?U}L}3I읳L]RikQ7dn@DIU_{)` @}(:+J?,UDy%wT{X3I3Sﰷe?V>pSA؍.:(V~ $N^` P3JŬ_ffwgfbg?6WJŪˣ<}b{{s~ iZED9~r68kRi1ZMw^}CIS_} @P[OJ袃o/` I_-ُ;Z`z:TZGelr~7LAtWsU3aoK?$^/jplkzI[yُ:Z`ڊ/TZVm]fV@Ms?_4ovc3bL?$ξ&2z1At6-g @mŞ/O?$ޡQUٷPkNYk|ُ8Z`ڊ=^~H*5Xܨ;v]$M_O~r/J[M9?w4Uov 3.I?$48fF"(<:+~ iz2)]jCRni'X$3O?4=Д.쪭?%~} EwN?4Д.쪭.;"@yYUYg @Sf6_[XBo&KQuϾu4DwH? vh` vժӳo AyYUf @Sf65?f2@)N? vh` vՖ{*b˾eL~t~e9vf @SfVj(~^!}Д.j截̾U RGyڕ.MP&bF-ٷ 0F~v!]Д.j[`ޚ~~!=Д.jRp1$#]26]MbŎO۲og~!Д.j]vdE9N?ϐ4Д.jh߉ܲs I.MP&bgGٷBc6lCdg @SfIjt1ٷRU(vyN` v`WRoF|5Cf @SfIQuɾ);g&3]26]MB+ξ)Q&Ce @SfzymL<$M^4e @mʬQm36ͨ=-Cde @SfF%>$MV4e @mʪw#*XwH vh` vO/`m<&,DDd @Sf}3bI.MPKn0LDR~4e @mZV>1{ʾ3sIД.j):fT)lDRn4e @mZ{tU/\Eg @SfltW/i6sI.MPA?4m;+7]26]-H+˲/g_[埳HZ vh` v NT HZ vh` vմb?})4VubǧHZ vh` vմ%_;[$-N4e @mjRGTUe pF(v{A` v`W[mg_ ntɡg/<]26]խɾ|GUFwN?Д.NOjٗ/xf` v`Wu&Xtޚ~#i2)]j3VQ?XtDgŖ1&]26]mn㫏;lL_{y` v`WS7g_Kz6\FR vh` v-򎋲/Y%78g3g @SfMٗ+@q;<5|FR vh` vI&7g_i?(]26]mJS>}zFi$` v`WW3ޟ}&FR vh` vx We 0(>5e @SfǪ%~e 01~f#^4e @mzFW;D&x8m$m~4e @mz./Q3I.MPgd_GwWHڼ vh` vHyK 0FWM?ÑyД.*o;?lU^~#i3)]j3?]ٗ%@+xbYM` v`W?(,hޗ LG&e @SfCٗ +g IDAT$@oNM` v`WʭzKuz_I.MPw?}9v$=~4e @mo6Q=t[Z/A` v`We_63I.MP]wÝٗ"@zcYG` v`W?}LNN?Д.x{Ge05nG` v`wf_Se| g>9]26nQ=t{%0uNُ` v`wv`*Fُ` v`wF[UToξSUEw?SД.f>}LGI vh` vguoʾ[UFw_? Д.^o`&.=<,H` v`wƚ[=We_vGw_?4.MPl?]ٗL]|H` v`w*on%0{_M?d @sf;; `&`ِ$]36i|ݷ/74GχY` v`w6ꈪʾfψY` v`w6]~T0ӪރQs"i3)]j3؝=^Q/578gE,g @Sf; /Be_}*H vh` vbgF :ٗ>=t{TS({s_UόY` v`wOٗ06h˻/O9kbp?F݇w;wFwߎ~%]ΪPӢQ~3zI@ ND )F?r9.[Eߐ2`mnԙ[~n$b4e @mSʭzK VU5'7KٻďG/Q.y}~=zG#'C '?<)_;˿M< f @Sf;ULc|17j;)-bDo "E*{4Д.Nof_^@~-b|7bp}_=KiZӊ-+{cxΚ6ܙY`umwi2)]j3؝z1&x=WCcpǣ?wEX=1QqQDUf_]yLwi2)]j3؝6>1bxή_2,WG]Q K9^D vh` vb>)Q.j Ht[ƹ-);1p5GY` v`wkm (2']=D1< f{Д.N/U/+`?6.ۥ"_]qtĠ}dx;Y` v`wK X@_Z Nx([m{[X1d_# d @Sf;]w]}I m<+k/:+H~-FTU% ,@+;4 Д.NO/!rb|1Ǣ)Ԯ6^3Sg?6J(>:sӿ[HӞ.MP4 Tnz~o;>-{e;1r]D9ʾz=;4Д.NG.EٗXF_s|}0~!bbpʧz #i` v`w:/ٗHQfUtrwX+ETU<>B vh` v[DK =W_:M } %Ώ5i` v`xgelA9k+ҿHVNjcx~^- 518_ޟ}[K-Yei3)]j3mwóv̾`w\uk2k~UCmDDkI~ Mc4e @m-nQ=xk%oԏ%FwWK\v1Kz9 wf?FhMj.MPn ZeTߝ}@0g>K]c|Oh)N<ښ.MP;O/HW~ateI Ԋ-bxُh_-FgI1_a}~tWc͏EEgRK2)]j3؝Vo1d_75K韵ي-bt!ُ2XRՆ;c|18}e{[FД.N^#ޙ}Y}2sVR˛[~{F+?{)` v`waLQ/Ǽ?UҔv| ^_7Uљ[9+My4e @mʭޟ}YwJ|:1pG9~7Dg韥,f @Sf;YGٗ,뢻?[%MwS>Sbp(v.3Sҿe @Sf;Y /B%o8gΣ>:e+΀2=+2 (J(ȓ47h%m蒒- v)mhZZP4uad}]|{yO{=>$}s瘝f_8iti;RȗFI;]J`w5[z~Z*QuM0-iyծ0]+,]J`w/G8@V̢*/ALs{m]뗦ֲ= v(e @6݅`?R 4rY'"5Uvm% }`Rd3]8w|9&7y~G%4pX'# ]F6JߞGx4?P`l G~"Gƺk oߌGicKn^ʽSko v(e @6݅Q3+G&3o ]- ;1Ճ_MÛJ6uOzMj-3.IZ0P`l F(7hi }Y Ѷi]oj#iAg @)].xzJn<ɿ?%鉴S?9 $>g$.]J`7o1'fOO1vJ$|fwc'(xǖ4ܼ*-Nݕ{O ). vf uW~7%)/JCwG=T;ֵ~>Ctf @)]7[7 uO)IuTD4^V~q\,uWvj!9P`lu{e|Uzk 4uNŔOVtϧ5G9H4Hjv2 nl~8Ge~/%i6攪q+ON ߻7)/Io2 n6D4[)IsQF^s{m]뗦}SK`Rd3؍}3R ԚY~/%i^ZڨzѶiiy>㒔. vfW7E??|WJ~+%iN[4\g4H[vƆޚRg^~#`Rd3؍k/~~w߸%zv}s[_U=4ܼ*-Nݕ{O |`Rd3؍kߡz}o$gc^΃ڹ=MKSw~B$g2 nL~,;Tu NJ|=u)G>Fw^W)Q$Eg @)]ԻϣJ~/>JRd) x;Uw{X3?[%ie @)]43(IQ=]ũr񟣒T v(e @6݀잪ηvqٮ~%i>v Is{m]뗦}S^JR]3. v ~ve;RgFIZHu/>kL6=ͩ} \i`Rd3؝~  UGSc?~%i!=wSj`ڍTUw{Rg^5(3P9]J`7K>4]Uo|Ok`T;-ũrZ:IjZ2 =+sMd @1]o~!h=EDIC~8U ,pU4ڶ1 6-O5Ί?$I=]J`w~_'9ePTwRџB1-iyU[:ǿ*fVIX2 <!|gP`@j4ں6/`;=-3I. vf;-=U݇zA-d4r`U8w]ojD.]J`w֎>o$չ/NU[,Ѷiiy/uV9#I v(e @6G?7MTU$MC}53-iyU[:ǿj߂"I v(e @6y2x @ =.J45v+ix驿S㿜Z?5C02. v穙R~ h7ֲ=$MS<}XGF[צggRקύ$- v(e @6sˣ=o$Mc_hIoѶiiy/uV7F&H. vf;?a7~$i\G=L(wlIͫR]wj-}r}IR3. vO~j|;}Ani/DԨvnOkS=uZgsIe @)]On~jw>IjBTvFCT݇h4pXo4$[2 >?TUO @C.f?IjJ "~q婷fYWjkW v(e @6ݹ{D?3M1α}ԨfvK;.0i|Mix;ݩsϦ֒=JP`ls` @C hݓ&>GR}( vnOkS=u:%I~P`l% @Tܛ>#IRS]Ssj?F_W|cj_w$M. vf;-}RJN3$IR-, x iiy/uVg<י$IP`ls[~b`md'IM}ԏ3,dƣ4ޱ% 7JuSwީS=I4P`ls;-7Ox2,UܞF[צz>9n$I v(e @6ݹmx')7zE$-fWGإ=F6wR5"IR`2 6'`uO'IG_Ҡ}"hA'q90ׂ$I -]J`w[gJa0Fw^$Iߵg?}&fQؒWũrpo IDAT)?$- v(e @6ݹ{үD?/ӬR_ w'/G_ Ds{m]뗦}SKT v(e @6ݹ)6rn$}'foITGh4ش<~[jeI%]J`w~`tc_~$I? 'E_ a74tLY5[ϭ$IӚ. vf;w}G0Fw\~$IOMUkG`!iix㩩}s«SkF%IjR2 >[L}o$؟JT;ֵ~iwx;gQg @)]MOj0~$I7zڇ(gN$ v(e @6ݹD?-Sw9Iu~YJ^a6icKn^z'uVZ3$I`Rd3؝7Lꑯ'9IR^ G2T;-ũr?K$)/]J`wn߷9iBK~$IT=ro9sG[צz>y?7$i2. v砥ONiԏ~ZL{$zV$;'UvѶiiy/uV!I6]J`wg` =רG8I4+If2 |{U oM4zVZߌ>1Sv]WR̷?$>P`l_~ Y"o mw_Dm$IAP`le]WE?'S`œo$)'ߘwDF4~ClZzkK{n<$I %]J`wvn~N@ iIƣ4ޱ% 7JuSwީ%Ir2 >)UUsPsU뛩d&Is/|c<G[צz>%I. vf;;u` =.IN$uWvj-$IӐ. vf;;yGS0FM$I$iZ3. vgZZ(QuNOi$I$Mk2 4O @=vK$I$IӜ. vf;;\S~$I$I v(e @6٩=٨=+I$I4P`l}~3Ps;g$I$M{2 ny)g$I$M{2 nyOA3Psc_~$I$I v(e @6W|(#fv g$I$M{2 nyN~FjlxL$I&d @)]XO+I$IԄ| @)]W=gGh-$I$ P`l-# ~G-$I$!P`le?O@ 7 e$I$5%]J`)~Bjw{o$I$IM`Rd3-?~Bjo$I$IM`Rd3-ٙ'΃5(I$IԔ v(e @6ݲׯ~BjjtEwL$I&e @)]~{O@M?;&I$IR2. vTwo1I$I. vf[V{$ a/ c$I$5)]J`7ψ~>jz;&I$IR2. vF[/ c$I$5-]J`77D?5_4I$IԴ v(e @6z;o c$I$5-]J`7tD>$I$IM`Rd3op@ ک5(I$IԴ v(e @6݂/wo=?/0I$I. vfk_~>jhx7L$I&f @)]W=twPC+9I$I v(e @6Ҡ|P~$I$Ijb2 n^탟tT瘗1I$I. vfcc+xZK~$I$Ijb2 n^S^tP=7L$If @)];O@ :I$I v(e @6ݼMPCO a$I$55]J`7UF?5_$I$I v(e @6ݼםtPoa$I$55]J`75O@ uO&I$IRS3. v3ؽG8I$I v(e @6ݼ;D?uSSk7L$If @)]U=fK$I&g @)]f4[JaP360I$I. vf;y탟l+0I$I. vf;y_lo$I$IM`Rd3؝Ήls0I$I. vf;y^lP&I$IR3. v'ߏ~6jwo$I$IM`Rd3؝ޅ~6j{0I$I. vf;y>lP縟 a$I$59]J`w;$Q?~$I$Ijr2 => a$I$59]J`w_:3(fv a$I$59]J`7K/~6jj+~I$I v(e @6mSP3o~$I$Ijz2 䍿qKP3{_$I$5=]J`w~6jftK$Ig @)]N^~ ѭ/I$I. vf;yi؍~6jf3$I$IM`Rd3؝%{D?547L$Ig @)]NVgG?54Š&I$IR3. v'}ďF?54pX $I$P`l9O@ / a$I$5=]J`w:':e~$I$Ijz2 duO'U $I$P`l g7L$Ig @)]NV̷D?5;7L$Ig @)]NV?~2jw;o$I$IM`Rd3؝ydP췇0I$I. vf;Y~2jw[o$I$IM`Rd3؝%~2j{ƛo$I$IM`Rd3؝~2j{0I$I. vf;Y+E?5o$I$IM`Rd3؝â &I$IR3. v'kiyPCS a$I$5=]J`wםdP׆0I$I. vf;Y?dԐ$I$IP`l5O@ uO{] $I$P`l5)O@ uWV $I$P`l5' a$I$5=]J`w7~2j{0I$I. vf;Y/dP﬷0I$I. vf;YÛϊ~2jwo$I$IM`Rd3؝-D?5;7L$Ig @)]Np˚'z3I$I v(e @6 yO@ >&I$IR3. v'B &I$IR3. v'B _W7L$Ig @)]N뢟 _&I$IR3. v'B+D?5_$I$I v(e @6 н';$I$I v(e @6]_0|4I$I| @)]N]WF?54&I$IR3. v'BE?54&I$IR3. v'Bw'7~$I$Ijz2 _'F[/ a$I$5=]J`w/tm~2jhte7L$Ig @)]B7ڶ1I$I| @)]NF?54os $I$P`l~{EO@ U~5I$I v(e @6 yO@ Uo$I$IM`Rd3؝-~2ha$I$5=]J`w7dTk1I$I. vf;YO~2j} $I$IM`Rd3؝ 'E?5K$I$IM`Rd3؝G?59$I$IM`Rd3؝c kwL$I&g @)]NGE?5=MwL$I&g @)]NsF?5;wL$I&g @)]NeO@M׾/I$I v(e @6v&nH$I$P`lտ \st$I$P`lտ n^~$I$Ijr2 d-~2jjtg$I$IM`Rd3؝dk$I$IM`Rd3؝d$I$IM`Rd3؝ޚ 1I$I. vf;Y3dxZ3o$I$IM`Rd3؝i~2j}so$I$IM`Rd3؝I~2jї2I$I. vf;Y~.Ή~$I$Ijj2 du~YPcU~$I$Ijj2 dQPc52I$I. vf;YdXҿe$I$55]J`w–d`L$If @)]N^v nd$I$P`lWl$I$IM`Rd3؝{ S$I$P`l7gGc$I$55]J`w^lxZ3o$I$IM`Rd3R+ k[&I$IR3. v3Խg:[&I$IR3. v'ox@uO[&I$IR3. v'ox' L$I&f @)]N`1@/[&I$IR3. v'op@ 6~$I$Ijb2 PPcÛV2I$I. vf;y2]W2I$I. vf;yslo$I$IM`Rd3؝7D?uo2I$I. vf;y1A g$I$5-]J`w:G,Ί$I$IM`Rd3؝!ϋ~6j{>L$Ie @)]fdqPcO+I$I԰ v(e @6ݼCO@P-$I$iP`lyUto$I$IM`Rd3kF^~$I$IjZ2 nw^to$I$IM`Rd3kx˧v~$I$IjZ2 n^N~:l%L$I&e @)]տO@uOzM=$I$IP`lywPss(I$IԤ v(e @6ݼzg%~$I$IjR2 n^ݓ=u'3I$I. vfWWD?57{&I$IR2. vj;~$I$IjR2 n^~(~+I$IԤ v(e @6Z@ g$I$5%]J`7{&I$IRS2. v @uxs=$I$)P`l_zAPsu$I$IM`Rd3ox݉@ >T=$I$)P`l \|p˹L$Id @)]_^~$I$IjJ2 n~|\f=$I$)P`luOzM0>#I$IԄ v(e @6:G,c6I$IԄ v(e @6>33~$I$IjB2 nYiЉ~Bj$I$IM`Rd3-zh[PsX=$I$ P`le~mPsׅ3I$I. vf[ {&I$IR2.D IDAT v^2 a7f4I$I=]J`UF?!S}ď4I$I=]J`ELI~$I$I v(e @6ݲzg- O+I$I4P`leu?O\M$I$i3. v,'` oZ~$I$I v(e @6–L=i$I$My2 nyU@U; g$I$M{2 ny]UOi$I$Ms2 ,|{g)9go$I$IӜ. vf[);7M$Ii`Rd3-G?#S?4I$I9]J`ާ8/~$I$I v(e @6LѶ 7M$Ii`Rd3-)P=zM$I$i3. vgLψk$I$Mi2 Tu~J@W4I$I5]J`wv` ~{M$I$iZ3. vgE?%S?4I$I5]J`wv^w}gA&4RئcicV3Nj[.iש&:K[6&Zg~@n,7(r1aE`a(9>}|?3 mo$I$IY3. v'SKџ_~$I$Iʚ. v(f;O @o$I$IY3. v'SȷEJh&I$IR ve @1>џ$ڇ6I$I1]jP`w2x~ )I$I1]jP`wr;EN蝻&I$I1]jP`wr&so$I$I3. v'c gDNuyM$I$)c2_t@ r*I$I-]jP`wrߣ?'I&I$IR ve @19Ϣ?'It|[]$I$)[2j @|*I$I-]jP`wr־ sD$I$I2. v'۸`' m1I$I-]jP`w,;o$I$I2. v'`)џ 㦵v&I$IR ve @1ֿ`O @C^~$I$Iʔ. v(f;zg|2D5I$I2e @-]NIH=$I$I2. v'[ߌ$1&I$IR ve @1 sf<$0&I$IR ve @17zwg AY^c]$I$)K2~ @}U]$I$)K2\ @c~$I$Iʒ. v(f;?\YHw$I$IY2. v'_DV\~D]$I$)K2lxsg 5I$Id @-]NEVwiV6I$I2d @-]NfЉ$o$I$I 2. v?-It&I$IR ve @1){æO @~6I$I!]jP`w:7$1&I$IR ve @1O @/ k$I$e`Z3؝N#iHbyY^Z~$I$I ve @1%џDZ{8I$I4P`bSjiU?/It|[m$I$i3. vk?/IL]$I$i3. vӢ?/I .Z]$I$i3. vW?/I o I$I4P`bӫ{G?/I?k$I${2|џDZv m$I$s2j @" o m$I$s2twFb&I$I.I$I4P`b+_WEvݷ%I$I4P`b ?=Ynύo$I$x2nL$>wo$I$I. v(fړ?=tWM$IY`Z3؍wO@" >I$I4P`b1uOxw -6I$If=]jP`7/$2n?~$I$I ve @1ݠV4v >/o$I$p2n\.$9o$I$I. v(fʣ??]~$I$I ve @1ݸz@"76I$If9]jP`71o$2~&I$I,g @-]џdZ$I$IO. v(fҪfy Ά77I$If4]jP`7[H m$I$j2nl~$2&I$IҬf @-]=#ODFm m$I$j2nlC_d4lw^}$I$i3. v4h H}$I$I3. v(f룟t7~,I$I4P`b 9! m$I$b2n| HdtM$IY`Z3؍sۣ[$I$I. v(f_kG?i&I$IҬe @-]FOD' I$I4kP`bHM$IY`Z3؝Hdx9M$IY`Z3؝}8)ȸ&I$IҬe @-]F')Lk7I$If)]jP`wFZS {D:M$I`Z3؝F^HnM$IY`Z3؝W}39o6I$If)]jP`wvD[ m$I$R29ɴ~$I$I ve @1٩ׯE?&I$IҬd @-]VwG? `)I$I4+P`bD? ^1I$I4+P`bUk#I$I4+P`bUwE? i}埇7I$If!]jP`wj/t&I$I,d @-]XKqg@"s$I$I ve @1kxyD[N m$I$B2߼o C6I$If!]jP`wdZ$I$IT3>d:G5I$I. v(f;ޱi@">I$I. v(f;$iړo$I$IP`bY'D? =xsm$I$):]jP`w6n@&q/7I$I"3. vg~$9MM$I ve @1m4Ͱ<Hw$I$IP`b螫 >>I$I. v(f; 8*yo$I$IP`b[D?2֞/ o$I$Ee @-]no1yLgÛ$I$IQP`b[kM3E?}M$I ve @1nMOD[N m$I$Ee @-]v~"$2~&I$IRT2l~"$EM$I ve @1ٮ7F?&I$IRD2lM3F?韷[}$I$)"]jP`ww]3 Mg6I$I"2. vgGG?/~$I$I`Z3؝zg~:LkM$I`Z3؝_C3 o$I$t2f4~*$?]}$I$i3. vѽD?r^m$I$i3. v [$I$I+. v(f;_ ɴ&I$IJf @-]G^TH{_7I$IV2]jP`wNM3G?_|`}$I$i3. vWD?qqm$I$i%3. v_~.d24k~$I$IZ ve @1d:I$IRP`bSD?nX}$I$i2. v50)o$I$P2|5?D?sUm$I$i2. vO~2d26{R}$I$i%2. v~2$$I$I+. v(f;_zU ޙ o$I$D2zǦ鷢 f}$I$i2. vE?=pSm$I$i%2. vF?2֞/ o$I$M;]jP`wg@2 o o$I$M;]jP`wj[dzg!I$I4 ve @19liftHdpiM$I)g @-]gΏ~:$2~&I$IҴ3. vE?i%I$I4 ve @1{t&I$I43. v&L$I$I`Z3؝ӖV5CD7}7I$I4 ve @1mxyDƭo$I$I`Z3؝|HeM$Iie @-]oݓ|H{{$I$I`Z3؝F mM$Iie @-]qKqgOD0I$I4 ve @1nxODݭM$Iid @-]w9 LW7I$I. v(f;uOxw  o$I$M#]jP`wk5 L7I$I. v(f;qo3 ѝ6I$I. v(f; o8#ɠ,)I$I4 ve @1g@2C~7I$I4 ve @1sE?#nx}$I$iP`b_K4qS G7I$I&. v(f7E?%ݷ%I$I4 ve @1 :6)xԴ~$I$Id2nzg~:)Lg[$I$I`Z3QkHw$I$I`Z3MniA79MM$I f @-]iK m$I$M2]jP`7OH~&I$IҤ2. v= d'/I$I4 ve @1<xEs }$I$I`Z3MҪfy(IM$I e @-]LT,)I$I4~ @-]/G?)i&I$I$2. vs9O dzg&I$I$2. vsZK G7I$I&. v(f#wF?+=pcm$I$iP`b\wZ i}$I$IP`bg@20I$IT. v(fΆ7G?+靻:I$IT. v(f4h$p IDATHdxәM$I ve @1ݜHdY*I$IT. v(fɴ&I$IRM2nzg|2iL7I$Ij2. vs>5O d~$I$I`Z3Mښg7MHdt%M$I ve @1ݼ(yɠ,&I$IRi2nH}$I$IP`by@23?~$I$I*`Z3[{Hfp͉M$I ve @1-jƭE?1?|{}$I$0]jP`7w^ /o$I$d @-]O dǿ+I$IT. v(fα~b$ӿ`&I$IRI2nZ_'@277I$IJ2. v7- LfyNM$Ig. v(f5'F?3i$I$I4]jP`7M3 ޙo$I$= ve @1ug@2kNo$I$= ve @1h5hHdЭM$Ig. v(f2Lk.M$Ig. v(f .ZS ~$I$Iz&P`bQ[9L$I$I$]jP`w1jF?5v~}$I$d @-].HK;4# LfyN7N$I`Z3]H}k$I$Iۛ. v(f8@2|*I$IP`bS?~n$3&I$If @-].NuD?7&I$If @-].VG~r$EM$I`Z3][N~r$9M$I`Z3]z'@2ׅ7I$I']jP`w| oq}$I$i{2. v=~iFg@&vf'I$Id @-].^{~v$>M$I`Z3]Hφ7I$I.]jP`wg@2-7I$I.]jP`wjd[ o$I$=]2zfHe7N$I`Z3]̆(L7I$I*]jP`w1럿.L$I$IO. v(fuOxw W7I$I*]jP`w1k@6aZs$I$2. v#?~~$9M$I'`Z3]܆}+LM$I'`Z3]zg!~$I$Iz ve @1ŭsěɌ4˫w q$I$=Q2Z ɴ'I$Ie @-].vD?AnD}$I$2. vGD?A\yL}$I$2. vƏE?A=xs}$I$2. vHn'I$I3. v;6Mo9Lw8I$I. v(fmG?C_O}$I$P`b6IqQ}$I$P`bg@6nso$I$I`Z3UkF?C7N$If @-]j[wE?E&I$Ic3. v" oN}$I$P`bV/F?Ewjvq$I$=. v(fmu6%)P.I$Ih2Z#d$I$ ve @1]=룟# >.I$Ih2mpődƏ~$I$Iz4]jP`W@B8I$Ie @-]:9P8I$Ie @-]YMoE?I'I$I.` @1]=훣$Ɍ6I$I-]jP`Wy' @6qү8I$I ve @1]=~$9Oo$I$I2[kO~$I$I2. v[~$3}s}$I$`Z3ް)Y͠,'I$IZ ve @1]=9_~$9?8I$Ibg @-]u|k mAH$I$-v2_kM3E?Mtf$I$-v2G?MwnW~$I$I. v(f'jpőO*I$I7]jP`WOTw'& o$I$iq3. vD~u '8I$If @-] [-G?O'I$IZ ve @1]=Y.~$7N$IP`bzG?On'I$IZ ve @1]=Y<Hhp17N$IP`bzZw~$4~'I$IZ ve @1]=UwG?QjY$I$-^2 ( uOP$I$-^29_~$4'I$IZ ve @1]=U o~$4?8I$Ie @-]j}AӌGZE$I$-V2}E?S'I$IZ ve @1]=]7D?S'I$IZ ve @1]=]M~$4'I$IZ ve @1]=]_Lh;{' vT @)[th$IeKg9;q ?: P.jO~G?4Ts s$I7e_;M|TL>6n\wT&d @Uf=-[tHJ( s$I+fyiqem۔RQ?7xb?d @UfiG='I$I;[,ze)ߺ>Ǧ46 ` v(`W{F?4(O$I-wUJ,7 gՄ v` v7.h# @C?ȣ$If-~eꮘW|"פbr[kBTe @iڛ:R# @C n8!I$IjPiyiqem۔RQ$i2*]J3^`я- 4z;'I$-?uJs`òo]ROM ` v(`W{[&*F);UwN$I-o^Ͻ P.jop|c @Cu?wN$Ix-:4uWN+>8GS%E2*]J3ֻя- 5;'I$)SS4ܸ2mJ(2FP.joˎ};'I$i`Y>+VM Ru}J^Ko;k@Te @i*S#я.MT)D$IjdҙjNꯛH5lHO? P.LݗD?4T9I$I+fyixEx?j^}?k2*]J3UW~2cD;.UPʔ-:$QDEc^~$I$XʖLUsRD7IE?1WQ?M` v(`We `.x$I+fyiqe*| 3Ÿg @Uf o;;7~$IFwďgsW ɉ㟝g @Uf.h @C'I$IM*;᭩znlXSvS/ .UP9_,;MN$IcҙjNꯛH5<)2P.t O?P%I$Ic^]1;KÍ+S}KWyQgP.Jaj I$IcՂRg[=7 4ڶ)b՝}(;Ua3*]J3U돋~hG$IYtf]4ذ,[ק4FM'XV` v(`WU]G,['I$qnw՜_7kR}?8c([gP.Jqo~h u$IT-:$uWNp4ڶ)75-}C[ v` vU/9I$R HRo4ذ,5bUßg @Ufw_PE4`['I$iҙwvsStV o .UPֿя1 9o$Iqnw՜_7kR=P.jϾ+1W|"I$IW٩v^n\F6EU:~6]{Te @iZ萔Fy @C]~$IԲ:giaY=rkJ(1?~<]24]ME~ f#^~$Iܲ3Sw՜4~IʷOiЉ 9ߗg @Ufhxя2 =o$IQ=ݩn"פb读:R;T v` v5.H @ ]~$ITHS4ܸT_oiWu` v(`WSюe['I1o|Vꭞ|AWYR3*]J3Քя3M5lѡN$IcSğN>7ܘҠ]w{u` v(`WSUuя3 ]5'I$)l+Swo^ǢB).UPKglǯ5u$I-<8uߤ_HœD9њg @Uf?~hѶo$IYzοo]Rޏ csۚg @Uf*;я3 {'IeKg9n"] Yq3*]J3TVlH`?~$Ige_+fH5ujsg @UflilxN$Ih9_;/ 7LmR*诏8ok.UPL"{WѶM)S@݌g ` v(`W衛osN$GNxkꭞ|M@g?ߚ.UPoէ$IjwٱoJ8 ~L__*& kBTe @iz}0ׇ;IԞE٩v^n\[-R<``2*]J3t);7O$5Yzn~3imSJ(bll@Te @iΊgp ~$IR˖L ?|93޷?+.UP/G?4ֳ$I8jNꯛH5Ⱦ%9 P.j:_G+n?#I,[]1;KÍ+hۦ/\ڄ v` v5uG| y$i Zp@,zeiȭ)*S" ` v(`Wڑ?hp;~{͓$IlԻ;ǹ) :_KM~%៻M` v(`Wۢs.rm$I?&RyM*ǣS;.,nBTe @i IDAT7t e_~$IԔ-|EꮘkƕimS po܄ v` v5Vύ~h~$IR:g`ò4z֔FyW 3d @UfsD? y$˖LUs%)ߺ>A'k@- n<)3 P.jڛ?#E?4\C7O$=la{λSD7gC _?:s P.j_G,'IRk[xpꮘkƕimSJE1vd @Uf}Q~h~$IjE HRo4ذ,[ק 4Z7 ]24]틺я:-߿.I:'t]4熔:;~y=hBTe @ieIiG?4]ys$Iu.;浩#SO_KE @JwoD2*]J3վjoF?@Ec~$I۲3Sw՜_7kR}20Fy?#N5!]24]:G]'IK6_ \m1/p߬d @Uf}ڂS{&vT'IK @ On YM` v(`W:Q}bIGDݓ$NxkF~6 @Uf}#{Z$I/V}.|Ք v` v{ZbpiwOwEKj wmjJTe @ieMiG?@ԃir'Is @ f5%]24]E4я>-~$I]?}*-g߬d @Uf7>I_S @ ~.UP"}?G? {$5GFJjՔ v` vQv[}ڢl'IҮtJk߬d @Uf~hޥ {$FIj`oYM` v(`WQ (%{~$IUk$5==7)P.*ڿ~ha/e }$hG@oVS2*]J3UT9Ez'IҏV$I?#0DPGDjHTe @i,rM+@KݧAO.;:toV2*]J3UdkEH }$se?}߬&e @UfȺ+7E7}:Iu@ -f5)]24]E->,b3$I;]'ѧ2f5)]24]E7zO΋>oV2*]J3Ut[Έ~ ho$I;\4,P oV2*]J3Uts_ZdORWYM` v(`We'55e:'t$)]Ik"f5)]24]C3ߍ~h}$7$P ~.UPơѯ-2z'IR6$Pݳ+f5)]24]CѯmR);_?IR{2PS~1n5)]24]C3~%Ue_'Ijo>Pׇْ߭&e @Ufhѯ-'Ijmݕ} ͢V2*]J3ոwU@-}C$@7iP.j\_=?ue_oO/> YM` v(`WR:2k$ ( P=߬e @Uf鈗4FI1Jْ@IR=|KLjZTe @iJ2K?~$I>@DjZTe @i.~%h+$]e>D?[M` v(`WTwGhcE $)~Ds [M` v(`WcƒSѯ-ӻ7PԚ@MtN}gjZTe @iFn~-hޯ?IR{_wѧȎymjZTe @i/~-h|_~%Ihxї:irմ v` v5nu?](IjGwn>{@ v` v5neMiGL~(IjGEx~.UPƱ#EM1J7@IRˎzu&~.UPƱ'FP(Ijv}ewP.j~_ Zh(Ijv?}[M` v(`WXvkvjrا"eǿ%J%譞~.UPƵѣwFb%I{.>uD [M` v(`WOG V<`&:'LjbTe @iz,~%I+;'(Fi򈗅߮&f @Ufq-[ꯛ=O5QopVS3*]J38F"$Y%Pk [M` v(`W\v웢_Zx4[(IjH OiE7jw] ` v(`W^}Kk@Ku}O$5o>kH]M` v(`WF&$V@dǿ%v55]24]{?V,e 7W  oWS3*]J3ո9mѯ -'"FBIR=|KI&[V3*]J3U*z0U wRO5߿.v58]24]աΏ~Uhbc~ %IsƯF_3jdxᷫP.._Z߅BIR}_S@ v` vU:'|@m 6S@ᷫP.͟mѯ -9$}~.UPp_ZlpPT2>cHvW3*]J3U]+&KCIR' :tW3*]J3U]{(IWO>_{ ]M` v(`WuxW]~ %Ijm  v` vU~ehb~%I([ʔFyF. _M` v(`Wuw_Zէ$uW~fz_P.NeT+@۷3o$i\$lP39~5=]24]խbѯ -=7$i=!dP3٢CW3*]J3Uzfk@ 7~.Jƻl!)@<~ڐ.UPVE6ݠŇDIF_+j&rMjCTe @i[ْץTѯ-׻7Q4 n>-TP3[N_m` v(`WulW=|K=$oO5_߯6d @Uf:6WRo$i,@ uW^ kCTe @ic@zfM$_>}~ڐ.UPXvԫS*Fѯm7Rvԫ$i,BP7^\ kCTe @ik~3 1jT>O;oXK2*]J3U]?.4vWM$Os~'4PCMoX[2*]J3U]vwQ4 n>5,PC am` v(`Wm)W[EIR|g釣5߱d @Uf:?p]+;IuwQ[3&"PSS~ڒ.UP\~`_]$6~i9A8(%]24]չ N-ir~Q{54z֦ v` vU쟊ѯ=?FIRH}X2*]J3Uv_~%I13@MxkSTe @i{K?tNyGm$F}~ڔ.UP^ķEF[ }[Gj,;ᷬMP. ~9^ʎymm$->Ty"-]24]57>*Tm$H-ѧʷ\Z.UPPDJ3ɉ$igl89-]24]5W4ʣ_'E ox'} em` v(`WMi7_'w)6JR}?Pc3~5,]24]5uGEN<(IS@-|E=k[Te @ijJݳ;u8>Jѧ=q_-kcTe @ijLԟ~"uϊ)/[AƆw})1]24]5ޯFR<[ 'O 57{ v` vդ_W oK7HI6F= @u v` vդ:'=\4FJ>-4@tfMkcTe @ijZ_+xt~#%IS/Ejx{ v` vմZ x$U/[AY~ښ.UPVZ >&;)IV>)4{}ښ.UPV? Ի$B Hœ[ ]wP.쪉\j yMN~'%I]S@Cd v` vW~2]];)I*衛 Pl~ڜ.UPXwFZKwJ[)Iڻgv !w~!9]24]53Rw_/إޗ,VJˢ ѿZ3*]J3US~ vi}~ʮ$ըβKEbOmmm` v(`WMw_/حRg o=3lEŇ߶6g @Uf~ ckirReK^Ұ}6h߶g @Uf&7zW v? ops@ o?/=]24]55GFb[-ir{)Io(F [3*]J3UW ^T_KIҮp|a+f߷g @UfF`Tdߏ~`g&3%I+[YIA<'o\3*]J3U~^k/է$ n8!<0n o2:]J3U] ^T}*eG&fJ+[z?])/D8P.eG*0U5~i͔$=Ɠ ;}7NTg @ijC_5xqNʎ}c͔xg2L?=` v(`Wm'_5xI[ <7@' qz.]24])K+FswSZw,/D9=.UPRѯ|˵7Sښӥwɟ9L ]J3U[ HMIj[;>{`t uz.]24]ߋ~`OG,vJRk8(O4Tٞ&3]24]#~`z4yo~.UP{GvFޑ&~?%qMFFnyz^Te @ij[뎊~`Uտ?ho.UPVgůEvW);7TRğNiЉxg @Uf5T~O%iˎzU*1 @ ~5jP.35"u{*Ic)OhZB6]24]u_C|,eK^~S%i\_=?[g @Uf9~ ۗwU~])eZ<&~ v` vHGPYUI ,;M;8DnZ~P.J?*@u^vx]&Lwn$k2&E3*]J3ؕ~,uWnS~~[%i_7`H~&&3*]J3ؕ~,MTt~`Jw_&ψ  ~P.J5L ~[h iaY]Kg @Uf+=W?~`ꌆ{oWI:o`lt}OmKg @Uf+T~%`5#^ ;_IQTe @i$WRw՜;+IU|OSxcwHyTe @i뭞Z(O)T1 4;=` v(`Wz~W_M37[Iڛ},v{λo<]24]~5i3ڶ)e 'g)EG'Z2M{=` v(`Wza/ѯ&L|˵ƾ($^j2*]J3ؕ^XvO4F0W3$K)DT]𛩽` v(`Wu=m07W~E2eP.J/_O'&$={x1h4z𻩽` v(`Wuْץ4ʣ_Q'm핤O(?` ]~;P.J/ѯ({״{g5V)BmLMbj㎩IZchbkպ5ɶScq 3 QA(i rN9ڀ3{?u=V0Uݯ| WֿbvH7~j3)]j3ؕ}D`tat|o篤knI;,R=qϰQp4e @mW"A1vߓ,iFZK n>!֡.MP 4GgIgXG (Z:ǽ5T2)]j3ؕ>0zFWE؆jǣlS` v`WzϏ*ѮEs̯l:t\g @Sf+w\}T GUEKAD}@#ޙД.J?Y}T w{'?%MpsKwɧ'0ɪ|V٪Д.J?b~3͕ɒ&bscpiW,3?[,]26]i| e;.Kڇc.X03(U2)]j3ؕi>0΋־Il4um6ƠŪ=?c,]26]i;[kT-GBQgI׊gG[f_Sw^9Д.J֓,rk?%OgA?LJU vh` vsdY+>Mђ|Dޜ}-(Q+V3)]j3ؕvDޔ}l`Z9Ӓrw_&*o#X4[G韹Z vh` vkpqO9yN4_?|]ja2)]j3ؕvΗޞ}l`糏.jkے>Q]/Xb-\4e @mRʇo>0A._7sfvKݷoH1c-h4e @mRz2qA-i;Q=y:+3Y .MPTbK#aQn;ڟgᒞ^û/;2 ]y2Z+vMlf @Sf+ox׳0LrDk?%X˗G :7w|ւg @Sf+կ{>0oקK?5$6 j9Z vh` v=|14DOEknig4cxٷXY` v`Wj/gchûŁ?.R[`V#?8Д.Jfui+|Y n:.f{kc-s[.MP԰e;E SaxQwi*{^?_ds{ՓGkni']26]yk>0=]01WN e @Sf+5}/fe:÷SR͊5{EQu>0Y*ڇ.\.MP0ܞ}`* ^Y/MBgquhD>0]y` v`WZzeqkE}wK̗Ʊ!ME {٧&Zkq3)]j3ؕbK"AV=PtH/CϿ%Q'L^+U{kq3)]j3ؕX|FGkN[n` n91s^.MPpuN# 3|o [sKbOGOESŷk3)]j3ؕe;G5pS>p}tE}/m1g5ZDkni?]26]ia_c 3kV(7ޒ}`&"_` v`WZڇ\W>|۶ckŮ?HmmM>F0;*_F.MP_}ۋGw(V j{ۿ{ ̤.Oy@` v`WZ =Uo>7~!ڇ.iko-{>0g/g.]26]i+V8*1XFt{k斤̠cx~i[r4 vh` vip xwFOEqnVmFtl m4e @m7`ЍEߊֲW]{UDUf AF.MPH-G>koYBU}w駣|ƈ l3)]j3ؕ `r梽?Sh*atOt\T[ лO3)]j3ؕbK#a1j{>?_(e;G_7WE>Ū=3)]j3ؕ& tW=$:m#5xyM.h 7UwK?=` n8:g d @Sf+-nSޕ}ERuG+/OC Zs]|ژ XD#ޘR2)]j3ؕe;G@ѿ|wӶO`wNxGo pyD}צ, vh` vůwZUFŚ&F{{{Qn%f t~_'J` v`WZ_Q;tw n?-z}":j}N)S]}GoK&|EkŮ?(-]26]i4 7}qS|zr.dtM۲}{Gﲹ?#G1g ՟9FД.Js;;0!֣17bp/:'hm#iF(zEt_sP 8?6D 1}kQj4e @m҈[`6myb`pqѻ3=Os[Q#gmQ}IxctNzgtOrR "?r5.MP4ze]r]1n879~o}m ֶh(~U(a[[׶[olۢsoF?O.TZgnFs勵 )?]26]itmU=1ZwIR~4e @mhvj)˗ i<2)]j3ؕF[縷f{1F%oB vh` vW>>̄_J d @Sf+ޅ>3}/i|2)]j3ؕF_"z0Ն?<H.MP;_>Ss錄i2)]j3ؕrj07 W4e @mR^e_SwG~4~Д.Jyu|O0uh=G.MP]@50UW` v`Wʭwg1Gٗh<3)]j3ؕr+xqĠ}L_Nf @Sf+7WTh-o= vh` vGBU0^Σ` v`W\}LΩƣ` v`W~u0MwGkNo< vh` v1iNQma0~0}Gc.MP4>.+`T[gh3)]j3ؕƧb#zk`.: vh` vjp糯Q?bst4Д.JU}"*j>` v`Ww=j{UwK` v`W:'3j{֦h2)]j3ؕư%Q>|k0(־$G.MP4u_D&/]26]iL[KTOޗ}ErAe @Sf+oK0vn` v`WߊU{Dy"Uߐn` v`WW;&o^` v`W/ Gb{&7]26]i| gh3)]j3ؕƿGTeu*}ϧh3)]j3ؕ&}]vj&?]26]i2 G9g4Д.JSy |B#]26]irWh >2 vh` v jni?~02d @Sf+MV>}mƠAHd @Sf+MXw{E׿MU4e @mg_kЉIte @Sf+M`+vꩇEӿ7M]4e @md_d_׊b^/ vh` v mQ˾B\5o/ vh` vɭw駳U7G. vh` vɭXgTM]7Mo4e @md׻|y5 '֊ghz3)]j3ؕ&bEy"*h{{Z4Д.J_W @#[54Eӝ.MP40|uP[Hcg @Sf+MGkʾNj~oV4Д.JQf~;J10ڇ!mE.MP4=;,J!|1ME.MP4=k_ߎISd @Sf+MWkʾVKo) vh` vEQud_-Ϩ*b祿h2)]j3ؕ7Wf_-ϨwP4{Д.JNS7e_/ ZKf/]26]i:]W ?soh63)]j3ؕG5pn87D3.MP4.X? kL4Д.JSgE 6+/Lg @Sf+Mws?}D(V>7D.MP4-)ǿ}3{{I4Д.J_f_5 wM斤H4e @m 44ʇo;nYT>#. ` v٨sʻ` n8:]DД.J3ܒ(v̐9  vh` v٩s[`!` v`Ww}3|d}" vh` v٪}E W0ͪ*:_ ҏg @Sf+^o}Slpӱ?.MP4{8BU(9jL3)]j3ؕf:P{HO.MP4[TOޗ}Sdxњ[!=M4e @m=W0-h{}{LД.J3()@oO` v`W:_z{5L;Ojod&.JyQUL!mO>.L8U]_S3IDAT]jkI%^wD9Ⱦ 4 i{+10 vuI%70U{S~!&۳ `ڊ_H*)b^Quʾ =oҎT>c3b鏤ƣesW0!^%ҎT=y_`P[qI%I+叾}-_Dsːv赲O`j#sʿ;1׻ob0)(4V (jTyl iG+0W>P*ijA7z͠u{]Huj ')` @mK>P*i_}`"B[>BL]j]}`CXGTO=}Ec[ZSTy>FL]jRIYe_Q8t}>oRW}6RIcܒse5$]w agd%.O=P*i|k0\e;QHM+!80 vb~Ů鏥Ʒ GgT@A7ڇ6!-DU{s` HqK%o/)Fw_KH Qٗg'.tNL%w 4F|h-9MBZ:'3H0% vhwSIc޲xKu ߐ!-PK?}42ۯ?J:JDUf_Y"}!lp) )a @#?J7~!𮋣5$ BZMwg-.TUVh*i+ξEPb^B4,]kSIQ?̾EIwi>ZL]] -Fk?}"46&WFZWŨ|#1n+vJ<49.d4U -F/S1`AG%Ul(7ޒ}u .LHu#1`At/[*ij0jwm[~90e vXO@4y;,vP՛^ -ZsKj=}2,?JU{D sޟ -fcE1` `:g7!U9] -vo>jL!]LY&s0'(7Ū=EmniTO=}B,~'Z+P4qk_U[ x:n7iOS`9&;=#o(2`A 6*iB[û.ξ3Xf4-#2`aZUIYq+>}M(Vf 9>rL1]\?Jܺ}8t}ԛ Q5S3` c۟~\4-}]҈j;0 vXc~5UV|Qu̾`f ֟> >vL9]EX%Mvs?}L*7~KFU"E`8h}YCnxٷ̖A7GR4X},ޕ?J습/9:꟧H#mDU<},DV>7UD=?d_g0 #u]UO?J ZmZ{4VՖ3`EU>`/vëXҨڛ4JU{syui./b ^^%M~ݳ$:S9QW|nTGO 3`EW?}9=In8/J_ߗ2]6}1DJ486f_i0w%QWzGc HTZXI_wDTU|(V=_hp뗳 3`]dC!WLY}>樓_0`taYISЊgG[ &OUEn/el(10 v=W|n~}D__wz)E>0]Fs?J$J1h-M>/eTV1`0rZZIpyrQxӬ6$w_} q|b#EQ=Pc<u{~ v>wj%MG~=*5?0:'vww)!%$.y'~?`+i:_}`c?K.|(!6?+V0|;Z1RbdC vH9??Jڇ\D}@]Dkե:'fDUfE vmEץ?J~(VTcwDOG*zETG[c~n35HuXRZƛ"o v̕4+c5a?:_|[r)_>2`t/D}"E#=ǥz|*2` [@$-Pݳߗ}HZ=\ʬ{{"*(2`TQ;Wt4 ,s54;U_t"<#]Rh^ISЊ]|;,룵sKI'~ ;]Dk|%M~AQ twkJ-e>5Q=PQb X|__I_QU,hyum)WFG.co_sɯ+ z>߳_dE!Lwω%Mxv=Wf_iP_9WdҿcKI"MweDaL-'aI]%Q?}~߭ڇՖO"b Dl8??;aXd⿌(WesߩG)cj3` _[ɮw駳3nI.-e9n>Ј.ipZbIܒqAu?{_ֲKK uT0`b ~&XV#Gg_goӿCK#onI._}`0ʧ?Kڇ: 7妻8ߝQW~~ 7G.׎iND4uvZRmy06;4G)?> vUk?vNP4.XMT>lҨ~}`Q0U?2Zk~:aYd6 3noN,b՞ezLrC>W%M`˟ɾU":Zciu/3`:}su/9YdUI {9_/F֊]ڈ>}0L7F?>KGBD}0+atҨ6d<)]_1?4!Z="*`UUt(*V??7d (Ғ&7We_]LEO+-zsK{$@]f˰+?RKpy7Sw"ۢxKqt̤sln870` .ߒx-i+٨Zf_YLMEknI]i1j{} n;%*]~FN̖4~}c07)ZsKӿJ ]{1r}`,W1p~|㶤soG 5h-)u?P~]q0őoJ4~gٷhpIƺ}Ntyo>Z01 v ::;BIf_OL3lRڇDޔ}`v>~/%AsKcpW`p)~&%÷e'h#?+'ߺ+z+vWeJmj"+~U.dސ}`j@MeGѿh1?xfb |14YZswWiw|ѿjMݔ}|`*(luGw]%BVd_C3u50:'N?\1dz|^({CfIŭ}#z10XlFOUUQc <]ݯ&_|[VH/i[if_9$|h-%;fϊbK}sܯGwGOD[bxQ>r{Tc7|O j8 :gQG9Z(_Rz|4z QmQ>tm%?V(MQvdsbWl8\IENDB`PNG  IHDR$$ pHYs{RkIDATx[HaG.RQC=DDcK뚮HQhI(a,] T cK3v\O̠Ks6p^rw|90̲ DۉM8WBΨVoWZB1 9WEIWi!C}gBA|u^eg>ϐ_T I u[!Ϥ.? 8֝sxJ${e~ ql2 WN.0rcQ}{>h2@;lЎ2  1w(;uʨ?Jsv Ƙ@S.Qkvd b;p3F]gw'(MAAZ|BT! SP ҚC @;KqoVA?U`NĤA]6!3r9o^S,}¼'6|G^凬ѵ(f ~Mo-$1k{z;b]`:Nl%?ğ\5Z!ļRxs.=AZ1PKVPOrdxBl[3(ČM`xܛ L@Y4t&au)u@0dH `H@;]yCP]qpVEH&0 h8@4uW@ eK&׶hy-x) e\&0 @GF&HkƠ0Q7I ^ԍ`?4bԍ`B-yXF0 laH-Lng$ih m3 y @Ӂ' a 9 2@Z u3@քvP S$`ĉ a9EC@ ݱk iX3P79dQ['P7=A\@+ͥn BSbI uS@`IZuS@+]U=K1wڝf捒7͠%@-A`4o2! $1P=Ȥ6hK m5b;m$TJӭ:`kBM䫂K76Ƃ̝ i 6EҎmf6 5kF0!3ycy4ӓ{zh9u']IuĒ-4W Hˆ?2=$e :@i!֛ ʮ(}Ӣ u$-@؎aX6n>?fl R+P\0xaӣ0#H;3`y VR\ڃҏ@`fϘ5?տmy T{b".NH0PR6hPlBg~b4$v&('o~7 ;Av0_U)hO[Fs# ͭ=ÂO-0̗edRדHu> zhЖQ[a֑GנoC;Ԛ3-%pnt j~2+͡){䩹gȪޒ,n|ŖK%!ވjBKAePcᵏ_=(I9q tgi7;MM1a;5r-\|Za"̇P8ɨ>=HЩٗŜc2.%v׃ ~.5T@y2\rZ3Sg })EzO!|uJiEgUg7'}OV>n)ʳ =_VSceG@7dKs N^ߩ//g|`8/&ʎhݜ,k@> [S}֮okxiw`O wDw- lF,= r+9X<0O]NLX~D$-/ͽ L>D8.5l5@AD-/ j=c&.^ nXc9؎]gDUUN鿂#T# ڸua UNTʤo3xrD;*$I6 >ƥ`tősғӮ~(hy^1Z-p_I-9S!+n7!ر-"2߃7"jSޯ]A۹",/+DMu6E>GS=ba#4)vb#)WP$l|WNw"=v-ΐsQ{~9>$1P{( m+OwU/,N B?L|~9eO1<޽6Nj0K*c3l  _n @͒?ƥWNFNoo"<)y7& i138Έ*ȋ0%v -?}Nmu)[r'^3PRhp/W\S!vuS&P$zY|Q'Ifu$s@)|x !ڸ4eCӭMm7G?>1MEg'ۅ%rn[N]\ԐsIyp!}_wPCTN*nw%hE@ lf,.Y/ @ g׳S>MZDlx@ 9FTN@٠ [S tgK]pDJ|3bF GNo@Qϗ˫sBmEe9C.D5)"4Ʌ,t!)^^-xr'q'_.^. LQ^@ [\omrVOȩpMi4rs|V.y>ϨGNyTwt R]?-P_"n%*MN K8mw6@IB/ƽ\O3'Ki/TZQB@¾}egn7D?VQ(b:#VMQ'߶ZQ; 9 "OL̒.-o_RTGojhWOI*}'JB9MP~NNKrkCm,Aˏ*ؕH! Ɲu'@ShEPu?'޳AutI_ [m%?9`UfP}ܴ^߼ 85@6_OFfVMwڍ`l0hN zt*;v𗏂0{ڕaa9ca9ca9ca9ca9ca9ca9ca9ca9ca90{wIENDB`PNG  IHDRHHUG pHYs{RkIDATxylUǧ-V@[Ĉ1^A$i0D%x$^1*11.-Ki҃ZA -`mDkKHZhQv~ IvM~&~ﳳ +1$'G*URA܀KŅ`1Tk*3ro5FˈRAW/dLbLkX$ K˗' BP^-gW &FIU7Mwq.ԝHZyWS&~2T +r)Z*zAr4]@LZt HO~ M <HW[ Y ]  )}2`J۝$+ |* e\!op_҇PE39Q\@k Yq'* e+|rG. : X@eu, d3 * 0%L +i)/RH Y~;* /@,iN4@#bYŎhR+ a)r7ԚDroA/@Ei4@@l0EU$0ly/@gP@HZt5* 1Ι_d+gVϷ`ČzBb1|USiuV) y* %a$EɟJU< <+1 z>* kJFpŚAu9D gcך-QsLGPa>7u%~)i5* ̀v` g)k lKR뒜"90H(uϺ?HdTGs$"Mo,li{sn{tegHMGDrx.[@r:?bFE - mE3}&BQFo*H˦=7/3v$ԥn1>yNIWP)#rԥd dVSHd}ցP xY\_} D(/KČRfhyӗI7r>5i _VXa`S5~9-IENDB`PNG  IHDR<<:r pHYs{RkIDATxkhEǷ*E|~Q[QQRXEUPQ~ ޼$j&6ij5HT1MmD4єVMmؙ_f}@ͽwdmwvfqY&&&,q`3aZpoET$ӷ5ٖ qȱ^ 7ς[hYrt)Fa{2^tV#rX l& *ai/>"+AlS7-ϛzT_I=r;b!Hޟ|z8`-ykK`5W,u|Mp{'(X܁*wn[ ([ w' s"z48\߅8 P[E`՗Rך`5k3S?е NZX-O6$!.?>6Q7fYឧl-%z?FkTȞ lֽtO&0e1&N$`o`Wb ^K ,惪Qي b69t i7 q{(bEbP^0>b=65w6qtCw#^6q iE,#,Ҁg,>-gf ­ٟ<*\+<{O)An}.;2yrxJ*f{Vr _|&05`iy[~Y=`kPV Oxv6X>\GVAV{|mx&`e*A5:ݷ+ <|WΥ9I/<+RUh`g_%ɷ%am}XޝUCFmmn`طߪ ˪.t};a7rٯ`p8+|}hu_$`&'@rUQ|i$|>Z3ko(W 8`̔Ǣ{:ϣ5/wIjK1h>JR=ۥH]vֱݫ釲_01\<~.K6KڤZGvD}Gcw6gifQ~Ot.\Go~eeI'埋濤%ծ}EG X}^4o~w#Iz}F۳_0 8`g%G;_Ē&b0>bR[e[H6‟e{Gx,3ǀGγXc/]I [%٧ vZ4n~#IвuD#2U36.\=ߔ-{d5wXy$ro%T2X`ǿM4o24d7wW8$i*WG5SɀHKkRl4Gòջ;{IҦ78_P4SŀjqfLR[yyt0zWwEwG/$IybZ2`*,;X(e?n$i_Q?-Cch,&"iLZm(h`uј[4>{.>Ah{(Ivyc\kBtqF ;]_%Im˷޷~ 2`*oHmgMH~/%ImK-'g`p02gmAdt|nJ4OIF-{ ٯ!XL֩)H7fZ=$IoѽfjinQ>8h YkW%I}Km_~ A-L4Vme?ZG8Jmwo"dLe{ƪ;eMn3ߝ~o%I}Ŋo"$LK?%W!h` YŞoL$bGᛳ_EPwXY/i|j x`L;cIF߆_WTbD?pU4vzqA/i|jg ϧXU}$iTD*f+724>[nx\4kIF_!aX+OEO?%O?keOLE+$I9lk6EƧwǠLjgw\7dj\1h>}40^w]vzq)MˀԻdPu1Xw_-I3YsFZ*d?z[4v.4壷eML;e}IF_ODYfYp0V6,ފϽ54+rUGS׹Xy$iu.;5ʀ:ῧؒƤ[Dγ%X}$I9ٯ!M_?%Gswq3}'$I##:Ekc\w4V,4u'X`V:wb>o!>+<hIQ٧3fP<ͽ$nL4E3_CpsYX>/$fTQ.L4ڊ_e3 UᛣlYR~co'@Fcnq]$iNW3 WYR~C1> ~_&Iqswߥٯ 0 O}cI5?c1AO{3Ihk~#z3΀SEcĒr+vxm4o&IYc~' 3`z(~K+)Eѻ6J$I#wyٯf#չxU+)ŻdEPIJW$(ٯf#S>6;m~Jʫ}_fEPݠQJ_$_~0 8IH?h%_peEI߳IFSk#:3ƀ?|s4l~JʩyFtj)>˷Io$e{ez1D똏r*|c y8ѻwnTzuD_Pet 8oFcnq+i+!XP*M4:ap0tͣ~3`Вͣ9G,~7Z/N4^p02 U1(`4W} ?ŮH$ ?aFp0T/z*iuyXY}$i{>~0 8 ik}Ht/5NN4<& 0`hZ'}< 4ښ+>~`th9Ipk~w`POƲRIf͠t4}{$iz+)gPl*it+r G)m,N4'Q)gk?;FԒ͢Ǚ'}:IZEdnb,ՇFVe;06:g|*N4ap64'}<F_H$ ~4,6L)T7MIuG3k$IéW Sʀ>LIï1h<}h,2.OOdk)eXSp+Vl7e80~'IZ/QXh,G&`>'IZz7a p`_Rp^{Qe|"=ސ~'IZ}42`A~4OXQXY$i*vzIDap W~HJ^̓kg50,K$-l~< ̀%իw͡٧ o:h{CIR'"-0`4T}AuXe$Zޑ a pI:~J3>Jgѽx;DIRŖlkgBpl։o!(i*v!Oޝ}ePF_JK$U|7΀MRP&4(}/`=Q>NQo993࠺~7˶N?%UsHkOS$m|~aAeoN?$Uu(GPA-J6I~m0 8c?I*x} Dz znIc$p~m0 8}\'B˶+`83s%I[+_L8*k}c釟{PSJk$@s"Ẁʚ|'i1)-Ns$=u~c0 8k>I/\sAk],ktGIsẀjzh-N?$@˶9`t/X(Izz`pPIoz^d0h~O$~ o &:/ГoG0DwFcEJ~ysٯ &tyL'ke^~)I:gm+ fA%~Izmf[}ʟf`T>oi'^y@Рh^~7)I~ fA%:Г􃵏h$vZ$kẀJZA'kg@~O)INC13ࠒL?$}OKrGhZ˿$Ewe`T<}釞{0w~_)IzQ4ẀJ&ГZGjĠ>1>c45g fA%~"Г(v}e ~(HȠT6Rf9B: 8釞4-_>1Կ;LIT fA%^oN?Y}c}cJҬ<_L0*iCOjw` ǣXLI 8ÀJ^~IZK|[0z7~)IX~0 8ĀCʫwݑG0A~$^Sf-0)q-&̠h"~Sf)0i{)ُ?0z7~)IupP4Gދ}`p]$HaA%hُ=0O?;wJ,dATb!w{` =pec ̸gߗJҔdATb!-\%>#w4 pPpH S ?d?ϬbN%i3*1[Ft< T&<0~݋Vf??hPFs{P%i3*1<]n ʇoƒR%iR3*1jl(91x^3>*IupPu/3xA(vm$MbaA%Ҧ<"~# Qz7~*IupP )j}7W%i2*1׽hG;l;VI 8ÀJ 8j5n I,KgIʀ: 8ĀCВͣ|`;m4!pPpH_ֿVI 8ÀJ 8k"=zG`A{WI 8ÀJ 8hnq}Y `m_%i3*1^Ι,K_%i3*1b7ŠL (|c=$saA%4(\ Mb%i3*1 ]~+IupP^ُ(Е[J8fATb!={~l {YI 8ÀJ 8uԇMdYI 8ÀJ 8X} ?h\Ch%i2*1Uf?9e4{ZI 8ÀJ 8=05WGcnq}$KaA%w[UܒHk;[I 8ÀJ 8ԽpE0<ʗJ8dATb!(#~F=n%i2*178߾ُA%i!2*1D|?1? y%faA%:s#sqF=$̀: 8ĀCZ+b^rs4l~,IU3*1$>6Qď3KR 8ÀJ 841-Y660};8<@cQ>Y6"0{s91`u_~,IupPƹbb|"1` ZВBpPph^s#t/-Z^(0kŪWEtُ-ђ|pPph\^ou/Y~-IϗupPƱb7DُiD+%2*18ֻG^"^Z+0[ͽQ Fd^;OKҳeATbqwُ#9i$=[aA%o̠Ak]+_~O-I10Sk~$H9SK̀: 8ĀCR"G$(Vl~_-IߛupPƥիu_ՒpPph*x@ Ǣ%֒opPph^y@w֒opPp(bDZُcbh,&Z6dATb/1`t_K҆ 8ÀJ 8713X@4m~-IaA%ʬ{>ُc}'%ɀ: 8ĀCY^oOK 8ÀJ 8U]?~-i3*1PFŊbz*++K6Oז4pPp(+hڒf70e[?L;dmI3upPF]?0a'à: 8ĀC#mnq+c)1s%\aA%e>`Bܒf/0ry&Tދ%^aA%U#>q`µ~_}ʀ: 8ĀCyw&\%VaA%E2b00h{oIupPFQ?L_L4;pPph{pD0-oIupP]=?0S1x(&wի{^ѽhet?}'}G߈2_?5mghw|p}ǣտ^Kt'z[O}D-1xfmD.{žߒf#0 bv1h&4kWwaѽpEtThKQc4O^hdž뎌]F"z:|֒;0 0O}^>8:sOhaCcߩӛ[n̏V:|6zo_̸3K 8ÀJ 84G]qf]ً;iѽth_7Gt^<uK=1X&:3bè|Œ;0 ѿ`tQ*z1ZG8H#q:󵿙,7EO SsL+i3*1а{QiNys:w[\w`@˷Ψ/|h,,̀: 8ĀCè;?L~'5DUۤUhѽl(b~UHw[IӛupPQ/f4rl>8ڧY4xW4nV%G%_0.+iz3*10݆) g|2wDFb/59k3k?K*i:3*1B׽pE14XwROhh-J knQ4蜿45WG kHSJ 8ÀJ 8-:G?ojɟb7WUz wI1h? ۠>oM*i2*1B>i Ǣwl)f[*Mn*i2*1BV*# (&%[grO9fLŪW'4UpPph~kwA:wX}wP>Ꮲ"G^,{ʟQph]wD!(;?eEcnQNiS+v!'~,w1d?Z ɠh4mSdATbfDγտb7הQ{<6`'}<;ɀ: 8ĀC Qdמ3>.;F֒͢uoS|&0nnQ+ 6n;}WJ+_RJ[]РD h 1%MGaA%[닿1`cqц|hQ>t} @ RTdATbojP::g|:UJ(MRM'D ^{!;π: 8ĀCu*ሲ1Y ?+?Q<? 0GnŊҿJn˶A#g:W3J 8ÀJ 8){)bPf|fǠ]F7Ǥqn:A{}&60mJ݋v̄Ak]tg~@PWct/Ykg#l0DsO4pPprK65]V>vGOd4oO&Gw`@ &30ULk}Ǣd}~M'd13m~:/Mn(i2*1P.2zI'i`ޖ}̬JN(i2*1P^Q?ӡߍ5Fs?=O[etLjN#9ߊ&*0Usg?߉_oI~')b? QJ.(i2*1F7h~ @իu$M#7gP39%MVaA%Zr`2uѽ|(V:;1*_0 A4?c%MLaA%z7q,n:0_]NdT|b06Zw?IupP6bK(aPΏ_ޜ=Nd>#1h<}LN#wH'i22*1>ϲ?o0Dsw4>VH'i22*1Կ*X+"ߝMq G]ј[}OgATb6)?hhh-J&iz{W>Nד4pPp71;39i4m}M:7cG |bw/18$}o}I6Xw4lNfATbl1(){ѽb(V4$=W˶?t~3{̀: 8ĀCUxwi4?$ickeҿI 8ÀJ 8\n9) 0rsƧIY˳R3(ӿI 8ÀJ 8l;kg<FQbT%G^Sw9IcupPih`h`[~ @-ҿI 8ÀJ 8l( 0|A9$ۧamQ>v{i 01~$;{|?\u*Vk;ƩYGGNit9Vό]3]U/񴝢r!1TFE`D@ 4A d/YXBo{s ~Mx%ՎJ2PVi" iJ$kGR [\]Ih d 8a//YJ$k.KS^~wA{ )U$IRCb 8?lW$IҼT~4/y[}[Ry&DZ$IRtZԋJ2PVS3~nva,I4iң-hJ/Dz$IRm6> 8T2^OR$kΕꤹiВ$Isl@}p$ee?5q{$I:` wnNs^~cCR֏E$Ieo׀0PIʀi(It`ԿXrTPwkNU$IRkūo5 8T2{}09J$W5ګ''$A/G$IRm\~` 83|(ITRWU#UK$զ?e 8{>o$IRQ_ `>oS?%IjӞ?,Fp$ee/-~$I?VUgW\hSi$IhW3 J2PV1ܹ9)J$e+ZgB-0i'D|?%IF߰ߑ:?f g 8b3$Inemj[ `b-:,<ǽ$IҼV1R7ƒ0v 8T2{$IܫԻiYj~GLU?%IHU4vޱcSԗ[X0PIʀCF?CI9Uuvo nq$Iyui}Cm\:kK Rc K*ɀCYpL?3X%I{S&~J3WWDH$={~>Կme|OS̎Po(`bp$ee1ݺOP$i 95~;LޗG$H$j׎4زvW\XrTL6d 8_~$IDž ל IޯBiYj>65O{>*ɀCYpLҗr$If7(?OFRHIkK婳Z` 8\'O$S3xn+5;$IoZjj,|^l 8T2^-WF??Ij?[ ~FlH1zԿ3ſ|'>?+d 8SVI:Uz8>ks?>$IRͪ:Ϥ { ҷ沗,% 8T2NK?I$@'ٯ ȷwJ)mKk9.V,HɀC%p(+OO$~k _'EHn8HGJ"u|Wj}ߥ!̀C%p(+)T~z$I ];n7zNX$IRgSѿSˀC%p(+oD?;I|>5~pqH4Ug`_rSs+ 0PIʀcnZ$IRϤƢCo#RkFH}5ͩZ 5f#jʀC%p(+3|g'IZy2spIjwqDž=uk2p$ee1]g\$ISޞwvLE֫?v$I];`](W$.s*ɀCYpL?~r$ir}0͓yzǏ$I[~* ]z7njJ2PVep$I_?y` 5O}Y>~oǐ$I߰P6J+ޙZ+w! IDAT,1PIʀc,92^3I)lw-E  :5̻$IѪ];`](WK_ p$ee1=z_;7I)种7G ߔҠ$IRhU4Իqij_|Ԙ98`,<$ ^'IũNoH%G0 8T2lo~b$i>)I<3_rSsN1PIʀc,|^:$Iӆ<7 ǞM^=uG$AoWv~9.V,ELIg 8di|C$Iڰ?/ ULIԪ'KMRwX|x^F*ɀCYpLu~R$iLѷ ^PI: Uvwy{yK{p$ee1Y[~R$i >|Gj,:4l3k?J%)|Rj_?Od 8YxH:$Iȯ2cj/Rn'$={^ܜ:kK fg?;3PIʀcr$Iư5'1P}[?R%iRӪ]w|j<&53(c 8^$IƬg;h4eU|'|voI/ Yx*ɀCYpL~N$ig/H'FJ|u`۸|Pg20*ɀCYpL$Iz7~ p1+ipٯB\Z 5f0PIʀc24O$IƨS00z7-4fUv]g`G,ÀC%p(+;$Iڟ?7MÇnTӪ]~Qj>654Pk*ɀCYpLWWD?%I4&yI):Ϥ}SSS)?c 8dzS$IcP//W(tg-ZԘ98g0 8T2_Ұ$IԽFf4_ITkGuY;>WKL$d 8_7E?#I4 ؚ]`g2n#cXRaծ`](WKLd 8ߞq$I_w D~/?%e~`۸G$մU U- wnNMRwXtX?C%p(+$IҳU=`j,>nxܻnXsj.=:-Ib 8ǘZ|DJ^$I5~pi zqy9.V,H9d*ɀCYp~:$u;MR1.hAܜVS{1* J2PV{_D?IT3yGkQ.j׎4زvW>65O60PYʀco?H$}Q`TǺƽ wnNMRwX|xg 8ixu$Iu~$5UOwQϦ15O|A;2PIʀctl$IRl2>IVuIRoԹ`Jp$ee1~z7l$IRj?'0Q>/ fG~mf֊1sp` 8T2?~6$& 35f O`Ҵ?TUaՓU^yLj,>"P*ɀCYpx$I5oT;?Qyڵ# MR{yKe 8xisOF$դj&UNUwwG :`۸|Pg2m0^ 8T2/d$IRM^ L5'D+~' sK}uE|_us3PIʀct~2$ LED٪iطRO?EƢC ǀC%p(+߼&HԿw L߉מ3׾??[y C%p(+2|'#IjP~4l::`۸WK { b 8|E?IT?N@/KUs`v=[֦E\ˀC%p(+ѻ"IY>j[y& ԻԾmyτC%p(+1res$Iڢ'A|~ܜV~Jצ`p$ee1>Ol~.$)=$Y|iڵcW\sBj<&5FŀC%p(+1䨔as$IuW7 0kpiRv?w~Qj>65"p$ee1ZzS$I z7 Wc>J^ٕrtZ|?ƀC%p(+YGOE$6w~:UW7JuǧֹMu3PIʀc<0$izk_{g2~'յj׎_r ٯgkȀC%p(+0"IƢCG"աjvн~&?۩yK0PIʀcW x 8T2ਿ=$Iz7~yZ>5N|~1PIʀcD$: C`p$eeQoS^D$IR@GSc[J2PV:uOD$Կ;0PYʀ:k(Hګ~*ˀCYp[$IqUwwj,>" 8T2਷]E?I4ׄ ^*ɀCYppף$Iq{B-2PIʀުSOD$JeA 8T2ਯ)/~$i ~g 8G}}m$I#wi7}*ɀCYpW5yH׾M7}*ɀCYpW~$i۩>d 8Ǣ$Iaׄ2PIʀ[~$iuA*ɀCYp{$IaZ d 8jj!IFT~j?~J2PV%YHԻ7d 8<,$I\wo*ɀCYp̒$IQ'd 8u$IE05N|~J2PV^yL$I#zw*ɀCYpK%IH4w]J2PVҽOB$gp$eeQ/N~$iu>w*ɀCYpK $IACJ2PV2'!IFPp$eeQ/_~$i 91PIʀ^];$I;n91PIʀFfNi؏~$iol̉J2PV\zts$I#d 8ꣵbAs$I#`n 8T2ਏ19H^d 8s$Ij}`n 8T2ਏ~$iXrT̍J2PVѽA$sGo` 8T2ਏgE?I4 sK̝J2PVwA$s/93PIʀ>~!9Hyp$eeQÇn~$i^?~ssg 8G}TO$I<׹o` 8T2ਏ;9Hy;d 8jbOA$}̙J2PV<$IA:΀C%p(+zhX$I|WU;d 8꡵ OA$sUc 8G=W9)Hyn]7ǀC%p(+z\OA$so)p$eeQݵ~ $i}y1PIʀ~ )Hy7ǀC%p(+zݴ,)Hyc 8G=o=/)Hy{o J2PVп I@d 8a Ig~sy 8T2ਇwn~ $iko J2PV0|lKS$I\*A IDATׇ@d 8z I~sy 8T2ਇtS$I\ԗ@d 8! OA$sG@d 8j`ɑ@$w05f;,*ɀCYpǩK 9|*ɀCYpkg I湪x3PIʀ#^# $Id 8uW@$s;/ 9|*ɀCYp^@$s;. 9|*ɀCYppr3$I\7πC%p(+xό~$ig 8G-~$irN3PIʀ#^G?I46~8p$ee@$s~s 8T2g Iކ3o J2PV\ $I<׻g 8G뢟$Iz7~s 8T27ؾ!Hy%7πC%p(+xÇn~$i_~s 8T27|g Iuo3PIʀ# $I<׽7πC%p(+xSG?I4u}3PIʀ#^w$I}0p$eeh3$I\g 8Gg Iޗ@>d 8U$Iz_>)p$ee/u@$sO 9|*ɀCYpKN3$I\o7πC%p(+xi8~$i|V3PIʀ#AO@$ẁC%p(+`~$in9'p$eelQO@$;l*ɀCYpj' IFPwπC%p(+XS^$IwπC%p(+XS^$IoZ~w 8T2\' IFPK J2PV 8$I[ ;|*ɀCYpj.=: H4vm3PIʀ#$I`MwπC%p(+XS_$I>t[3PIʀ#$Ipg 8G,I J2PVd$I#ڵ#p$eeˀCj=~w 8T2\' IFQ~w 8T2e!IҔTU1sP1PIʀ#$IScɑǀC%p(+XͥGG?I4'D1PIʀ#VG?I4T1PIʀ#VF?I4Zc 8G$I҈jb 8GGD?I4ڟb 8GEF?I4^d1PIʀ#O@$Κo J2PVRUE?I4WE1PIʀ#^$IAk~wy 8T2g IFPS J2PVR $Ic 8G+Hߴ*p$eej= $I|c 8G3H4o}1PIʀ#^@$C@d 8  $I>~o1PIʀ#p@$jwǀC%p(+xÇ~$i;wǀC%p(+x $I҈j,9*΀C%p(+xo~$iD5;d 8 ] $I҈j}o` 8T27g IFT~{sg 8GݗG?I4:=΀C%p(+xo^ $I҈\;d 80Hս0w*ɀCYpz^3$I#w0w*ɀCYp}C@$=V̝J2PVz7.~$iD \~{sg 8G3@$7p$eeſ~$iD ~{sg 8GD?I4;d 8u.g IFհ3p$eesG?I4š'(ƀC%p(+xտ $Ikd 8?[@$7p$eeu~$i/y[̍J2PVZj3$I#s`n 8T2/F?I4ºp$eeyOG?I4z_;7ƀC%p(+x͓_ $I}y̍J2PV5𐔪*)H5xd 8!OA$[o`n 8T2ਇjOA$+ƀC%p(+z;q%IXrTJ2PV0| IFX~g 8G= 1)H:u*ɀCYp$Ia~7πC%p(+z IFX? ?3PIʀ$I^*ɀCYpC3$Ia[>~g 8G=t/~ $i76πC%p(+z~/$Ia7p$eeQOA$` 8T2ਇ%o~ $i z1sp J2PVоOA$沗 p$eeQJS$I#u p$eeQ&)H׾-7o*ɀCYpĒ$Iq+d 8G}~'9Ho*ɀCYpG IFX?}3PIʀ>;~$i ^~f 8G} 99H6|7d 8cems$I#j=~f 8G}7~$i5~̀C%p(+}CA$ٿ~̀C%p(+_$I҈k_op$eeQݫ$I҈\7 8T2ਏg[s$I#{_ s3PIʀ>ګ$I҈m\~̀C%p(+h IF\?:ixf5+˜˲i53ZL3eSMciZM4 rQ䦨 "Eᠢrܿms>{=k=w7k{Ag 8TG;s$IOop&eюOJ?IMWAg 8TGC~l6$IV{lvȀC5p(Lw$IງTv̀C5p(Lݔ~$iW7cɀCEperۧOB$mp$~;f 8TG[_8?$$I7ܺ%~;f 8TG[FW;$$I71d 82$Io` 8T2h'!I67cɀCEpepKOB$mtluG 8T2hK祟$I 9w@ɀCEpwԳOB$;x d 8}ݏ$I ?w@ɀCEp'!I <j2PQ ;g!I6%o p&eўB$mpώ p&eў͟H? IMn:~d 8TG{ל~$ivf+wp_ɀCEpgt[B$wp_ɀCEpgu$IG=3~e 8TG{gyYH@w(~e 8TG{'^YH@ 8T2hO_J? Ihtq;/d 8=t$I7^C2PM*ʀ=-OH? Ihwp_ɀCEpi6즟$I覓꾏!p&eѦ鶛OC$'wmɀCEpiOC$;6d 84Ӑ$IgỳC5p(6.=*4$IRE 8T2hpӐ$IWCo3PM*ʀM^~$)˟!p&eѦ~?4$IRi|j2PQmgiHPEo1PM*ʀMXiHP#}ŀC5p(Fl:M?I^[ɀCEpkz{yH@^Co1PM*ʀ][/K?Ihtٱ;d 85$I7~8~b 8TG~$)w-ɀCEpkp?$I -p.eѮ/N?I{oCup(v$I-p.eѮ~<<$IRy"2PQ 1t~"$)So"2PQmv~"$)Cup(MnE`p&eѶq9D$IRo" 8T2h[?~"$)OoXvɀCEp4n'"IBM;woXrɀCEpoڽ3L$IRΫ'~23PM*ʀ}/_~&$)T_" 8T2h$I ,3d 873$IE`p&eѾVD$]qBef 8TG3$I&~2~23PM*ʀ}㞝~&$)ԴlueSee 8TG:3$I:Pee 8TQd~*$)W%e 8T|n)T$IR/" 8T2$I 5a[j2PQa$I 59[j2PQap"IBM-ʀC5p(?"IRM~# 8T21T$IRψ# 8T2(T$IR){XFɀCEp̉M٨~.$)},!d 8kק$I 5-ȀC5p(19"IBMn<~22PM*ʀc~.92\$IRaw[ec 8Ts$I:?%~1PM*ʀc~s$Izo=ƀC5p(ᇃ$I'~;:d 8Gߗ~.$)#,d 8˴wHP/E`p&e1_&_2d$IRݷoX6ɀCEp̗g$I =ĀC5p(2a'#Im=ĀC5p(2x_$I ?,d 8KN?Il,d 8KOO?Il|{j2PQ'#IM|eb 8TvH?Ij:n=~0PM*ʀcLtqH`#G`Yp&e1F~gH`w(~0PM*ʀc 'l$IRᅯ#, 8T2?S l$IR5#, 8T2?~HHMlewsɀCEp̟OL?Il2nMC5p(4|-t$IRMe` 8T|ӑ$IG`p&e1Fz[H`í[,d 8J?Ilt{,d 8S]O?Il,d 8Sg$IJ6V}t&Eg 8T|l:M?I{oXtɀCEp̯7~>$)XXtɀCEp̯MI?Ilx=΀C5p(5$IFWG`p&e1"|$IRW# 8T2_~>$)d4[j2PQ{Ϧ$I }7 ,2d 8g4$IRI`p&e1ߦw})$IR,2d 8 OH$_}ZEf 8T|]$I&w~.~"3PM*ʀc >w'$IM'I`Qp&e1z'v Ip7|&Ee 8T|'$IO{I&Ee 8Tǜѳd~F$)C7 ,(d 8_H?#Ils,*d 8$I 6=ʀC5p(7Ag$IuxR&Ed 8T?H$j2PQ{3H$MȀC5p(H$]MȀC5p(0WOI$c{j2PQa|S$Ig+7 ,d 870 IDAT$I 9)j2PQaH?%Iߌ$h 8T2X S$I"~1PM*ʀc1t|r)IpO3~1PM*ʀcAlMw$I 6j2PQcr%$I}#~"1PM*ʀcq.?>$IRI`p&e8"$IR/$H 8T2X~'$IR-j2PQL?'In|j2PQ dGfAII`ӯ!1PM*ʀcLn:$IRtM€C5p(2$IzG=+~0PM*ʀc nI?)InpK7 , d 8K/J?)Int[7 , d 8KM6$IR͟$( 8T2X0wͦ$IՕw ,d 8tMg%Iu#~"0PM*ʀc?;$IRII`p&ex~V$)p~j2PQKJ$_{F&E` 8TCD$MI`ݛj2PQ ht~Z$)t:w 9d 8ϥ$I ;fM΀C5p(4%I zY&yg 8Tbnݒ~Z$)GowɀCEp,/L?-Inr%j2PQ{Ϥ$IJ7V~D.yf 8TǂQx~^$)\%0 8T2X\|&$IRI`p&eFW~^$)WogɀCEp,y~^$)ogɀCEp, ~^$)7ogɀCEp,~,$IRu^j2PQ lel~b$)\_%0 8T2Xl[.I?1In$0 8T2XlˎK?1In=I`^p&e$I&~2~2PM*ʀck'&Iҍ}K`p&e:PIj2PQoڹ#$IR{(~<2PM*ʀcopIpÏI`p&e~f$) 7 #d 8̗$I 75[]K`p&ez~f$:<5~1PM*ʀcu^g&Isw d 8/$I 7ܺ%~1PM*ʀc9IpΊ$0o 8T2X:$IR]o7ɀCEp,/H?5I@@.yb 8TrS&I_%0O 8T2X{?b6vM$j2PQcr%&I<)~<1PM*ʀcy>ytIp^I`p&e<s$I馓YgɀCEp,1{$Ij[c.ya 8T]t~r$)̗ɀCEp,鶛ON$]zT&ya 8Tr_{FIp[.$0/ 8T2X.í$IJ7VyT.y` 8Tr$I =gw d 8Ku?~r$8~<0PM*ʀcɬ6~v$)c%0 8T2X>?~v$)j2PQgtɑg'IM{f+w ΀C5p(38N$5P%:d 8Og$IjމKuɀCEp,ΖfIIp %:d 8ϧ$I 7M3PM*ʀc9~OIp7 ΀C5p(48ӓ$I 9Zf 8Tr;'IKeɀCEp,!OM?=I@ %2d 8ʦٴ$IםKaɀCEp,$I 7M-3PM*ʀcy ?vhI=ƀC5p(?O$5PKUɀCEp,?~~$Z%*d 8ޏ͆$IלKQɀCEp,ɗ.N?AIn7 ʀC5p(6$I 9w ȀC5p(?OOP$5Phj2PQ˭{/$Ijy%"d 8ܾ3$IFWKAɀCEp0gP$n1~@ 8T2`tP$5PK5ɀCEp08P$5P%~@k 8T2wJ?CI@s^K5ɀCEpl:M?EInw ƀC5p(~ (IM|&p&evޝ~$)t:w ĀC5p(S$I ;Ww ĀC5p((Ih%d 8خH?EI@+N%d 8Q$|M-1PM*ʀ{9Jt鬳w €C5p(1ps$I ;f]0PM*ʀ{O|n9J|ow €C5p(9(IhtʼnZa 8Tʦٴ$I&w|6@# 8T27\~$)t:]Z` 8T6$I ;Z` 8T?e$I 48Z` 8T=t$I 4Z` 8Ti6mK?KIn] 0PM*ʀ߰5,%IRuxR.4d 8E$Ijω%f 8T?e$I 4%f 8T=t$I 4]iɀCEp+f޶Ӕ$IwݒK ̀C5p(vd|Ӕ$I y[f 8T;2Ӕ$I {oH2PM*ʀ韲WiJ^9~@j2PQH=OS$5H2PM*ʀZ4$I 7]j. d 8x0$IjA?K ŀC5p($IjIϋ%b 8T S$5ï%b 8T{)Ihsw p&eZ4$I 7~_mɀCEpP7lM?QI@X.d 8x(Ï~$'0~@j2PQ<$I>L%` 8T{'*IhUK%` 8Tielۖ~$)ܴluem̀C5p(q+I=w l4d 8x8$IRhɀCEpp'0L%IR ?]̀C5p(N=T$5% 8T2alMw$IJ7VyT6 d 8T;cOU$5PgHɀCEp3> T%IR]ɀC5p(vF禟$Ij'% 8T2`gtS$I 46j2PQ7~$)d<]ŀC5p(v$Ij1{(ɀCEp~$]ŀC5p(vV~$FW+~F1PM*ʀ9I*Ihw ld 8(1OV$5P% 8T2SOV$5P-~F0PM*ʀs_~$K`#p&eAqN?YI@K`#p&eAOͦ$Iᦝ;f+ 7d 8(5g+IsSw 7d 8(5$I ?֛j2PQWg+Ihx֛j2PQ$I 4#֛j2PQۼl6$IJ7V~d6ud 8Tb+OW$5PO% 8T2`W.;6t%IRw 'd 83,t%IR.}K.d 8TO?]I@.% 8T2`٨~$)d4[։j2PQ-$IjQϊ%^ 8T2`W /~SJ֋j2PQi/I?_I@+N%^ 8T2`Wu$I 4s֋j2PQ첕f]',IMΫ7:0PM*ʀ/~’$z?'~z0PM*ʀ~’$Z% 8T2F禟$IjugXɀCEpPsOX$5t]C5p(jM5%IRuyj.f 8T׼7%IRO~a.f 8TcK~]k̀C5p(j{vK]k̀C5p(jul6$IJ7V}t6d 8TkakOY$5P?K`-p&eZ}m,Ihpw %d 8X <%IR>]kɀC5p(ւ\$i{;>K`-=j2PQ}5 ,IMΫ71PM*ʀ2,Iwsw d 8X+Ï~Β$K`p&eZ$IjgX+ɀCEpVs$I 49[]M`-p&eY4vH?iI@C& 8T2`-?wNIKw d 8XKí$Ij?K`-p&eZOZ$5Kw d 8XK?%IR Mj2PQ鶛Z$5P-!~@-d 8XkϜ~֒$gU.ZɀCEp$I 4] 8T2`3%IRM~C.ZɀCEp6>MF-I&PC5p(W$Ij;~3~@ d 8XO~ڒ$[a 8TN?mI@ϟKj2PQ?~ڒ$oVWv& 8T2`]l~ޒ$t6]d 8Te|G[$5P=K`Wp&ez^tpyK]]ʀC5p(K$Ijm% 8T2`tyjyKfw&+ 8T2`=MWoO?qI@c%+ 8T2`={_K]€C5p(}O\$5w d 8XO㟓~$Y]€C5p(SU3Mg.IsS 2PM*ʀ6sg.I(e 8Tmt g.Ihχ(e 8Tmp_$Ij-(e 8T{3\$x8[ݼ{6ɀCEp}̿F$w/o(` 8Tare.Ihp?(a 8TaxO]$5w 0PM*ʀ?%.Ihͯ(a 8T$Ij?M`gp&eXm6ߕ~$앿M`'p&eFpAK~ vj2PQlG^~$&\K`gp&eF.IZh9%IR#O+~1PM*ʀtI?Kp&eA$Ijɭx0ɀCEp28/IZh2u<>~p&eAJ_I?IHM`G 8T2 e/n%IZ&#ɀCEp4' Ihd 8H]vl$I 45[]-~p&eAR?M$L63PM*ʀ?$IR#mvo?d 8`5H]~|61PM*ʀMI$&w~.~p&eA?IH`6{3PM*ʀ~?HF;̀C5p(:H3$I4̀C5p(Z0 IhNl IDATŏ7d 8h3ҟ$IjQc ÀC5p(Z08OA$5Rgoj2PQwܳӟ$Ij.~= 8T2-ͦ Ihػx"DB3N8ziت}L;MڜQL3Zϱ2cNM6Dn!JD FA0KD T.QŀEI"^ߺ籓I?xWwdD$I$I_pPY 8T{~@ {I$I$eAd1P]}isjyΏ&$I$I\TaAեb;PM96$I$I2 p.5/|msj&$I$I\TaAզE)uO&$I$IpŀCuحOD$I$I2 pNun=;I5D$I$I2 pN'DU᷉$I$IdAd1Pj'DoI$I$ɀ* 8bU~@ 4D$I$IӝUpŀCuu~&6$I$ItgAd1P*nzwj&$I$I 8€,[K,~H$I$i3 pn5V44(?~H$I$i3 p=4h᷉$I$I70 XwdžD~H$I$iz3 p(i5ѽ᷉$I$I70 X?4{06$I$IfAd1P-YR<hqJ$I$)&0 Z~H$I$i:3 pun;7y51wD&$I$I 8€,kDM$I$I4pPY 8Tg*yui''$I$I 8€,s'Dׇ&$I$I 8€,s>D|D$I$IӗUpŀCuiEjM᷉$I$I/0 \7F?.4;(>$I$IteAd1Pk>1Lh~߄'$I$I 8€,{}D?&em"I$Iʀ* 8bݱ!5ѻ᷉$I$I+0 ^qG?&ƾ4D$I$IӓUpŀCu~&@4X}"I$Iɀ* 8b7(N35ѾI$I$MMTaACǷG?&w_~H$I$iz2 phvnSjC᷉$I$I'0 ơo~*@4ּ<>$I$ItdAd188O''$I$I 8€,ٽoI$I$MGTaAK~.@M#6$I$ItdAd1иTܴ"uQSc$I$I&?0 ƥeo~.@6. O$I$I4pPY 84.)۹?m 0}$I$I&?0 Ʃ P~H$I$i3 phdwSI$I$MvTaAS?~2@.}C}"I$I΀* 8bqy뢟 P#O O$I$I4pPY 84V,Jӌ~6@MD$I$IUpŀCVn;͞D$I$IUpŀCVs P#)>$I$IfAd1иվ-$I$I&70 ƭٯ~6@1>$I$IfAd18V2uiٙ'$I$I 8€,z\ti^s$I$I&30 ƱwG?F*>$I$IdfAd18ֺO O$I$I4pPY 845VRُ~>@MgcoI$I$M^TaAk}D?F&>$I$IeAd1иݱ!5R|I$I$M^TaAk?~>@t:>$I$IeAd1иּu/ͮ8&F$I$IdeAd16(N3 5\oI$I$MTTaAsn~B@~H$I$O~"~k~~|M70 ƹmD?!F\~H$I$}g5'ƥ:z6o=׆opPY 84ε|Kj|k$I$IZ뗤bݱ!O?r=t}n͟UpŀC\WF?!fh"I$IM*cS*ٿ}K͛UpŀC^gH? O$I$I~JSg۽-Ns(/pPY 84.5I$I4cƥ:z6od?0 ƽwG?#F~H$IZ$[(=;3O=@gAd1и׺  Q$I$IRM[y\j[ڛ(wTC/?sѼpPY 845V47F$I$I(-gm)un79i 8€,{wE?%F\~H$IԺ:z6/N#π* 8bI{eO rvO]qL"I$IFWc~I*,OR4~?O͟UpŀCPP3~"F$I$ICjqnqjoZ:צwI2;UpŀCPE?%f7$I$I:kNJKS3Ro12_]3 ph"YR{U"I$I[cuSu&vmN4gUpŀCRۢP#s3E$I$V$/IŖ婻cCٙRYF6B-4zE ̀* 8bIs9 2F$I$ij[ylj[ڛ? WDvAm5gUpŀCR߉~N@I"I$IҴXsRjm\zP1N#Jׄ; 8€,j1{7$I$IXcK~J]S9'^sχ{ 8€,OF?)FSivoI$IƺEyReyؐ{vT?O%Z3 ph[c_~H$I46<65-NMRg۽-^ThmUpŀCTqӻP3Ŗ? Q$I$Ik5'ƥ:sPZD(?ڗv ΀* 8bIuP3 Q$I$IC/MKRq5|,y?F480 &Le?Y5R6J+~H$I,J _-Swdž߳31Ch__7UpŀCVgLׄ($I$ǦũiYl_zmG8NSkI3 ph}Yj_($I$ Y?W:L|! pPY 84i\E$Iq%? ޫRM3 phj^gLz_'}H$Itf(kߞ;6)e,ƿ5pPY 84q,Jӌ~Z@4/|]"I$I?qR{Ӳپ6voKێ@֕&580 &cF?-fE$I45ԾS5ͩl?25ӹyUS ΀* 8bIs9O ރQ$I$IQRkTlY~Pgc1c 8€,WNꦘM3/S$I$I̢\8}FΔ~O-gz 8€,g"i5/)$IqR{Ӳپ6voKۊq vfo ΀* 8bIdj:~H$IƧƚRk?OvmNem`sk^3 phR;[oI$IR=kvBj_-|J?2e: UpŀCZqD?/nzEj:>N$I$\Gt(LGʔ~~ 8€,Z>y5;E$IҾپ6voKۊK+UpŀCZcK-vf"I$IXqi*EtX~480 &]O Q$I$Iic2[뗤bݱG7pPY 84u,uS~H$I2[y\j[ڛ(w[(sM#i`TaAMrwD?1>8N$I$P~~kvoKӌqFN3 phk^'P S$I$I>hm\3ks*t׽pPY 84,Jӈ~f@z(N$I)Z$[ ggP { UpŀC^[PC^~H$Iķ\87-;Q('Lߋj{oV3 phzv3jS$I$iR? s{[Jf06z_580 &~w$I$s'֥O֙۵9{ԃ{wpPY 84ߩd]qL"I$IcѪ%زwꁏk(߈ z5B3 phj]Pz6ͮ<6V$I%~I*,ORΔ2G1`fAd14XҔ~sj U$I$r+K*ԽC/Ed=|C ̀* 8bi;7u"I$I5֜ZbL=|cJFW@EL ΀* 8bi{ #[I$I:T_Zyƃ[R0>F3 phZj_Q}soI$I:̢Լuز |,JÿjpTaAMcGo~z@M6)V$I4O+Ku|JRΔ~Cu_g500 zv"I$[Ҿپ6voKۊ`d:uW3 phk}7PS' U$Iik6.M֙۵9oDxfAd14xG?={E$IZ뗤bݱ!O?c@ζ} 8€,P̧}[oI$ibZy\j[ڛ)v>=kfAd1дǢPS/}4V$IPW:צm)u'>X|=_580 S*+$I85ZbL|tn^u]3 phZ8 W$I:Xu|j_-Swdž7ZoJTaAMm3R4 PSW$IVe> ĝ)3`}g ̀* 8bigp {[E$IZBr34OrS\'480 ζ3 PWv]{E$Iv3~ >sil>}}Rj_UpŀC\ߎ~@ {E$IRc~I*,OR3y?7480 ƚG?A:~H$IGRs޴,uM'Lߋ>8Bs4{fAd1дW>x3j|[E$Iƚq[HR4Oh*hm-UpŀC^ޫ!Pc͵2^$IOLK_3ks*gF Y_ ~pPY 84gXI$MY^Z뗤bݱ!L,OcFi`TaAM{͋m3j W$I4<65-NMRgڃ+`4/|m% ̀* 8bmG?E4{oI$MD5'ƥ? S4/^jbn}J3 pHKkm{E$IWcK~J]S9'g2{gAd1w௧Ogy$Ij̢ԼuزO@({gAd1V>DsjOI$ꗦ%]ks*?}0 2ͮ8&gAd1ֻ W$I4f慯KŖ婻cCy?/j 8€,*9uiS'f$IQ\87-KkSo+([ԼpPY 8Ԗ5 IDAT.\7,$I:kNJKSuG4>'`^s_ ީ3 pHS'^'I5ֹE$IUMK~ʽWrѧ#d)~4π* 8b!}wE?I{w+$IS̢rSwdž߳3>j 8€,ҷ~~jqoIijjoZ:צm)u'! 03 pHߪߍ~@~H$Mj5'ƥ:z6T m߇5TaA[5' HY$I&S7wޮOrףO={͚?0 ~@i,$Ic)/J͋~.[6S*j{߯5oTaAۛ;M7$IRk޴,uMR궢O8]pPY 8o~@un"ITkNJKSu͕ͧ5;s?0 uR>X"IQRkcC*~44йyUy͟UpŀCfiD?ME$i<.5->Q(;.J=;S*gL5{̀* 8b!}wݷD?M["I4Bi_q½{[JVS}o͟UpŀC:_xojn?jD,$IUKSu&vmNeLo 4TaA黛 CR-$IZ$[ ? ֆ_ 4TaAk|+pXs}H$}[+Ku)sNc`nl~Gh 8€,{~@u"f$IG8Xc#R}"G~Wh 8€,w~(y5WI3I4]5X=|Á[ ~8!/*0 4տ<1/-$ij}7O `O 14TaAips4ycsYw$IW5,co ͟UpŀCǤrvOjE$MUŖ?>!*UpŀCF?Q` ]w$I30DsO:tTaAiϾ3c_-$izvn QUpŀC~=rS"IݗF?z{}CgAd1)/Lۊ~@:E$ME~!=|C}CgAd1][)0W~Hѧ0Dݝ :0 t:~~Hѧ0Dݻ>~_pPY 8CoD?S` }iv᷋$Iʧ>}!l_~_pPY 8C8e)eS@_ ]$IW>{!|B΀* 8b!*0:~H of?h_:dTaA}|%n$I]cˣO`C΀* 8b!5T1|]$I<`Z~c07pŀC:|~<ciE"I&֥>w!k^C΀* 8b!A+I w.$ibk_`gpCgAd1ޮegP"I&b˟E_;ͮzICgAd1wE?W`LI"I&WG:0uUpŀC:Z 7.$i2qQ QUpŀC:NyaJvAE$M\>}CBπ* 8b!yǷG?Y`L?oI4yvo>s!=t}}gAd1ζ3,0&^~Hɫ3G}gAd1~+c,S^~Hɪl?}Cپ63 pHG^T9~$IS`ȊV:|TaA)7>c{E᷋$Ixy Y_# 8,R^ݻ/~(?fWo!k_:|TaA)l1Ҽ߆/$i2joѧ 0dCπ* 8b!\8cs$I}C|O:|TaA)ǤTD#$I:?q?1t 8€,R~>t1<I4u:,̢Cπ* 8b!WO#W/$it}#ˀ* 8b!׺.0F_$IW~g 0Do}}#ˀ* 8b!E~OJ"cnq #IƷO׉>i!?=eAd1 H[W/$i|kC 0d]o YTaAܲ&c//$i|q0y_`#ˀ* 8b!]K/0fx #IƳo>e!uOTaAjR*O#ō=$IYu&}: 8€,7Ww/$i<}Y) Ykï: 8€,׹' 9g #IƯW>}C<7,0 t' a$IU>X Y: 8€,800f_=$Ic̢3^fWg2 pH?P3IYY?~Hi#R>CpŀCVK10fOy #IƧ%}C{CGUpŀCVߋ~~H}ۢ`Ⱥ;?~c3 pHט~jyy#IƣζE_/un;7БgAd1W>DSL? a$Ix 1tpPY 8u")cgJ#S#π* 8b!U20n25zE#Ij̢zև9gAd11ڸ4$Iuζ3 gAd1_sF?m`Lu2$I}#P\w3 pHïuɯD?m`\u[{F$V~W 09P~TaAi=)uSkHs᷆3 pH W>~Hd.02͞[CpPY 8ԹyUUYٯ g$IRL֙krw.0 4ZjXqg$IRLD";CGUpŀCQ8n;c{F$T>Esyˀ* 8b!mOcs9}HqO`D:_8=eAd1FW󫣟80:.$I [ʷD }{ˀ* 8b!֥o~+gٙE7$IZ:}#2 o ]TaAizE3XkF$-X>&W 5ttpPY 8{gW3$iZylJlBO0QeAd1F[~8Rc7$I} ~:FWo U 8,hk]g5o i$I+6#FdcҢo }TaAiĝzESG4$iu<F#᷆>0 4zo~k7$ImsOD7;gAd1F_sD?u`u/$IyΏD89P[̀ 8b!ſ1W2, k$Ihj_0B_~o3 pH R*f;0ZF$ݗE4{ }TaAia=|Cs\o'oI4ʧ>5)~kZTaAia*n~75ּ<$Ií2={C2 pH S? P\F$ 7F{C2 pH cSz&c4F$ E(P 8€,۵9_k$I{ Fu Uˀ* 8b!-\ŧ"{%w$IN`iC2 pH W~$(fSoITo,Q*f}dAd1Ǥrvo&@?m$IR]}V#{C3 pH [ޫ=0ok$IRVֳg0B{.9T90  ѼoIt> 0b֙C3 pH [sE?{`BtF$}O>'k_C3 pH _ͯF?}`RoItts 9T=0 uw|$}oI_TO `25V~wzTaAik>0!_Rm#Ik_`g94 8€,8~i^s$IʫcC Xo '0 S?0!w_~HVٽ'0bϏ;4 8€,RL;.~4S~H#u/F_(,;4 8€,RL+N~)>$I::}: u '0 ܟMe?K0!O=fW~HW>h,{?p2 pHq/i]$I:t _}2 ~wh7pŀCӣ$I:tO>{Cˀ* 8b!/G &Ik^~H?yO,m^TaA)TF&Hs8$i`s~$TH =4;΀ 8b!{_IS^~H﮸O`4/|meAd1b+>_ }[oI3X^={o /0 [WG&Lkw8$k_T` =4 8€,Rp+IG)&LC.Α$I>ҽC̀* 8b!ǢsS#IU_>R7᷇UpŀC}E)&Mg2Α$IKu/`>|pPY 8|.u~H} q+ 70 T{rLLj:>Α$i[qL*JY,܁7UpŀCGE9&Pw$I\_>{Cπ* 8b!գG/{0ͮx~#IҴֽc}9,]~hpPY 8z8턔z/ jmxS#IT6T6>oœ 8€,R}%K0z]~H4>п A4 8€,R}*L u$Iz}"RYo ?0 T>K0\~H4M5 S|fw dAd1jRz608U$ISRqDXo&0 T]ePu$IV@^o$i N@# 8€R 8z73LHԸᛣF&ѼgAb!ջ_>!IRGQp υI4pPpH0!z?#IRyQo XI4pPpH5ojQ*6>4#IRC5)YTaA)R]uh&D}$IjBΎ ND UpPT~4T"ԙZ$xklFW. IDATdAb!տl6)y&D$IsΉq ha2 J1Q~%[SgfIXwDj&Z 8€R 8f4>_Ičo?74P0ApPpHͨ0A)[uH:;]?vvD UpPԐb' 3$Fo?/3PsVMppPpHit' E|^H:;=?;-\TaA)Rs'0 V$IC]GXSs'Z 8€R 83S0IݔzI;HG@_>fAb!5ߌ>]uhH>#e_hA3 J1?>l(Rw7$Ihq ha3 J1Uˣ0.NEo!IlIE@d,̀* 8(ŀCj^O0_H;Hlx?~)7π* 8(ŀCj^ VE`ܕ:˷  IuxuJa_fFNQЀ 8(ŀCj^L_  Iwr]-|TaA)R[i*z0$IXwDj_h3 J1_ato!I歩)@ :3e{E UpP<|G68?ib2 J1Yrq &T~e3rH,~e)g/ (&0w]}B ?!IFxjw{+ɀ* 8(ŀCjn3}B VtNI4@m7b2 J1[w_>!]ypH-*ko X~UoeAb!5EXw&YQށoIT;EDjnx>oeAb!5ѷ>#>un.$i6uՔ@ 8R 8f;g O"IJ78((PwEĿ]UpPmѧt,e|H NtOP{ (60?6Ie,G| 0pb3 J1_Ec?6$i~umgGbW_UpP힓x}NR=[HjpdMRbb3 J1ֳ '$Iz{6Q/%;/ (>0 NL9>$q-<嫯1 4ogAb!lT'`F=^F$^sHazogAb!|5'GF>$|[J8#$lo~(>0= ^}RwԇH$e=;431GTaA)R{~ףO cVl燿$Iâ$ 48_1GTaA)R*}VcSSgjQ;I4XB1-zdAb!{GIɫf~w=@YEYI{FȀ* 8(ŀCjWC}Vo +I&l)_scO@7Q}2 J1ZR]}Z'Y$M-Jh)Ө6pPpHktQѧ 1$Ijӿ#h޿Q}2 J1W>-OSw$I{[R Vt5OTaA)RVtJAyxBSr7$}e;l*6Q4躣5WTaA)R;*o&IRZi~^8'~2mZeAb!I}^%o&IR{^k6%_Q2 J1Y3c<ywI'~*ׇmT 8€R 86ΚiIz= Gw ߨ~pPpHmpO $u>#$Ij^ݽ~9u?FqT 8€R 8)ExZ v;IUS-?)Sgf/0\}f^Q1v$5[oGZfݯſsT 8€R 8v78_ vg>D$I5oj̿\k*ZfAb!>3xޔ7$M-9W)[UpPF6YyJT??W_Q}3 J1%ѧՇ$IwԇRG?2fAb!^>5 Nw$}oJ~&z-ͣfAb!MF @98{;J[w4FTZK%{T 8€R 8hxvaf[JπhO#F5ݣzgAb!MF}}nfI^$-l}~5݇ ?pPpHS-'`V57l OILņ?~IP)E;0irSβ-T-XwG`B^Q3 J1&w4cRgjqJ4?e^F&@TaA)5(}v*^{J4/F?f =- ?0iM78kiJ4we,0Ewm,$-gAb!MV+̉$UǫR+]{T[HȀ* 8(ŀCO@uE_$iuz?OCjFTaA)5l07q$|~3C?II5lo"5#0i0wƃ;wXw{R1`&Rs2 J1&ר'̝Q?`;KÙ R.Rs2 J1&{D5ޡ gI7z_)o#5'0i20OZhjQ4mĿԨ 8€R 8 mjQ*}$իHk#S>FR2 J1&;F a!I(i|?#$5+0ir0]#I +R{E;Iˀ* 8(ŀC57D!R$i[謉)83VR2 J1&ˢǩ_$iRɔ{r{Iˀ* 8(ŀC{& ̿HS?Vd4<n3pPpHW_}X~{IRVnƷ}MjfTaA)g|1,ᅻԢ7$oJ;o'530Iٮ0׊L5Ga'~* I .覙_)&_4̢O7@)Ew_JpPpHa;Ώ>I! ~o IR]S=\SjvTaA)~OG$8,7$cu4`J΀* 8(ŀCvx~J(,)48eT)Ii<}3VjtTaA)~-gD%pËH%$)lEcFR3 J1g 7m>HE}R3 J1e+~zR~u)o4IZ_7}zL}vEITaA)~uD&([Z_pSËvgpPpHz 4x'M;MlՋD_YyM-#0Ikf<}jgtŁl$Umjqw诏>X{[L-wpPpHz}j)5Im}~5w]}N]jOTaA)('7_7$jipҔƃ3 0{.ߙPpHz57F(*4`_?nbї`A|'veAb!P{= I5}?%T,o0+0IOVR*3P{E?S7IQ˷KO$3\gAb!~^huGl焿$MpSSkG>!{&S2 J1TODhbw;q&ۓwU582/0IOUݳSvO@E]Vl{*?6+zqLˀ* 8(ŀCC koMvixٗS@-LJ7ڙUpPwE**4dmwvm4i3l6o620Iҽ@+uYRo|6}jk|I660ISwߌ>WQMS>:K6 I߸qSauQpPpH}Z%_sCw3gF^ SdβqjmTaA)6O@E]wtvزf*/@ /#-vgAb!icv}̿`` :i:˶IZزU/IËvK`C%h>өpPpH*@H?:S~FWx}z+wڟUpP2M_wS$}ޚ7o8ڟUpPR-2GOrfwj-*O8 92lzj}TaA)6WOd)4q%+eixTdE_֙ߓ{ 8€R 8$Od*_oBIO;it)Z&"0I)0q]sDw*[MT5J^}d7&#0IipE_Jm4F01dAb!i6e+$@ `L- +JP%ip?bm&Rw_ jr2 J14F9>{.O~$un^Vb?S*?+&+0I}xņipҔ&(5%!NK`CmRJ?NDeAb!i-$>cclqKe[#Z6{c^s*'1&.0IUva޺4|uI)^;F`MoNMlTaA)o>g̳9+GSfY?[6?"̣jb3 J14W&G4|;l&2̇g+2=&FG5pPpH}>?F9>S =e|柫ѕ[Q υM5pPpHKiԋ>k+:7$LM يߩjNٮۢQݔm3oUMvTaA)5G5dK[Lӿ)ulfU=ʶ}V48KiS=O+54E]%0IsYF5l%wSgoX-@K6Iݽ^Y^唯&|O# YM|TaA)OM1=RLEoZUhfﯥ2 /giE@^ 8ȀR 8$u>}h6o>= YzG}(eQGMvzQ48sitŁ)Fh JpPpH?@i|3~ylKߙ'm}{4 ̗HldAEb!i>]~@y`ޛƷ=3*[ z?uwYIq#U/I>_9)za7L{ǿ̀* 8(ŀC|G7&xgѕRށ5It>#ͼe>+u;'itai|93ƃctzm;ZaTaA)ˢO<&_ƷFW{^* N =@5)dZivx~wR']߆7)Tߠ@o?/-XTaA)")gKWͧmOËLw[cMw3w=*s\ṙ57⑻R1 0~4pPpHo3@CكlҏeAb!i>`c !pPpHϦgx*S@壔OfAb!iTF=[z 8€R 8$wc?}o -=QTaA)潥HEs@M([$pPpHZ}Y@ IDAT[z 8€R 8$-Dٮ/OȣO5S#ul[z 8€R 8$-TN>yχ*0I Uߏ>yH4e=;TpPpHZ[51hodAb!i!@ÿ[KOUpP,[u*OFZ7kic2 J1 /'wo6&0I ]wWT W660Io:-GÿSKUpPz?XO,,;pPpH ijQ}X`9T"0IQ NBf)[R 8€R 8$EmT>,efAb!)EEAB>N_]Z*UpPȲ]~~@=24 8€R 8$E7ѧT¿GKɀ* 8(ŀCRt} G!_hipPpHCk!{[¿CK̀* 8(ŀCRs<zV7hJTaA)j-S=}cC ZUpP4<vgjTaA)RKSGg9;CߞpPpHS뎎>́| 38T50IuS*@E?Y 8€R 8$խߊ>TP<>eL7ei>2 J1TF}*x óK+0IuǫR*s (zRsÿ%KUpP&4s ߐ̀* 8(ŀCRs O(Sbo|fAb!)0dco|gAb!) *6N[;;0IijQn`o8ߍȀ* 8(ŀCR 0GK[3"0IjXwh&{@pPpHjZ-1GK UpPƵl?K UpP&6?EO?|K,,pPpHjd>35'`gAb! R C7ΒMÿ K UpPTtFQꟆ"2 J1g/>wuL-&,EdAb!e='GO)@yw`)*0IMoxѧ?5;UpP|^*)@yRdTaA)])@댮<8UpP6” ^v~i_):0Imix'5 +!0Im)[F xE`ʶ{vw_pPpHjS>78{dAb!MM>4FV*ޖ:6+%0Imktաѧ_Hw^NpPpHj[=^R>>ԙZWSTaA)â+@~g]npPpHjc.?x}bc|Iv:fAb! 8uzmw]pPpHjkN?0>7oR]3 J1}fmIN/ +50Im.[M*FZoR3 J1笈>T5umWsTaA)^ݳS}8N? +=0I/F[ZoR2 J14mTl?C>Jݽ_Vj@TaA)&)>0hoRS2 J141-<}vBRsJ ɀ* 8(ŀC$?g TOUpPj&){ѧ D~U3IÿJ ʀ* 8(ŀCҤ?cѧ`EoR2 J14qM-Nk/]sxYpPpHzG}(,b!e^mVjbTaA)&KO0oRS3 J14}o w÷βÿJM̀* 8(ŀC$73 0zG~XpPpHjJ8̋-gUpPIot!ѧ`ǫÿJMπ* 8(ŀCҤzqJN9SóڐUpP$T]93C7β-¿JmȀ* 8(ŀC~*e>+VGd9;]dAb!I?hpDdFUjSTaA)-$|',Z]^UjQTaA)_ 0k?Uj[TaA)Ʒ~+4}iL-*-0Izl}ߐRGgRwׇ_ژUpP$=ѵGFg6OwÿJmwۣ`Y'Iu,9>OjtWÿJmw` GOFi'TקlՋÿJmwEq 8(%5GOjRMѧq'}:4?4d>IR0&ԙZT?4d_GOjԢ4s akN '`=GO^wצO6@,4I b{̀R'IR^w&\Y$5`?4GOPsSY}IR+TFW3ࠔ~$)OT&HIl`28kiѓ48w_} !umT.>4 .+IR攊"|S{QiR9 `2'IMktas&*MlSS fA)[Ό?|԰_\wSgDI-[3@pP$5i}6+=-BIwۢ/ gA9_}$q-4_}cwPigѧ3࠴N/ ?~z+-?Ye7Pi4p=$5w}6ǩÿ}J4@pPZ~$e;4a}^*{EI 8('IMnxS@.-Ie6(IMnXw{9S4SwD_Z7JRGh;_pY 8(oQژߛg| &%m\]D Zƀz|$8JRV>/5gX ţl6&%=}/7i3 8lxaRZ}g~r7IIuigIIjkO><$[/A p0'0HJRb!d|9do6nק0/ 8ë?|6ذ:e;0opFZʀ9Mm~,%M-N;/>\*;]%*;׃2`c)ImǫRv=0Gg/ (\}:h1$7)s`|٩do5Ap0w;$i~T)E%*) Bp0Bᔤ5)z'"OCQR'm 8SnNjp<% %ͮ|5'3`uzgַdӔsyJ~^,$z{ ap0~@%i)gEgMV85)g ` RgQIg-);}%ͮ^M(/ y18C*IT,ۻgAE[-"XeZSZ2ESK]tpԩt֎S% Y0 "(2 RD0H  F!r!ْ{}9k'<<%q#ԄfDKT'*oabe%Y/u̘UOT:W}.{S%yݛ=J̘rǯcjCUjijG?hzkPVtiB8`F.h`T,Ө;G?>34=J̨r!IXG?^o]U,=4'Ԍf\OXIS{P[僷Gc޾{BIӫwr+S>d%.ǿ$S5bwWWDB 9`V/A+Iud~!}7(i_=Q)̊rC15oa+IufGϥ%MGfjWTqDȆc}4w,{Pc8=v^?x%FVyG73ܼ.OJ~+?=R9̪IT/0hWqX|PTG 5瀃Y<Xjo%{xh~wO@FT̾;bjb!,Iu?43}'i0}OH]p}$խe0/ĜW,x~T;6f9:E|'$jsFZݻ~᛾4.+;8Hӻژ,IuXt`T;7e?0bk4OҸZֈ-;8HպYV댷E'FK3>}'i0rgOpj/IВTHi_׳ {1u̜!-Ijr?pS#{;=I}G @ε:IXGQmEhgC|dc4(}KR=' 4uEcbNNҀO7\=Zs򦘚;KR[~`֕nƼwtĜ]=Z`8`un>)KRjN# YSx %$ G 6 IT~4{:SwrW-Gp02Z?}KRfVsޕ4Z7eO#8 V4W>%V}n~`fTU/DNj|g9`dDq+$թI3 \34+H0p0RG6FHRj}v5ޚ{7IQ5g6@Teј;}&i05OymTဃ߲>^ HRm;n0-nƼmRsj<=Z``p0? T%/_g#X|PM`j۲G FZ>Cf֪DvK5PK߯IL٣#=K IK+?=\7{5IEZٓfB}C^`HR]q~Fw$ w-gO18FqkICrW'WUѾ4Ihr3c,Es[IA_UOsDM_=R`V8`:Q$ՠYqu ޚ3Iӯ8(7ݖ=R`8`=j] g_wu(ဃZ*wn(IҸֻmU`Uoykwa7?kqpP_U5+bj$]>;Ϟh4O;<&i+dJ8CwFץ?V4nr}cqmF댷$fs}Q>uxLg?^4F5QwfOyEN{Iڽ'*1{s4#1IZ__DUfxF]ُJwIz DFxD?j4.u(h_rtK3lYFx壛NƤggvFTϦ$=Z_{{e I8i7ŊM$i䛻O){0b?ے5O;<^=2`9g*?~4jS ;-IO]7Fe~LVtn\E?45OzeT!јϒ5>w_pv#:?<1_8J(:"ziYxCZ+7`8rXJҨվ#~8ސc ek8`Ttn>)e?4Bu="xCWQM==p e4_{G*I#Ĝ]=ΈijwVRݛO`ڧ(,s3h}oC+I}6|mĜh<"Us{Hr3l=5+Wb ͽ#7'::GfWFOGc$ [,ƖQ ,r!rGFDccd(m=8$!yQu4wY7YXvX/9:z?VT]Q,{y#.IٵV;eOgf i;1::z)0bpo/:,ƼzIJ}'"*{$0zkq! XWGGѿZp # ^'z!:/Dc YsD`zkWGcrݓ4Jok#9QRUrwt׬ I3UǧgO^(HlQ,;lW寏3Kݛ+\;#E?]`9QWUQn?zw]D낏c*Inr]1?u IENDB`PNG  IHDR K pHYs{Rk IDATxOgARPHA`aBPbpa a0*bL 3Ni,TXP$%T d)Z )Ri9{=fμ~y~缿}Kp]2<}@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@  @@ ͷacS[~w,5cqx%fw>qlcy˦ߍyS\}MϾ{x#O<:۱ɱ? ny͋;_}p>cL#33 ~qnw߸}lxt㈧@pm_ޙ67r.׾tlw=l󒱺c}cnf? G{?v cqf6u;q#&?pK쪟;ƱCSLӇ7΍2S _\bݙ]_5߻ֱ]=1uQ\`'o;cqfv׍㳏+o=3_8̎N]6VwX/f?.: aog?ɱcqn׏fZw겱{gnc Ap?[7s7f=˧ߩ1ڻfn|ُ43l|l~X_"3;6۽cl708gG0pffԷv燳g9g7??VX|/88}Sycqecuͷ8!x:'C0c}ӲyNgffO{?w16mǚaػCcy/M"TlqX\wnffu/{cx;Ob3_0ofw'5nϨ}t,N\:;}Xugsjk7go}yށM33ՎrcXo֋ßX\l3;c5djřYΆ{;uG{_X\?fؕ_ .'gff/3c;ßuG|bw̿33|ُ#Gkn{vyc8oGgffݝxXw;z1v|KP3kOß}}[v3 "ʕ+(*6ՋkA~zw3-mRI#ɄTRH!4@:4ˤ6֮k树d9{)Sf'<*aY$i+{a_1E5z`pyQ~濤BJևf_ _Տ;N4{){/&kxtNٷ%4y߭ߎ~9N4-4_D5n`pӗx_;ة;OF{?Ó$5~<}%1 _4IS[Q}AVhh^IҨYS>_FS4b`p__}W?qwH$9{!&A/,bfa/)nVQ+L7FI-wN*.Tk}ߒ$i+{aT\}3(=?OԬڇ'i5 뎞_I ˾Īnr7?$5ꞋcM@ՏbfA/E1W=xkt/I}7GLYy(3E?̭IY焿tbZL@uףy_I_S0wI?$5r4 GyвGuW/{0:'E9$uT_nzs$[Fuٗ=nU?:7(Ijl/cİI3Q 5EKaKjH77Ͼ@# -ʝ~8P:8$?dI i&1K4ˣXUy$u^LX>~WDWRCY+̾QwL?7$5;ߎI0 #7G6?TI ifA//|~v(IjtwcP=x};")A/'[$)51vz(V2(9/X}I]G#J]_wG돦$5ٟξϥGw'J]ޓ-On?CԜz~,dyS$uafkrmXSٗ?`=eEIR~b܌d, UY F6|IͨQ?~gIR+h@՟zKjF/׌R>pu˷J?$5ѿf,tOofyQ}/s@'D10R^7M@ӿђMf|_[N)Ijt}+szFo#i4,Uq?$5Ή9 N%+/y$6` :^3KIR_t-to: IDATf;c^`h٥$;/g蟿Sy$-*Go%M}uS{܇5%Iͭs;e`X~+^͓4ݕ;:'0hs盒ֿZ|#4I]݋bq \zesJYbXqn3 ҿi%EuW4KXEy$uO XQo)nfA 9|N/]@3 >,Sg^= ݳ>4/X1-zC$6۽Uy=W,os竮JY@MH:G/bX% iuh砒Uc$Mo+r .[JWOp>oNH{dsrx6bfA$a-4(i-iz*W2' |<.ۤJMc{wg`IӲ70*Fd3UIR#, Q_)ifa nx]˞~*IϞ1L$M~|tCfj1VI=~`X<-ӿ8I]݋b76t+ݓ&U4-2csлh/Ldxn=mcfi2F{柿J@׶_ɮ7fKwG`%I[{n`p_ɮ{G7v[-F1 ,VԚچ<7 ?H:jD՟`ldy$5os+XU#i2+wGh|cAt|G$56z_ɬ1|膹^}QYIRk*>x-t@!iYͧ 0[ObfA9$)޹K6|`]Ų&E 01zg~"VԚyH'|dgeRk%Ik>w_ɪoǸ 0Q'rǗJZSU7`WDt/ir*WlSӨ 0y[NbfA$55u_|j 4A-,Λ`b3\IRLMK6Z/\Կt&WՏʷJZSSuۙP-i2~s4xDKs%Iw'}z,i2j3|opqg<[şIƿrQ?u|S{_JZ¨Gm}{_nQ}(a+OJbx:, Ql+i\a2|(n~+IjMt> ժ_{GF5L%{JZ]_{ޥPI[{#Qөs|%I:Q 4;,' 0(w~uٯ$5 ]^"%a3 QξS(o,IIlpϼ0|(i<럷è^F}π%IwǞy`_sg? yP[ς%I_~9K_Ǣn?6qQ KZU+y}勵@Ic-cQϹԿlsaIRLZǼO/.IW14ڏd>$&_ 5Q,Lqƣ6ihx$L?#$&Շ}@u/Lx"ݬѪΌbfAY$5@/LR~/Z"w?KZQ|@O0I,, Yߐn,Iq~@ $;g&k{ &%KZc]/LR^1X~;KZM9@0I);"ի2gX~z8\ȒXW~[Gky*IJjfaT:r'Kb\Fz$)޹SWϓ%Iͧ Is~0::7\YW-տ$i;"իRUw.w|Y$5v/Ew$i,궳RU_ug̒_]=/HꝻ8u@`uP9$5VVĿLAFSwF  Wwrפ7KZcSK}>/HWWJLxgG1 YV_JA湙QvV@ ~=Kb{OZoLAFL:~,YJsػ?"I5̽ί(IR|@k_\>zk wgђVj~B/H4y+w{&9=OZ/IA,u`4|$5}*o$mk=S';Ϧ%I:b/Hdwi h3jIR. 4w/%u GuyQ,L?$FZ4Eu{wD=L0?UKZ#4+z̓%zE.ZYikfAT<#u`tCK6O?$, ҄NPtsoIRkβ MR7LA7{T$)" ;wI:/gFg@ڟ}KDON>~.IjmtIh1|UߊrW䟇Kbc M@ V~L5O?$6* Ҙ^a: Cߕ~..Ijmpqn1|a樟+[埏KbC qKLhyۧKZiLz:@U/{m~N.IjwqlV1|:?咤X,HctrIRk YCQשCkrKZiZUԏߑ:__ٹ$)5 տtAK=_H??$) ҘvZ;H8>x]7M?G$3 8t>rSϤw%I\YƠnl(w&<]z,Hɵو up23uIRY ex>puso埭K♲ %A XY$ %kۈA7uP;_%I)śS4uwu;:]ߛ)YL`c =2],H## 6J]G_I?s$+ (Ygd0#%埽K? I:\wIR,H#\ʨۏb0SQ3xIRk6 ҈|! C%I,H#sS/7uoO?$,H]݋~ pUQ,L?ױ oK`'y$5iZGQS.zCQnyIjr |cԿ`E$5i~my#WOKR,HP{tSg,Ptr9$ 4,ꞋR+9=yYީK Xi$ 4+DPw%hX9lp푩x;<^e@:jD]S0N}6^e@l>yFwVMYW-u~qUzZ9$ &ޚ YJ?ϗY6ꦓR&wk?FXi$Si#Z<M?חbʳ mh˞wK0)({Q$-,HXkS%4vH?ߗb m@=^1I0q(w{m9$Sin==u>I5s~I*4 z=S#huޖ~/If@Z=/'N`Uw_/I/ z;wI@Ӣs寧KR1eYֱrL᣷DdI*( :6AMK~/Ie@ZbD]A0m({asI*$ s50_:Ꝼ$Y$-,HQ䏦>0ޚ(W2y$SY*{QkL|`//$SY_G0D{mӟ HR1Y^?QSh'?b³ =Cխ:4ߑ|@ 0Ѩ(${[Y 5u; $idf@z}tC3 ӟHR1YrF]<:@ugTL`ԁ+[?7b² {.DԁީKv Ińe@:.TLPEh0u[O?Cb -jEuWR՝'e$5I^gֿ`g TLHfSY :Qg hF=/Sg XLA ۲G} ~x}IZ4YPcYXwkO IŘg@釣>:aXE{mӟ1HR1YP#_XM Ig@e~;u@6@]GoI IŘf@kpRg`U7A1U3%b8HL>ӟ9HR1YP\ԁx7H If@ϛ#a@̍AA1Su)0w/H IŘe@}":uV_O!Ie@{=?bsogTI4 z̟ὗ?bLsgTA4,צ.Ԛ:l97ӟMHRMg3 b0:=?EYT=S `:F3 I*M0.^H.AÇ} D]4uoLʲHR1YDTvV$跣^*f W]]E3bpq1_o/X1[>>ݓ?^TG{.WGQߊ0/H"If@c_{7:\I7^` .Ό5EG #ryS;:eKoᇢ}ۢs{{DE#>|cDzbopŁ7~9Ts/g>S?6PDb(fEjK5:;'MDuQ?u_OfEsu/}O W{I ;juĿArx?-*ڟ}Kt_;1wiݧ0z݈@m|4YzFtgߢ>?CQ.A4rF>9UW3_9Ʒ%G>L}>\.w䟤lw 8鯢~12K1(w~ IDATU/I6. ۺ_{=LoE1+{mM}Rީk;`1Emk" XGun FOEwEz/G UWF T[uq&)&= :3&neU735:jۿ8}Wn_>xmD=U;s$eM'`Twi/3q6}ft]"~4C^*7ҭ(-&,hj F(n>,?={Wh̟%iцe@cW}Ro0r"ώ޹KsoFd\*o#kdW㒴hòQwJQzzhsQ,$}[D^P wޙ?KҢƪީzCR?~G X9_ُ_gk[4V !s.uGEDgmi^Zit{w :0]:{m?sKҢƦAz/v>gJ:{ƖFڲE?"U?Gh+??gKҢƦǤ` QqnN(w]L-KWFÇW ߎrN%X,h,ZQSNzE n86}(^>KKw\y4sԒTG4]zgoGu)⇣\Y^ݓ?UWfuVGtyZu[iOݗz㡿4o{k X9 .̞%X,(Hq|Q,{^,M{劭g^@~xFUWΒTc^u97nٷ&/I|,5%E?=Xq9WfIZYPj~jF~_"{>}.u|ooEIuI鳲$ֿd6RwD{gaI^{7#~"U.}N9=?kao֫r%{F :ٗn\=KRYPZݓ:F toED{7Ͼ6r跳//4T]/N%x,(}ިN]E?b3\_ERNXgRj4S_E{ߟNu%rmbpU? @ԏMaI*! Ji`#իWE%QWRNn+#U% s$ϐ[~+ls}.${ͧd_hfϿTJ+!{.ξb09}d@#ԛ2rMe%MH3 {Fٗ0T^IZYH+wzzS`2O>/Nc%MhK93v% )SDKg^IZYHmy 77{_DdU,W7)O鳮$ߓQ?yO'4śϮ!Gnξ0%>#{Ε;_6Ç/~8śϬВͣw#zE)oϸ?UxbM2|Q,HU%5rEu˩ٗB&\3g[I*# I劭#~MƢ u=k\+Iſg@#w'R䫟+'|[K=/1/L%{ϴYH>tCE4z`Ć\2ʝ^>J҆XkgbfA+I oSoNuMs$ջ\»N:VRXШ~^ÇoM?%i>j|w9 ;:}vgI0־SĿbfa)IڲE"aqU\u*u,h*{QDz` ѿd(q)IsȯG0cwMY%5Wݓ:& :/9}ޔʝ^7Ⱦ0'b&3f@Vu7Yڿx~Q,H5%);U? yUR45 ~,So_K_>gJҸ99URsyw΢ԛ+sc5gKI_ɾd0.:{>}Njd4/ 9 F;S>P֣ VϧZ?zS`TnM+%ik-1|K9(n>Jj5. _; {܇II^mgf_H=OgSIe@s¨WJ[ίʟ'%iZZ۾WTR4- :zSwM#%iZ~} I{7ϤZ+SogD63$M{}:̾Vk񦳟 x;OIq/soX]~+[ϣZaz`>GgGIjdK6d ?Jd@sCRo< z,b&s$51fgPId@sӒͣn?z;:#f$=]{/D]>}`D{!}jD4'u'?%$kӯnV#9ip7N[[3%i*w~U :<[O-OI6[F}* >rsyS(IZo-_ξ}0Ϻq))= _7L>Hʞ%IMbpٷQuWNI1YFseH6Dﴏφw֧":ػx;Aζ:ztPi{ڢX/jOڣm=jj{y!BP Q d 8@4  f7Wv[kz!=kg'.|Fj搟˹ }XJ$5ჷI?[t9Nj$IvseY/zFj%Ib+6^[>'|.`\~H$igso7O |gngAF?$IY}<Ź{޻s먗χiiu>t%IVqUu@m3|tSH$ :yx}}k@sFgCÒ$IMjpi㿂)| LؗჷG?$IjS]y~y;i3@E)P$IjLe9;?fQ/o~:I$Ur\l\9sްrN3jIFK>0? 觔$IҌnŦ5_bnn %)#w>%I }LÞ#q%Iߠ;~֒ܽ?4:+|^HA'>Y.IT?el,ܽCdNNg*T!+>:H$ձG4:+|ZG,acM$ɕe>qK?ۧfNcNC $IjUY>Pc_G~IWnݜ\{Wk:3@jL۶t.$IRGg<uG$I =Mkr]1wg<dLW$IiX2|ڟ񟾓$Im yeWKitvȓ8`ڶ=%I=v߶+G?$IR+<|CIo>08`Z_;,t $ItEo'(g:{_+Ip[6ުy>08`Z/tF$I7~g<觢$IÕ[7oʝe3#{:$I4,r? _8(IvSe\yu\sm#IToYdtvzASR$hMkƏ+99Ί-3Tl$t$I\0w/s'.x,;(E,LBIջf4|h ܺ9)IR*[=;ߑ[G |&`V07O$IT'o#K$z)Źbnn/?#I |?t>$IJ vTw\$Ua[6幷jW`q0%I4u^ߘ<-|~ջ_$Uss;)E @rd_J$ 7ߘ[<+|v]5XǪ$I3W9:mHp7:TI$ͭc~1|nbl\}]U؊~n!.ss{ɜFg?`8੍e:gI$}үmxA>|GcVӰ-`[5/wŸvR{C.I]ϝ3>>u<$iWnݜ+soW~@snԻ򓡃$IҌ,sw_k'uAASWl?~5]G8 i/pS*&t8$I?2|Vw?G?v%I^Eם+96Y )Eȹ$IfbW`y Yypя_IܰsoռYvPN nO?I$=sj7yVǰ$[7b[=U|49ЁN$i& ¶g`y4q,Ij@e\lZkyέ^T1w\K$E,G:gQ0,ISEם+99@8<ɶ\s$IL>LпDz$<<[^z`NcO@!0:;~L>Ws֒<ܲ!/݋?K挿!&~ur.Q$i&]d/ q-Iӕ<|]ilg02)LΓ$I3esToISEwտoɭCFv~fSBLI[ӢgeP OJWݚMkr]17usȻ~fmC$IRhnn _ιߎ~K&k8-ҽCdNNß!q_:J$E׻3TQ~KMypj^,;(EV#{u/СT$)s>@U nR\Y\l\{r笃s?P7)$IROXi<|Ǻ$պ5w__?*wyWn_:J$EYY _ϹE?% yeC_>*s[G,t$IjY w?F?%o&ʝe_Jr@V$)֡VFgb%яyIѕOܿϝ3ߖ[uЁW$iW㋶9 u s觽$͈ش&.ss{ɜH9 9t$I$|:vhNp[6幷j^n/=0MF@õ}N"t.$Iڛܕ!?>@y㠤7|n %IV ?@-xZQ@+nƕ_[]IIka[$ioUqEM>5ԖYmmfw/ z0 ֻc$I^3|^@R+y_8wW%sr elp˹3$Iިs]qۥѣ:47 'f V>vO.I+In خur~$zDTʭsqW֜girPc~!th$IuO9-xZ#T3j$I{ [M iVnݜ+soW~@hlߜ$I{~; \qE i7~{wn1@?$Idk[{E.[I;R-`ݩbnn/3~qá$ITeڒ[>;|##I*+/ϽUrgA9-/#r@O I^Y ؉_pcmߺ9W9:_#;@ zk I=iڟ9[ԨΣܿ9uKÿ04Lg<,B?\H$s IDAT/|v^OER}+yeC;5wW%sr@t>~֐$I =Z.X$ID>g}o\G R[7b[=;g[??2#a4C?H$K>Y=^H35o(f$IT? ݧussCO7'6YF4H~f$I zzA;i Y1$I?>c{Fqۥѣb[=;g[G #Az׌~$Iڝݓg,`hʜC㹸ku_d'u/`4H~ؑ$Iڝ.x|Y+?=rH;p[6o/=Я M|?$IPn <-9zo˃_̽>ۧF8haP"IT. w44#*ޗ+soXupn4D%$In߲lެn׏sޕ[Ǿ<ip~G$IR ػZG$Ǣյ lȃsoռ^z`N@ bp$IvKe'6|W)zQM*n*+?;i3~@M4$IvGmU@Oß=bGsqչz,w:8|Qe8h}s.z$IvG?[a:y@SKش&.ss{ɜFg9ho%I;̈́<ܲ!/ϽUl9hW*$IU@1ѣr͹ظrxkNw L$ʕO4Uл`eڒ.ͽ rg/;"4@C?I$jkT 2o>x[Q/bӚ`鮘KO09Y<9N$i_>W3J=hGe{s_i> Ոku$IZTTqEI*+n97.9M9-zfH5\K9g*`fj*W|eQsu~@j 5׻C?I$JÇ;`I4zdi^E?7ߐkd jnpә%Ivury4zlo"lȃsoռYvPN <%57w]gDIέß>O3_ODO.ܺ9W?y}isPgs$I;)=TP.n<]4$l@juC?DJ$J>O=]̮r]17itV7`drPc(s$IV>r4ÊcfF"lȃsoռYv[#{]Ϛ$I;[ ianZ͹ظ2VYFB8/~$IکEnY Mg:WWuuK@ )$Iδm=G:sr-*_]17itv102c99ۡQ%IvJ_db#w幷j^,;(Y#ڟ$I;J[n`W{^.[\=yaE]֡sF*@Muǡb%Iv Q@=OyTvŝW˝ߙ[G,%5ջӡl%Ivo w{ l9㿪1M7?J$B`9 3#wj^,;ȯ3r$5U{$Ivq <|nWʭsqe˝έ#^`@Mwۇ[IQ M\lZ3~]17U45:ݸ$InitVSqՓ#An0*%s 5$IT#g('ZIzA;in+"hu/IsO~} [oͭÞ !jB$I;R'Tjh%$IҎ @54%$IҎO%$It+i3sP3^ė$Iڑ>?pP33~?t/I#u@ 5ӻC$InͭC>?pP3oǗ$In>;qP3. ]K$MުR8 ]K$M9@5Sv]K$M{&T3ju C$Imp@5o.%I[>;qP#ȗ$IVe[G4|vH5FzW}:t/I4R 9SC$Iө&TCje$It, Ր>|g2_$iʆEn ՐXOE?t/I4UM@M{e2_$i: Ք|wC$Iө{MD]K$Mֱ/RM95C$ISU>)|fH5&N ]K$M{gLDq }Ipj@M 9t/I4Uo R9XB_$iҊ^NcL@g%Ijx ՜hЅ$IT {Jj@ t|[B_$i(|fH5}0t/I4UL@څ }II+z9-/|fH57~!t/I4Yn R8ΫB$I5y 5n~R_$iz+?>/pPeХ$Idu>_%n }Ij `~9q ]K$MVz(|^H ڧvR_$iM_RC89ԗ$IS%*#K}I]y 5_(t/I4Y3>/pPquB$I:@jWl\ԗ$IDN%*nxwC$I5w]@ŕ$t/I4Q[ R8Y9ž$ID?2~^*u C$Iսo% *?.%I&s% *ԗ$I R8y]K$MX9i~@j[н$ID$|VH z.%I&ش&|VH kO ]K$M`g%0*lp9}I_(|VH Š; ]K$MTJaTB$IYY 5 +'t/I4Q>+qPa]K$MT먗JaTTg.%I&lX`y 5jн$IDO>+rPQzb_$i>+rPQ3ؗ$I_ R9 ]K$Mg%@*{߅.%I&g%@*wէC$Iջc@j տž$IDuY 5|s}I{@j 5ž$ID1|VH /]K$MTWJT𞵡}IjY 5>ž$ISVs>+rPQBw$IOU~$|NH rܗ$IzG RC9}C$I5|c0TP먗.%I&Y 5 jž$ID 6RC97.%I&jnY@uN{sb_$ik RC9w.%I&z,|VH ;t/I4Q+9|VH _ž$ID.h@.Xb_$i_Y 5 ]/}IY 5 ž$IDu@j( }I@j(4ž$IDuN{S@ n97t/I4Qo RC9KC$I>@j(T}]b_$iZǽ"|VH ?Nb_$iZG8|VH ?%t/I4QC>+rPAÇ~ؗ$IpY 5 *'t/I4Qi@j(TB$IFgJTPؗ$I9 :'ž$IS6,$&8١{}I +z@uT̢g%I&ߎZZ??t/I4QeY :uχ.%I&<>+4Y@ub_$i@uTK{ɜž$IDY :}B$IU>qd>B$IU>~od9͡}I*Id9-}I*>+4Y@t|[b_$iʴ%|Vhj|C$IU Z:g3t/I4QeY :{λB$IUZ't/I4avdҽ}{}I +z@uTKK$MذZ}0t/I4Yѳ@uTK ]K$MVZO@.hR_$iؾ@j(ӻK}IJ>/rP1Х$Id}v@DR_$iZ=/|^H bzWsR_$iZG$|^H bH\WKTLO.%I&}k%P*$IɵO~}@8$I3>/rP1+?ԗ$Io RC9$i&KTI4@j(ӻӡK}I^y 5q Ifr݋g@Х$Id.X@8$I3ޕ RC9@$z%P*wB$Iտy 5]Х$IdyB@.xR_$i떅KTLﲏ.%I&kp˹@j([Х$Id RC9%ԗ$IbӚy 5^?C$I5{@j(_.%I&|y 5Х$Id%P*{B$IV%P*{{Cw$IS=#|fH b;t/I4U^>3rP1sЗ$I R9 ]K$MU{3@j .%I>3rP1/t/I4U/q@tN{SB_$i+LTL ]K$MUҿR9IЗ$IU>3rP1_З$Icg&@*uC$IS53@j :B$ISU 5iЅ$IT?>|fH bZ>'t/I4U-g&@f }I*?~f<ftVB_$iʊ^0yTP.;}Ij 5 *{O.%Iu+g&0*l=З$IoR8{B$IS93@j4|Ѕ$ITuO@ )t/I4UR8 ]K$MU3@jTyuB_$iL@/ ]K$M` 5 rnB_$i. R8_]K$MoLaTP'.%I| 5 9&t/I4eV@]ϗ$INC>7qPA+?̗$IN 5 ꭚ̗$INe>7qPA݋>̗$INs$|nH Y2_$i:u/ 5 ,G2_$i:VMATP7.%IS;K& *}ү.%I_R8]K$MR8֑/ ]K$MwMATC$Iөn7E?t/I4ҢgM!TT~$t/I4Zǽ2|nH ~̗$INSs@E zk2_$i:u~g@E Y̗$IN݋&|nH ; ]K$M5s@j5ذ"t/I4=%|nH 7|>t/I4. RC87 ]K$M}7M!TԶߧ+I4+Ӗ 5]e$IҴ*˜>;pPQsCw$Iӭu+g'*s.%I[{NTT7.%I[wNTTȗ$In?>;pPQc_ȗ$In5džNTTg.%I/NTXB$Iө&*l=̗$INÇR8mtI_>7pPa{ׅ%I[g'Ts*E$Itkg'Ts*lpy|I9@9ɡ|I_N+Ȟ IDATTXCB$Iӭwhj@VC"_$i ֝>;sPa ȗ$InWNfޟ-+/8FGIbXN/X&Qk4*3IbbtTcrhsh rmA. \[ @m}{6#r;{g?ߪ?pᩧZo fsPcȗ$IZh7NXgB$I nR9!Ǘ$IOX{.%I&s䯄OC$I {{'rPsE?t/I~4|vH ȗ$IZh+ R9].%I3g'`jni}"_$i6|vH ȗ$IZhE?|vH  ]K$MRZ 5%$I$u{e@N%$I$u?@j(5=K|IIP@uxm_$i>?rPs_ė$I'Oʧe1]K$-і\39h-t/IЊ[g'P`||I7i@j  0ri_$i4|~H 7ė$Iq>?r ]K$MRO4=C$I4ظO@K|IIpr@tOyO_$iw5|~H :G)t/I4IE/|~H %$IҤ~v @,%$I$uxM 0,|?t/I4Iݓ>?q7.%I&'0btdž%$I$ T@C o89t/I4Io~)|~H !ė$IOa4Dė$IaLPA4D%I&}Kg( .%I&{g( sC$I;3@j B$I6x 5).%I&ix@j 2~`s_$iFw]>?q ;. ]K$MRw' dφ.%I&(ʴ3@j 2d$IҤuxM @ |II=|H LI:Կ3@j 9ⵡ |II^w\ @W?/t/I4i;>Cp0ė$I{'fo.%I&g(ftdž$IҤu>g(fx |II}P4`㾡 |II_O3@j _.%I&mφP4Lw.%I&mt3@j B$IVg( |I*yNj@N_$i:Gj j@$Iީ>Cs@o_$I3@9 4$IҤ /3@9 4tu_$i[ R9h*t/I4iE3@9 =] |I*}nj@u$IR:k>Gs@5/]K$Uw(Tch~EY |II\*~/ 5v[_$i҆7>CsP/ ]K$Mg(TcjcB$I7is@) տB$IUj9 Ք{I*uOx[j@Cu~S^$Js?>GrP^$I(TS$IҤ}I j@%t/I4iP4h9 |I*yNj@ T^$Jo R 9hy ]K$UwQ4X.%I4ظoj@u>$IR>Gr`}~6ty/IT}Q4\$IQL+>Gqp|=t/IT')|H5v+IT'3|H5$IR>Gf4\.%I49 Ռ$IRFw^>Gqp^$IR^j@,$IRګ?KՇP<|o^$Jc~#|H5`2ty/ITY>Gq07$I(T#f`㾡{I*u^j \IU;ty/IT7>Gp0#W$IR}Kj/C$I*g)TfD3o K$Usg)TfD.%I;@b~tB$IU|eY `n9!n]K$Ui9 Հ2tV^$JR 8!]K$Ui3g)4̐%I9Wg)4̐q$IZ? Ҕs0C8tq/ITg)4̒e8ty/ITѭ_榛3{I*>G)` o>-ty/ITb\>K)`|?W$u>Y M13wB$IU@bfL ]K$UmqY M13 C$IUm:+|HS *.%I4޷(4̠=ׅ.%I*U˴@Rfυ%I9Wg)4̠%B$IUY M)3w.%I6Y M)3sB$IUv~,^Ž$IRՊ>K)`Fm{IW??|HS}e^$j~+|HS^w\^$j:|HSB$IU^6|HS ]K$Umt@BfT_]K$U=T@2f.e9.%I>etq0$I!6zHS Ž$IR|"|HS \g^$jo>K)`>{I|(zHS Ž$IRF2S@"fٞ?]Q^$jS<07≠C$IUQ,7|N^$jKq0$IhY M3wC$IUQ,9B$I+e{ճ)4%̸> K$Yy M  ]K$UmsFѳ@(G߾$tq/IT Ҕp@9Ž$IRFwlҔp@?#{IRiJ8Ž$IRN^>O)}KB$I9uO|G<4,z;B$IU_y `.~`ׄ.%I6q],~`x {I>K)\IZ6igS)pC$I9uy st}E^$)ޙ R0$I)X=ׅ.%I6ڲ1|H#O]K$Un/y rŽ$IRN_>O@?$Iʩ{;)?>߇.%Ir_O@ G~$IRtj,9Fw]$IoR)axŽ$IRq^y q#H^$)7S)8C$I9(|HA]K$4y q7tq/ITѝR)etE{Ie_>Ox.%Irjy pХ$IRNݓ>Oxo ]K$߰2|H(U*ˢ]K$Umx@ Tl$Ix@ 4|v^$rŸly -3Oe5н$IRN;42ro#ti/IS? 2r=ti/IC):"ti/Ih˥@ZFx|e?.%IVvi~EL0<[]K$>?Si8 vL^$)޺)Lg8ti/I`>@Z&xBc$Iiy -OEJ ]K$1zHtOyO^$){)PI.%Irk -"TVt.%Ir9GSi9B$I97 "r@e ]K$4ڴ>|HNХ$IRNŎ@ZDsثB$I{aLߥ,.%Ir `nq8 +C$I9/y -d\Х$IRN["q@Y$Iʩؾ%|HY:Gr^$)Ti8 O-Q?ti/IS߉9 ;ׇ.%Ir_y -d^Х$IRNÛN "p@9 ]K$4v{<uХ$IRVEQ}nL29 [{ճʲ%Ir~濆T)o.%Iro)bxB$I9 o\>OLX?$Iiy er;K{Il~^L28`Q\K$չ3@ES=|Hhͅ.%Ir*>O X4$Iʭf UE^Ѕ$IRn>S[C$I97 REXTMg.%Iry UEտh.ti/IS@{C$I UE^Ѕ$IRnݓ>S [C$I9 .Y>O Fև.%Ir}y UE׿h>ti/IS~ |H8`uOx{^$)A/ ҄k^$Iʭn MKر5ti/I5@hХ$IRN/ ҄$͇.%Ir*i~EL&%=K{I:bL&%^[^$)WL&%S$IipA@hХ$IRN-)4,EK{Ie%|H %=K{I:*|H %^[^$)>Sr*vl ]K$4y -hХ$IRN9`I/]K$e5hiSg*XR$Iʭskg*XR^$Iʭwg*XrŎK{IW>Oprf^$)~-|H %׿C$IYe3@zXr'tg/I[gg*$\YE^$)9 ғpo-ti/I)$,7 ]K$4~`s<E.%I*sg*,Ǿ9tg/I[T 8`yB$I9/ `9`ٌ9ti/IhY@zX6ï4 IDAT$Iʩx;@zX6/U^$)/pЅ$IRnS>SSr ]K$4tuL0\$IitE@zXVk ]K$Tt,.3@z XV3?$Iʭs+g*:G&ta/I[? cpZkYS^$)UntK{I[ cp\Х$IRV^|ZL~]?K$93@ XvC_$Iʭſ Op_QK{I_?>~{$qQ^$)}S'8 5K{Iqgg*cnН$IRn~;|H?!4ta/I[T8 LwC$I9 o>=|H?aF ]K$TS$D {IzqLnϟ. ti/IેTs{ ]K$4zu<0 $Ij/ӞO ;;{I:G)|: ZW.%Irog*RK{I7?S3i0šK{I>Ot0 _/ti/I[{n30ۺu.%Ir9XGTl:`xI^$)%g*`u0- ]K$4y m]LѦB$I9e%|fF ]K$93005ǿ5ta/I[TrheYC$I9 >2|f[C$I9.|f ]K$e5igT@k&9`p^$)1>S9 {I},|Z3e$Iixg*E:W.%Ir*+|Z3SgC$I hLi ]K$=g*5s0u:"ta/I3К9>+ʢХ$IRN;6T@9k0F$Iʩ=TT@k8`* .;ti/I[WT@k8`*uOzg^$)Y;|Z3SfЅ$IRnï>SUl3ti/I)5S07$Ij<*۫>S߅%Ir pڹ0$Is>|Z3k3r< ]K$4 (g7.%Ir*'|Z3Smx?.%Irk hL$IʭT@k&8`u>Ѕ$IRnLpt[kYS^$)]WT@9 0Fw^$Ij+ӞO V9`l$IR}cLS?]K$?3j<L/]K$6s3j<B ]K$TSFs@-}nYE^$)]T@Pm.%Iv˴Sg*X '%Ir}CL? {I_ h5js̯.%Ir޸.|Zr4]K$Tl3~ʦr@.ti/I[{T@P+ ]K$;3j$J? ]K$6 h5jsثB$I,|Zz_QK{I2 (3Н$IRn^>Sq@ 6$IʭGg*8I ]K$6 h5jfЅ$IRn-3jRХ$IRn]L4Ѕ$IRnݓ>SFq@- {I_?|ZZЅ$IRn-T@QPO{=,Х$IRVN (5;{I:GJL5fm^$)>Sp@m`^$)7N Vc8::ta/I[oT@1P_EoG^$)/ Pk;6.%Ir=|ZZ\&ta/Ig*]K$63jZ{.%I ʴ3*U{bН$IRnc>Ss@ o>=ta/I[T@P{/]^$)ѭ_{ow]jWڎNѫNGN[Զx3:͜i[$ bCE.B40^ }#;#rYx%o^bҹk/%I*U*h.0NxJD^$i~&W1\`*t {IAk7PL4 ݫ7$I5oNT@1\`*7/%IMB社$Ig*X.0VU%I8OU@L*/}4$IҠu>vbScm {IA;p1{SrѺOR_K$ \ ߕb"(O$Iux/*H.0Uo|5$IҠMJw$I o*H.0U|M {IA-}SDr|o$Ig*8.0UGD{/%IuKwPL:ݐ^$i:Wb^s^ {IAvmSuS_K$ \ OMU@1Q\`4$IIU@1Q\`^H}a/I4hU@LJ};R_K$ ZsOT@1Q\`*uv^$iЪ7baա (& L;,$IR5]Ry3S_K$QW*.0oK}a/I4h7o*.0z7]^$iЪbbj_~\ {I:*Ow (& L$I/MU@1\`j/%IswPLj7$INT@1\`uݘ^$i~'>#}Wsֺ앩%I?HU@1\`5znzI:|]cܲB {IAۑw.0z\^$iX8I (ƚ L$I (ƚ Lօ/I}Y/ITGsS}WqҺ%/%Ie*;.0SӞ^$X8 (Ɗ ̜SK$QͿb,e$IR/?.}WXqse$IҤwP9I}Y/ITGUX[bl)W?-ꧾ$IKV@16\`&)e$IR (Ɔ ̤u秾$IM*.0Z2e$IRU{baա (Ƃ ̤YM}Y/ITW3b,l[^H}Y/ITG]bۙ^$7\b,\qZzI:#}WXpպ%/%IꪱӷPsU$IuպoӷPsV{zI:~[t.0z{/K}Y/ITGoMU@fZR_K$Uyڏo+H3/%Iꪵe (RL+WQS_K$QҷPr׿ԗ$IuԿs (R^w~zI*H4.0Z2E$IR].O (Ҹk$Iuչmi\eԗ$Iu ,.kۙ^$*`.k\qZzIj^m)\Ѻ%/%I7o+Hg$Imצo+&wEG, \o=e$IR-{>ʵGEGg׺m.Z:p b .7^^$omashoޭQw?{~#b .7/?nD%I[g +Oxj47,ݽ)zBGf$IԹm0NxJ47,ݽ)DTULz%|/%I?C.{[LeXt]e^;Εg&|օ/N=X%IjߋMW\{T478U_7}_59I8WE#*&g&_zJ$Yϧ+`iӟ-Fg׺mfjvYu%sWDO=h%I<7ʵGEshoޭQwgRЌןJOd.cA+ITgwuG{ս_~}qϦX2q^1$IoOW0Ecы_߽㛈5V5|b\ǡu+RZI:Z,:$}c|Gg׺id1 ŒC_J=h%I4X0ܼ"磷wkTٯ'\^X2;,zJ$Y`'<5G{t)3ŒSoߎV$z7]`b-[6֖cʿ5U?4J9b\ǩsi$IRUͯ/~Qq*ΎogDQ^Y {b\ǩuS[Ik5OD{|n+#ZͿb\ǩ<$IRݵ?/ F<ܰ~RtSayM߿'?RKSہoH}O, $IRrUGGk˱ٵW?? rv IDATS]IZ<{7\{6^*/\)?)K3_~6P, uݘzJ$]~#~_[Z؟X#Ժ%ŒOPW$Iu?<g?/VFwQU%=Z4 !xgR+ITw~Q`GGk˱ٵ.zvFw%-%Kz_;sij~P, };R^IsGRFpgGXICN?{(XSS^I^1}clhho[ݛODUed4Z[^K,AzJ$][7#4wX4|N_{ѿ}wDT",AGR^IaxO,\{T478U{Fո7c1uџYK,Q$Iu׺ '>#~/^쏜&օ/I?(XKR_Iْxuˣ{S쏘&;4l#X)$IyπY[jܛQ |K,OS`IkoY3\ſx޶27\wdD43b\rU,ITw>2{cLãh]{"~GBIZIb\tvzK$^#w4)Ov]/^GO[7ܤX2`_zK$ ;(}gLrQܼ"磷wkT{?Ig)Œ(OX$iu|c#ay\*/ekW%sT=pG!,ITw?ܲh?zW{"~G8IyK wӻSaIatSf,o]Z};#j4|ILd.|M!,I4Z"}gWD{|n;c$82Œj$I0ْ\}nmo[ݛ~$z{Fո'{zK4:WL 0$>,H$Mk`GDsho[ W}_Ξؒ$E?) Iy_$ijk_?<.GcѺ߿'gOjIƲGOvpSiIaջ O޶27E)IFTi[b ..{Ea-I4̪ƽ0,}ss귵ůvy$I3XՏUb.4|Ny-I4fg۷3Ȟ$iL_O*sFaա3N$iZ<%s嚧Gc}>z{Fpgl$Ic\[ \}$I0ySi'<%G{{"*{&J ~H4Ġ\ioK=%I] ?fܲh?:Z[ήuʿΞ$iߺ+rF׭I$Msm=}sLrQܼWN=$Iv۬w\)OxjDzpK$ >&]ſH{Fpg̓$I3Rҷ\߾;$Ijv&́ u{uߗ$I׼9}Q Ugܒ$Iî?K\qf8I\qZ. 0BK*$IvO\qf8IA(PySnIawg.:4}wL˞q$I~(ߖ.hUߞzxK$ -{sLE=$I(XK=%I]磫7$i] 'IwY. 0bS-I4N\ɞp$I|"#8$I(*O{V'g7Ih+黈b`.n3$Iv6}wLɞo$I8w\[H=%I]o.I̅M$)S~4}Q HyJ.I4:Xx.Iכ$IR'<5}Q HмE$I(jw$&If IEs'P.I4׾%}wL]7gO7I4U7E-\${>zK$ jX;,}w;{I雈.@u$I_O]cmnYDUe6I4]DHzߤ$Isi `'pd$Igߗ(j$i$I(0g>'{I$EwwE-\,Y$I^_^cw$IRt8=}QԳ/]<.M=%IFQïM]uʞk$IѾ]DQ  QN=%IFQW.q~g5Ih]]DQ  Q$I#<ߥo/qך$IR4/xQ. i":e.I40:W=$I_OEp]$i0{.ɞj$I8wE-\dzK$^'7}{9D$C }QH|$Iu_o/qcL$I^ՏwE-\d嚧/$I^ҷe4I4U]雈6.3$I(ON^cuߓ=$I]DN=%IFUso/qןʞg$I۷3}QK2`$IUOE-=$IwӻwE}W$IҨZ,:4})D$Cݫ7"ڸc$IҨj `?i&I(jgޙzK$Ύӷ8|_$IRO黈6.hRwIQU0{.ɞf$I]DQ`L4zn.I4gRֻٳL$)o]DQ`\U$IҨ|tuHVݷ/{I$E"ڸc$I ժC"Y&IFD]\1>zK$O_Y`$IZ\mDQ`4۩$I(;p1{di闳$IRD(j}A+I4 uK$IRTKErL]$I(k C_$I-HErLgɩ$I(k_~\ԛ$IRt\(joJIi۵ CsϞb$IuF. 0f5GF{$I(kߧo0Qus $I_(jק$IW/ZuHD=$Iu_o#N.\yfa/I4_2}RG'$Ib͍(jօ/I=%IFZUEyڳ746Z$IZgҷE\1Té$IҨko0Qi]K$irۈV._$in"}Jï͞_$IQOEsTڷ$I#/, 0 k^_$Iѿ]DQ;`L?$IO`۷#{zI$EwE\1UC_$i 0 %Iߞ(j_I=%IFcN 0L^]$Iuv(jg.L=%IF]}#} SdO.IVo#ڹcK=%IF]+Wo0aj믳'$IbwY6 0g>'$IʨLarv%IơL(jUDUޝzK$% Iwg-IӞ(jޭ$IҨq}7e-I㟔(j^zK$eX; vs"z%ImD 0J@$)G^X3K$iӷPnnYTR$Iw@͚og$IbnKFٜ.}éIgP'?Q$Kkޜ(sI:;֦0:uߜ=$I|mD1.hI Ibu%IX5}Q 0 RD $Iʨ@赳$Ib͍/G0>$I2|r}C㍿=$I $IʨzX;,} u_eO+I{N(ͷV@$)+_ILSg$Ib}ҷи'EtIWob}ٳJ$iޗ?( dIYjܻx2{ Y%IXo#q&H#ǧ>$Ij]'[ `@$Iz}D14.iS$IYnzwXd)IkmyY>t&O6S $I)Q{ ` 5%I`~#}Q 0az_xCA$)Wo1ޔ=$I$Iʬu1f$Iʓ8}#Q 0:;1!IفΎg$IӈUo$r&T󭿛$IJ׎Odd&IyS>:`R{_|K$jdfաQ=$Io$b\ ֿuWB$)Lc_̞K$Isb\ ؚ$IRvGo2G~gO%I7йy1 I:;OMd{SI$!5b\Iv#ԇ$IRfX?<|۳$ICjsb\ GS$IٹƺɞH$Iߍ㟔(ps Iz{o2oպI$!\F `57,O}`H$FGwҽ~sB$IzHߓ(FtsˢjݟА$IʮeT}y$I:W(FϾ/!I]ªCw@yڏgO#IպowHSW>4$Iơ=},{I$=y(FА$Iםל=$IVy$pCjܛ$IJ#{I$=y_F`Jn|WC$ijow0"{I$=WLI#L{!!I4oݕ9$I7$qDcϧ><$Iƥӷ0z{/˞B$I}q;bd\iꐨ#"I4uv3xTodO!Izo%bT\)IqZ3R6fK̞A$IX_HJۥ.h]IquKӷ0[:}$IzxU?rV`4S!$IRoߎm̖eO IUD1R.rD$i\v'PDUeIҷHS{$IҸԹm֖̆eOIGMJ#L֖cS$$IRպ?G3`u?#I.{eV)`ʔhD$ij] rj#I5{%` 9a"I4.oߝkٓG$Q+(FBJ}H$SsyJܑ$IzD1R.j^$I8սvc>WgIG.䆍S $@eH2 0I&$+$fH@WͶ,a^p6*K{Žwɖ>u{׽ullIJgs>e%9]IY4۾<*o|Wh$ijM`/59ދC @NL$ _3E9;ZiH럽MP|$I^sVs ߗԚHCZgu&I|7TU+j_359T`h$ih!V/i+nYpHo $IpTu^vZ-Kj@z'SpyKw4I[NU%;Z!9n .uSWl{$Ijv>zX1ߙ 4UO:`{Ww4I[O^i֨w&Br y 0uS>zKi$ۿ&r^OM&Br yc*tQIf;埣W5*6|gR+,Ґ/* 4uSrr&IYyeѫ  >,|gR+,4~TUj/{g&IUUMj@:h{$IjVE0k9{Za9F_~^IT> `7iZaPGSIFWڏMj@;8uT+e6 $IR_gVσ&Bs H 8u9Ow5ITo`;)E@?ϡ{/ $IR`R)|wR+vwu H6G5ITLJ{Nj@:tꪸ]M$ճ|kS* Ue$|R+4=ˡs*w{O&IWo7I)-|wR+<Pg+$IR U+^S&epO'H#VM~w|c&ISOFo(;_'s X :|.$IOōG'9Z9F!:|j|w6I_uU^CiZiJVr )Z:{g7I4=y?dwߧԪ]$:|(|$IW{ٻ|-"hݟMNVr )e6LU{Ehq_$Iz5`woNVr iG)&Vݟ/$IҺ4Z}r {Z~!tP4Mp$i\wt*^[O ߩԪe$Moʔ"tX4W(۽"|$IS{h*jITsQhۄp$ij ?6zXo߫Ԫe$=SoC@/ym'I&W{z?| ^[UHzWMԿx=N$M↟F뭼J@s;th4NO]I5wS`/5|R9:hp{$IZCcsRq++@sСHU:}4|$I/\-L|7Wj6R硃 /O$Izn7IE ӢZqG~THz^-/WỜ$Iznӿ"LՇWj:W勞//e6$Iۿ:U'Wi=+;Zd3s$L ߱Ԫu$`ׇ0'*9IFwT7i3F{Z!d~I4LSw,jI/Xg1F#;$IZGoӮ{ZnFjdMV}au$Z7I7DӮsRs i 9"t4] $Iz˿LEZj>V ꩇR+:IF.oKߎ^]y%ỖZՖoʔ"t4]=:IF▓G?_KV#r iw-*S{u$ {c>=fLoՈHZc7`_yv$ k[j#`K_sՈHZc=:Eg$I=fLZV#t dʗ>|$ij_0s՘HZk6a1NjF|0?K)9:~-,~Ǔ$w{wJNhQC׆]j5*&B0響c~'IRq*4z̸?߽I{BP#;$IMi0+:}:|RQ94E/zӨ|䦔-4|ϓ$iѥ3,R/Iũs`،{1zǓ$Q-<=fEyRr iuOJ: rc(|ד$u 0:}"|Sq94{/ vèւ=O:oT=P=nnոHR wC$IkM'FOkYUqvV#s iJw{OVCץl$Iu{4|,|S94~:U]w=IT{ϣG4k{ỘZ)׿`С0ji$Ih| 0S)q>Hr?:Y=%[|$E7Gc DqỘZ7oTe?aVrJ}$= L jl$S+ ~î{Ww>I"jQ f|jl$S?:ޠڻ7|$i6˷{eV=Tc) |/S9n-5> +"e ^I40=~B ?&~/Sjr$sM'AQпxO٨c \įej5:ֹq:FEI4u*zk7w3I\d2tTj/{g'IL}ꮊo j|$WŝCQQ>zsʷyi'It/2=fjѲL@z;` 9"|$iښI*<'zF?єIU|G,PhpՏ*@})[YVs i+Й0Rw@I֧EOTZ)nYP@z;;C`T+=Pu{_4A_;k{ZCI]ӛ`w?ѻ$ISRt(@wykP@ҴTE`E+ %Ilޝ P;#7jj M$MK F %IZ[ץj]c5494-w}GpYE?u:|$iu۾<^=1jsHʇ j?ڻ-|$y-,w=*꫗l6aiւ 0Ə1m^JL7N-'GHZ+n:!~oSHڻ/tHSR6oPll4P{!~wSHGo np~;$i=!M0@Ҵ?wq BI?oi(hEnj ]$Mk~;tXR߆ѫvS15t94U+n~ỡ$itꟽ(z4J瀭w8.;LVuL=>JG==I@ҴáCP=y_w~K(Izg΋wS=NolN'tpoK1H˩594#} s]ů %IC؜Կ`LU) c$H ]m^+JEˢ@}) k$L6LSP-4~_$5yG3F-^^494c .a7`TtBhwvJÚI3GM3zg$5|-Rq9 Gn H6HՓRVop1$Ik-5|0lߩ594/5tfkLټ FIR=kT>q04{OχB)k7h Iz^/NWc `hjr66'|Sks ifwT$uLJxu|`IwII;)Q05294k )%;)|$MS _W=^FFJIVoTUCuSz O;$iw|W0K~ʷ{E@ҬV{I`UwJIҺѧR^=NFJqi{Z#IZoZӠ:Gi^)IB6LI*}Pir iV˗ MW^/*=9FSU|wBF*fB-ӣւR:|2U#`dw_5r94NЁ \q`ocJռR)UUiӾ*Z$zI]OqoE)Ij.oKG*;%|?Tkr )$?0\ʇONo 3%iT ;ދCF2BWz ]SF|񖩸1NVH@RHvH_;O;?T)IRO㯇jd$ C,R4ۼ, .geꥸ}QIau \sDnwJҰ9{3jts )*,t0Lo=%iʔ/}}:yժS{ =%u~)h⎳wGv"A ,tSoԴ%M-$uOJѮ@RhcsRa )niʷ"~76'uhH%5uHy *1w{w*IuRyEѿ3wI@Rtf@`URχTm^Rя5 :owJ@R*8t(cp)$QKDZ`] :N9Tz'}-t.ZygT"jTu~b=z2Rx˔^p POKټ wSI_RYD`tL)e$թB3;INoM%iZiSy"W.ӤjHق\j@wwS6A*IY?JՊۣ0kJ/s >-4UC(n==;1~OGSyѿV!99T:d唍 U%iw{w\wtJUR?e6 =9T:,tPPO7UIL㿯WRUF`1|g@RwkjMVIzKKLG``*e?ga @]|8|o|פyK&FR+9Tڻ#t`Um_JOoGV @IWr ]:hx͔0|4:K;=YE?ۿ:|7_Z7B' IDAT6RE=Vpip~) ѿVT^ jLZUՇ|7ﳒ' ?fG`\?Sr 7:h^g-Hﴒ]OѿꩇR6}U^ j[OpLįlFử5=Sѿ;6oT?t|壷QK؜WRwwSѿ_l59T-  S瀭w\Ij4D. al 9Tڻ=  Ru%QKm)4w9T_VuOF|}?|Z)[C$վO.t0܊[OO?Jm:?T*n:1@ =*~9ߢS]:~W_H;.ן~;0$:A+ekF4С(C؂MSϥ)UUH}.JsלIGB;ZyW)e546'uipپ>!?wq+]{$5C;iڻ;|'+Μo5h/{g,e4ݍ*'>VsM8z?F|So#0B/߅l9Ԙ%My7T)۽2|OF߂1wRYD0}1|/I@R*n:!ts ipѩs'|*4_~!7Xvʷ}y,eF9OB<SNVo7KM,ox?2GỲM!ռRԃ֨,Rqw/g _CK5ۻSS^x ߛl 9Ը:`^χh8ux_kV# kT>r{SjZ$5w|XcH ߩ,S/↟*G&mkޢi)b$5B>jZm{v9?_hA7勷߯SF=s#%g/J~GKI7▓S{* Cwmis ^E%N=WG}nb޻Օ/ye{t`uh-eImpŁfT/Kōǥq߿5;Fo&V>~kǪwp)[Hjl}>lV>nOv}\#/<wFY;;c$5+CQRq9χS6\m&:l=TF 8vʷ{E.eI{?P <zgO?/UoOc:/+^RYD \uH.]Hj;UNO=;Mo м S{w12U违Pk_?Ks=V5z07z?K ۽2|4ũIݟ]_{*0^^~9{?t!VݟۖE_xƣw|?>7N;4wr i(xw y*$ ./NNLcL|mCO!/)7GoND TWL|VICT'@?C9?}E&hZ/4I_KwLō=nA7m9 vwMC$ G 6MUXr#:/HKsK:Ijs$0o/}}jRGJݟMoipSq&WUV=!]H?m#R=REwʷ&G'>R+&c&N#t;A{Kꟽğp̧᩸gGX/N !eӔICG2e1}Փj ?M^m-'?sz*4Ul9MS$ U?]Vޕy?ߐi{gC9z7نMc$ W6JժC/~U i@?{}e?Ӑi+S*Х!eӜICYqIKP_mßeH @rxΡ,Cf  R['#?ːN$ m] 0lr ih˗6DQuW|?ÐnpPv v!e3IC]{.@MTejgR694^O7$p$ }c>P^3 )Ho' ]*8}?|$D3.@ V!eI#QStB `U+LټŸUH,@4}Bf)F ]0UW|KŸQH,@HUu~̞ۇ?Y{B `k&ls iQ'tfCKHsg7Fp3R{?Y+)н9M'?Hx3GŸEHY@$d3?p):/9@V~fL ,(Fӫ|ڔ !eA94m."ܸHz~;tG=)q) .e>wß;HYp$|w]HSelß9HYp$|oI.&94X7U牔oE)A$in+@JUS?kAs)I$SRxg RVH/; 05?_@UU 0INʗ.ق(~!tW&Ѳ RVHҳq;ta֢|7?W++Nv}ß'HY s IڢS?kxo ͭ_$ꟻ8tw^}Ÿ#HYMs I/Pd/5@VBw@jIZM]ߑRU.2ӛßHYs Ik]xZŸHYs IkGB`==/ i`/3y5 :&t67?/@|FUHsIDHSŸHYCr IiZug@&Yo.90JS)A9ɶũ]v`TΜl@۬HeFA?m^\@IJ6OUhîw& m^$iΜ0V=09)oE:+CV,@IZgo0Vޙ?@֡|R]9uK R6ARH:/*~ 9Ѯ S_!$Gץ4.EhU{~05)Hz6{4_뗲!$goL.GHѯKِ@GDs/eCIڻ5r$@T)vlr ICC%hھ Y$ij/{gJU,@T+Hق/eCI8ta&_ӗ!$McߗRU.MPg}llNkR69inpѡY/eCIڻ=r<@7: q$i\ypS{_×!$@NoJQP' ^ʆ<4C/+tSïv/eCIKSP3燿n/e#IP@{Shlr I3XxTu ] RzH$i럽(t(=llNkR6"9.vT]`Uej__$B35t6lr IѢSԃ̖Tʗ.yih@f ]`2nR69j&ZqG3Zq{l4wr IX/.]0:&x)Hl6oT>zs3@f|(z;_FI6HW`0- ^:$i#S|.zSyšL;uwI-UO.c0;I؜%HRdŭ.e^"@Z9{? `]/ZZ39WV=m_:39ސRTuᯱKj='TTںr I5h#e &N]ںr I5wwB5 @҂MSХ ֤|$5uIr I5{_.nZU:%VISc+C7x!]RZS$f_O@Tc)_ekZk$հB9x_\Rk9)e9ᯝKj5T- ] ᯙKjM̏IQW"t`Μz֤/me6 Iީ0~V.5?g~[O-,$IzV7X`u%=K mI[0zW֔g~[ I_qyj?r ne;ZH?2t`4twᯋKjS{g I 7ЅW M\Rk_3?ϭ|ٻ@._UO.~ *;)pIunp!L}>$i ]^!upIgLڇ~:$IZC7I7. 3}4^u I\7t `Kjw=?$i 0赢u'?Ӗ}Sj|s_p=}20t?V 7If^QnF`sgْb?{O<]'I]SMD9H:ꃒaKjU=l$ivo>-Gj{_%?k;PW&U,?b?PC{_+}L%Is!~ @ YXg֒}#:W~<$;E1W'^ϫ%Ÿk?<5;O %Is~g%7?ZRc"uSGAJ^'~vőK~F-1.Ps˒?PI;bߙ7z,e?Zkޔ|ZRLj=I`%IsߞJ^4jKOz=@wI$i4`+H|h.;^FSQuvM% Thђy7reM%I{G&:ޗZRc-YUDD3AKFӒ3@^w)t׆ AKFW_> Gq􋓟?KjL׏ڳ{?hIh]{8k0)UߑYR#I[l0<$io;LHҟ9KGh?KF[̷=M*kR7Kj$s!O{x@?xIq`hϙ%55tig&V,/'YR#Ġ;@D־3$};w.Ԣ˒\ݺ^<s? Ixs({0&գXseI jn?pij?I+V4#| zZgʒI+V(qA'#IOK>4A$?KH^u);/Hd$IcjjQ Q`/9M~,)RW>thkGs?!Ix*{UT`TG7GgȒk|]?z03_OJ4\އ0Jn>gǒi>$bp5sy; t/ύ%E-Z:F;*>?9I*?0ۜQF`hN-J~f,Q:޷בt7I[3@(XR6[1@Ӈ Jn6KA/Z99K~mV /xo')IoE۳0;/4FIJ_wfuC` sI4%?ԨMFZk|$-?pn*+ IDAT-Q8 SOue%,˪o.<ߒ[Q/dDs勓?yI+yYTs|;˞WRv~Ԝ1Y}$5?yId\xȜo6/\NxMs_IUxaT ۊ/I"H&S |XЪ2g#yF-]H.5 7NJ"H&SEQ5ɍ`!^gX^vN4yyC4:{$7fpϺhN-J~+Qz7: kڑ݀r(z~]IZ#~=1Eqk(4|Zd7!UǢu/&?ەԨm{׏3S "I\QFsUUigw3P3ő$M5+FqVG%?˕ԨoՎs01=8$ILK7w%LRI^uX?# u.PI4Zdq_O~+Qۊ^m{PvDLTK>4kE7$?Ԩu{ehd$$IljQ 6^:[ ?us!cteߒE$Mb勢Ho'Mo k%5j]Q "Kœ$M߉QR}WGs3JjԺ_hWLI&[oÉ㸥Z}SK~F+޵&e~JQ4V߿m,:ZDk/?T늕?`z{LIZPNxmTukA/gFsYI5ojQ 6]6KC+KJ&ZCykL~+u?6u0ּ)*Ilo}nzNH~+N}CĠ "ʝ[y U,{n70qr4,N~+-{N7N5Pӿ:W'jợ8_%տ&NMd0Ծ_dId?tR:5]%տ&ٵjbXJbK&^1IjƣߎoN*?"~MZaO_q+jnKzɚ`1}آ/$ir?f#JOݜ5PʏH&Z+0k._lxEs ,u;!$IkjQ sq*eI*=:ꢑ%bH&WQz0խ`TbKJul0T?+_"I\5.bKyxrV>g_wDNő$MCS~Ds URkfMPe1=8I4R~~JҿL~*Vj1tZ/$ir+ͩo?3z_;2:Q=56USɿ`5;Z菉 \3g>4zWvuVPgǒ$Is񟧾 `\g]qˢq_]CK"P4}6XʇnbsJwŪD}cDUE$BJ&D>R^G8ZW(7z2_ɿT`T>P5EğO~.*޵Nz]Tru +ILQ>@zh硒]7̌z*:4X4z_[j˧~sPI}[j?Q?ѽfe/$iMM^@%պι0I!ռ u?1kE$bQ| mGS}Jwݯ'gj0Ի^w/$iN^d맣9(tD`\O6<#yzV,/]Q`oIx]wl[0OŲ&?TZx}7FN`ln֚7'Ɛ$%cݯL}S+6Z9NGn`F goI*ՎRqyztsǾ"٦tݰ:r5?ѿeML/;7$i,NŨ:Rnۢu뒟iJ_1/#g [n1*7$i~'ڟ痒jU_rXHD <ɿ$I8g|Է~疒jԒѽ^,4Yc^dVRf*:_畒S䃣|X]Fsɿ$I}ƯG o1@":9tľѽz9*w}?ڟWo>IԷ |RR=jvޟT jw檗%F$ކSZ ]*Ǿ"wT+ r0[DCczjߘ9dq 6^L@39(tXTԗYl1NM*ISQϏr=o+}N4rp+:c[S_jkfen9#+_V4Z'&G* sI4RRgF[RT{B~,:oL/}Vo`Ij?F o) :QRsפ Oq}OLZ ?`Q,{nsGI}[c𽯦;Oah}!$z_[6`(|^FI}bpU/?n|>݆4ZN} frCGLFIo9=Q>xcKϼg[ng!$͗V 6CoiT,/?ծR_va0 /IL/}f ISW8 C[\gWo-kNd`釣sՒh.? $+?0éo()J}Q/Ed`En:-N#IzgzDѿ㼈~'efA0F:MjW?Է 3`/eҒ>-ѻaOM` pY:1LOuw_(~3%?;4x3j=L@pbּ@jPR=$?3>;Uw:償0r^w|%cpϺԷX|4*ut.xoo9=G$ *E]hvOsĠR,U5\?cq걭yH}hsGѿ(|#ԗF`lFCuۣy_0$)ZrT]/\?g~SlZ9=?nf>{ɇcѽm81MEQ>r_ 湲sz7?Ͽ+S'5IO>~'e` Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`0 @ Ȁd2`ڵAU:ހ  @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @\e~IDAT @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ ;UIENDB`PNG  IHDRF pHYs{Rk IDATxi[@5e ĄĔ@UMԄ+$U-gaA`aA=(þ [0 ^=M߯קn{I ,H$I!B $ H)$R IY0k6# G0Uvf9%q4we5$b 2`}5l$ML蓟W@PfH6%2W\ Z`7sA}o5n%]fђpV"V)]Vమ>Zc$V*Tr yP AW;~9@T{A1|cE-eT" PoM kXP]oXp$k'&6+mD-jx?GNm/xg+}Wv ee~YS6@E9{N$ 4'=K(๠ :1 oVѩ5@0<wIG Zapmps#pv_¯7 *镝!xZ=ۧ1 {Xqˌ z/w!/J,ڀ/Ȯٳ.YjZ7_U3P@j $C %̤iCڃ{7>:@ƜW )xχ~5Fik7aj7Wӻ2O >v}Z֍c[ ۧG9/:B6upk`0^9GO@ze'>ɚshE9 0QO+i%7G*o@R;[޹c`7g } do`I$kI4 P{#wVoRr HX{Pr,(~WxY#@mv d)>T7@*jQ^?RxY#@8(ڡRmU3@xY#[[XmGv= Tr d) xE'<"GD:R-ց*Be/@DWqt5P>N"KqH>P ct@6a'DId)E_4^Id)z?TsU@j2j'4Mm.lFz,(G2W@RW9"kY+zD'4/05w@K]E'0| D2ц~Ux2Y "-Iv+dFN'6UsdFN`ŀdFNs[O(KY$V8PF5 e)ܚ&hĘEz(PȽq@9OL/iH, Q^l  %\pQKM̅Tȯ.i>8DtRY"/U褲E^d>`щe)є1IJD^4O"+{U'$T+q,P O.KA->@}“Ry D 䲤EQsІm;q9 ̥D}{bR@;!v. \Gke¥U:. 1"w l·}ZT( dz (O~Nc"5_\:['[/@\,`m 0_6#WyՓpA<U?/ ΡDCkUK2эr\WY˻eYOp\Iyk<RٿX"WHYgJo.~@2KR}yBDK2>#$uo( 1n. AX:P#PǘpQu2ȮM0pO8W ]/wu;"6'vP&UѲ+B PŮ@C}oUo'.^BAaǝ¥aM=Y T'(>0suee¥a x}[-TEou<_-E; 5Dya]Jpu(co@n~Hن d?^ Ԅd $੧APtzۍ?#^*^~ФegBRpOnW=Lz\ȢW)CKE"OQs0!0?"V <ca / JlTuW$g$Q_/޹NxUK"?ȘkshKC8?Jۀ^+;17Uw $K"2jy߄°7T!I.CH36$8u#Rx&Wg[Jhc\ ~ڻPt$ñr8"6;Y(V'쮑 $MΗ3kb,~+l+>ZnDq[Ι1S:PĊ[{j}FMYuWuAjO"7s#ciPMI.}(ևӘZjWo$x⑨8>Tbz`79~LR,}ص$f[Y[wκlۗ~$;"#ɄX-טsW ZeFwa$.(G흆W{,5X@$k $E $ H)$R I @@H$I!B $ 8dgdIENDB`PNG  IHDR22? pHYs{Rk IDATx}hVUoRA %¬H-JA)e( gnTr,7f@^tK02)/根{^˹8=>ov}}{{ε! [>\B;Yc:N{Y7 wս{{.}C*sEwa]< vJ  rrBʼxxkQ"T?`_))ewg[&ZvɈ dX77f! (Udd}:LLj w@\9 ꉼx}13<C@k$sc6' lKx096؎YYMɾ~xZ{ Dt`; oa{j2ՕdaBGiAHχ_`^(vt tsZ q^I.M7sQSBv^@lx0z ava&Aa; @xfZ ΁f-6@옅D恈xF0+4 ;Z7oz,99f-@CKF. _>dHzv]fG6-U0 + `ݓ~~|<N쀸֩I7>DgdX2g,REqtsfYi<۪*e7v* 9Dޓi[> HU)D6d^Y.4 R)VzdK;B:-YW  : BWw3yh=~3<<K2Uiwo=+^] EVMYs8:$l 쫗`m뺬 ~= $ahBԾc$ #ffffff PNG  IHDR00W pHYs{RkIDATx[l QGĽB4'$n *֖F.*QUZBF;q)[3sv/gmjGAPb|8R䴔qS`HA?E[xU 1{ -"5+)^zydpbjJ.ĬaZ7%hOeHcT!zn%]:;`K_!/nh2 y{>H45\Of~{&Jr(E }lR c+hUoſ(bw%9g37?AN^12ꢎGϡ+z~-ȁ7p HۆZ rlVT7 0iXIJH H[8+my(%PN.={Q~MP@@@hxl7;<qз5 yX 9n$e "IUjhW~(EIg0Mx@d,s3¹0]ЮV @lK ӹ@uH[^֕R-_ tCYbް+}]Nyg\v,hcn!WL ǵXyL9`$/}[=c=R8n `c$Z")KL^/*ȱsdxsn8Ӻ~nֹ0/V+0q5rb3ipRf A[wl[x(glxn\yc `mI: g1uuA 5K Jom2k9aeć|B=UImM@!%D+ys&9"3)ZxRN ?n:1;CZM D*ng##ޔ&Jٚ<b|ߡu'IENDB`PNG  IHDR szz pHYs{RkIDATx]HQ"z"1{H(衇 xz6wYME"sl[2/!]2(J$Ŋҵ̝{⎥c3w|ef9{W{;%Pe\1S(fǶ48/KGZo fZJg -z"CC:;N@ D3ԍJG H[P}BT! Ɨ>n+PRz$G-E%v P?OQe4[WP}GҴ !Ҹ -us'He'>H@8 >X1]' HG޻P{= cZ"]vwʽ\uwqӿ7Z +rh|Q/D\4@di} \:p.;P}\M?խh/nRوv?@J;|c/@kv*MwekP탡\zٱ@0t_AZ69{gW'&vI}K>ߖ ~Q3 D7<^IlDQpbF*d<9XS_H^|]mUEF16UȦAZP?WәOlBIENDB`PNG  IHDRF pHYs{Rk IDATxwibh1p4&@$DHǒĔWw,R-"%,eiW!]| 73}7wgw'I@ @ @ :szW ;_`m)Aʑ) #o(Պز{Glm/? );K}Lq@l8]ڂ&_WPxo_ Ƕ@-{2\2%Pz&H-j_dl@Wa(u ]"mnWɣWܗe5 YW 0AzWe7}MS )E]}s~_-z`BHZWcū}Z\X7$Q(h|I-vp*Z-T5#%׆?,; \:[CH[\}_&pN2f͌ZFI)t>D) `  :'! oSz\I`7X;. QO[ e#;eL +uw 0wN):G.c2+j]S#-17FG -p```_QY厰zn4R((u`mA2<֡enWd-PF}@fLJ(Lc!V16+[QQ/>;@!*8OkV`n QC[?k! ا Q?=,f\VhrO(Y$ݭroc e1=(ub}HHZeqf hDH ZRn:/EjMw /$b) mx'(RQN,I$/'$R8@f^".8X TOWsO,I,Fb \HY u@;DQoil=,jqݶ8Uc`> ɤ?ch(ȣ 8pkȃn~+6> p>R:Q"?+<6F_k l]XnlU*X0 eO$31jyBxK u }}Hk @p wQu'O T(:adN4x!}P:(z#<2iǽY- &U̚ O:ԡg^_OP|;wia@9:FU>wiX@W:z-yw 5D^W.% x9 :~1w/]w@) C~7ٗ5.GCp󠌺?|yBz?QWYx/lNhRb`e`rAQ<@zdȂȭRQ©?n BΑzXFR\R"J7< $v@O@o4rڒJjYa`c\ԙ=>칒VLI}es&sT,[HƜ>]4 V&ZR@GBqՅ!7_s#c(U_Υ\y\*z&QآGV+G +Ѵ'V"QVXGe0ڽ?&6-r ywÐHff2?omXWP!5V6DkS!=ư/"5Q=KPgl%vN Œ 6^G)ꪪs06@ @ @A嫟(]=IENDB`getStatus()) { $problem->setStatus(500); } if ('' === $problem->getTitle()) { $code = $problem->getStatus(); $problem->setTitle(Response::$statusTexts[$code] ?? 'unknown status'); } try { $content = $problem->asJson(); } catch (JsonException $exception) { $problem = new ApiProblem($exception->getMessage()); $content = $problem->asJson(); } parent::__construct($content, $problem->getStatus(), \array_merge($headers, ['Content-Type' => 'application/problem+json'])); } /** * Creates a ApiProblemResponse from exception. */ public static function createFromException(\Throwable $exception, bool $debug = \false) : self { $headers = []; if ($exception instanceof ApiProblemException) { $problem = $exception->getApiProblem(); } else { $problem = new ApiProblem($exception->getMessage()); if ($exception instanceof HttpExceptionInterface) { $problem->setStatus($exception->getStatusCode()); } if ($exception instanceof ProcessOutputException || $exception instanceof ProcessFailedException) { $problem->setStatus(Response::HTTP_BAD_GATEWAY); $problem->setDetail($exception->getProcess()->getErrorOutput() ?: $exception->getProcess()->getOutput()); } if ($debug) { $problem['debug'] = $exception->getTraceAsString(); } } if ($exception instanceof HttpExceptionInterface) { $headers = $exception->getHeaders(); } return new self($problem, $headers); } } check(); unset($xdebug); if (\function_exists('ini_set')) { @\ini_set('display_errors', 1); @\ini_set('zlib.output_compression', 0); // Set user defined memory limit if ($memoryLimit = \getenv('COMPOSER_MEMORY_LIMIT')) { @\ini_set('memory_limit', $memoryLimit); } else { $memoryInBytes = static function ($value) { $unit = \strtolower(\substr($value, -1, 1)); $value = (int) $value; switch ($unit) { /** @noinspection PhpMissingBreakStatementInspection */ case 'g': $value *= 1024; // no break (cumulative multiplier) /** @noinspection PhpMissingBreakStatementInspection */ case 'm': $value *= 1024; // no break (cumulative multiplier) case 'k': $value *= 1024; } return $value; }; $memoryLimit = \trim(\ini_get('memory_limit')); // Increase memory_limit if it is lower than 1.5GB if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) { @\ini_set('memory_limit', '1536M'); } unset($memoryInBytes); } unset($memoryLimit); } // Workaround PHP bug on Windows where env vars containing Unicode chars are mangled in $_SERVER // see https://github.com/php/php-src/issues/7896 if (\PHP_VERSION_ID >= 70113 && (\PHP_VERSION_ID < 80016 || \PHP_VERSION_ID >= 80100 && \PHP_VERSION_ID < 80103) && Platform::isWindows()) { foreach ($_SERVER as $serverVar => $serverVal) { if (($serverVal = \getenv($serverVar)) !== \false) { $_SERVER[$serverVar] = $serverVal; } } } Platform::putEnv('COMPOSER_BINARY', \realpath($_SERVER['argv'][0])); // Always create kernel to initialize the application $kernel = new ApiKernel('@symfony_env@' === 'prod' ? 'prod' : 'dev'); $input = new ArgvInput(); switch ($input->getFirstArgument()) { // This "test" command is only for the dev version, if the Phar is compiled this is done in the stub.php case 'test': die(\json_encode(['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'sapi' => \PHP_SAPI])); case 'composer': $application = new ComposerApplication(); $argv = $_SERVER['argv']; \array_shift($argv); $input = new ArgvInput($argv); break; default: $application = new ApiApplication($kernel); } $application->run($input); getConfigDir() . \DIRECTORY_SEPARATOR . 'uploads.json', $filesystem, $kernel->getTranslator()); } } getConfigDir() . \DIRECTORY_SEPARATOR . 'users.json', $filesystem, $kernel->getTranslator()); } /** * Gets the application secret. */ public function getSecret() : string { $this->initialize(); if (!isset($this->data['secret'])) { $this->setSecret(\bin2hex(\random_bytes(40))); } return $this->data['secret']; } /** * Sets the application secret. * * @param string $secret */ public function setSecret($secret) : void { $this->initialize(); if (empty($secret)) { throw new \InvalidArgumentException('Secret cannot be empty.'); } $this->data['secret'] = (string) $secret; $this->save(); } public function hasUsers() : bool { $this->initialize(); return isset($this->data['users']) && \is_array($this->data['users']) && [] !== $this->data['users']; } /** * Gets all users. * * @return array */ public function getUsers() : array { $this->initialize(); if (!$this->hasUsers()) { return []; } $users = []; foreach ($this->data['users'] as $user) { $users[] = new User($user['username'], $user['password'], $user['scope'] ?? null); } return $users; } /** * Returns whether a user with the given username exists. */ public function hasUser(string $username) : bool { $this->initialize(); return isset($this->data['users'][$username]); } /** * Gets the user by username or null if it does not exist. */ public function getUser(string $username, string|null $scope = null) : User|null { $this->initialize(); if (!isset($this->data['users'][$username])) { return null; } $data = $this->data['users'][$username]; $user = new User($data['username'], $data['password'] ?? null, $scope ?? $data['scope'] ?? null); if ($data['totp_secret'] ?? null) { $user->setTotpSecret($data['totp_secret']); } if ($data['passkey'] ?? null) { $user->setPasskey($data['passkey']); } return $user; } /** * Creates user from given username and plaintext password but does not add it. */ public function createUser(string $username, string $password, string|null $scope = null) : User { $this->initialize(); $encodedPassword = $this->passwordHasherFactory->getPasswordHasher(new User($username, null))->hash($password); return new User($username, $encodedPassword, $scope); } /** * Adds a user to the configuration file. */ public function addUser(User $user) : void { $this->initialize(); $username = $user->getUserIdentifier(); if (isset($this->data['users'][$username])) { throw new \RuntimeException(\sprintf('Username "%s" already exists.', $username)); } $this->data['users'][$username] = $user->jsonSerialize(); $this->save(); } /** * Replaces a user in the configuration file. */ public function replaceUser(User $user) : void { $this->initialize(); unset($this->data['users'][$user->getUserIdentifier()]); $this->addUser($user); } /** * Update properties of a user in the configuration file. */ public function updateUser(string $username, array $data) : void { $this->initialize(); if (!isset($this->data['users'][$username])) { throw new \RuntimeException(\sprintf('Username "%s" does not exist.', $username)); } if (isset($data['password'])) { $data['password'] = $this->passwordHasherFactory->getPasswordHasher(new User($username, null))->hash($data['password']); } $this->data['users'][$username] = \array_merge($this->data['users'][$username], $data); } /** * Deletes a user from the configuration file. */ public function deleteUser(string $username) : void { $this->initialize(); unset($this->data['users'][$username]); $this->save(); } public function getWebauthnOptions(string $key) : string|null { $this->initialize(); if (($this->data['webauthn'][$key]['expires'] ?? 0) < \time()) { return null; } return $this->data['webauthn'][$key]['options'] ?? null; } public function setWebauthnOptions(string $key, string $value) : void { $this->initialize(); $this->data['webauthn'][$key] = ['options' => $value, 'expires' => \strtotime('+5 minutes')]; $this->save(); } public function deleteWebauthnOptions(string $key) : void { $this->initialize(); unset($this->data['webauthn'][$key]); $this->save(); } /** * Gets tokens from the configuration file. */ public function getTokens() : array { $this->initialize(); if (!isset($this->data['tokens']) || !\is_array($this->data['tokens'])) { return []; } $data = []; foreach ($this->data['tokens'] as $id => $payload) { $data[] = \array_merge(['id' => $id], $payload); } return $data; } /** * Gets token payload by ID (hashed token value). */ public function getToken(string $id) : array|null { $this->initialize(); if (!isset($this->data['tokens'][$id])) { return null; } return \array_merge(['id' => $id], $this->data['tokens'][$id]); } /** * Finds token payload by unhashed token value. */ public function findToken(string $token) : array|null { $this->initialize(); return $this->getToken(\hash('sha256', $token)); } /** * Creates a token for given username. */ public function createToken(string $username, string $clientId, string $scope = 'admin', bool $oneTime = \false) : array { $this->initialize(); if (!$this->hasUser($username)) { throw new \RuntimeException(\sprintf('Username "%s" does not exist.', $username)); } if (!$oneTime) { foreach ($this->getTokens() as $payload) { if ($payload['username'] === $username && $payload['client_id'] === $clientId) { $this->deleteToken($payload['id']); } } } $token = \bin2hex(\random_bytes(16)); $id = \hash('sha256', $token); if (isset($this->data['tokens'][$id])) { throw new \RuntimeException(\sprintf('Token with ID "%s" already exist.', $id)); } $data = ['username' => $username, 'client_id' => $clientId, 'scope' => $scope]; if ($oneTime) { $data['grant_type'] = 'one-time'; $data['expires'] = \strtotime('+30 seconds'); } $this->data['tokens'][$id] = $data; $this->save(); return \array_merge(['id' => $id, 'token' => $token], $this->data['tokens'][$id]); } /** * Deletes a token from the configuration file. */ public function deleteToken(string $id) : void { $this->initialize(); unset($this->data['tokens'][$id]); $this->save(); } public function createInvitation(string $scope = 'admin') : array { $this->initialize(); $token = \bin2hex(\random_bytes(16)); $id = \hash('sha256', $token); if (isset($this->data['tokens'][$id])) { throw new \RuntimeException(\sprintf('Token with ID "%s" already exist.', $id)); } $data = ['scope' => $scope, 'grant_type' => 'invitation', 'expires' => \strtotime('+1 week')]; $this->data['tokens'][$id] = $data; $this->save(); return \array_merge(['id' => $id, 'token' => $token], $this->data['tokens'][$id]); } protected function initialize() : void { parent::initialize(); $hasChanges = \false; if ([] !== $this->data && (!isset($this->data['version']) || (int) $this->data['version'] < 2)) { throw new \RuntimeException('Unsupported user.json version'); } if (!isset($this->data['version'])) { $this->data['version'] = 2; $hasChanges = \true; } foreach ($this->data['tokens'] ?? [] as $id => $token) { if (isset($token['expires']) && $token['expires'] < \time()) { unset($this->data['tokens'][$id]); $hasChanges = \true; } } foreach ($this->data['webauthn'] ?? [] as $key => $data) { if (($data['expires'] ?? 0) < \time()) { unset($this->data['webauthn'][$key]); $hasChanges = \true; } } if ($hasChanges) { $this->save(); } } } getConfigDir() . \DIRECTORY_SEPARATOR . 'manager.json', $filesystem, $kernel->getTranslator()); } } */ abstract class AbstractConfig implements \IteratorAggregate, \Countable { /** * @var array|null */ protected array|null $data = null; private bool $deleted = \false; public function __construct(private readonly string $file, private readonly Filesystem $filesystem, private readonly Translator $translator) { } /** * Returns the config. */ public function all() : array { $this->initialize(); return $this->data; } /** * Returns the config keys. */ public function keys() : array { $this->initialize(); return \array_keys($this->data); } /** * Replaces the current config by a new set. */ public function replace(array $data = []) : void { $this->initialize(); $this->data = $data; $this->save(); } /** * Adds config options. */ public function add(array $data = []) : void { $this->initialize(); $this->data = \array_replace($this->data, $data); $this->save(); } /** * Returns a config option by name. */ public function get(string $key, array|bool|float|int|string|null $default = null) : array|bool|float|int|string|null { $this->initialize(); return \array_key_exists($key, $this->data) ? $this->data[$key] : $default; } /** * Sets a config option by name. */ public function set(string $key, array|bool|float|int|string $value) : void { $this->initialize(); $this->data[$key] = $value; $this->save(); } /** * Returns true if the config option is defined. */ public function has(string $key) : bool { $this->initialize(); return \array_key_exists($key, $this->data); } /** * Removes a config option. */ public function remove(string $key) : void { $this->initialize(); unset($this->data[$key]); $this->save(); } /** * @return \ArrayIterator */ public function getIterator() : \ArrayIterator { $this->initialize(); return new \ArrayIterator($this->data); } public function count() : int { $this->initialize(); return \count($this->data); } /** * Saves current data to the JSON config file. */ public function save() : void { if ($this->deleted || null === $this->data) { return; } try { $this->filesystem->dumpFile($this->file, \json_encode($this->data, \JSON_PRETTY_PRINT)); } catch (IOException $exception) { $this->throwNotWritable($exception); } } public function delete() : void { $this->deleted = \true; try { $this->filesystem->remove($this->file); } catch (IOException $exception) { $this->throwNotWritable($exception); } } protected function initialize() : void { if (null !== $this->data) { return; } if (!$this->filesystem->exists($this->file)) { $this->data = []; return; } $data = \json_decode(\file_get_contents($this->file), \true); if (!\is_array($data)) { throw new \InvalidArgumentException('The config file does not contain valid JSON data.'); } $this->data = $data; } private function throwNotWritable(\Throwable $throwable) : void { $problem = (new ApiProblem($this->translator->trans('error.writable.config-file', ['file' => $this->file]), 'https://php.net/is_writable'))->setDetail($this->translator->trans('error.writable.detail')); throw new ApiProblemException($problem, $throwable); } } getConfigDir() . \DIRECTORY_SEPARATOR . 'config.json', $filesystem, $kernel->getTranslator()); } public function config() : PartialConfig { return new PartialConfig($this, 'config'); } public function repositories() : PartialConfig { return new PartialConfig($this, 'repositories'); } public function allowPlugins() : void { $config = $this->config(); if (\true !== $config->get('allow-plugins')) { $config->set('allow-plugins', \true); } } protected function initialize() : void { if (null !== $this->data) { return; } parent::initialize(); // Make sure the config is in the correct subkey if (!$this->has('config') || [] === $this->get('config')) { $config = $this->all(); unset($config['config']); $this->replace(['config' => $config]); } } } */ class PartialConfig implements \IteratorAggregate, \Countable { public function __construct(private readonly AbstractConfig $parent, private readonly string $key) { } /** * Returns the config. */ public function all() : array { return $this->parent->get($this->key, []); } /** * Returns the config keys. */ public function keys() : array { return \array_keys($this->parent->get($this->key, [])); } /** * Replaces the current config by a new set. */ public function replace(array $data = []) : void { $this->parent->set($this->key, $data); } /** * Adds config options. */ public function add(array $data = []) : void { $this->replace(\array_replace($this->all(), $data)); } /** * Returns a config option by name. */ public function get(string $key, array|bool|float|int|string|null $default = null) : array|bool|float|int|string|null { $data = $this->all(); return \array_key_exists($key, $data) ? $data[$key] : $default; } /** * Sets a config option by name. */ public function set(string $key, array|bool|float|int|string $value) : void { $this->replace([$key => $value]); } /** * Returns true if the config option is defined. */ public function has(string $key) : bool { $data = $this->all(); return \array_key_exists($key, $data); } /** * Removes a config option. */ public function remove(string $key) : void { $data = $this->all(); unset($data[$key]); $this->replace($data); } /** * @return \ArrayIterator */ public function getIterator() : \ArrayIterator { return new \ArrayIterator($this->all()); } public function count() : int { return \count($this->all()); } } getConfigDir() . \DIRECTORY_SEPARATOR . 'auth.json', $filesystem, $kernel->getTranslator()); } /** * Returns the GitHub OAuth token from the config file. */ public function getGithubToken() : string|null { $this->initialize(); if (!isset($this->data['github-oauth']['github.com'])) { return null; } return (string) $this->data['github-oauth']['github.com']; } /** * Stores the GitHub OAuth token in the config file. */ public function setGithubToken(string $token) : void { $this->initialize(); $this->data['github-oauth'] = ['github.com' => $token]; $this->save(); } /** * Adds basic authentication info for given domain. */ public function setBasicAuth(string $domain, string $username, string $password) : void { $this->initialize(); $this->data['http-basic'][$domain] = ['username' => $username, 'password' => $password]; $this->save(); } /** * Deletes basic authentication for given domain. */ public function deleteBasicAuth(string $domain) : void { $this->initialize(); if (!isset($this->data['http-basic'][$domain])) { return; } unset($this->data['http-basic'][$domain]); $this->save(); } } $userProvider */ public function __construct(private readonly UserProviderInterface $userProvider, private readonly UserConfig $userConfig, JwtManager $jwtManager, Filesystem $filesystem, ApiKernel $kernel) { parent::__construct($jwtManager, $this->userConfig, $filesystem, $kernel); } public function supports(Request $request) : bool { if (!parent::supports($request) || !$request->request->has('token')) { return \false; } $token = $this->userConfig->findToken($request->request->get('token')); return $token && 'one-time' === ($token['grant_type'] ?? null); } public function authenticate(Request $request) : SelfValidatingPassport { $token = $this->userConfig->findToken($request->request->get('token')); if (null === $token || 'one-time' !== ($token['grant_type'] ?? null)) { throw new AuthenticationCredentialsNotFoundException(); } $this->tokenId = $token['id']; $userBadge = new UserBadge($token['username'], $this->userProvider->loadUserByIdentifier(...), ['scope' => $token['scope']]); return new SelfValidatingPassport($userBadge); } public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName) : Response { $this->userConfig->deleteToken($this->tokenId); return parent::onAuthenticationSuccess($request, $token, $firewallName); } } '@contao_manager.webauthn.serializer', '$authenticatorAttestationResponseValidator' => '@contao_manager.webauthn.authenticator_attestation_response_validator', '$authenticatorAssertionResponseValidator' => '@contao_manager.webauthn.authenticator_assertion_response_validator'])] class WebauthnAuthenticator extends AbstractBrowserAuthenticator { /** * @param UserProviderInterface $userProvider */ public function __construct(private readonly SerializerInterface $serializer, private readonly AuthenticatorAttestationResponseValidator $authenticatorAttestationResponseValidator, private readonly AuthenticatorAssertionResponseValidator $authenticatorAssertionResponseValidator, private readonly UserProviderInterface $userProvider, private readonly UserConfig $userConfig, JwtManager $jwtManager, Filesystem $filesystem, ApiKernel $kernel) { parent::__construct($jwtManager, $this->userConfig, $filesystem, $kernel); } public function supports(Request $request) : bool { return parent::supports($request) && $request->request->has('passkey'); } public function authenticate(Request $request) : Passport { $rpEntity = $this->createRpEntity($request->getHost()); if ($request->request->has('username') && (!$this->userConfig->hasUsers() || $request->request->has('invitation'))) { if ($this->userConfig->hasUser($request->request->get('username'))) { throw new UnprocessableEntityHttpException('Username exists.'); } $user = $this->createUser($rpEntity, $request->request->get('username'), $request->request->get('passkey'), $request->request->get('invitation')); $userBadge = new UserBadge($user->getUserIdentifier(), $this->userProvider->loadUserByIdentifier(...)); return new SelfValidatingPassport($userBadge); } $authenticatorAssertionResponse = $this->serializer->deserialize($request->request->get('passkey'), PublicKeyCredential::class, 'json')->response; if (!$authenticatorAssertionResponse instanceof AuthenticatorAssertionResponse) { throw new BadRequestException(); } $username = $authenticatorAssertionResponse->userHandle; $userBadge = new UserBadge($username, $this->userProvider->loadUserByIdentifier(...)); $credentials = new CustomCredentials(function (AuthenticatorAssertionResponse $response, User $user) use($rpEntity) : bool { $passkey = $user->getPasskey(); $challenge = \bin2hex($response->clientDataJSON->challenge); $requestOptions = $this->userConfig->getWebauthnOptions($challenge); if (!$passkey || !$requestOptions) { throw new AuthenticationCredentialsNotFoundException(); } $this->userConfig->deleteWebauthnOptions($challenge); try { $publicKeyCredentialSource = $this->serializer->deserialize($passkey, PublicKeyCredentialSource::class, 'json'); $publicKeyCredentialRequestOptions = $this->serializer->deserialize($requestOptions, PublicKeyCredentialRequestOptions::class, 'json'); $this->authenticatorAssertionResponseValidator->check($publicKeyCredentialSource, $response, $publicKeyCredentialRequestOptions, $rpEntity->id, $user->getUserIdentifier()); return \true; } catch (\Exception $e) { throw new AuthenticationException($e->getMessage(), $e->getCode(), $e); } }, $authenticatorAssertionResponse); return new Passport($userBadge, $credentials); } public function onAuthenticationFailure(Request $request, AuthenticationException $exception) : Response { if ($exception instanceof InvalidTotpException) { return new JsonResponse(['username' => $exception->getUser()?->getUserIdentifier(), 'totp_enabled' => \true], Response::HTTP_UNAUTHORIZED); } return parent::onAuthenticationFailure($request, $exception); } public function getCredentialOptions(string $host, string|null $username) : string { $challenge = \random_bytes(32); $rpEntity = $this->createRpEntity($host); if (null === $username) { $options = new PublicKeyCredentialRequestOptions($challenge, $rpEntity->id, userVerification: PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_REQUIRED); } else { $options = new PublicKeyCredentialCreationOptions($rpEntity, new PublicKeyCredentialUserEntity($username, $username, $username), $challenge, [ PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_ES256K), // More interesting algorithm PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_ES256), // || PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_RS256), // || PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_PS256), // \/ PublicKeyCredentialParameters::create('public-key', Algorithms::COSE_ALGORITHM_ED256), ], new AuthenticatorSelectionCriteria(userVerification: AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED)); } $serialized = $this->serializer->serialize($options, 'json', [AbstractObjectNormalizer::SKIP_NULL_VALUES => \true, JsonEncode::OPTIONS => \JSON_THROW_ON_ERROR]); $this->userConfig->setWebauthnOptions(\bin2hex($challenge), $serialized); return $serialized; } private function createUser(PublicKeyCredentialRpEntity $rpEntity, string $username, string $data, string|null $invitation = null) : User { $scope = null; if ($invitation) { $token = $this->userConfig->findToken($invitation); if (null === $token || 'invitation' !== ($token['grant_type'] ?? null)) { throw new AuthenticationCredentialsNotFoundException('Invitation not found.'); } $scope = $token['scope']; } elseif ($this->userConfig->hasUsers()) { throw new AccessDeniedException(); } $authenticatorAttestationResponse = $this->serializer->deserialize($data, PublicKeyCredential::class, 'json')->response; if (!$authenticatorAttestationResponse instanceof AuthenticatorAttestationResponse) { throw new BadCredentialsException(); } $challenge = \bin2hex($authenticatorAttestationResponse->clientDataJSON->challenge); $creationOptions = $this->userConfig->getWebauthnOptions($challenge); if (!$creationOptions) { throw new BadCredentialsException(); } $this->userConfig->deleteWebauthnOptions($challenge); $publicKeyCredentialCreationOptions = $this->serializer->deserialize($creationOptions, PublicKeyCredentialCreationOptions::class, 'json'); $publicKeyCredentialSource = $this->authenticatorAttestationResponseValidator->check($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $rpEntity->id); $user = new User($username, null, $scope); $user->setPasskey($this->serializer->serialize($publicKeyCredentialSource, 'json')); $this->userConfig->addUser($user); if ($invitation) { $this->userConfig->deleteToken($token['id']); } return $user; } private function createRpEntity(string $host) : PublicKeyCredentialRpEntity { if ('127.0.0.1' === $host) { $host = 'localhost'; } return new PublicKeyCredentialRpEntity('Contao Manager ' . ApiKernel::MANAGER_VERSION, $host); } } $userProvider */ public function __construct(private readonly UserProviderInterface $userProvider, private readonly UserConfig $config) { } public function supports(Request $request) : bool { if ($request->headers->has('Contao-Manager-Auth')) { return \true; } $authentication = $this->getAuthenticationHeader($request); return \is_string($authentication) && 0 === \stripos($authentication, 'bearer '); } public function authenticate(Request $request) : SelfValidatingPassport { $token = $this->config->findToken($this->getToken($request)); if (null === $token || 'one-time' === ($token['grant_type'] ?? null)) { throw new AuthenticationCredentialsNotFoundException(); } $this->tokenId = $token['id']; $userBadge = new UserBadge($token['username'], $this->userProvider->loadUserByIdentifier(...), ['scope' => $token['scope']]); return new SelfValidatingPassport($userBadge); } public function onAuthenticationFailure(Request $request, AuthenticationException $exception) : Response|null { return null; } public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName) : Response|null { $token->setAttribute('authenticator', static::class); $token->setAttribute('token_id', $this->tokenId); return null; } /** * Gets the authentication header from request or HTTP headers. */ private function getAuthenticationHeader(Request $request) : string|null { if ($request->server->has('HTTP_AUTHORIZATION')) { return $request->server->get('HTTP_AUTHORIZATION'); } if ($request->server->has('REDIRECT_HTTP_AUTHORIZATION')) { return $request->server->get('REDIRECT_HTTP_AUTHORIZATION'); } if (\function_exists('getallheaders')) { $headers = \getallheaders(); if (isset($headers['authorization'])) { return $headers['authorization']; } } return null; } private function getToken(Request $request) : string { if ($request->headers->has('Contao-Manager-Auth')) { return $request->headers->get('Contao-Manager-Auth'); } $authentication = $this->getAuthenticationHeader($request); if (\is_string($authentication) && 0 === \stripos($authentication, 'bearer ')) { return \substr($authentication, 7); } throw new AuthenticationCredentialsNotFoundException(); } } */ class UserProvider implements UserProviderInterface, PasswordUpgraderInterface { public function __construct(private readonly UserConfig $config) { } public function loadUserByIdentifier(string $identifier, array $attributes = []) : UserInterface { $user = $this->config->getUser($identifier, $attributes['scope'] ?? null); if (null === $user) { $ex = new UserNotFoundException(\sprintf('Username "%s" does not exist.', $identifier)); $ex->setUserIdentifier($identifier); throw $ex; } return $user; } public function refreshUser(UserInterface $user) : UserInterface { if (!$user instanceof User) { throw new UnsupportedUserException(\sprintf('Instances of "%s" are not supported.', $user::class)); } return $this->loadUserByIdentifier($user->getUserIdentifier()); } public function supportsClass(string $class) : bool { return User::class === $class; } public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword) : void { if (!$user instanceof User) { throw new UnsupportedUserException(\sprintf('Instances of "%s" are not supported.', $user::class)); } $this->config->replaceUser(new User($user->getUserIdentifier(), $newHashedPassword, $user->getScope())); } } scope ??= 'admin'; if (!\in_array($this->scope, self::SCOPES, \true)) { throw new \InvalidArgumentException('Invalid scope'); } } public function getUserIdentifier() : string { return $this->username; } public function getPassword() : string|null { return $this->password; } public function eraseCredentials() : void { $this->password = null; } public function getPasskey() : string|null { return $this->passkey; } public function setPasskey(string|null $passkey) : void { $this->passkey = $passkey; } public function getScope() : string { return $this->scope; } public function getRoles() : array { return self::rolesFromScope($this->scope) ?? []; } public function getTotpSecret() : string|null { return $this->totp_secret; } public function setTotpSecret(string|null $secret) : void { $this->totp_secret = $secret; } public function jsonSerialize() : array { return ['username' => $this->username, 'password' => $this->password, 'passkey' => $this->passkey, 'scope' => $this->scope, 'totp_secret' => $this->totp_secret]; } public static function rolesFromScope(string|null $scope) : array|null { if (null === $scope || !\in_array($scope, self::SCOPES, \true)) { return null; } return ['ROLE_' . \strtoupper($scope)]; } public static function scopeFromRoles(array $roles) : string|null { $scopes = \array_map(static fn(string $role) => \strtolower(\substr($role, 5)), $roles); $scopes = \array_values(\array_intersect(self::SCOPES, $scopes)); if ([] === $scopes) { return null; } return $scopes[0]; } } $userProvider */ public function __construct(private readonly UserProviderInterface $userProvider, private readonly JwtManager $jwtManager) { } public function supports(Request $request) : bool { return $this->jwtManager->hasRequestToken($request) && null !== $this->jwtManager->getPayload($request); } public function authenticate(Request $request) : Passport { $credentials = $this->jwtManager->getPayload($request); if (null === $credentials) { throw new AuthenticationCredentialsNotFoundException(); } $userBadge = new UserBadge($credentials->username, $this->userProvider->loadUserByIdentifier(...), ['scope' => $credentials->scope ?? null]); return new SelfValidatingPassport($userBadge); } public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName) : Response|null { $token->setAttribute('authenticator', static::class); return null; } public function onAuthenticationFailure(Request $request, AuthenticationException $exception) : Response|null { return null; } } kernel->getConfigDir())) { return \false; } return '/api/session' === $request->getPathInfo() && $request->isMethod(Request::METHOD_POST); } public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName) : Response { // Reset lock counter $this->filesystem->dumpFile($this->kernel->getConfigDir() . \DIRECTORY_SEPARATOR . self::LOCK_FILE, '0'); $token->setAttribute('authenticator', static::class); $user = $this->userConfig->getUser($token->getUserIdentifier()); $scope = User::scopeFromRoles($token->getRoleNames()); $json = ['username' => $token->getUserIdentifier(), 'scope' => $scope, 'limited' => $scope !== User::scopeFromRoles($user?->getRoles())]; if ($user?->getPasskey()) { $json['passkey'] = \true; } else { $json['totp_enabled'] = (bool) $user?->getTotpSecret(); } $response = new JsonResponse($json, Response::HTTP_CREATED); $this->jwtManager->addToken($request, $response, $token); return $response; } public function onAuthenticationFailure(Request $request, AuthenticationException $exception) : Response { // Increase lock counter $this->filesystem->dumpFile($this->kernel->getConfigDir() . \DIRECTORY_SEPARATOR . self::LOCK_FILE, (string) (self::getLockCount($this->kernel->getConfigDir()) + 1)); return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_UNAUTHORIZED)); } public static function isLocked(string $configDir) : bool { return self::getLockCount($configDir) >= 3; } private static function getLockCount(string $configDir) : int { return (int) @\file_get_contents($configDir . \DIRECTORY_SEPARATOR . self::LOCK_FILE); } } resolved = \true; if (null === $user->getTotpSecret()) { return $this->resolved = \true; } if (!TOTP::createFromSecret($user->getTotpSecret())->verify($this->code)) { $exception = new InvalidTotpException(); $exception->setUser($user); throw $exception; } return $this->resolved = \true; } public function isResolved() : bool { return $this->resolved; } } $userProvider */ public function __construct(private readonly UserProviderInterface $userProvider, private readonly UserConfig $userConfig, JwtManager $jwtManager, Filesystem $filesystem, ApiKernel $kernel) { parent::__construct($jwtManager, $this->userConfig, $filesystem, $kernel); } public function supports(Request $request) : bool { return parent::supports($request) && $request->request->has('username') && $request->request->has('password'); } public function authenticate(Request $request) : Passport { if (!$this->userConfig->hasUsers()) { $user = $this->userConfig->createUser($request->request->get('username'), $request->request->get('password')); $this->userConfig->addUser($user); } elseif ($request->request->has('invitation')) { $token = $this->userConfig->findToken($request->request->get('invitation')); if (null === $token || 'invitation' !== ($token['grant_type'] ?? null)) { throw new AuthenticationCredentialsNotFoundException(); } $user = $this->userConfig->createUser($request->request->get('username'), $request->request->get('password'), $token['scope']); if ($this->userConfig->hasUser($user->getUserIdentifier())) { throw new UnprocessableEntityHttpException('Username exists.'); } $this->userConfig->addUser($user); $this->userConfig->deleteToken($token['id']); } $userBadge = new UserBadge($request->request->get('username'), $this->userProvider->loadUserByIdentifier(...)); $passport = new Passport($userBadge, new PasswordCredentials($request->request->get('password'))); if ($this->userProvider instanceof PasswordUpgraderInterface) { $passport->addBadge(new PasswordUpgradeBadge($request->request->get('password'), $this->userProvider)); } $passport->addBadge(new TotpBadge($request->request->getString('totp'))); return $passport; } public function onAuthenticationFailure(Request $request, AuthenticationException $exception) : Response { if ($exception instanceof InvalidTotpException) { return new JsonResponse(['username' => $exception->getUser()?->getUserIdentifier(), 'totp_enabled' => \true], Response::HTTP_UNAUTHORIZED); } return parent::onAuthenticationFailure($request, $exception); } } cookies->has(self::COOKIE_AUTH)) { return null; } try { return JWT::decode($request->cookies->get(self::COOKIE_AUTH), new Key($this->users->getSecret(), 'HS256')); } catch (\Exception) { return null; } } /** * Checks if the request has a JWT cookie. */ public function hasRequestToken(Request $request) : bool { return $request->cookies->has(self::COOKIE_AUTH); } /** * Checks if the response has a JWT cookie. */ public function hasResponseToken(Response $response) : bool { return $this->hasCookie($response); } /** * Adds JWT auth cookies to the given response. */ public function addToken(Request $request, Response $response, TokenInterface $token) : void { $payload = ['iat' => \time(), 'exp' => \strtotime('+30 minutes'), 'username' => $token->getUserIdentifier(), 'scope' => User::scopeFromRoles($token->getRoleNames())]; $response->headers->setCookie($this->createCookie(JWT::encode($payload, $this->users->getSecret(), 'HS256'), $request)); } /** * Clears the JWT cookie in the response. */ public function removeToken(Request $request, Response $response) : void { if (!$request->cookies->has(self::COOKIE_AUTH)) { return; } $response->headers->clearCookie(self::COOKIE_AUTH, ApiKernel::isPhar() ? $request->getBaseUrl() . '/' : '/', null, $request->isSecure()); } /** * Returns whether the response has a cookie with that name. */ private function hasCookie(Response $response) : bool { $cookies = $response->headers->getCookies(); foreach ($cookies as $cookie) { if (self::COOKIE_AUTH === $cookie->getName()) { return \true; } } return \false; } /** * Creates a cookie configured for Contao Manager. */ private function createCookie(string $value, Request $request) : Cookie { return Cookie::create(self::COOKIE_AUTH, $value, 0, ApiKernel::isPhar() ? $request->getBaseUrl() . '/' : '/', null, $request->isSecure(), \true, \false, Cookie::SAMESITE_STRICT); } } restoreBackgroundProcess('composer-remove'); parent::__construct($process); } catch (\Exception) { $arguments = \array_merge(['composer', 'remove'], $this->removed, ['--no-update', '--no-scripts', '--no-ansi', '--no-interaction']); $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-remove'); parent::__construct($process); } } public function getSummary() : string { return 'composer remove ' . \implode(' ', $this->removed); } } restoreBackgroundProcess('clear-cache')); } catch (\Exception) { parent::__construct($processFactory->createManagerConsoleBackgroundProcess(['composer', 'clear-cache', '--no-interaction'], 'clear-cache')); } } public function getSummary() : string { return 'composer clear-cache'; } } restoreBackgroundProcess('dump-autoload')); } catch (\Exception) { parent::__construct($processFactory->createManagerConsoleBackgroundProcess(['composer', 'dump-autoload', '--optimize'], 'dump-autoload')); } } public function getSummary() : string { return 'composer dump-autoload'; } public function getDetails() : string|null { $total = $this->getTotalClasses($this->process->getOutput()); if (null !== $total) { return $this->translator->trans('taskoperation.dump-autoload.result', ['count' => $total]); } return ''; } private function getTotalClasses(string $output) : string|null { $lines = \explode("\n", $output); foreach ($lines as $line) { if (\preg_match('{Generated optimized autoload files containing ([\\d.]+) classes}', $line, $match)) { return $match[1]; } } return null; } } restoreBackgroundProcess('composer-install'); $retries = (int) $this->taskConfig->getState('install-retry', 0); if ($retry && $retries < 4 && $process->isTerminated() && !$process->isSuccessful()) { $process->delete(); $this->taskConfig->setState('install-retry', ++$retries); throw new \RuntimeException('Install process failed, restarting'); } parent::__construct($process); } catch (\Exception) { $arguments = ['composer', 'install', '--no-dev', '--no-progress', '--no-ansi', '--no-interaction', '--optimize-autoloader']; if ($this->dryRun) { $arguments[] = '--dry-run'; $arguments[] = '--no-scripts'; $arguments[] = '--no-plugins'; } if ($environment->isDebug()) { $arguments[] = '--profile'; $arguments[] = '-vvv'; } $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-install'); // An install task should never need 5min to install $process->setTimeout(60 * 5); parent::__construct($process); } } public function getSummary() : string { $summary = 'composer install'; if ($this->dryRun) { $summary .= ' --dry-run'; } return $summary; } public function getDetails() : string|null { if (!$this->isStarted()) { return null; } if ($this->isRunning() && ($attempt = (int) $this->taskConfig->getState('install-retry', 0)) > 0) { return $this->translator->trans('taskoperation.composer-install.retry', ['current' => $attempt + 1, 'max' => 5]); } if ($this->isSuccessful()) { $output = $this->process->getOutput(); if (\str_contains($output, 'Nothing to install or update')) { return $this->translator->trans('taskoperation.composer-install.nothing'); } $operations = $this->getPackageOperations($output); if (null !== $operations) { return $this->translator->trans('taskoperation.composer-install.result', $operations); } } return ''; } private function getPackageOperations(string $output) : array|null { // Package operations: 6 installs, 85 updates, 0 removals $lines = \explode("\n", $output); foreach ($lines as $line) { if (\false !== ($pos = \strpos($line, 'Package operations:'))) { $operations = \substr($line, $pos); if (\preg_match('{Package operations: (\\d+) installs, (\\d+) updates, (\\d+) removals}', $operations, $match)) { return ['installs' => $match[1], 'updates' => $match[2], 'removals' => $match[3]]; } } } return null; } } restoreBackgroundProcess('composer-update')); } catch (\Exception) { $arguments = \array_merge(['composer', 'update'], $this->packages, ['--with-dependencies', '--no-install', '--no-scripts', '--no-dev', '--no-progress', '--no-ansi', '--no-interaction', '--optimize-autoloader']); if ($this->dryRun) { $arguments[] = '--dry-run'; $arguments[] = '--no-scripts'; $arguments[] = '--no-plugins'; } if ($environment->isDebug()) { $arguments[] = '--profile'; $arguments[] = '-vvv'; } parent::__construct($processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-update')); } } public function getSummary() : string { $summary = 'composer update'; if ([] !== $this->packages) { $summary .= ' ' . \implode(' ', $this->packages); } $summary .= ' --no-install'; if ($this->dryRun) { $summary .= ' --dry-run'; } return $summary; } } restoreBackgroundProcess('composer-require'); parent::__construct($process); } catch (\Exception) { $arguments = \array_merge(['composer', 'require'], $this->required, ['--no-update', '--no-scripts', '--prefer-stable', '--sort-packages', '--no-ansi', '--no-interaction']); $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-require'); parent::__construct($process); } } public function getSummary() : string { return 'composer require ' . \implode(' ', $this->required); } } restoreBackgroundProcess('composer-create-project')); } catch (\Exception) { $folder = \uniqid('contao-'); $arguments = ['composer', 'create-project', $this->package . ($this->version ? ':' . $this->version : ''), $folder, '--no-install', '--no-scripts', '--no-dev', '--no-progress', '--no-ansi', '--no-interaction']; if ($isUpload) { $arguments[] = '--repository=' . \json_encode(['type' => 'artifact', 'url' => $this->environment->getArtifactDir()]); } if ($this->environment->isDebug()) { $arguments[] = '--profile'; $arguments[] = '-vvv'; } $process = $processFactory->createManagerConsoleBackgroundProcess($arguments, 'composer-create-project'); $process->setMeta(['folder' => $folder]); parent::__construct($process); } $this->publicDir = $taskConfig->getState('public-dir'); if (null !== $this->publicDir) { return; } if ($kernel->getProjectDir() === $kernel->getPublicDir()) { throw new \RuntimeException('Cannot install without a public directory.'); } $taskConfig->setState('public-dir', $this->publicDir = $kernel->getPublicDir()); } public function getSummary() : string { return 'composer create-project ' . $this->package . ($this->version ? ':' . $this->version : ''); } public function run() : void { parent::run(); if ($this->process->isSuccessful() && !$this->isInstalled()) { $folder = $this->process->getMeta()['folder'] ?? null; if ($folder) { $fs = new Filesystem(); $files = Finder::create()->exclude(['__MACOSX'])->notName(['theme.xml', '.DS_Store'])->ignoreVCS(\true)->ignoreDotFiles(\true)->depth(0)->in($folder); foreach ($files as $file) { $fs->copy($file->getPathname(), \dirname($file->getPath()) . \DIRECTORY_SEPARATOR . $file->getFilename()); } $fs->removeDirectory($folder); // write public-dir in composer.json try { $file = $this->environment->getComposerJsonFile(); $json = $file->read(); $json['extra']['public-dir'] = \basename((string) $this->publicDir); $file->write($json); } catch (\RuntimeException) { // ignore } $this->process->setMeta(['installed' => \true]); } } } public function isRunning() : bool { return parent::isRunning() || $this->isStarted() && !$this->hasError() && !$this->isInstalled(); } public function isSuccessful() : bool { return parent::isSuccessful() && $this->isInstalled(); } private function isInstalled() : bool { return (bool) ($this->process->getMeta()['installed'] ?? \false); } } changes->getUpdates()) { $summary .= \implode(' ', $this->changes->getUpdates()); } $summary .= ' --no-install'; if ($this->changes->getDryRun()) { $summary .= ' --dry-run'; } return $summary; } public function getDetails() : string|null { $job = $this->getCurrentJob(); if (!$job instanceof CloudJob) { return ''; } switch ($job->getStatus()) { case CloudJob::STATUS_QUEUED: return $this->translator->trans('taskoperation.cloud.queued', ['seconds' => $job->getWaitingTime(), 'jobs' => $job->getJobsInQueue() + $job->getWorkers(), 'workers' => $job->getWorkers()]); case CloudJob::STATUS_PROCESSING: $seconds = $this->taskConfig->getState('cloud-job-processing'); if (!$seconds) { return ''; } $seconds = \time() - $seconds; return $this->translator->trans('taskoperation.cloud.processing', ['seconds' => $seconds]); case CloudJob::STATUS_ERROR: return ''; case CloudJob::STATUS_FINISHED: $seconds = $this->taskConfig->getState('cloud-job-finished', \time()) - $this->taskConfig->getState('cloud-job-processing'); $profile = $this->getFinalProfile($this->getOutput()); \preg_match('{Memory usage: ([^ ]+) \\(peak: ([^)]+)\\), time: ([0-9.]+s)\\.}', $profile, $match); return $this->translator->trans('taskoperation.cloud.finished', ['job' => $job->getId(), 'memory' => $match[1] ?? '', 'peak' => $match[2] ?? '', 'time' => $match[3] ?? '', 'seconds' => $seconds]); } return ''; } public function getConsole() : ConsoleOutput { $console = new ConsoleOutput(); $job = $this->getCurrentJob(); if ($this->exception instanceof CloudException) { return $console->add(\sprintf("> The Composer Resolver Cloud failed with status code %s\n\n %s", $this->exception->getStatusCode(), $this->exception->getErrorMessage())); } if ($this->exception instanceof RequestException && 404 === $this->exception->getStatusCode()) { return $console->add(self::CLOUD_ERROR); } if ($this->exception instanceof \Exception) { return $console->add($this->exception->getMessage()); } if (!$job instanceof CloudJob) { if ($this->hasError()) { $console->add(self::CLOUD_ERROR); } return $console; } $title = '> Resolving dependencies using Composer Cloud ' . $job->getVersion(); switch ($job->getStatus()) { case CloudJob::STATUS_QUEUED: break; case CloudJob::STATUS_PROCESSING: if ($this->environment->isDebug()) { $console->add($this->getOutput(), $title); } else { $console->add($title); } break; case CloudJob::STATUS_ERROR: $console->add(\sprintf("%s\n\n# Cloud Job ID %s failed", $this->getOutput(), $job->getId()), $title); break; case CloudJob::STATUS_FINISHED: $output = $this->getOutput(); $seconds = $this->taskConfig->getState('cloud-job-finished', \time()) - $this->taskConfig->getState('cloud-job-processing'); $profile = $this->getFinalProfile($output); \preg_match('{Memory usage: ([^ ]+) \\(peak: ([^)]+)\\), time: ([0-9.]+s)\\.}', $profile, $match); $console->add($output, $title); $console->add("# Job ID {$job->getId()} completed in {$seconds} seconds\n# " . $profile); break; default: throw new \RuntimeException(\sprintf('Unknown cloud status "%s"', $job->getStatus())); } return $console; } public function isStarted() : bool { try { return null !== $this->taskConfig->getState('cloud-job'); } catch (\Exception $exception) { $this->exception = $exception; return \true; } } public function isRunning() : bool { try { return $this->isStarted() && null === $this->taskConfig->getState('cloud-job-successful'); } catch (\Exception $exception) { $this->exception = $exception; return \false; } } public function isSuccessful() : bool { return (bool) $this->taskConfig->getState('cloud-job-successful', \false); } public function hasError() : bool { return \false === $this->taskConfig->getState('cloud-job-successful'); } public function run() : void { try { if (null === $this->taskConfig->getState('cloud-job')) { // Retry to create Cloud job, the first request always fails on XAMPP for // unknown reason $attempts = (int) $this->taskConfig->getState('cloud-job-attempts', 0); if ($attempts >= 5) { $this->taskConfig->setState('cloud-job-successful', \false); $this->output = self::CLOUD_ERROR; return; } $this->taskConfig->setState('cloud-job-attempts', $attempts + 1); $this->job = $this->cloud->createJob($this->changes, $this->environment); $this->taskConfig->setState('cloud-job', $this->job->getId()); return; } $job = $this->getCurrentJob(); if (!$job instanceof CloudJob) { return; } if ($job->isSuccessful() && !$this->taskConfig->getState('cloud-job-successful', \false)) { if (!$this->validateComposerJson($job)) { $this->taskConfig->setState('cloud-job-successful', \false); return; } $this->filesystem->dumpFile($this->environment->getLockFile(), $this->cloud->getComposerLock($job)); $this->taskConfig->setState('cloud-job-successful', \true); } if ($job->isFailed()) { $this->taskConfig->setState('cloud-job-successful', \false); } } catch (\Exception $exception) { $this->exception = $exception; $this->output = self::CLOUD_ERROR; } } public function abort() : void { $this->taskConfig->setState('cloud-job-successful', \false); } public function delete() : void { try { $this->output = $this->taskConfig->getState('cloud-job-output', ''); $this->cloud->deleteJob((string) $this->taskConfig->getState('cloud-job')); } catch (\Exception $exception) { $this->exception = $exception; } } public function getSponsor() : array|null { if (!$this->job instanceof CloudJob) { return null; } return $this->job->getSponsor(); } private function getCurrentJob() : CloudJob|null { if ($this->job instanceof CloudJob) { return $this->job; } if (null === $this->taskConfig->getState('cloud-job')) { return null; } try { if (\is_array($content = $this->taskConfig->getState('cloud-job-status'))) { $this->job = new CloudJob($content); if (null !== $this->taskConfig->getState('cloud-job-successful')) { $this->output = $this->taskConfig->getState('cloud-job-output', ''); return $this->job; } $lastUpdated = \time() - (int) $this->taskConfig->getState('cloud-job-updated', \time()); $isProcessing = (int) $this->taskConfig->getState('cloud-job-processing', 0) > 0; if ($isProcessing && $lastUpdated <= 5 || $lastUpdated <= 10) { $this->output = $this->taskConfig->getState('cloud-job-output', ''); return $this->job; } } } catch (\Exception $exception) { // do nothing } try { $this->job = $this->cloud->getJob((string) $this->taskConfig->getState('cloud-job')); } catch (\Exception $exception) { $this->exception = $exception; if ($exception instanceof CloudException && $exception->isClientError()) { $this->taskConfig->setState('cloud-job-successful', \false); } return $this->job; } if (!$this->job instanceof CloudJob) { return null; } $this->taskConfig->setState('cloud-job-status', $this->job->jsonSerialize()); $this->taskConfig->setState('cloud-job-updated', \time()); if ($this->job->isProcessing() && !$this->taskConfig->getState('cloud-job-processing')) { $this->taskConfig->setState('cloud-job-processing', \time()); } if (!$this->taskConfig->getState('cloud-job-finished') && ($this->job->isSuccessful() || $this->job->isFailed())) { $this->taskConfig->setState('cloud-job-finished', \time()); } return $this->job; } private function getFinalProfile(string $output) : string { // Memory usage: 353.94MB (peak: 1327.09MB), time: 160.17s $lines = \array_reverse(\explode("\n", $output)); foreach ($lines as $line) { if (\false !== ($pos = \strpos($line, 'Memory usage:'))) { return \substr($line, $pos); } } return ''; } private function getOutput() : string { if (null !== $this->output) { return $this->output; } $job = $this->getCurrentJob(); if (null === $job) { return $this->output = self::CLOUD_ERROR; } try { $this->output = $this->cloud->getOutput($job); if (null === $this->output) { $this->output = self::CLOUD_ERROR; } else { $this->taskConfig->setState('cloud-job-output', $this->output); } return $this->output; } catch (\Exception) { return $this->output = self::CLOUD_ERROR; } } /** * The composer.json of a cloud job must be identical to the local file. If that * is not the case, either an incorrect job is trying to be installed, or the * local composer.json was modified after the cloud job was started. Both cases * are not valid and unsupported. */ private function validateComposerJson(CloudJob $job) : bool { $remoteJson = JsonFile::parseJson($this->cloud->getComposerJson($job)); $localJson = $this->environment->getComposerJson(); return $remoteJson === $localJson; } } translator->trans('taskoperation.install-uploads.summary'); } public function getDetails() : string|null { $files = \array_map(static fn($config) => $config['name'], $this->uploads); return \implode(', ', $files); } public function getConsole() : ConsoleOutput { $console = new ConsoleOutput(); if (!$this->isSuccessful()) { return $console; } $installed = $this->taskConfig->getState($this->getName() . '.files'); if (!empty($installed)) { $console->add(\implode('', \array_map(fn($upload): string => '- ' . $this->translator->trans('taskoperation.install-uploads.console', $upload), $installed))); } return $this->addConsoleOutput($console); } protected function doRun() : bool { $installed = []; foreach ($this->uploads as $config) { $target = \basename((string) $config['package']['dist']['url']); // Ignore if a file is already installed, so it's not deleted on failed operation if ($this->filesystem->exists($this->environment->getArtifactDir() . '/' . $target)) { continue; } $this->filesystem->copy($this->environment->getUploadDir() . '/' . $config['id'], $this->environment->getArtifactDir() . '/' . $target); $installed[$target] = ['name' => $target, 'package' => $config['package']['name'], 'version' => $config['package']['version']]; } $this->taskConfig->setState($this->getName() . '.files', $installed); return \true; } protected function getName() : string { return 'install-uploads'; } } filesystem->remove($this->environment->getVendorDir()); return \true; } protected function getName() : string { return 'remove-vendor'; } } translator->trans('taskoperation.remove-uploads.summary'); } public function getDetails() : string|null { $files = \array_map(static fn($config) => $config['name'], $this->uploads); return \implode(', ', $files); } protected function doRun() : bool { foreach ($this->uploads as $config) { $this->uploadsConfig->remove($config['id']); try { $this->filesystem->remove($this->environment->getUploadDir() . '/' . $config['id']); } catch (IOException) { // Ignore if file could not be deleted } } return \true; } protected function getName() : string { return 'remove-uploads'; } } environment; } protected function doRun() : bool { $this->filesystem->remove($this->getCacheDir()); return \true; } protected function getName() : string { return $this->name . '@' . $this->getCacheDir(); } /** * Gets the Contao cache directory for current environment. */ private function getCacheDir() : string { return $this->kernel->getProjectDir() . '/var/cache/' . $this->environment; } } isSuccessful()) { return $this->translator->trans('taskoperation.self-update.success', ['new' => $this->updater->getOldVersion()]); } return $this->translator->trans('taskoperation.self-update.detail', ['old' => $this->updater->getOldVersion(), 'new' => $this->updater->getNewVersion()]); } protected function doRun() : bool { return $this->updater->update(); } protected function getName() : string { return 'self-update'; } } addConsoleOutput(new ConsoleOutput()); } public function isStarted() : bool { return null !== $this->taskConfig->getState($this->getName()); } public function isRunning() : bool { return TaskStatus::STATUS_ACTIVE === $this->taskConfig->getState($this->getName()); } public function isSuccessful() : bool { return TaskStatus::STATUS_COMPLETE === $this->taskConfig->getState($this->getName()); } public function hasError() : bool { return TaskStatus::STATUS_ERROR === $this->taskConfig->getState($this->getName()); } public function run() : void { // Inline task should never need more than 60secs to complete. Assume something // went wrong. $started = (int) $this->taskConfig->getState($this->getName() . '.started', 0); if ($started > 0 && $started + 60 < \time()) { $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR); $this->taskConfig->setState($this->getName() . '.error', 'Inline operation did not complete within 60 seconds.'); return; } // Do not start the inline task again if it has been started if ($this->isStarted()) { return; } $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ACTIVE); $this->taskConfig->setState($this->getName() . '.started', \time()); $success = null; \register_shutdown_function(function () use(&$success) : void { if (null === $success) { $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR); } }); try { $success = $this->doRun(); } catch (\Throwable $throwable) { $this->taskConfig->setState($this->getName() . '.error', $throwable->getMessage()); $success = \false; } if ($success) { $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_COMPLETE); } else { $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR); } } public function abort() : void { if ($this->isRunning()) { $this->taskConfig->setState($this->getName(), TaskStatus::STATUS_ERROR); } } public function delete() : void { // Do nothing } /** * Adds the exception message to the console output. */ protected function addConsoleOutput(ConsoleOutput $console) : ConsoleOutput { if ($error = $this->taskConfig->getState($this->getName() . '.error')) { $console->add((string) $error); } return $console; } /** * Gets the name to store this operation state in the config file. */ protected abstract function getName() : string; /** * Executes the operation and returns whether it was successful. * * @throws \Exception */ protected abstract function doRun() : bool; } output; } /** * Adds output to the console log. */ public function add(string $output, string|null $title = null) : self { if (null !== $title) { $output = \sprintf("%s\n\n%s", $title, $output); } if ('' === $output) { return $this; } if ('' !== $this->output) { $output = $this->output . "\n\n" . $output; } $this->output = $output; return $this; } } 'SIGHUP', 2 => 'SIGINT', 3 => 'SIGQUIT', 9 => 'SIGKILL', 15 => 'SIGTERM']; public function __construct(protected readonly Process|ProcessController $process) { } public function getDetails() : string|null { return ''; } public function getConsole() : ConsoleOutput { $console = new ConsoleOutput(); if (!$this->process->isStarted()) { return $console; } $console->add($this->process->getOutput() . $this->getProcessError(), '$ ' . $this->process->getCommandLine()); return $console; } public function isStarted() : bool { return $this->process->isStarted(); } public function isRunning() : bool { return $this->process->isRunning(); } public function isSuccessful() : bool { return $this->process->isSuccessful(); } public function hasError() : bool { return $this->process->isTerminated() && $this->process->getExitCode() > 0; } public function run() : void { if (!$this->process->isStarted()) { $this->process->start(); } } public function abort() : void { if ($this->isRunning()) { $this->process->stop(); } } public function delete() : void { $this->process->delete(); } protected function getProcessError() : string { $output = ''; if ($this->process->isTerminated()) { $signal = ''; if ($this->process->hasBeenSignaled()) { $signal = $this->getSignalText($this->process->getTermSignal()); } elseif ($this->process->hasBeenStopped()) { $signal = $this->getSignalText($this->process->getStopSignal()); } if ($this->process instanceof ProcessController && $this->process->getForker() instanceof InlineForker) { $output = <<<'OUTPUT' # WARNING: INLINE PROCESS EXECUTION # Background processes are not support by your server/shell. # The operation might have be affected by script runtime (e.g. stop after 30 seconds). # OUTPUT; } $output .= \sprintf("\n# Process terminated with exit code %s\n# Result: %s%s\n", $this->process->getExitCode(), $this->process->getExitCodeText(), $signal); } return $output; } private function getSignalText(int|null $signal) : string { if (isset(self::SIGNALS[$signal])) { return \sprintf(' [%s]', self::SIGNALS[$signal]); } return \sprintf(' [signal %s]', $signal); } } state; } protected function getName() : string { return 'maintenance-' . $this->state; } protected function doRun() : bool { $process = $this->processFactory->createContaoConsoleProcess(['contao:maintenance-mode', $this->state, '--no-interaction']); $process->run(); return $process->isSuccessful(); } } restoreBackgroundProcess($processId)); } catch (\Exception) { parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['contao:backup:create'], $processId)); } } public function getSummary() : string { return 'vendor/bin/contao-console contao:backup:create'; } } restoreBackgroundProcess($processId)); } catch (\Exception) { parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['cache:warmup', '--env=' . $environment], $processId)); } } public function getSummary() : string { return 'vendor/bin/contao-console cache:warmup'; } } version = $taskConfig->getOption('version'); $this->publicDir = $taskConfig->getState('public-dir'); if (!\in_array($this->version, self::SUPPORTED_VERSIONS, \true)) { throw new \InvalidArgumentException('Unsupported Contao version'); } if (null !== $this->publicDir) { return; } if ($kernel->getProjectDir() === $kernel->getPublicDir()) { throw new \RuntimeException('Cannot install without a public directory.'); } $taskConfig->setState('public-dir', $this->publicDir = $kernel->getPublicDir()); } public function getSummary() : string { return 'composer create-project contao/managed-edition:' . $this->version; } protected function getName() : string { return 'create-project'; } protected function doRun() : bool { $protected = [$this->environment->getJsonFile(), $this->environment->getLockFile(), $this->environment->getVendorDir()]; if ($this->filesystem->exists($protected)) { throw new \RuntimeException('Cannot install into existing application'); } $this->filesystem->dumpFile($this->environment->getJsonFile(), $this->generateComposerJson($this->taskConfig->getOption('version'), (bool) $this->taskConfig->getOption('core-only', \false))); return \true; } private function generateComposerJson(string $version, bool $coreOnly = \false) : string { $coreBundle = ''; if ($this->isDevVersion($version)) { $version .= '.x-dev'; $coreBundle = ', "contao/core-bundle": "' . $version . '"'; } else { $version .= '.*'; } if ($coreOnly) { $require = <<=')) { $publicDir = \basename((string) $this->publicDir); $script = '@php vendor/bin/contao-setup'; } else { $publicDir = 'web'; $script = 'Contao\\\\ManagerBundle\\\\Composer\\\\ScriptHandler::initializeApplication'; } return <<restoreBackgroundProcess($processId)); } catch (\Exception) { parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['contao:backup:restore', $this->file], $processId)); } } public function getSummary() : string { return 'vendor/bin/contao-console contao:backup:restore ' . $this->file; } } restoreBackgroundProcess($processId)); } catch (\Exception) { parent::__construct($processFactory->createContaoConsoleBackgroundProcess(['cache:clear', '--env=' . $environment, '--no-warmup'], $processId)); } } public function getSummary() : string { return 'vendor/bin/contao-console cache:clear --no-warmup'; } } 'tasks'])] class CloudResolver implements LoggerAwareInterface { use LoggerAwareTrait; private const API_URL = 'https://www.composer-resolver.cloud'; public function __construct(private Request $request) { } /** * Creates a Cloud job for given composer changes. */ public function createJob(CloudChanges $changes, Environment $environment) : CloudJob { $environment->reset(); $data = ['composerJson' => $environment->getComposerJson(), 'composerLock' => $environment->getComposerLock(), 'platform' => $environment->getPlatformPackages(), 'localPackages' => $environment->getLocalPackages()]; $command = $changes->getUpdates(); $command[] = '--with-dependencies'; $command[] = '--profile'; if ($environment->isDebug()) { $command[] = '-vvv'; } $body = \json_encode($data); $headers = ['Composer-Resolver-Client: contao', 'Composer-Resolver-Command: ' . \implode(' ', $command)]; if (null !== $this->logger) { $this->logger->info('Creating Composer Cloud job', ['headers' => $headers, 'body' => $body]); } $content = $this->request->postJson(self::API_URL . '/jobs', $body, $headers, $statusCode); switch ($statusCode) { case 200: case 201: case 202: // Location redirect to fetch the job content return new CloudJob(JsonFile::parseJson($content)); case 400: throw new CloudException('Composer Resolver did not accept the API call', $statusCode, $content, $body); case 503: throw new CloudException('Too many jobs on the Composer Resolver queue.', $statusCode, $content, $body); default: throw $this->createUnknownResponseException($statusCode, $content, $body); } } /** * Gets job information from the Composer Cloud. */ public function getJob(string $jobId) : CloudJob|null { if ('' === $jobId) { return null; } $content = $this->request->getJson(self::API_URL . '/jobs/' . $jobId, ['Composer-Resolver-Client: contao'], $statusCode); return match ($statusCode) { 200, 202 => new CloudJob(JsonFile::parseJson($content)), default => throw $this->createUnknownResponseException($statusCode, $content), }; } /** * Deletes a cloud job and returns whether it was successful. */ public function deleteJob(string $jobId) : bool { if ('' === $jobId) { return \false; } $content = $this->request->deleteJson(self::API_URL . '/jobs/' . $jobId, ['Composer-Resolver-Client: contao'], $statusCode); if (204 === $statusCode) { return \true; } throw $this->createUnknownResponseException($statusCode, $content); } /** * Gets the composer.json file. */ public function getComposerJson(CloudJob $job) : string { return $this->getContent($job->getLink(CloudJob::LINK_JSON)); } /** * Gets the composer.lock file or null if the cloud job was not successful. */ public function getComposerLock(CloudJob $job) : string|null { if (!$job->isSuccessful()) { return null; } return $this->getContent($job->getLink(CloudJob::LINK_LOCK)); } /** * Gets the console output for a cloud job. */ public function getOutput(CloudJob $job) : string|null { if ($job->isQueued()) { return null; } return $this->getContent($job->getLink(CloudJob::LINK_OUTPUT)); } private function getContent(string $link) : string { $content = $this->request->getJson(self::API_URL . $link, ['Composer-Resolver-Client: contao'], $statusCode, \true); if (200 === $statusCode) { return $content; } throw $this->createUnknownResponseException($statusCode, $content); } private function createUnknownResponseException(int|null $statusCode, string|null $responseBody, string|null $requestBody = null) : CloudException { return new CloudException('Composer Resolver returned an unexpected status code', (int) $statusCode, (string) $responseBody, $requestBody); } } remove[$packageName]); $this->require[$packageName] = $version ? $packageName . '=' . $version : $packageName; $this->addUpdate($packageName); } public function getRequiredPackages() : array { return $this->require; } public function removePackage(string $packageName) : void { unset($this->require[$packageName]); $this->remove[$packageName] = $packageName; $this->addUpdate($packageName); } public function getRemovedPackages() : array { return $this->remove; } public function setUpdates(array $updates) : void { $this->updates = []; foreach ($updates as $packageName) { $this->updates[$packageName] = $packageName; } } public function addUpdate(string $packageName) : void { $this->updates[$packageName] = $packageName; } public function getUpdates() : array { return \array_values($this->updates); } public function setDryRun(bool $dryRun) : void { $this->dryRun = $dryRun; } public function getDryRun() : bool { return $this->dryRun; } } result['jobId']; } public function getStatus() : string { return $this->result['status']; } public function getLink(string $name) : string|null { return $this->result['links'][$name] ?? null; } public function getSponsor() : array { return $this->result['sponsoredBy']; } public function getWaitingTime() : int { if (self::STATUS_QUEUED !== $this->result['status']) { return 0; } $currentPos = $this->result['queuePosition'] ?: $this->result['stats']['numberOfJobsInQueue']; return (int) \round($currentPos * $this->result['stats']['averageProcessingTimeInMs'] / 1000 / \max($this->result['stats']['numberOfWorkers'], 1)); } public function getJobsInQueue() : int { return (int) $this->result['queuePosition'] ?: $this->result['stats']['numberOfJobsInQueue']; } public function getWorkers() : int { return (int) $this->result['stats']['numberOfWorkers']; } public function getVersion() : string { return isset($this->result['stats']['appVersion']) ? 'v' . $this->result['stats']['appVersion'] : ''; } public function isQueued() : bool { return self::STATUS_QUEUED === $this->getStatus(); } public function isProcessing() : bool { return self::STATUS_PROCESSING === $this->getStatus(); } public function isSuccessful() : bool { return self::STATUS_FINISHED === $this->getStatus(); } public function isFailed() : bool { return self::STATUS_ERROR === $this->getStatus(); } public function jsonSerialize() : array { return $this->result; } } getCode(); } /** * Returns the Cloud error message or the exception message as fallback. */ public function getErrorMessage() : string { $message = $this->getMessage() . "\n\nResponse:\n" . $this->responseBody; if ($this->requestBody) { $message .= "\n\nRequest:\n" . $this->requestBody; } return $message; } public function isInvalid() : bool { return $this->getStatusCode() < 100 || $this->getStatusCode() >= 600; } public function isInformational() : bool { return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200; } public function isSuccessful() : bool { return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300; } public function isRedirection() : bool { return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400; } public function isClientError() : bool { return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500; } public function isServerError() : bool { return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600; } } composer = null; } /** * Returns whether debug mode is activated. */ public function isDebug() : bool { return $this->kernel->isDebug(); } /** * Gets path to the directory where all Contao Manager related information is stored. */ public function getBackupDir() : string { return $this->kernel->getConfigDir(); } /** * Gets path to the composer.json file in the Contao root. */ public function getJsonFile() : string { return $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'composer.json'; } /** * Gets path to the composer.lock file in the Contao root. */ public function getLockFile() : string { return $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'composer.lock'; } /** * Gets the directory where Composer installs its packages to. */ public function getVendorDir() : string { return $this->kernel->getProjectDir() . \DIRECTORY_SEPARATOR . 'vendor'; } /** * Gets the directory where uploads are stored to. These are temporary and only * until they are installed as artifact or provider. */ public function getUploadDir() : string { $dir = $this->kernel->getConfigDir() . '/uploads'; $this->filesystem->mkdir($dir); return $dir; } /** * Gets the path where artifacts are installed to. Artifacts are ZIP files that * contain Composer packages. * * @see https://getcomposer.org/doc/05-repositories.md#artifact */ public function getArtifactDir() : string { $dir = $this->kernel->getConfigDir() . '/packages'; $this->filesystem->mkdir($dir); return $dir; } /** * Gets list of file names in the artifacts directory. */ public function getArtifacts() : array { $files = []; $finder = (new Finder())->files()->depth(0)->in($this->getArtifactDir()); foreach ($finder->getIterator() as $file) { $files[] = $file->getFilename(); } return $files; } /** * Gets the Composer instance. */ public function getComposer(bool $reload = \false) : Composer { $this->composerConfig->allowPlugins(); if (null === $this->composer || $reload) { $this->composer = Factory::create(new NullIO(), $this->getJsonFile()); } return $this->composer; } /** * Gets whether the Cloud resolver is enabled in the Manager configuration. */ public function useCloudResolver() : bool { return !$this->managerConfig->get('disable_cloud', \false); } public function getComposerJsonFile() : JsonFile { $file = $this->getComposer()->getConfig()->getConfigSource()->getName(); return new JsonFile($file); } public function getComposerJson() : array { $json = $this->getComposerJsonFile()->read(); $repositories = $this->getComposer()->getConfig()->getRepositories(); unset($repositories['packagist.org']); if ([] !== $repositories || !empty($json['repositories'])) { $json['repositories'] = []; foreach ($repositories as $repository) { if (isset($repository['url'])) { $repository['url'] = $this->normalizeRepositoryPath($repository['url']); } $json['repositories'][] = $repository; } } return $json; } public function getComposerLockFile() : JsonFile { return new JsonFile($this->getLockFile()); } public function getComposerLock() : array { $locker = $this->getComposer()->getLocker(); if (!$locker->isLocked()) { return []; } return $locker->getLockData(); } public function getPlatformPackages() : array { $platformOverrides = $this->getComposer()->getConfig()->get('platform'); $platform = []; foreach ((new PlatformRepository([], $platformOverrides))->getPackages() as $package) { if (\in_array($package->getName(), ['composer-plugin-api', 'composer-runtime-api'], \true)) { continue; } $platform[$package->getName()] = $package->getVersion(); } return $platform; } public function getLocalPackages() : array { $packages = []; $repositories = $this->getComposer()->getRepositoryManager()->getRepositories(); $dumper = new ArrayDumper(); foreach ($repositories as $repository) { if ($repository instanceof ArtifactRepository || $repository instanceof PathRepository) { foreach ($repository->getPackages() as $package) { $dump = $dumper->dump($package); if (isset($dump['dist']['path'])) { $dump['dist']['path'] = $this->normalizeRepositoryPath($dump['dist']['path']); } // see https://github.com/composer/composer/issues/7955 unset($dump['dist']['reference']); $packages[] = $dump; } } } return $packages; } public function hasPackage(string $packageName) : bool { try { $json = $this->getComposerJson(); return isset($json['require'][$packageName]); } catch (\Exception) { return \false; } } public function mergeMetadata(array $package, string|null $language = null) : array { if (isset($package['source']) || \preg_match('{https?://}', $package['dist']['url'] ?? '') || empty($package['extra']['contao-metadata-url'])) { return $package; } try { $headers = []; if ($language) { $headers[] = 'Accept-Language: ' . $language; } if ($package['version'] ?? null) { $headers[] = 'Contao-Package-Version: ' . $package['version']; } $metadata = JsonFile::parseJson($this->request->getJson($package['extra']['contao-metadata-url'], $headers), $package['extra']['contao-metadata-url']); if (\is_array($metadata)) { // Make sure only allowed keys are preserved in metadata $metadata = \array_intersect_key($metadata, \array_flip(['title', 'description', 'homepage', 'suggest', 'support', 'funding', 'abandoned', 'logo'])); // Do not allow custom logo URLs since they could track the Contao Manager user/browser if (isset($metadata['logo']) && \preg_match('{https?://}i', (string) $metadata['logo'])) { unset($metadata['logo']); } return \array_merge($package, $metadata, ['private' => \true]); } } catch (\Exception) { } return $package; } private function normalizeRepositoryPath(string $path) : string { if (null === $this->composerFs) { $this->composerFs = new \Composer\Util\Filesystem(); } $normalizedPath = $this->composerFs->normalizePath($path); if (\str_starts_with($path, './')) { return './' . $normalizedPath; } return $normalizedPath; } } a:35:{i:0;O:51:"Symfony\Component\Config\Resource\DirectoryResource":2:{s:61:"Symfony\Component\Config\Resource\DirectoryResourceresource";s:82:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller";s:60:"Symfony\Component\Config\Resource\DirectoryResourcepattern";s:8:"/\.php$/";}i:1;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Config/AuthController.php";}i:2;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Config/ComposerController.php";}i:3;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Config/ManagerController.php";}i:4;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/ConstraintController.php";}i:5;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/AccessKeyController.php";}i:6;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/BackupController.php";}i:7;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/DatabaseMigrationController.php";}i:8;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/InstallToolLockController.php";}i:9;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/JwtCookieController.php";}i:10;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/MaintenanceModeController.php";}i:11;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/FileController.php";}i:12;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:100:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/LogController.php";}i:13;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/CloudController.php";}i:14;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/LocalPackagesController.php";}i:15;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/MissingPackagesController.php";}i:16;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:117:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/RootPackageController.php";}i:17;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/UploadPackagesController.php";}i:18;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/AdminUserController.php";}i:19;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/ComposerController.php";}i:20;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/ConfigController.php";}i:21;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/ContaoController.php";}i:22;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/DatabaseController.php";}i:23;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/OpcacheController.php";}i:24;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/PhpCliController.php";}i:25;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/PhpWebController.php";}i:26;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/PhpinfoController.php";}i:27;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/SelfUpdateController.php";}i:28;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:104:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/SessionController.php";}i:29;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/TaskController.php";}i:30;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/UserController.php";}i:31;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:85:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/ApiKernel.php";}i:32;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/vendor/symfony/http-kernel/Kernel.php";}i:33;O:72:"Symfony\Component\DependencyInjection\Config\ContainerParametersResource":1:{s:84:"Symfony\Component\DependencyInjection\Config\ContainerParametersResourceparameters";a:0:{}}i:34;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:132:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.php";}} 'HxlxvCx', 'container.build_id' => '261f1c67', 'container.build_time' => 1739992507, 'container.runtime_mode' => \in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true) ? 'web=0' : 'web=1'], __DIR__ . \DIRECTORY_SEPARATOR . 'ContainerHxlxvCx'); [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController'], [], [['text', '/api/config/auth']], [], [], []], 'contao_managerapi_config_auth_putgithubtoken' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController::putGithubToken'], [], [['text', '/api/config/auth/github-oauth']], [], [], []], 'contao_managerapi_config_composer__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController'], [], [['text', '/api/config/composer']], [], [], []], 'contao_managerapi_config_manager__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController'], [], [['text', '/api/config/manager']], [], [], []], 'contao_managerapi_constraint__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController'], [], [['text', '/api/constraint']], [], [], []], 'contao_managerapi_contao_accesskey__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController'], [], [['text', '/api/contao/access-key']], [], [], []], 'contao_managerapi_contao_backup__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController'], [], [['text', '/api/contao/backup']], [], [], []], 'contao_managerapi_contao_databasemigration__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController'], [], [['text', '/api/contao/database-migration']], [], [], []], 'contao_managerapi_contao_installtoollock__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController'], [], [['text', '/api/contao/install-tool/lock']], [], [], []], 'contao_managerapi_contao_jwtcookie__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController'], [], [['text', '/api/contao/jwt-cookie']], [], [], []], 'contao_managerapi_contao_maintenancemode__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController'], [], [['text', '/api/contao/maintenance-mode']], [], [], []], 'contao_managerapi_file__invoke' => [['file'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController'], [], [['variable', '/', '[^/]++', 'file', \true], ['text', '/api/files']], [], [], []], 'contao_managerapi_log_listfiles' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::listFiles'], [], [['text', '/api/logs']], [], [], []], 'contao_managerapi_log_retrievefile' => [['filename'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::retrieveFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], 'contao_managerapi_log_deletefile' => [['filename'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::deleteFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], 'contao_managerapi_packages_cloud_getclouddata' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::getCloudData'], [], [['text', '/api/packages/cloud']], [], [], []], 'contao_managerapi_packages_cloud_writeandinstall' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::writeAndInstall'], [], [['text', '/api/packages/cloud']], [], [], []], 'contao_managerapi_packages_localpackages__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController'], [], [['text', '/api/packages/local']], [], [], []], 'contao_managerapi_packages_localpackages__invoke_1' => [['name'], ['name' => null, '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController'], ['name' => '.+'], [['variable', '/', '.+', 'name', \true], ['text', '/api/packages/local']], [], [], []], 'contao_managerapi_packages_missingpackages__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController'], [], [['text', '/api/packages/missing']], [], [], []], 'contao_managerapi_packages_rootpackage__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController'], [], [['text', '/api/packages/root']], [], [], []], 'contao_managerapi_packages_uploadpackages__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController'], [], [['text', '/api/packages/uploads']], [], [], []], 'contao_managerapi_packages_uploadpackages_upload' => [[], ['form-data' => \true, '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::upload'], [], [['text', '/api/packages/uploads']], [], [], []], 'contao_managerapi_packages_uploadpackages_delete' => [['id'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::delete'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/api/packages/uploads']], [], [], []], 'contao_managerapi_server_adminuser__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController'], [], [['text', '/api/server/admin-user']], [], [], []], 'contao_managerapi_server_composer__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController'], [], [['text', '/api/server/composer']], [], [], []], 'contao_managerapi_server_config_getconfig' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::getConfig'], [], [['text', '/api/server/config']], [], [], []], 'contao_managerapi_server_config_setconfig' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::setConfig'], [], [['text', '/api/server/config']], [], [], []], 'contao_managerapi_server_contao__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController'], [], [['text', '/api/server/contao']], [], [], []], 'contao_managerapi_server_contao_update' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::update'], [], [['text', '/api/server/contao']], [], [], []], 'contao_managerapi_server_database__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController'], [], [['text', '/api/server/database']], [], [], []], 'contao_managerapi_server_database_write' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::write'], [], [['text', '/api/server/database']], [], [], []], 'contao_managerapi_server_opcache_getopcache' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::getOpcache'], [], [['text', '/api/server/opcache']], [], [], []], 'contao_managerapi_server_opcache_deleteopcache' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::deleteOpcache'], [], [['text', '/api/server/opcache']], [], [], []], 'contao_managerapi_server_phpcli__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController'], [], [['text', '/api/server/php-cli']], [], [], []], 'contao_managerapi_server_phpweb__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController'], [], [['text', '/api/server/php-web']], [], [], []], 'contao_managerapi_server_phpinfo__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController'], [], [['text', '/api/server/phpinfo']], [], [], []], 'contao_managerapi_server_selfupdate__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController'], [], [['text', '/api/server/self-update']], [], [], []], 'contao_managerapi_session__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController'], [], [['text', '/api/session']], [], [], []], 'contao_managerapi_session_getwebauthnoptions' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController::getWebauthnOptions'], [], [['text', '/api/session/options']], [], [], []], 'contao_managerapi_task__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController'], [], [['text', '/api/task']], [], [], []], 'contao_managerapi_user_listusers' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listUsers'], [], [['text', '/api/users']], [], [], []], 'contao_managerapi_user_createuser' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createUser'], [], [['text', '/api/users']], [], [], []], 'user_get' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_replaceuser' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::replaceUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_deleteuser' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_setpassword' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setPassword'], [], [['text', '/password'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_gettotp' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::getTOTP'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_setuptotp' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setupTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_deletetotp' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_listtokens' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listTokens'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_createtoken' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createToken'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_retrievetoken' => [['username', 'id'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_deletetoken' => [['username', 'id'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], 'contao_managerapi_user_inviteuser' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::inviteUser'], [], [['text', '/api/invitations']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController'], [], [['text', '/api/config/auth']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController::putGithubToken' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController::putGithubToken'], [], [['text', '/api/config/auth/github-oauth']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController'], [], [['text', '/api/config/composer']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController'], [], [['text', '/api/config/composer']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController'], [], [['text', '/api/config/manager']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController'], [], [['text', '/api/config/manager']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController'], [], [['text', '/api/constraint']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController'], [], [['text', '/api/constraint']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController'], [], [['text', '/api/contao/access-key']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController'], [], [['text', '/api/contao/access-key']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController'], [], [['text', '/api/contao/backup']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController'], [], [['text', '/api/contao/backup']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController'], [], [['text', '/api/contao/database-migration']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController'], [], [['text', '/api/contao/database-migration']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController'], [], [['text', '/api/contao/install-tool/lock']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController'], [], [['text', '/api/contao/install-tool/lock']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController'], [], [['text', '/api/contao/jwt-cookie']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController'], [], [['text', '/api/contao/jwt-cookie']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController'], [], [['text', '/api/contao/maintenance-mode']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController'], [], [['text', '/api/contao/maintenance-mode']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController' => [['file'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController'], [], [['variable', '/', '[^/]++', 'file', \true], ['text', '/api/files']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController::__invoke' => [['file'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController'], [], [['variable', '/', '[^/]++', 'file', \true], ['text', '/api/files']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::listFiles' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::listFiles'], [], [['text', '/api/logs']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::retrieveFile' => [['filename'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::retrieveFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::deleteFile' => [['filename'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::deleteFile'], [], [['variable', '/', '[^/]++', 'filename', \true], ['text', '/api/logs']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::getCloudData' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::getCloudData'], [], [['text', '/api/packages/cloud']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::writeAndInstall' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::writeAndInstall'], [], [['text', '/api/packages/cloud']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController'], [], [['text', '/api/packages/missing']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController'], [], [['text', '/api/packages/missing']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController'], [], [['text', '/api/packages/root']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController'], [], [['text', '/api/packages/root']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController'], [], [['text', '/api/packages/uploads']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::upload' => [[], ['form-data' => \true, '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::upload'], [], [['text', '/api/packages/uploads']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::delete' => [['id'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::delete'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/api/packages/uploads']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController'], [], [['text', '/api/server/admin-user']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController'], [], [['text', '/api/server/admin-user']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController'], [], [['text', '/api/server/composer']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController'], [], [['text', '/api/server/composer']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::getConfig' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::getConfig'], [], [['text', '/api/server/config']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::setConfig' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::setConfig'], [], [['text', '/api/server/config']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController'], [], [['text', '/api/server/contao']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::update' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::update'], [], [['text', '/api/server/contao']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController'], [], [['text', '/api/server/database']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::write' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::write'], [], [['text', '/api/server/database']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::getOpcache' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::getOpcache'], [], [['text', '/api/server/opcache']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::deleteOpcache' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::deleteOpcache'], [], [['text', '/api/server/opcache']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController'], [], [['text', '/api/server/php-cli']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController'], [], [['text', '/api/server/php-cli']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController'], [], [['text', '/api/server/php-web']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController'], [], [['text', '/api/server/php-web']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController'], [], [['text', '/api/server/phpinfo']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController'], [], [['text', '/api/server/phpinfo']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController'], [], [['text', '/api/server/self-update']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController'], [], [['text', '/api/server/self-update']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController'], [], [['text', '/api/session']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController::getWebauthnOptions' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController::getWebauthnOptions'], [], [['text', '/api/session/options']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController'], [], [['text', '/api/task']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController::__invoke' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController'], [], [['text', '/api/task']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listUsers' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listUsers'], [], [['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createUser' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createUser'], [], [['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveUser' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::replaceUser' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::replaceUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteUser' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteUser'], [], [['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setPassword' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setPassword'], [], [['text', '/password'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::getTOTP' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::getTOTP'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setupTotp' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setupTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteTotp' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteTotp'], [], [['text', '/totp'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listTokens' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listTokens'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createToken' => [['username'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createToken'], [], [['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveToken' => [['username', 'id'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteToken' => [['username', 'id'], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteToken'], [], [['variable', '/', '[^/]++', 'id', \true], ['text', '/tokens'], ['variable', '/', '[^/]++', 'username', \true], ['text', '/api/users']], [], [], []], '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::inviteUser' => [[], ['_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::inviteUser'], [], [['text', '/api/invitations']], [], [], []]]; [[['_route' => 'contao_managerapi_config_auth__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2], null, \false, \false, null]], '/api/config/auth/github-oauth' => [[['_route' => 'contao_managerapi_config_auth_putgithubtoken', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController::putGithubToken'], null, ['PUT' => 0], null, \false, \false, null]], '/api/config/composer' => [[['_route' => 'contao_managerapi_config_composer__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2], null, \false, \false, null]], '/api/config/manager' => [[['_route' => 'contao_managerapi_config_manager__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2], null, \false, \false, null]], '/api/constraint' => [[['_route' => 'contao_managerapi_constraint__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController'], null, ['POST' => 0], null, \false, \false, null]], '/api/contao/access-key' => [[['_route' => 'contao_managerapi_contao_accesskey__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]], '/api/contao/backup' => [[['_route' => 'contao_managerapi_contao_backup__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController'], null, ['GET' => 0], null, \false, \false, null]], '/api/contao/database-migration' => [[['_route' => 'contao_managerapi_contao_databasemigration__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]], '/api/contao/install-tool/lock' => [[['_route' => 'contao_managerapi_contao_installtoollock__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]], '/api/contao/jwt-cookie' => [[['_route' => 'contao_managerapi_contao_jwtcookie__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]], '/api/contao/maintenance-mode' => [[['_route' => 'contao_managerapi_contao_maintenancemode__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController'], null, ['GET' => 0, 'PUT' => 1, 'DELETE' => 2], null, \false, \false, null]], '/api/logs' => [[['_route' => 'contao_managerapi_log_listfiles', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::listFiles'], null, ['GET' => 0], null, \false, \false, null]], '/api/packages/cloud' => [[['_route' => 'contao_managerapi_packages_cloud_getclouddata', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::getCloudData'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_packages_cloud_writeandinstall', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController::writeAndInstall'], null, ['PUT' => 0], null, \false, \false, null]], '/api/packages/local' => [[['_route' => 'contao_managerapi_packages_localpackages__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController'], null, ['GET' => 0], null, \false, \false, null]], '/api/packages/missing' => [[['_route' => 'contao_managerapi_packages_missingpackages__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController'], null, ['GET' => 0], null, \false, \false, null]], '/api/packages/root' => [[['_route' => 'contao_managerapi_packages_rootpackage__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController'], null, ['GET' => 0], null, \false, \false, null]], '/api/packages/uploads' => [[['_route' => 'contao_managerapi_packages_uploadpackages__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_packages_uploadpackages_upload', 'form-data' => \true, '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::upload'], null, ['POST' => 0], null, \false, \false, null]], '/api/server/admin-user' => [[['_route' => 'contao_managerapi_server_adminuser__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController'], null, ['GET' => 0, 'POST' => 1], null, \false, \false, null]], '/api/server/composer' => [[['_route' => 'contao_managerapi_server_composer__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController'], null, ['GET' => 0], null, \false, \false, null]], '/api/server/config' => [[['_route' => 'contao_managerapi_server_config_getconfig', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::getConfig'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_config_setconfig', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController::setConfig'], null, ['PUT' => 0], null, \false, \false, null]], '/api/server/contao' => [[['_route' => 'contao_managerapi_server_contao__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_contao_update', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::update'], null, ['POST' => 0], null, \false, \false, null]], '/api/server/database' => [[['_route' => 'contao_managerapi_server_database__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_database_write', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::write'], null, ['POST' => 0], null, \false, \false, null]], '/api/server/opcache' => [[['_route' => 'contao_managerapi_server_opcache_getopcache', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::getOpcache'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_server_opcache_deleteopcache', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController::deleteOpcache'], null, ['DELETE' => 0], null, \false, \false, null]], '/api/server/php-cli' => [[['_route' => 'contao_managerapi_server_phpcli__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController'], null, ['GET' => 0], null, \false, \false, null]], '/api/server/php-web' => [[['_route' => 'contao_managerapi_server_phpweb__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController'], null, ['GET' => 0], null, \false, \false, null]], '/api/server/phpinfo' => [[['_route' => 'contao_managerapi_server_phpinfo__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController'], null, ['GET' => 0], null, \false, \false, null]], '/api/server/self-update' => [[['_route' => 'contao_managerapi_server_selfupdate__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController'], null, ['GET' => 0], null, \false, \false, null]], '/api/session' => [[['_route' => 'contao_managerapi_session__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController'], null, ['GET' => 0, 'POST' => 1, 'DELETE' => 2], null, \false, \false, null]], '/api/session/options' => [[['_route' => 'contao_managerapi_session_getwebauthnoptions', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController::getWebauthnOptions'], null, ['GET' => 0, 'POST' => 1], null, \false, \false, null]], '/api/task' => [[['_route' => 'contao_managerapi_task__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController'], null, ['GET' => 0, 'PUT' => 1, 'PATCH' => 2, 'DELETE' => 3], null, \false, \false, null]], '/api/users' => [[['_route' => 'contao_managerapi_user_listusers', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listUsers'], null, ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_createuser', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createUser'], null, ['POST' => 0], null, \false, \false, null]], '/api/invitations' => [[['_route' => 'contao_managerapi_user_inviteuser', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::inviteUser'], null, ['POST' => 0], null, \false, \false, null]], ], [ // $regexpList 0 => '{^(?' . '|/api/(?' . '|files/([^/]++)(*:29)' . '|logs/([^/]++)(?' . '|(*:52)' . ')' . '|packages/(?' . '|local(?:/(.+))?(*:87)' . '|uploads/([^/]++)(*:110)' . ')' . '|users/([^/]++)(?' . '|(*:136)' . '|/(?' . '|password(*:156)' . '|to(?' . '|tp(?' . '|(*:174)' . ')' . '|kens(?' . '|(*:190)' . '|/([^/]++)(?' . '|(*:210)' . ')' . ')' . ')' . ')' . ')' . ')' . ')/?$}sDu', ], [ // $dynamicRoutes 29 => [[['_route' => 'contao_managerapi_file__invoke', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController'], ['file'], ['GET' => 0, 'PUT' => 1], null, \false, \true, null]], 52 => [[['_route' => 'contao_managerapi_log_retrievefile', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::retrieveFile'], ['filename'], ['GET' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_log_deletefile', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController::deleteFile'], ['filename'], ['DELETE' => 0], null, \false, \true, null]], 87 => [[['_route' => 'contao_managerapi_packages_localpackages__invoke_1', 'name' => null, '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController'], ['name'], ['GET' => 0], null, \false, \true, null]], 110 => [[['_route' => 'contao_managerapi_packages_uploadpackages_delete', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController::delete'], ['id'], ['DELETE' => 0], null, \false, \true, null]], 136 => [[['_route' => 'user_get', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveUser'], ['username'], ['GET' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_user_replaceuser', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::replaceUser'], ['username'], ['PUT' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_user_deleteuser', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteUser'], ['username'], ['DELETE' => 0], null, \false, \true, null]], 156 => [[['_route' => 'contao_managerapi_user_setpassword', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setPassword'], ['username'], ['PUT' => 0], null, \false, \false, null]], 174 => [[['_route' => 'contao_managerapi_user_gettotp', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::getTOTP'], ['username'], ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_setuptotp', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::setupTotp'], ['username'], ['PUT' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_deletetotp', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteTotp'], ['username'], ['DELETE' => 0], null, \false, \false, null]], 190 => [[['_route' => 'contao_managerapi_user_listtokens', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::listTokens'], ['username'], ['GET' => 0], null, \false, \false, null], [['_route' => 'contao_managerapi_user_createtoken', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::createToken'], ['username'], ['POST' => 0], null, \false, \false, null]], 210 => [[['_route' => 'contao_managerapi_user_retrievetoken', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::retrieveToken'], ['username', 'id'], ['GET' => 0], null, \false, \true, null], [['_route' => 'contao_managerapi_user_deletetoken', '_controller' => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController::deleteToken'], ['username', 'id'], ['DELETE' => 0], null, \false, \true, null], [null, null, null, null, \false, \false, 0]], ], null, ]; a:35:{i:0;O:51:"Symfony\Component\Config\Resource\DirectoryResource":2:{s:61:"Symfony\Component\Config\Resource\DirectoryResourceresource";s:82:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller";s:60:"Symfony\Component\Config\Resource\DirectoryResourcepattern";s:8:"/\.php$/";}i:1;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:108:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Config/AuthController.php";}i:2;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Config/ComposerController.php";}i:3;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Config/ManagerController.php";}i:4;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:107:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/ConstraintController.php";}i:5;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/AccessKeyController.php";}i:6;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/BackupController.php";}i:7;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/DatabaseMigrationController.php";}i:8;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/InstallToolLockController.php";}i:9;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/JwtCookieController.php";}i:10;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Contao/MaintenanceModeController.php";}i:11;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/FileController.php";}i:12;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:100:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/LogController.php";}i:13;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/CloudController.php";}i:14;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:119:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/LocalPackagesController.php";}i:15;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:121:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/MissingPackagesController.php";}i:16;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:117:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/RootPackageController.php";}i:17;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:120:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Packages/UploadPackagesController.php";}i:18;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:113:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/AdminUserController.php";}i:19;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/ComposerController.php";}i:20;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/ConfigController.php";}i:21;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/ContaoController.php";}i:22;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:112:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/DatabaseController.php";}i:23;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/OpcacheController.php";}i:24;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/PhpCliController.php";}i:25;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:110:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/PhpWebController.php";}i:26;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:111:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/PhpinfoController.php";}i:27;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:114:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/Server/SelfUpdateController.php";}i:28;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:104:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/SessionController.php";}i:29;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/TaskController.php";}i:30;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:101:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Controller/UserController.php";}i:31;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:85:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/ApiKernel.php";}i:32;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:105:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/vendor/symfony/http-kernel/Kernel.php";}i:33;O:72:"Symfony\Component\DependencyInjection\Config\ContainerParametersResource":1:{s:84:"Symfony\Component\DependencyInjection\Config\ContainerParametersResourceparameters";a:0:{}}i:34;O:46:"Symfony\Component\Config\Resource\FileResource":1:{s:56:"Symfony\Component\Config\Resource\FileResourceresource";s:132:"/Users/aschempp/Projects/Contao/contao-manager/contao-manager-1.9.1/api/Resources/cache/Contao_ManagerApi_ApiKernelProdContainer.php";}}= 7.4 when preloading is desired use _ContaoManager\Symfony\Component\DependencyInjection\Dumper\Preloader; if (\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], \true)) { return; } require \dirname(__DIR__, 3) . '/vendor/autoload.php'; (require __DIR__ . '/Contao_ManagerApi_ApiKernelProdContainer.php')->set(\_ContaoManager\ContainerHxlxvCx\Contao_ManagerApi_ApiKernelProdContainer::class, null); require __DIR__ . '/ContainerHxlxvCx/RequestPayloadValueResolverGhost8d82153.php'; require __DIR__ . '/ContainerHxlxvCx/getServicesResetterService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_UserValueResolverService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_UserCheckerLocatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_SecurityTokenValueResolverService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_RouteLoader_LogoutService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Listener_UserProviderService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Listener_UserChecker_ApiService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Listener_PasswordMigratingService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Listener_CheckAuthenticatorCredentialsService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Listener_Api_UserProviderService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_HelperService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Firewall_Map_Context_ApiService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Firewall_EventDispatcherLocatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Firewall_Authenticator_ApiService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_EventDispatcher_ApiService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_ChannelListenerService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Authenticator_ManagersLocatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Authenticator_Manager_ApiService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_AccessMapService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_AccessListenerService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Access_RoleHierarchyVoterService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecurity_Access_AuthenticatedVoterService.php'; require __DIR__ . '/ContainerHxlxvCx/getSecrets_VaultService.php'; require __DIR__ . '/ContainerHxlxvCx/getRouting_LoaderService.php'; require __DIR__ . '/ContainerHxlxvCx/getPropertyInfo_SerializerExtractorService.php'; require __DIR__ . '/ContainerHxlxvCx/getMonolog_Logger_TasksService.php'; require __DIR__ . '/ContainerHxlxvCx/getMonolog_Logger_SecurityService.php'; require __DIR__ . '/ContainerHxlxvCx/getMonolog_LoggerService.php'; require __DIR__ . '/ContainerHxlxvCx/getErrorControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getDebug_ErrorHandlerConfiguratorService.php'; require __DIR__ . '/ContainerHxlxvCx/getContainer_GetRoutingConditionServiceService.php'; require __DIR__ . '/ContainerHxlxvCx/getContainer_EnvVarProcessorsLocatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getContainer_EnvVarProcessorService.php'; require __DIR__ . '/ContainerHxlxvCx/getCache_SystemClearerService.php'; require __DIR__ . '/ContainerHxlxvCx/getCache_SystemService.php'; require __DIR__ . '/ContainerHxlxvCx/getCache_SecurityIsGrantedAttributeExpressionLanguageService.php'; require __DIR__ . '/ContainerHxlxvCx/getCache_GlobalClearerService.php'; require __DIR__ . '/ContainerHxlxvCx/getCache_AppClearerService.php'; require __DIR__ . '/ContainerHxlxvCx/getCache_AppService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_VariadicService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_UidService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_SessionService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_ServiceService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_RequestAttributeService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_RequestService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_QueryParameterValueResolverService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_DefaultService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_DatetimeService.php'; require __DIR__ . '/ContainerHxlxvCx/getArgumentResolver_BackedEnumResolverService.php'; require __DIR__ . '/ContainerHxlxvCx/getTemplateControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getRedirectControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getTaskManagerService.php'; require __DIR__ . '/ContainerHxlxvCx/getUpdateTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getSetupTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getInstallTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getSelfUpdateTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getRebuildCacheTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getBackupRestoreTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getBackupCreateTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getDumpAutoloadTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getClearCacheTaskService.php'; require __DIR__ . '/ContainerHxlxvCx/getServerInfoService.php'; require __DIR__ . '/ContainerHxlxvCx/getSelfUpdateService.php'; require __DIR__ . '/ContainerHxlxvCx/getRequestService.php'; require __DIR__ . '/ContainerHxlxvCx/getWebauthnAuthenticatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getUserProviderService.php'; require __DIR__ . '/ContainerHxlxvCx/getTokenAuthenticatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getPasswordlessAuthenticatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getLoginAuthenticatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getJwtAuthenticatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getContaoConsoleService.php'; require __DIR__ . '/ContainerHxlxvCx/getContaoApiService.php'; require __DIR__ . '/ContainerHxlxvCx/getConsoleProcessFactoryService.php'; require __DIR__ . '/ContainerHxlxvCx/getSysTempDirCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getSymlinkCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getSessionCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getProcessCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getPhpExtensionsCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getMemoryLimitCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getIntegrityCheckFactoryService.php'; require __DIR__ . '/ContainerHxlxvCx/getGraphicsLibCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getAllowUrlFopenCheckService.php'; require __DIR__ . '/ContainerHxlxvCx/getTranslatorService.php'; require __DIR__ . '/ContainerHxlxvCx/getExceptionListenerService.php'; require __DIR__ . '/ContainerHxlxvCx/getUserControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getTaskControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getSessionControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getSelfUpdateControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getPhpinfoControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getPhpWebControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getPhpCliControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getOpcacheControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getDatabaseControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getContaoControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getConfigControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getComposerController2Service.php'; require __DIR__ . '/ContainerHxlxvCx/getAdminUserControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getUploadPackagesControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getRootPackageControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getMissingPackagesControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getLocalPackagesControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getCloudControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getLogControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getFileControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getMaintenanceModeControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getJwtCookieControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getInstallToolLockControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getDatabaseMigrationControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getBackupControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getAccessKeyControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getConstraintControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getManagerControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getComposerControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getAuthControllerService.php'; require __DIR__ . '/ContainerHxlxvCx/getUploadsConfigService.php'; require __DIR__ . '/ContainerHxlxvCx/getManagerConfigService.php'; require __DIR__ . '/ContainerHxlxvCx/getComposerConfigService.php'; require __DIR__ . '/ContainerHxlxvCx/getEnvironmentService.php'; require __DIR__ . '/ContainerHxlxvCx/getCloudResolverService.php'; require __DIR__ . '/ContainerHxlxvCx/get_ServiceLocator_Y_Xs7MwService.php'; require __DIR__ . '/ContainerHxlxvCx/get_ServiceLocator_AH5O6SdService.php'; require __DIR__ . '/ContainerHxlxvCx/get_ServiceLocator_EZsc_DOService.php'; $classes = []; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\SecurityBundle'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\MonologBundle'; $classes[] = '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ServiceLocator'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Config\\AuthConfig'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerInterface'; $classes[] = '_ContaoManager\\Webauthn\\Denormalizer\\WebauthnSerializerFactory'; $classes[] = '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupportManager'; $classes[] = '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponseValidator'; $classes[] = '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManager'; $classes[] = '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManagerFactory'; $classes[] = '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponseValidator'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\System\\Request'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Process\\PhpExecutableFinder'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask'; $classes[] = '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\Clock\\Clock'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter'; $classes[] = '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\Psr6CacheClearer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AdapterInterface'; $classes[] = '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessor'; $classes[] = '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractAdapter'; $classes[] = '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessor'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\CacheAttributeListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\IsGrantedAttributeListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\ErrorHandlerConfigurator'; $classes[] = '_ContaoManager\\Monolog\\Logger'; $classes[] = '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ErrorController'; $classes[] = '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\SerializerErrorRenderer'; $classes[] = '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\HtmlErrorRenderer'; $classes[] = '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Filesystem\\Filesystem'; $classes[] = '_ContaoManager\\Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner'; $classes[] = '_ContaoManager\\Symfony\\Component\\Runtime\\Runner\\Symfony\\ResponseRunner'; $classes[] = '_ContaoManager\\Symfony\\Component\\Runtime\\SymfonyRuntime'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernel'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory'; $classes[] = '_ContaoManager\\Monolog\\Handler\\FingersCrossedHandler'; $classes[] = '_ContaoManager\\Monolog\\Handler\\ErrorLogHandler'; $classes[] = '_ContaoManager\\Monolog\\Processor\\PsrLogMessageProcessor'; $classes[] = '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy'; $classes[] = '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBag'; $classes[] = '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor'; $classes[] = '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor'; $classes[] = '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor'; $classes[] = '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestStack'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Router'; $classes[] = '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCacheFactory'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\RequestContext'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\XmlFileLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\Config\\FileLocator'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\YamlFileLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\PhpFileLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\GlobFileLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\DirectoryLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ContainerLoader'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AttributeRouteControllerLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeDirectoryLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeFileLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Psr4DirectoryLoader'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\SodiumVault'; $classes[] = '_ContaoManager\\Symfony\\Component\\String\\LazyString'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AuthenticatedVoter'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AffirmativeStrategy'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleHierarchyVoter'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchy'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AccessListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMap'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ChainRequestMatcher'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PathRequestMatcher'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManager'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ChannelListener'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Logout\\LogoutUrlGenerator'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AuthenticatorManagerListener'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ExceptionListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\HttpUtils'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallConfig'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckCredentialsListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserCheckerListener'; $classes[] = '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactory'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Routing\\LogoutRouteLoader'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorage'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserChecker'; $classes[] = '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Serializer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UnwrappingDenormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ProblemNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UidNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ConstraintViolationListNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeZoneNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateIntervalNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\FormErrorNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\BackedEnumNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DataUriNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\JsonSerializableNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer'; $classes[] = '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor'; $classes[] = '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorFromClassMetadata'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\XmlEncoder'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncoder'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\YamlEncoder'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\CsvEncoder'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CacheClassMetadataFactory'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderChain'; $classes[] = '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AttributeLoader'; $classes[] = '_ContaoManager\\Psr\\Cache\\CacheItemPoolInterface'; $classes[] = '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter'; $classes[] = '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerInterface'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter'; $classes[] = '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener'; $preloaded = Preloader::preload($classes); $classes = []; $classes[] = '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator'; $classes[] = '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher'; $preloaded = Preloader::preload($classes, $preloaded); _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default '%kernel.debug%' * @param ParamConfigurator|bool $value * @return $this */ public function debug($value) : static { $this->_usedProperties['debug'] = \true; $this->debug = $value; return $this; } /** * @default null * @param ParamConfigurator|'none'|'short'|'full' $value * @return $this */ public function traceLevel($value) : static { $this->_usedProperties['traceLevel'] = \true; $this->traceLevel = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function traceHeader($value) : static { $this->_usedProperties['traceHeader'] = \true; $this->traceHeader = $value; return $this; } /** * @default null * @param ParamConfigurator|int $value * @return $this */ public function defaultTtl($value) : static { $this->_usedProperties['defaultTtl'] = \true; $this->defaultTtl = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function privateHeaders(ParamConfigurator|array $value) : static { $this->_usedProperties['privateHeaders'] = \true; $this->privateHeaders = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function skipResponseHeaders(ParamConfigurator|array $value) : static { $this->_usedProperties['skipResponseHeaders'] = \true; $this->skipResponseHeaders = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function allowReload($value) : static { $this->_usedProperties['allowReload'] = \true; $this->allowReload = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function allowRevalidate($value) : static { $this->_usedProperties['allowRevalidate'] = \true; $this->allowRevalidate = $value; return $this; } /** * @default null * @param ParamConfigurator|int $value * @return $this */ public function staleWhileRevalidate($value) : static { $this->_usedProperties['staleWhileRevalidate'] = \true; $this->staleWhileRevalidate = $value; return $this; } /** * @default null * @param ParamConfigurator|int $value * @return $this */ public function staleIfError($value) : static { $this->_usedProperties['staleIfError'] = \true; $this->staleIfError = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function terminateOnCacheHit($value) : static { $this->_usedProperties['terminateOnCacheHit'] = \true; $this->terminateOnCacheHit = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('debug', $value)) { $this->_usedProperties['debug'] = \true; $this->debug = $value['debug']; unset($value['debug']); } if (\array_key_exists('trace_level', $value)) { $this->_usedProperties['traceLevel'] = \true; $this->traceLevel = $value['trace_level']; unset($value['trace_level']); } if (\array_key_exists('trace_header', $value)) { $this->_usedProperties['traceHeader'] = \true; $this->traceHeader = $value['trace_header']; unset($value['trace_header']); } if (\array_key_exists('default_ttl', $value)) { $this->_usedProperties['defaultTtl'] = \true; $this->defaultTtl = $value['default_ttl']; unset($value['default_ttl']); } if (\array_key_exists('private_headers', $value)) { $this->_usedProperties['privateHeaders'] = \true; $this->privateHeaders = $value['private_headers']; unset($value['private_headers']); } if (\array_key_exists('skip_response_headers', $value)) { $this->_usedProperties['skipResponseHeaders'] = \true; $this->skipResponseHeaders = $value['skip_response_headers']; unset($value['skip_response_headers']); } if (\array_key_exists('allow_reload', $value)) { $this->_usedProperties['allowReload'] = \true; $this->allowReload = $value['allow_reload']; unset($value['allow_reload']); } if (\array_key_exists('allow_revalidate', $value)) { $this->_usedProperties['allowRevalidate'] = \true; $this->allowRevalidate = $value['allow_revalidate']; unset($value['allow_revalidate']); } if (\array_key_exists('stale_while_revalidate', $value)) { $this->_usedProperties['staleWhileRevalidate'] = \true; $this->staleWhileRevalidate = $value['stale_while_revalidate']; unset($value['stale_while_revalidate']); } if (\array_key_exists('stale_if_error', $value)) { $this->_usedProperties['staleIfError'] = \true; $this->staleIfError = $value['stale_if_error']; unset($value['stale_if_error']); } if (\array_key_exists('terminate_on_cache_hit', $value)) { $this->_usedProperties['terminateOnCacheHit'] = \true; $this->terminateOnCacheHit = $value['terminate_on_cache_hit']; unset($value['terminate_on_cache_hit']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['debug'])) { $output['debug'] = $this->debug; } if (isset($this->_usedProperties['traceLevel'])) { $output['trace_level'] = $this->traceLevel; } if (isset($this->_usedProperties['traceHeader'])) { $output['trace_header'] = $this->traceHeader; } if (isset($this->_usedProperties['defaultTtl'])) { $output['default_ttl'] = $this->defaultTtl; } if (isset($this->_usedProperties['privateHeaders'])) { $output['private_headers'] = $this->privateHeaders; } if (isset($this->_usedProperties['skipResponseHeaders'])) { $output['skip_response_headers'] = $this->skipResponseHeaders; } if (isset($this->_usedProperties['allowReload'])) { $output['allow_reload'] = $this->allowReload; } if (isset($this->_usedProperties['allowRevalidate'])) { $output['allow_revalidate'] = $this->allowRevalidate; } if (isset($this->_usedProperties['staleWhileRevalidate'])) { $output['stale_while_revalidate'] = $this->staleWhileRevalidate; } if (isset($this->_usedProperties['staleIfError'])) { $output['stale_if_error'] = $this->staleIfError; } if (isset($this->_usedProperties['terminateOnCacheHit'])) { $output['terminate_on_cache_hit'] = $this->terminateOnCacheHit; } return $output; } } _usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function secret($value) : static { $this->_usedProperties['secret'] = \true; $this->secret = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('secret', $value)) { $this->_usedProperties['secret'] = \true; $this->secret = $value['secret']; unset($value['secret']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['secret'])) { $output['secret'] = $this->secret; } return $output; } } _usedProperties['prefixSeed'] = \true; $this->prefixSeed = $value; return $this; } /** * App related cache pools configuration * @default 'cache.adapter.filesystem' * @param ParamConfigurator|mixed $value * @return $this */ public function app($value) : static { $this->_usedProperties['app'] = \true; $this->app = $value; return $this; } /** * System related cache pools configuration * @default 'cache.adapter.system' * @param ParamConfigurator|mixed $value * @return $this */ public function system($value) : static { $this->_usedProperties['system'] = \true; $this->system = $value; return $this; } /** * @default '%kernel.cache_dir%/pools/app' * @param ParamConfigurator|mixed $value * @return $this */ public function directory($value) : static { $this->_usedProperties['directory'] = \true; $this->directory = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function defaultPsr6Provider($value) : static { $this->_usedProperties['defaultPsr6Provider'] = \true; $this->defaultPsr6Provider = $value; return $this; } /** * @default 'redis://localhost' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultRedisProvider($value) : static { $this->_usedProperties['defaultRedisProvider'] = \true; $this->defaultRedisProvider = $value; return $this; } /** * @default 'memcached://localhost' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultMemcachedProvider($value) : static { $this->_usedProperties['defaultMemcachedProvider'] = \true; $this->defaultMemcachedProvider = $value; return $this; } /** * @default 'database_connection' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultDoctrineDbalProvider($value) : static { $this->_usedProperties['defaultDoctrineDbalProvider'] = \true; $this->defaultDoctrineDbalProvider = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function defaultPdoProvider($value) : static { $this->_usedProperties['defaultPdoProvider'] = \true; $this->defaultPdoProvider = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Cache\PoolConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Cache\PoolConfig : static) */ public function pool(string $name, mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig|static { if (!\is_array($value)) { $this->_usedProperties['pools'] = \true; $this->pools[$name] = $value; return $this; } if (!isset($this->pools[$name]) || !$this->pools[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig) { $this->_usedProperties['pools'] = \true; $this->pools[$name] = new \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "pool()" has already been initialized. You cannot pass values the second time you call pool().'); } return $this->pools[$name]; } public function __construct(array $value = []) { if (\array_key_exists('prefix_seed', $value)) { $this->_usedProperties['prefixSeed'] = \true; $this->prefixSeed = $value['prefix_seed']; unset($value['prefix_seed']); } if (\array_key_exists('app', $value)) { $this->_usedProperties['app'] = \true; $this->app = $value['app']; unset($value['app']); } if (\array_key_exists('system', $value)) { $this->_usedProperties['system'] = \true; $this->system = $value['system']; unset($value['system']); } if (\array_key_exists('directory', $value)) { $this->_usedProperties['directory'] = \true; $this->directory = $value['directory']; unset($value['directory']); } if (\array_key_exists('default_psr6_provider', $value)) { $this->_usedProperties['defaultPsr6Provider'] = \true; $this->defaultPsr6Provider = $value['default_psr6_provider']; unset($value['default_psr6_provider']); } if (\array_key_exists('default_redis_provider', $value)) { $this->_usedProperties['defaultRedisProvider'] = \true; $this->defaultRedisProvider = $value['default_redis_provider']; unset($value['default_redis_provider']); } if (\array_key_exists('default_memcached_provider', $value)) { $this->_usedProperties['defaultMemcachedProvider'] = \true; $this->defaultMemcachedProvider = $value['default_memcached_provider']; unset($value['default_memcached_provider']); } if (\array_key_exists('default_doctrine_dbal_provider', $value)) { $this->_usedProperties['defaultDoctrineDbalProvider'] = \true; $this->defaultDoctrineDbalProvider = $value['default_doctrine_dbal_provider']; unset($value['default_doctrine_dbal_provider']); } if (\array_key_exists('default_pdo_provider', $value)) { $this->_usedProperties['defaultPdoProvider'] = \true; $this->defaultPdoProvider = $value['default_pdo_provider']; unset($value['default_pdo_provider']); } if (\array_key_exists('pools', $value)) { $this->_usedProperties['pools'] = \true; $this->pools = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig($v) : $v, $value['pools']); unset($value['pools']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['prefixSeed'])) { $output['prefix_seed'] = $this->prefixSeed; } if (isset($this->_usedProperties['app'])) { $output['app'] = $this->app; } if (isset($this->_usedProperties['system'])) { $output['system'] = $this->system; } if (isset($this->_usedProperties['directory'])) { $output['directory'] = $this->directory; } if (isset($this->_usedProperties['defaultPsr6Provider'])) { $output['default_psr6_provider'] = $this->defaultPsr6Provider; } if (isset($this->_usedProperties['defaultRedisProvider'])) { $output['default_redis_provider'] = $this->defaultRedisProvider; } if (isset($this->_usedProperties['defaultMemcachedProvider'])) { $output['default_memcached_provider'] = $this->defaultMemcachedProvider; } if (isset($this->_usedProperties['defaultDoctrineDbalProvider'])) { $output['default_doctrine_dbal_provider'] = $this->defaultDoctrineDbalProvider; } if (isset($this->_usedProperties['defaultPdoProvider'])) { $output['default_pdo_provider'] = $this->defaultPdoProvider; } if (isset($this->_usedProperties['pools'])) { $output['pools'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Cache\PoolConfig ? $v->toArray() : $v, $this->pools); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function hincludeDefaultTemplate($value) : static { $this->_usedProperties['hincludeDefaultTemplate'] = \true; $this->hincludeDefaultTemplate = $value; return $this; } /** * @default '/_fragment' * @param ParamConfigurator|mixed $value * @return $this */ public function path($value) : static { $this->_usedProperties['path'] = \true; $this->path = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('hinclude_default_template', $value)) { $this->_usedProperties['hincludeDefaultTemplate'] = \true; $this->hincludeDefaultTemplate = $value['hinclude_default_template']; unset($value['hinclude_default_template']); } if (\array_key_exists('path', $value)) { $this->_usedProperties['path'] = \true; $this->path = $value['path']; unset($value['path']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['hincludeDefaultTemplate'])) { $output['hinclude_default_template'] = $this->hincludeDefaultTemplate; } if (isset($this->_usedProperties['path'])) { $output['path'] = $this->path; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default '_token' * @param ParamConfigurator|mixed $value * @return $this */ public function fieldName($value) : static { $this->_usedProperties['fieldName'] = \true; $this->fieldName = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('field_name', $value)) { $this->_usedProperties['fieldName'] = \true; $this->fieldName = $value['field_name']; unset($value['field_name']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['fieldName'])) { $output['field_name'] = $this->fieldName; } return $output; } } _usedProperties['headers'] = \true; $this->headers[$name] = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function vars(ParamConfigurator|array $value) : static { $this->_usedProperties['vars'] = \true; $this->vars = $value; return $this; } /** * The maximum number of redirects to follow. * @default null * @param ParamConfigurator|int $value * @return $this */ public function maxRedirects($value) : static { $this->_usedProperties['maxRedirects'] = \true; $this->maxRedirects = $value; return $this; } /** * The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function httpVersion($value) : static { $this->_usedProperties['httpVersion'] = \true; $this->httpVersion = $value; return $this; } /** * @return $this */ public function resolve(string $host, mixed $value) : static { $this->_usedProperties['resolve'] = \true; $this->resolve[$host] = $value; return $this; } /** * The URL of the proxy to pass requests through or null for automatic detection. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function proxy($value) : static { $this->_usedProperties['proxy'] = \true; $this->proxy = $value; return $this; } /** * A comma separated list of hosts that do not require a proxy to be reached. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function noProxy($value) : static { $this->_usedProperties['noProxy'] = \true; $this->noProxy = $value; return $this; } /** * The idle timeout, defaults to the "default_socket_timeout" ini parameter. * @default null * @param ParamConfigurator|float $value * @return $this */ public function timeout($value) : static { $this->_usedProperties['timeout'] = \true; $this->timeout = $value; return $this; } /** * The maximum execution time for the request+response as a whole. * @default null * @param ParamConfigurator|float $value * @return $this */ public function maxDuration($value) : static { $this->_usedProperties['maxDuration'] = \true; $this->maxDuration = $value; return $this; } /** * A network interface name, IP address, a host name or a UNIX socket to bind to. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function bindto($value) : static { $this->_usedProperties['bindto'] = \true; $this->bindto = $value; return $this; } /** * Indicates if the peer should be verified in a TLS context. * @default null * @param ParamConfigurator|bool $value * @return $this */ public function verifyPeer($value) : static { $this->_usedProperties['verifyPeer'] = \true; $this->verifyPeer = $value; return $this; } /** * Indicates if the host should exist as a certificate common name. * @default null * @param ParamConfigurator|bool $value * @return $this */ public function verifyHost($value) : static { $this->_usedProperties['verifyHost'] = \true; $this->verifyHost = $value; return $this; } /** * A certificate authority file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cafile($value) : static { $this->_usedProperties['cafile'] = \true; $this->cafile = $value; return $this; } /** * A directory that contains multiple certificate authority files. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function capath($value) : static { $this->_usedProperties['capath'] = \true; $this->capath = $value; return $this; } /** * A PEM formatted certificate file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function localCert($value) : static { $this->_usedProperties['localCert'] = \true; $this->localCert = $value; return $this; } /** * A private key file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function localPk($value) : static { $this->_usedProperties['localPk'] = \true; $this->localPk = $value; return $this; } /** * The passphrase used to encrypt the "local_pk" file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function passphrase($value) : static { $this->_usedProperties['passphrase'] = \true; $this->passphrase = $value; return $this; } /** * A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...) * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function ciphers($value) : static { $this->_usedProperties['ciphers'] = \true; $this->ciphers = $value; return $this; } /** * Associative array: hashing algorithm => hash(es). */ public function peerFingerprint(array $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\PeerFingerprintConfig { if (null === $this->peerFingerprint) { $this->_usedProperties['peerFingerprint'] = \true; $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\PeerFingerprintConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "peerFingerprint()" has already been initialized. You cannot pass values the second time you call peerFingerprint().'); } return $this->peerFingerprint; } /** * The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cryptoMethod($value) : static { $this->_usedProperties['cryptoMethod'] = \true; $this->cryptoMethod = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function extra(ParamConfigurator|array $value) : static { $this->_usedProperties['extra'] = \true; $this->extra = $value; return $this; } /** * @template TValue * @param TValue $value * @default {"enabled":false,"retry_strategy":null,"http_codes":[],"max_retries":3,"delay":1000,"multiplier":2,"max_delay":0,"jitter":0.1} * @return \Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig : static) */ public function retryFailed(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig|static { if (!\is_array($value)) { $this->_usedProperties['retryFailed'] = \true; $this->retryFailed = $value; return $this; } if (!$this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig) { $this->_usedProperties['retryFailed'] = \true; $this->retryFailed = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "retryFailed()" has already been initialized. You cannot pass values the second time you call retryFailed().'); } return $this->retryFailed; } public function __construct(array $value = []) { if (\array_key_exists('headers', $value)) { $this->_usedProperties['headers'] = \true; $this->headers = $value['headers']; unset($value['headers']); } if (\array_key_exists('vars', $value)) { $this->_usedProperties['vars'] = \true; $this->vars = $value['vars']; unset($value['vars']); } if (\array_key_exists('max_redirects', $value)) { $this->_usedProperties['maxRedirects'] = \true; $this->maxRedirects = $value['max_redirects']; unset($value['max_redirects']); } if (\array_key_exists('http_version', $value)) { $this->_usedProperties['httpVersion'] = \true; $this->httpVersion = $value['http_version']; unset($value['http_version']); } if (\array_key_exists('resolve', $value)) { $this->_usedProperties['resolve'] = \true; $this->resolve = $value['resolve']; unset($value['resolve']); } if (\array_key_exists('proxy', $value)) { $this->_usedProperties['proxy'] = \true; $this->proxy = $value['proxy']; unset($value['proxy']); } if (\array_key_exists('no_proxy', $value)) { $this->_usedProperties['noProxy'] = \true; $this->noProxy = $value['no_proxy']; unset($value['no_proxy']); } if (\array_key_exists('timeout', $value)) { $this->_usedProperties['timeout'] = \true; $this->timeout = $value['timeout']; unset($value['timeout']); } if (\array_key_exists('max_duration', $value)) { $this->_usedProperties['maxDuration'] = \true; $this->maxDuration = $value['max_duration']; unset($value['max_duration']); } if (\array_key_exists('bindto', $value)) { $this->_usedProperties['bindto'] = \true; $this->bindto = $value['bindto']; unset($value['bindto']); } if (\array_key_exists('verify_peer', $value)) { $this->_usedProperties['verifyPeer'] = \true; $this->verifyPeer = $value['verify_peer']; unset($value['verify_peer']); } if (\array_key_exists('verify_host', $value)) { $this->_usedProperties['verifyHost'] = \true; $this->verifyHost = $value['verify_host']; unset($value['verify_host']); } if (\array_key_exists('cafile', $value)) { $this->_usedProperties['cafile'] = \true; $this->cafile = $value['cafile']; unset($value['cafile']); } if (\array_key_exists('capath', $value)) { $this->_usedProperties['capath'] = \true; $this->capath = $value['capath']; unset($value['capath']); } if (\array_key_exists('local_cert', $value)) { $this->_usedProperties['localCert'] = \true; $this->localCert = $value['local_cert']; unset($value['local_cert']); } if (\array_key_exists('local_pk', $value)) { $this->_usedProperties['localPk'] = \true; $this->localPk = $value['local_pk']; unset($value['local_pk']); } if (\array_key_exists('passphrase', $value)) { $this->_usedProperties['passphrase'] = \true; $this->passphrase = $value['passphrase']; unset($value['passphrase']); } if (\array_key_exists('ciphers', $value)) { $this->_usedProperties['ciphers'] = \true; $this->ciphers = $value['ciphers']; unset($value['ciphers']); } if (\array_key_exists('peer_fingerprint', $value)) { $this->_usedProperties['peerFingerprint'] = \true; $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\PeerFingerprintConfig($value['peer_fingerprint']); unset($value['peer_fingerprint']); } if (\array_key_exists('crypto_method', $value)) { $this->_usedProperties['cryptoMethod'] = \true; $this->cryptoMethod = $value['crypto_method']; unset($value['crypto_method']); } if (\array_key_exists('extra', $value)) { $this->_usedProperties['extra'] = \true; $this->extra = $value['extra']; unset($value['extra']); } if (\array_key_exists('retry_failed', $value)) { $this->_usedProperties['retryFailed'] = \true; $this->retryFailed = \is_array($value['retry_failed']) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig($value['retry_failed']) : $value['retry_failed']; unset($value['retry_failed']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['headers'])) { $output['headers'] = $this->headers; } if (isset($this->_usedProperties['vars'])) { $output['vars'] = $this->vars; } if (isset($this->_usedProperties['maxRedirects'])) { $output['max_redirects'] = $this->maxRedirects; } if (isset($this->_usedProperties['httpVersion'])) { $output['http_version'] = $this->httpVersion; } if (isset($this->_usedProperties['resolve'])) { $output['resolve'] = $this->resolve; } if (isset($this->_usedProperties['proxy'])) { $output['proxy'] = $this->proxy; } if (isset($this->_usedProperties['noProxy'])) { $output['no_proxy'] = $this->noProxy; } if (isset($this->_usedProperties['timeout'])) { $output['timeout'] = $this->timeout; } if (isset($this->_usedProperties['maxDuration'])) { $output['max_duration'] = $this->maxDuration; } if (isset($this->_usedProperties['bindto'])) { $output['bindto'] = $this->bindto; } if (isset($this->_usedProperties['verifyPeer'])) { $output['verify_peer'] = $this->verifyPeer; } if (isset($this->_usedProperties['verifyHost'])) { $output['verify_host'] = $this->verifyHost; } if (isset($this->_usedProperties['cafile'])) { $output['cafile'] = $this->cafile; } if (isset($this->_usedProperties['capath'])) { $output['capath'] = $this->capath; } if (isset($this->_usedProperties['localCert'])) { $output['local_cert'] = $this->localCert; } if (isset($this->_usedProperties['localPk'])) { $output['local_pk'] = $this->localPk; } if (isset($this->_usedProperties['passphrase'])) { $output['passphrase'] = $this->passphrase; } if (isset($this->_usedProperties['ciphers'])) { $output['ciphers'] = $this->ciphers; } if (isset($this->_usedProperties['peerFingerprint'])) { $output['peer_fingerprint'] = $this->peerFingerprint->toArray(); } if (isset($this->_usedProperties['cryptoMethod'])) { $output['crypto_method'] = $this->cryptoMethod; } if (isset($this->_usedProperties['extra'])) { $output['extra'] = $this->extra; } if (isset($this->_usedProperties['retryFailed'])) { $output['retry_failed'] = $this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailedConfig ? $this->retryFailed->toArray() : $this->retryFailed; } return $output; } } _usedProperties['code'] = \true; $this->code = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function methods(ParamConfigurator|array $value) : static { $this->_usedProperties['methods'] = \true; $this->methods = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('code', $value)) { $this->_usedProperties['code'] = \true; $this->code = $value['code']; unset($value['code']); } if (\array_key_exists('methods', $value)) { $this->_usedProperties['methods'] = \true; $this->methods = $value['methods']; unset($value['methods']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['code'])) { $output['code'] = $this->code; } if (isset($this->_usedProperties['methods'])) { $output['methods'] = $this->methods; } return $output; } } _usedProperties['sha1'] = \true; $this->sha1 = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function pinsha256(mixed $value) : static { $this->_usedProperties['pinsha256'] = \true; $this->pinsha256 = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function md5(mixed $value) : static { $this->_usedProperties['md5'] = \true; $this->md5 = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('sha1', $value)) { $this->_usedProperties['sha1'] = \true; $this->sha1 = $value['sha1']; unset($value['sha1']); } if (\array_key_exists('pin-sha256', $value)) { $this->_usedProperties['pinsha256'] = \true; $this->pinsha256 = $value['pin-sha256']; unset($value['pin-sha256']); } if (\array_key_exists('md5', $value)) { $this->_usedProperties['md5'] = \true; $this->md5 = $value['md5']; unset($value['md5']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['sha1'])) { $output['sha1'] = $this->sha1; } if (isset($this->_usedProperties['pinsha256'])) { $output['pin-sha256'] = $this->pinsha256; } if (isset($this->_usedProperties['md5'])) { $output['md5'] = $this->md5; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * service id to override the retry strategy * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function retryStrategy($value) : static { $this->_usedProperties['retryStrategy'] = \true; $this->retryStrategy = $value; return $this; } /** * @template TValue * @param TValue $value * A list of HTTP status code that triggers a retry * @return \Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig : static) */ public function httpCode(string $code, array $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig|static { if (!\is_array($value)) { $this->_usedProperties['httpCodes'] = \true; $this->httpCodes[$code] = $value; return $this; } if (!isset($this->httpCodes[$code]) || !$this->httpCodes[$code] instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig) { $this->_usedProperties['httpCodes'] = \true; $this->httpCodes[$code] = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "httpCode()" has already been initialized. You cannot pass values the second time you call httpCode().'); } return $this->httpCodes[$code]; } /** * @default 3 * @param ParamConfigurator|int $value * @return $this */ public function maxRetries($value) : static { $this->_usedProperties['maxRetries'] = \true; $this->maxRetries = $value; return $this; } /** * Time in ms to delay (or the initial value when multiplier is used) * @default 1000 * @param ParamConfigurator|int $value * @return $this */ public function delay($value) : static { $this->_usedProperties['delay'] = \true; $this->delay = $value; return $this; } /** * If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries) * @default 2 * @param ParamConfigurator|float $value * @return $this */ public function multiplier($value) : static { $this->_usedProperties['multiplier'] = \true; $this->multiplier = $value; return $this; } /** * Max time in ms that a retry should ever be delayed (0 = infinite) * @default 0 * @param ParamConfigurator|int $value * @return $this */ public function maxDelay($value) : static { $this->_usedProperties['maxDelay'] = \true; $this->maxDelay = $value; return $this; } /** * Randomness in percent (between 0 and 1) to apply to the delay * @default 0.1 * @param ParamConfigurator|float $value * @return $this */ public function jitter($value) : static { $this->_usedProperties['jitter'] = \true; $this->jitter = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('retry_strategy', $value)) { $this->_usedProperties['retryStrategy'] = \true; $this->retryStrategy = $value['retry_strategy']; unset($value['retry_strategy']); } if (\array_key_exists('http_codes', $value)) { $this->_usedProperties['httpCodes'] = \true; $this->httpCodes = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig($v) : $v, $value['http_codes']); unset($value['http_codes']); } if (\array_key_exists('max_retries', $value)) { $this->_usedProperties['maxRetries'] = \true; $this->maxRetries = $value['max_retries']; unset($value['max_retries']); } if (\array_key_exists('delay', $value)) { $this->_usedProperties['delay'] = \true; $this->delay = $value['delay']; unset($value['delay']); } if (\array_key_exists('multiplier', $value)) { $this->_usedProperties['multiplier'] = \true; $this->multiplier = $value['multiplier']; unset($value['multiplier']); } if (\array_key_exists('max_delay', $value)) { $this->_usedProperties['maxDelay'] = \true; $this->maxDelay = $value['max_delay']; unset($value['max_delay']); } if (\array_key_exists('jitter', $value)) { $this->_usedProperties['jitter'] = \true; $this->jitter = $value['jitter']; unset($value['jitter']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['retryStrategy'])) { $output['retry_strategy'] = $this->retryStrategy; } if (isset($this->_usedProperties['httpCodes'])) { $output['http_codes'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailed\HttpCodeConfig ? $v->toArray() : $v, $this->httpCodes); } if (isset($this->_usedProperties['maxRetries'])) { $output['max_retries'] = $this->maxRetries; } if (isset($this->_usedProperties['delay'])) { $output['delay'] = $this->delay; } if (isset($this->_usedProperties['multiplier'])) { $output['multiplier'] = $this->multiplier; } if (isset($this->_usedProperties['maxDelay'])) { $output['max_delay'] = $this->maxDelay; } if (isset($this->_usedProperties['jitter'])) { $output['jitter'] = $this->jitter; } return $output; } } _usedProperties['scope'] = \true; $this->scope = $value; return $this; } /** * The URI to resolve relative URLs, following rules in RFC 3985, section 2. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function baseUri($value) : static { $this->_usedProperties['baseUri'] = \true; $this->baseUri = $value; return $this; } /** * An HTTP Basic authentication "username:password". * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function authBasic($value) : static { $this->_usedProperties['authBasic'] = \true; $this->authBasic = $value; return $this; } /** * A token enabling HTTP Bearer authorization. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function authBearer($value) : static { $this->_usedProperties['authBearer'] = \true; $this->authBearer = $value; return $this; } /** * A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension). * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function authNtlm($value) : static { $this->_usedProperties['authNtlm'] = \true; $this->authNtlm = $value; return $this; } /** * @return $this */ public function query(string $key, mixed $value) : static { $this->_usedProperties['query'] = \true; $this->query[$key] = $value; return $this; } /** * @return $this */ public function header(string $name, mixed $value) : static { $this->_usedProperties['headers'] = \true; $this->headers[$name] = $value; return $this; } /** * The maximum number of redirects to follow. * @default null * @param ParamConfigurator|int $value * @return $this */ public function maxRedirects($value) : static { $this->_usedProperties['maxRedirects'] = \true; $this->maxRedirects = $value; return $this; } /** * The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function httpVersion($value) : static { $this->_usedProperties['httpVersion'] = \true; $this->httpVersion = $value; return $this; } /** * @return $this */ public function resolve(string $host, mixed $value) : static { $this->_usedProperties['resolve'] = \true; $this->resolve[$host] = $value; return $this; } /** * The URL of the proxy to pass requests through or null for automatic detection. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function proxy($value) : static { $this->_usedProperties['proxy'] = \true; $this->proxy = $value; return $this; } /** * A comma separated list of hosts that do not require a proxy to be reached. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function noProxy($value) : static { $this->_usedProperties['noProxy'] = \true; $this->noProxy = $value; return $this; } /** * The idle timeout, defaults to the "default_socket_timeout" ini parameter. * @default null * @param ParamConfigurator|float $value * @return $this */ public function timeout($value) : static { $this->_usedProperties['timeout'] = \true; $this->timeout = $value; return $this; } /** * The maximum execution time for the request+response as a whole. * @default null * @param ParamConfigurator|float $value * @return $this */ public function maxDuration($value) : static { $this->_usedProperties['maxDuration'] = \true; $this->maxDuration = $value; return $this; } /** * A network interface name, IP address, a host name or a UNIX socket to bind to. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function bindto($value) : static { $this->_usedProperties['bindto'] = \true; $this->bindto = $value; return $this; } /** * Indicates if the peer should be verified in a TLS context. * @default null * @param ParamConfigurator|bool $value * @return $this */ public function verifyPeer($value) : static { $this->_usedProperties['verifyPeer'] = \true; $this->verifyPeer = $value; return $this; } /** * Indicates if the host should exist as a certificate common name. * @default null * @param ParamConfigurator|bool $value * @return $this */ public function verifyHost($value) : static { $this->_usedProperties['verifyHost'] = \true; $this->verifyHost = $value; return $this; } /** * A certificate authority file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cafile($value) : static { $this->_usedProperties['cafile'] = \true; $this->cafile = $value; return $this; } /** * A directory that contains multiple certificate authority files. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function capath($value) : static { $this->_usedProperties['capath'] = \true; $this->capath = $value; return $this; } /** * A PEM formatted certificate file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function localCert($value) : static { $this->_usedProperties['localCert'] = \true; $this->localCert = $value; return $this; } /** * A private key file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function localPk($value) : static { $this->_usedProperties['localPk'] = \true; $this->localPk = $value; return $this; } /** * The passphrase used to encrypt the "local_pk" file. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function passphrase($value) : static { $this->_usedProperties['passphrase'] = \true; $this->passphrase = $value; return $this; } /** * A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...) * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function ciphers($value) : static { $this->_usedProperties['ciphers'] = \true; $this->ciphers = $value; return $this; } /** * Associative array: hashing algorithm => hash(es). */ public function peerFingerprint(array $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\PeerFingerprintConfig { if (null === $this->peerFingerprint) { $this->_usedProperties['peerFingerprint'] = \true; $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\PeerFingerprintConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "peerFingerprint()" has already been initialized. You cannot pass values the second time you call peerFingerprint().'); } return $this->peerFingerprint; } /** * The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cryptoMethod($value) : static { $this->_usedProperties['cryptoMethod'] = \true; $this->cryptoMethod = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function extra(ParamConfigurator|array $value) : static { $this->_usedProperties['extra'] = \true; $this->extra = $value; return $this; } /** * @template TValue * @param TValue $value * @default {"enabled":false,"retry_strategy":null,"http_codes":[],"max_retries":3,"delay":1000,"multiplier":2,"max_delay":0,"jitter":0.1} * @return \Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig : static) */ public function retryFailed(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig|static { if (!\is_array($value)) { $this->_usedProperties['retryFailed'] = \true; $this->retryFailed = $value; return $this; } if (!$this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig) { $this->_usedProperties['retryFailed'] = \true; $this->retryFailed = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "retryFailed()" has already been initialized. You cannot pass values the second time you call retryFailed().'); } return $this->retryFailed; } public function __construct(array $value = []) { if (\array_key_exists('scope', $value)) { $this->_usedProperties['scope'] = \true; $this->scope = $value['scope']; unset($value['scope']); } if (\array_key_exists('base_uri', $value)) { $this->_usedProperties['baseUri'] = \true; $this->baseUri = $value['base_uri']; unset($value['base_uri']); } if (\array_key_exists('auth_basic', $value)) { $this->_usedProperties['authBasic'] = \true; $this->authBasic = $value['auth_basic']; unset($value['auth_basic']); } if (\array_key_exists('auth_bearer', $value)) { $this->_usedProperties['authBearer'] = \true; $this->authBearer = $value['auth_bearer']; unset($value['auth_bearer']); } if (\array_key_exists('auth_ntlm', $value)) { $this->_usedProperties['authNtlm'] = \true; $this->authNtlm = $value['auth_ntlm']; unset($value['auth_ntlm']); } if (\array_key_exists('query', $value)) { $this->_usedProperties['query'] = \true; $this->query = $value['query']; unset($value['query']); } if (\array_key_exists('headers', $value)) { $this->_usedProperties['headers'] = \true; $this->headers = $value['headers']; unset($value['headers']); } if (\array_key_exists('max_redirects', $value)) { $this->_usedProperties['maxRedirects'] = \true; $this->maxRedirects = $value['max_redirects']; unset($value['max_redirects']); } if (\array_key_exists('http_version', $value)) { $this->_usedProperties['httpVersion'] = \true; $this->httpVersion = $value['http_version']; unset($value['http_version']); } if (\array_key_exists('resolve', $value)) { $this->_usedProperties['resolve'] = \true; $this->resolve = $value['resolve']; unset($value['resolve']); } if (\array_key_exists('proxy', $value)) { $this->_usedProperties['proxy'] = \true; $this->proxy = $value['proxy']; unset($value['proxy']); } if (\array_key_exists('no_proxy', $value)) { $this->_usedProperties['noProxy'] = \true; $this->noProxy = $value['no_proxy']; unset($value['no_proxy']); } if (\array_key_exists('timeout', $value)) { $this->_usedProperties['timeout'] = \true; $this->timeout = $value['timeout']; unset($value['timeout']); } if (\array_key_exists('max_duration', $value)) { $this->_usedProperties['maxDuration'] = \true; $this->maxDuration = $value['max_duration']; unset($value['max_duration']); } if (\array_key_exists('bindto', $value)) { $this->_usedProperties['bindto'] = \true; $this->bindto = $value['bindto']; unset($value['bindto']); } if (\array_key_exists('verify_peer', $value)) { $this->_usedProperties['verifyPeer'] = \true; $this->verifyPeer = $value['verify_peer']; unset($value['verify_peer']); } if (\array_key_exists('verify_host', $value)) { $this->_usedProperties['verifyHost'] = \true; $this->verifyHost = $value['verify_host']; unset($value['verify_host']); } if (\array_key_exists('cafile', $value)) { $this->_usedProperties['cafile'] = \true; $this->cafile = $value['cafile']; unset($value['cafile']); } if (\array_key_exists('capath', $value)) { $this->_usedProperties['capath'] = \true; $this->capath = $value['capath']; unset($value['capath']); } if (\array_key_exists('local_cert', $value)) { $this->_usedProperties['localCert'] = \true; $this->localCert = $value['local_cert']; unset($value['local_cert']); } if (\array_key_exists('local_pk', $value)) { $this->_usedProperties['localPk'] = \true; $this->localPk = $value['local_pk']; unset($value['local_pk']); } if (\array_key_exists('passphrase', $value)) { $this->_usedProperties['passphrase'] = \true; $this->passphrase = $value['passphrase']; unset($value['passphrase']); } if (\array_key_exists('ciphers', $value)) { $this->_usedProperties['ciphers'] = \true; $this->ciphers = $value['ciphers']; unset($value['ciphers']); } if (\array_key_exists('peer_fingerprint', $value)) { $this->_usedProperties['peerFingerprint'] = \true; $this->peerFingerprint = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\PeerFingerprintConfig($value['peer_fingerprint']); unset($value['peer_fingerprint']); } if (\array_key_exists('crypto_method', $value)) { $this->_usedProperties['cryptoMethod'] = \true; $this->cryptoMethod = $value['crypto_method']; unset($value['crypto_method']); } if (\array_key_exists('extra', $value)) { $this->_usedProperties['extra'] = \true; $this->extra = $value['extra']; unset($value['extra']); } if (\array_key_exists('retry_failed', $value)) { $this->_usedProperties['retryFailed'] = \true; $this->retryFailed = \is_array($value['retry_failed']) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig($value['retry_failed']) : $value['retry_failed']; unset($value['retry_failed']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['scope'])) { $output['scope'] = $this->scope; } if (isset($this->_usedProperties['baseUri'])) { $output['base_uri'] = $this->baseUri; } if (isset($this->_usedProperties['authBasic'])) { $output['auth_basic'] = $this->authBasic; } if (isset($this->_usedProperties['authBearer'])) { $output['auth_bearer'] = $this->authBearer; } if (isset($this->_usedProperties['authNtlm'])) { $output['auth_ntlm'] = $this->authNtlm; } if (isset($this->_usedProperties['query'])) { $output['query'] = $this->query; } if (isset($this->_usedProperties['headers'])) { $output['headers'] = $this->headers; } if (isset($this->_usedProperties['maxRedirects'])) { $output['max_redirects'] = $this->maxRedirects; } if (isset($this->_usedProperties['httpVersion'])) { $output['http_version'] = $this->httpVersion; } if (isset($this->_usedProperties['resolve'])) { $output['resolve'] = $this->resolve; } if (isset($this->_usedProperties['proxy'])) { $output['proxy'] = $this->proxy; } if (isset($this->_usedProperties['noProxy'])) { $output['no_proxy'] = $this->noProxy; } if (isset($this->_usedProperties['timeout'])) { $output['timeout'] = $this->timeout; } if (isset($this->_usedProperties['maxDuration'])) { $output['max_duration'] = $this->maxDuration; } if (isset($this->_usedProperties['bindto'])) { $output['bindto'] = $this->bindto; } if (isset($this->_usedProperties['verifyPeer'])) { $output['verify_peer'] = $this->verifyPeer; } if (isset($this->_usedProperties['verifyHost'])) { $output['verify_host'] = $this->verifyHost; } if (isset($this->_usedProperties['cafile'])) { $output['cafile'] = $this->cafile; } if (isset($this->_usedProperties['capath'])) { $output['capath'] = $this->capath; } if (isset($this->_usedProperties['localCert'])) { $output['local_cert'] = $this->localCert; } if (isset($this->_usedProperties['localPk'])) { $output['local_pk'] = $this->localPk; } if (isset($this->_usedProperties['passphrase'])) { $output['passphrase'] = $this->passphrase; } if (isset($this->_usedProperties['ciphers'])) { $output['ciphers'] = $this->ciphers; } if (isset($this->_usedProperties['peerFingerprint'])) { $output['peer_fingerprint'] = $this->peerFingerprint->toArray(); } if (isset($this->_usedProperties['cryptoMethod'])) { $output['crypto_method'] = $this->cryptoMethod; } if (isset($this->_usedProperties['extra'])) { $output['extra'] = $this->extra; } if (isset($this->_usedProperties['retryFailed'])) { $output['retry_failed'] = $this->retryFailed instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig\RetryFailedConfig ? $this->retryFailed->toArray() : $this->retryFailed; } return $output; } } _usedProperties['code'] = \true; $this->code = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function methods(ParamConfigurator|array $value) : static { $this->_usedProperties['methods'] = \true; $this->methods = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('code', $value)) { $this->_usedProperties['code'] = \true; $this->code = $value['code']; unset($value['code']); } if (\array_key_exists('methods', $value)) { $this->_usedProperties['methods'] = \true; $this->methods = $value['methods']; unset($value['methods']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['code'])) { $output['code'] = $this->code; } if (isset($this->_usedProperties['methods'])) { $output['methods'] = $this->methods; } return $output; } } _usedProperties['sha1'] = \true; $this->sha1 = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function pinsha256(mixed $value) : static { $this->_usedProperties['pinsha256'] = \true; $this->pinsha256 = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function md5(mixed $value) : static { $this->_usedProperties['md5'] = \true; $this->md5 = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('sha1', $value)) { $this->_usedProperties['sha1'] = \true; $this->sha1 = $value['sha1']; unset($value['sha1']); } if (\array_key_exists('pin-sha256', $value)) { $this->_usedProperties['pinsha256'] = \true; $this->pinsha256 = $value['pin-sha256']; unset($value['pin-sha256']); } if (\array_key_exists('md5', $value)) { $this->_usedProperties['md5'] = \true; $this->md5 = $value['md5']; unset($value['md5']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['sha1'])) { $output['sha1'] = $this->sha1; } if (isset($this->_usedProperties['pinsha256'])) { $output['pin-sha256'] = $this->pinsha256; } if (isset($this->_usedProperties['md5'])) { $output['md5'] = $this->md5; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * service id to override the retry strategy * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function retryStrategy($value) : static { $this->_usedProperties['retryStrategy'] = \true; $this->retryStrategy = $value; return $this; } /** * @template TValue * @param TValue $value * A list of HTTP status code that triggers a retry * @return \Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig : static) */ public function httpCode(string $code, array $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig|static { if (!\is_array($value)) { $this->_usedProperties['httpCodes'] = \true; $this->httpCodes[$code] = $value; return $this; } if (!isset($this->httpCodes[$code]) || !$this->httpCodes[$code] instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig) { $this->_usedProperties['httpCodes'] = \true; $this->httpCodes[$code] = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "httpCode()" has already been initialized. You cannot pass values the second time you call httpCode().'); } return $this->httpCodes[$code]; } /** * @default 3 * @param ParamConfigurator|int $value * @return $this */ public function maxRetries($value) : static { $this->_usedProperties['maxRetries'] = \true; $this->maxRetries = $value; return $this; } /** * Time in ms to delay (or the initial value when multiplier is used) * @default 1000 * @param ParamConfigurator|int $value * @return $this */ public function delay($value) : static { $this->_usedProperties['delay'] = \true; $this->delay = $value; return $this; } /** * If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries) * @default 2 * @param ParamConfigurator|float $value * @return $this */ public function multiplier($value) : static { $this->_usedProperties['multiplier'] = \true; $this->multiplier = $value; return $this; } /** * Max time in ms that a retry should ever be delayed (0 = infinite) * @default 0 * @param ParamConfigurator|int $value * @return $this */ public function maxDelay($value) : static { $this->_usedProperties['maxDelay'] = \true; $this->maxDelay = $value; return $this; } /** * Randomness in percent (between 0 and 1) to apply to the delay * @default 0.1 * @param ParamConfigurator|float $value * @return $this */ public function jitter($value) : static { $this->_usedProperties['jitter'] = \true; $this->jitter = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('retry_strategy', $value)) { $this->_usedProperties['retryStrategy'] = \true; $this->retryStrategy = $value['retry_strategy']; unset($value['retry_strategy']); } if (\array_key_exists('http_codes', $value)) { $this->_usedProperties['httpCodes'] = \true; $this->httpCodes = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig($v) : $v, $value['http_codes']); unset($value['http_codes']); } if (\array_key_exists('max_retries', $value)) { $this->_usedProperties['maxRetries'] = \true; $this->maxRetries = $value['max_retries']; unset($value['max_retries']); } if (\array_key_exists('delay', $value)) { $this->_usedProperties['delay'] = \true; $this->delay = $value['delay']; unset($value['delay']); } if (\array_key_exists('multiplier', $value)) { $this->_usedProperties['multiplier'] = \true; $this->multiplier = $value['multiplier']; unset($value['multiplier']); } if (\array_key_exists('max_delay', $value)) { $this->_usedProperties['maxDelay'] = \true; $this->maxDelay = $value['max_delay']; unset($value['max_delay']); } if (\array_key_exists('jitter', $value)) { $this->_usedProperties['jitter'] = \true; $this->jitter = $value['jitter']; unset($value['jitter']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['retryStrategy'])) { $output['retry_strategy'] = $this->retryStrategy; } if (isset($this->_usedProperties['httpCodes'])) { $output['http_codes'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptions\RetryFailed\HttpCodeConfig ? $v->toArray() : $v, $this->httpCodes); } if (isset($this->_usedProperties['maxRetries'])) { $output['max_retries'] = $this->maxRetries; } if (isset($this->_usedProperties['delay'])) { $output['delay'] = $this->delay; } if (isset($this->_usedProperties['multiplier'])) { $output['multiplier'] = $this->multiplier; } if (isset($this->_usedProperties['maxDelay'])) { $output['max_delay'] = $this->maxDelay; } if (isset($this->_usedProperties['jitter'])) { $output['jitter'] = $this->jitter; } return $output; } } $value * * @return $this */ public function paths(ParamConfigurator|array $value) : static { $this->_usedProperties['paths'] = \true; $this->paths = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('paths', $value)) { $this->_usedProperties['paths'] = \true; $this->paths = $value['paths']; unset($value['paths']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['paths'])) { $output['paths'] = $this->paths; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cache($value) : static { $this->_usedProperties['cache'] = \true; $this->cache = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function enableAnnotations($value) : static { $this->_usedProperties['enableAnnotations'] = \true; $this->enableAnnotations = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function enableAttributes($value) : static { $this->_usedProperties['enableAttributes'] = \true; $this->enableAttributes = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function staticMethod(ParamConfigurator|array $value) : static { $this->_usedProperties['staticMethod'] = \true; $this->staticMethod = $value; return $this; } /** * @default 'validators' * @param ParamConfigurator|mixed $value * @return $this */ public function translationDomain($value) : static { $this->_usedProperties['translationDomain'] = \true; $this->translationDomain = $value; return $this; } /** * @default null * @param ParamConfigurator|'html5'|'loose'|'strict' $value * @return $this */ public function emailValidationMode($value) : static { $this->_usedProperties['emailValidationMode'] = \true; $this->emailValidationMode = $value; return $this; } /** * @default {"paths":[]} */ public function mapping(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Validation\MappingConfig { if (null === $this->mapping) { $this->_usedProperties['mapping'] = \true; $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Validation\MappingConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "mapping()" has already been initialized. You cannot pass values the second time you call mapping().'); } return $this->mapping; } /** * @default {"enabled":true,"endpoint":null} */ public function notCompromisedPassword(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Validation\NotCompromisedPasswordConfig { if (null === $this->notCompromisedPassword) { $this->_usedProperties['notCompromisedPassword'] = \true; $this->notCompromisedPassword = new \_ContaoManager\Symfony\Config\Framework\Validation\NotCompromisedPasswordConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "notCompromisedPassword()" has already been initialized. You cannot pass values the second time you call notCompromisedPassword().'); } return $this->notCompromisedPassword; } /** * @template TValue * @param TValue $value * A collection of namespaces for which auto-mapping will be enabled by default, or null to opt-in with the EnableAutoMapping constraint. * @example [] * @example ["validator.property_info_loader"] * @return \Symfony\Config\Framework\Validation\AutoMappingConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Validation\AutoMappingConfig : static) */ public function autoMapping(string $namespace, array $value = []) : \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig|static { if (!\is_array($value)) { $this->_usedProperties['autoMapping'] = \true; $this->autoMapping[$namespace] = $value; return $this; } if (!isset($this->autoMapping[$namespace]) || !$this->autoMapping[$namespace] instanceof \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig) { $this->_usedProperties['autoMapping'] = \true; $this->autoMapping[$namespace] = new \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "autoMapping()" has already been initialized. You cannot pass values the second time you call autoMapping().'); } return $this->autoMapping[$namespace]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('cache', $value)) { $this->_usedProperties['cache'] = \true; $this->cache = $value['cache']; unset($value['cache']); } if (\array_key_exists('enable_annotations', $value)) { $this->_usedProperties['enableAnnotations'] = \true; $this->enableAnnotations = $value['enable_annotations']; unset($value['enable_annotations']); } if (\array_key_exists('enable_attributes', $value)) { $this->_usedProperties['enableAttributes'] = \true; $this->enableAttributes = $value['enable_attributes']; unset($value['enable_attributes']); } if (\array_key_exists('static_method', $value)) { $this->_usedProperties['staticMethod'] = \true; $this->staticMethod = $value['static_method']; unset($value['static_method']); } if (\array_key_exists('translation_domain', $value)) { $this->_usedProperties['translationDomain'] = \true; $this->translationDomain = $value['translation_domain']; unset($value['translation_domain']); } if (\array_key_exists('email_validation_mode', $value)) { $this->_usedProperties['emailValidationMode'] = \true; $this->emailValidationMode = $value['email_validation_mode']; unset($value['email_validation_mode']); } if (\array_key_exists('mapping', $value)) { $this->_usedProperties['mapping'] = \true; $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Validation\MappingConfig($value['mapping']); unset($value['mapping']); } if (\array_key_exists('not_compromised_password', $value)) { $this->_usedProperties['notCompromisedPassword'] = \true; $this->notCompromisedPassword = new \_ContaoManager\Symfony\Config\Framework\Validation\NotCompromisedPasswordConfig($value['not_compromised_password']); unset($value['not_compromised_password']); } if (\array_key_exists('auto_mapping', $value)) { $this->_usedProperties['autoMapping'] = \true; $this->autoMapping = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig($v) : $v, $value['auto_mapping']); unset($value['auto_mapping']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['cache'])) { $output['cache'] = $this->cache; } if (isset($this->_usedProperties['enableAnnotations'])) { $output['enable_annotations'] = $this->enableAnnotations; } if (isset($this->_usedProperties['enableAttributes'])) { $output['enable_attributes'] = $this->enableAttributes; } if (isset($this->_usedProperties['staticMethod'])) { $output['static_method'] = $this->staticMethod; } if (isset($this->_usedProperties['translationDomain'])) { $output['translation_domain'] = $this->translationDomain; } if (isset($this->_usedProperties['emailValidationMode'])) { $output['email_validation_mode'] = $this->emailValidationMode; } if (isset($this->_usedProperties['mapping'])) { $output['mapping'] = $this->mapping->toArray(); } if (isset($this->_usedProperties['notCompromisedPassword'])) { $output['not_compromised_password'] = $this->notCompromisedPassword->toArray(); } if (isset($this->_usedProperties['autoMapping'])) { $output['auto_mapping'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Validation\AutoMappingConfig ? $v->toArray() : $v, $this->autoMapping); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function limiter(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig { if (!isset($this->limiters[$name])) { $this->_usedProperties['limiters'] = \true; $this->limiters[$name] = new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "limiter()" has already been initialized. You cannot pass values the second time you call limiter().'); } return $this->limiters[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('limiters', $value)) { $this->_usedProperties['limiters'] = \true; $this->limiters = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig($v), $value['limiters']); unset($value['limiters']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['limiters'])) { $output['limiters'] = \array_map(fn($v) => $v->toArray(), $this->limiters); } return $output; } } _usedProperties['interval'] = \true; $this->interval = $value; return $this; } /** * Amount of tokens to add each interval * @default 1 * @param ParamConfigurator|int $value * @return $this */ public function amount($value) : static { $this->_usedProperties['amount'] = \true; $this->amount = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('interval', $value)) { $this->_usedProperties['interval'] = \true; $this->interval = $value['interval']; unset($value['interval']); } if (\array_key_exists('amount', $value)) { $this->_usedProperties['amount'] = \true; $this->amount = $value['amount']; unset($value['amount']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['interval'])) { $output['interval'] = $this->interval; } if (isset($this->_usedProperties['amount'])) { $output['amount'] = $this->amount; } return $output; } } _usedProperties['lockFactory'] = \true; $this->lockFactory = $value; return $this; } /** * The cache pool to use for storing the current limiter state * @default 'cache.rate_limiter' * @param ParamConfigurator|mixed $value * @return $this */ public function cachePool($value) : static { $this->_usedProperties['cachePool'] = \true; $this->cachePool = $value; return $this; } /** * The service ID of a custom storage implementation, this precedes any configured "cache_pool" * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function storageService($value) : static { $this->_usedProperties['storageService'] = \true; $this->storageService = $value; return $this; } /** * The algorithm to be used by this limiter * @default null * @param ParamConfigurator|'fixed_window'|'token_bucket'|'sliding_window'|'no_limit' $value * @return $this */ public function policy($value) : static { $this->_usedProperties['policy'] = \true; $this->policy = $value; return $this; } /** * The maximum allowed hits in a fixed interval or burst * @default null * @param ParamConfigurator|int $value * @return $this */ public function limit($value) : static { $this->_usedProperties['limit'] = \true; $this->limit = $value; return $this; } /** * Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent). * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function interval($value) : static { $this->_usedProperties['interval'] = \true; $this->interval = $value; return $this; } /** * Configures the fill rate if "policy" is set to "token_bucket" */ public function rate(array $value = []) : \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig\RateConfig { if (null === $this->rate) { $this->_usedProperties['rate'] = \true; $this->rate = new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig\RateConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "rate()" has already been initialized. You cannot pass values the second time you call rate().'); } return $this->rate; } public function __construct(array $value = []) { if (\array_key_exists('lock_factory', $value)) { $this->_usedProperties['lockFactory'] = \true; $this->lockFactory = $value['lock_factory']; unset($value['lock_factory']); } if (\array_key_exists('cache_pool', $value)) { $this->_usedProperties['cachePool'] = \true; $this->cachePool = $value['cache_pool']; unset($value['cache_pool']); } if (\array_key_exists('storage_service', $value)) { $this->_usedProperties['storageService'] = \true; $this->storageService = $value['storage_service']; unset($value['storage_service']); } if (\array_key_exists('policy', $value)) { $this->_usedProperties['policy'] = \true; $this->policy = $value['policy']; unset($value['policy']); } if (\array_key_exists('limit', $value)) { $this->_usedProperties['limit'] = \true; $this->limit = $value['limit']; unset($value['limit']); } if (\array_key_exists('interval', $value)) { $this->_usedProperties['interval'] = \true; $this->interval = $value['interval']; unset($value['interval']); } if (\array_key_exists('rate', $value)) { $this->_usedProperties['rate'] = \true; $this->rate = new \_ContaoManager\Symfony\Config\Framework\RateLimiter\LimiterConfig\RateConfig($value['rate']); unset($value['rate']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['lockFactory'])) { $output['lock_factory'] = $this->lockFactory; } if (isset($this->_usedProperties['cachePool'])) { $output['cache_pool'] = $this->cachePool; } if (isset($this->_usedProperties['storageService'])) { $output['storage_service'] = $this->storageService; } if (isset($this->_usedProperties['policy'])) { $output['policy'] = $this->policy; } if (isset($this->_usedProperties['limit'])) { $output['limit'] = $this->limit; } if (isset($this->_usedProperties['interval'])) { $output['interval'] = $this->interval; } if (isset($this->_usedProperties['rate'])) { $output['rate'] = $this->rate->toArray(); } return $output; } } |mixed $value * * @return $this */ public function adapters(mixed $value) : static { $this->_usedProperties['adapters'] = \true; $this->adapters = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function tags($value) : static { $this->_usedProperties['tags'] = \true; $this->tags = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function public($value) : static { $this->_usedProperties['public'] = \true; $this->public = $value; return $this; } /** * Default lifetime of the pool * @example "300" for 5 minutes expressed in seconds, "PT5M" for five minutes expressed as ISO 8601 time interval, or "5 minutes" as a date expression * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function defaultLifetime($value) : static { $this->_usedProperties['defaultLifetime'] = \true; $this->defaultLifetime = $value; return $this; } /** * Overwrite the setting from the default provider for this adapter. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function provider($value) : static { $this->_usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @example "messenger.default_bus" to send early expiration events to the default Messenger bus. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function earlyExpirationMessageBus($value) : static { $this->_usedProperties['earlyExpirationMessageBus'] = \true; $this->earlyExpirationMessageBus = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function clearer($value) : static { $this->_usedProperties['clearer'] = \true; $this->clearer = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('adapters', $value)) { $this->_usedProperties['adapters'] = \true; $this->adapters = $value['adapters']; unset($value['adapters']); } if (\array_key_exists('tags', $value)) { $this->_usedProperties['tags'] = \true; $this->tags = $value['tags']; unset($value['tags']); } if (\array_key_exists('public', $value)) { $this->_usedProperties['public'] = \true; $this->public = $value['public']; unset($value['public']); } if (\array_key_exists('default_lifetime', $value)) { $this->_usedProperties['defaultLifetime'] = \true; $this->defaultLifetime = $value['default_lifetime']; unset($value['default_lifetime']); } if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('early_expiration_message_bus', $value)) { $this->_usedProperties['earlyExpirationMessageBus'] = \true; $this->earlyExpirationMessageBus = $value['early_expiration_message_bus']; unset($value['early_expiration_message_bus']); } if (\array_key_exists('clearer', $value)) { $this->_usedProperties['clearer'] = \true; $this->clearer = $value['clearer']; unset($value['clearer']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['adapters'])) { $output['adapters'] = $this->adapters; } if (isset($this->_usedProperties['tags'])) { $output['tags'] = $this->tags; } if (isset($this->_usedProperties['public'])) { $output['public'] = $this->public; } if (isset($this->_usedProperties['defaultLifetime'])) { $output['default_lifetime'] = $this->defaultLifetime; } if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['earlyExpirationMessageBus'])) { $output['early_expiration_message_bus'] = $this->earlyExpirationMessageBus; } if (isset($this->_usedProperties['clearer'])) { $output['clearer'] = $this->clearer; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function enableAnnotations($value) : static { $this->_usedProperties['enableAnnotations'] = \true; $this->enableAnnotations = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function enableAttributes($value) : static { $this->_usedProperties['enableAttributes'] = \true; $this->enableAttributes = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function nameConverter($value) : static { $this->_usedProperties['nameConverter'] = \true; $this->nameConverter = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function circularReferenceHandler($value) : static { $this->_usedProperties['circularReferenceHandler'] = \true; $this->circularReferenceHandler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function maxDepthHandler($value) : static { $this->_usedProperties['maxDepthHandler'] = \true; $this->maxDepthHandler = $value; return $this; } /** * @default {"paths":[]} */ public function mapping(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Serializer\MappingConfig { if (null === $this->mapping) { $this->_usedProperties['mapping'] = \true; $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Serializer\MappingConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "mapping()" has already been initialized. You cannot pass values the second time you call mapping().'); } return $this->mapping; } /** * @return $this */ public function defaultContext(string $name, mixed $value) : static { $this->_usedProperties['defaultContext'] = \true; $this->defaultContext[$name] = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('enable_annotations', $value)) { $this->_usedProperties['enableAnnotations'] = \true; $this->enableAnnotations = $value['enable_annotations']; unset($value['enable_annotations']); } if (\array_key_exists('enable_attributes', $value)) { $this->_usedProperties['enableAttributes'] = \true; $this->enableAttributes = $value['enable_attributes']; unset($value['enable_attributes']); } if (\array_key_exists('name_converter', $value)) { $this->_usedProperties['nameConverter'] = \true; $this->nameConverter = $value['name_converter']; unset($value['name_converter']); } if (\array_key_exists('circular_reference_handler', $value)) { $this->_usedProperties['circularReferenceHandler'] = \true; $this->circularReferenceHandler = $value['circular_reference_handler']; unset($value['circular_reference_handler']); } if (\array_key_exists('max_depth_handler', $value)) { $this->_usedProperties['maxDepthHandler'] = \true; $this->maxDepthHandler = $value['max_depth_handler']; unset($value['max_depth_handler']); } if (\array_key_exists('mapping', $value)) { $this->_usedProperties['mapping'] = \true; $this->mapping = new \_ContaoManager\Symfony\Config\Framework\Serializer\MappingConfig($value['mapping']); unset($value['mapping']); } if (\array_key_exists('default_context', $value)) { $this->_usedProperties['defaultContext'] = \true; $this->defaultContext = $value['default_context']; unset($value['default_context']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['enableAnnotations'])) { $output['enable_annotations'] = $this->enableAnnotations; } if (isset($this->_usedProperties['enableAttributes'])) { $output['enable_attributes'] = $this->enableAttributes; } if (isset($this->_usedProperties['nameConverter'])) { $output['name_converter'] = $this->nameConverter; } if (isset($this->_usedProperties['circularReferenceHandler'])) { $output['circular_reference_handler'] = $this->circularReferenceHandler; } if (isset($this->_usedProperties['maxDepthHandler'])) { $output['max_depth_handler'] = $this->maxDepthHandler; } if (isset($this->_usedProperties['mapping'])) { $output['mapping'] = $this->mapping->toArray(); } if (isset($this->_usedProperties['defaultContext'])) { $output['default_context'] = $this->defaultContext; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * Throw an exception if an entry is missing from the manifest.json * @default false * @param ParamConfigurator|bool $value * @return $this */ public function strictMode($value) : static { $this->_usedProperties['strictMode'] = \true; $this->strictMode = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function versionStrategy($value) : static { $this->_usedProperties['versionStrategy'] = \true; $this->versionStrategy = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function version($value) : static { $this->_usedProperties['version'] = \true; $this->version = $value; return $this; } /** * @default '%%s?%%s' * @param ParamConfigurator|mixed $value * @return $this */ public function versionFormat($value) : static { $this->_usedProperties['versionFormat'] = \true; $this->versionFormat = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function jsonManifestPath($value) : static { $this->_usedProperties['jsonManifestPath'] = \true; $this->jsonManifestPath = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function basePath($value) : static { $this->_usedProperties['basePath'] = \true; $this->basePath = $value; return $this; } /** * @param ParamConfigurator|list|mixed $value * * @return $this */ public function baseUrls(mixed $value) : static { $this->_usedProperties['baseUrls'] = \true; $this->baseUrls = $value; return $this; } public function package(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Framework\Assets\PackageConfig { if (!isset($this->packages[$name])) { $this->_usedProperties['packages'] = \true; $this->packages[$name] = new \_ContaoManager\Symfony\Config\Framework\Assets\PackageConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "package()" has already been initialized. You cannot pass values the second time you call package().'); } return $this->packages[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('strict_mode', $value)) { $this->_usedProperties['strictMode'] = \true; $this->strictMode = $value['strict_mode']; unset($value['strict_mode']); } if (\array_key_exists('version_strategy', $value)) { $this->_usedProperties['versionStrategy'] = \true; $this->versionStrategy = $value['version_strategy']; unset($value['version_strategy']); } if (\array_key_exists('version', $value)) { $this->_usedProperties['version'] = \true; $this->version = $value['version']; unset($value['version']); } if (\array_key_exists('version_format', $value)) { $this->_usedProperties['versionFormat'] = \true; $this->versionFormat = $value['version_format']; unset($value['version_format']); } if (\array_key_exists('json_manifest_path', $value)) { $this->_usedProperties['jsonManifestPath'] = \true; $this->jsonManifestPath = $value['json_manifest_path']; unset($value['json_manifest_path']); } if (\array_key_exists('base_path', $value)) { $this->_usedProperties['basePath'] = \true; $this->basePath = $value['base_path']; unset($value['base_path']); } if (\array_key_exists('base_urls', $value)) { $this->_usedProperties['baseUrls'] = \true; $this->baseUrls = $value['base_urls']; unset($value['base_urls']); } if (\array_key_exists('packages', $value)) { $this->_usedProperties['packages'] = \true; $this->packages = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Assets\PackageConfig($v), $value['packages']); unset($value['packages']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['strictMode'])) { $output['strict_mode'] = $this->strictMode; } if (isset($this->_usedProperties['versionStrategy'])) { $output['version_strategy'] = $this->versionStrategy; } if (isset($this->_usedProperties['version'])) { $output['version'] = $this->version; } if (isset($this->_usedProperties['versionFormat'])) { $output['version_format'] = $this->versionFormat; } if (isset($this->_usedProperties['jsonManifestPath'])) { $output['json_manifest_path'] = $this->jsonManifestPath; } if (isset($this->_usedProperties['basePath'])) { $output['base_path'] = $this->basePath; } if (isset($this->_usedProperties['baseUrls'])) { $output['base_urls'] = $this->baseUrls; } if (isset($this->_usedProperties['packages'])) { $output['packages'] = \array_map(fn($v) => $v->toArray(), $this->packages); } return $output; } } _usedProperties['email'] = \true; $this->email = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function phone($value) : static { $this->_usedProperties['phone'] = \true; $this->phone = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('email', $value)) { $this->_usedProperties['email'] = \true; $this->email = $value['email']; unset($value['email']); } if (\array_key_exists('phone', $value)) { $this->_usedProperties['phone'] = \true; $this->phone = $value['phone']; unset($value['phone']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['email'])) { $output['email'] = $this->email; } if (isset($this->_usedProperties['phone'])) { $output['phone'] = $this->phone; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Messenger\RoutingConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\RoutingConfig : static) */ public function routing(string $message_class, array $value = []) : \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig|static { if (!\is_array($value)) { $this->_usedProperties['routing'] = \true; $this->routing[$message_class] = $value; return $this; } if (!isset($this->routing[$message_class]) || !$this->routing[$message_class] instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig) { $this->_usedProperties['routing'] = \true; $this->routing[$message_class] = new \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "routing()" has already been initialized. You cannot pass values the second time you call routing().'); } return $this->routing[$message_class]; } /** * @default {"default_serializer":"messenger.transport.native_php_serializer","symfony_serializer":{"format":"json","context":[]}} */ public function serializer(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Messenger\SerializerConfig { if (null === $this->serializer) { $this->_usedProperties['serializer'] = \true; $this->serializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\SerializerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "serializer()" has already been initialized. You cannot pass values the second time you call serializer().'); } return $this->serializer; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Messenger\TransportConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\TransportConfig : static) */ public function transport(string $name, string|array $value = []) : \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig|static { if (!\is_array($value)) { $this->_usedProperties['transports'] = \true; $this->transports[$name] = $value; return $this; } if (!isset($this->transports[$name]) || !$this->transports[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig) { $this->_usedProperties['transports'] = \true; $this->transports[$name] = new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "transport()" has already been initialized. You cannot pass values the second time you call transport().'); } return $this->transports[$name]; } /** * Transport name to send failed messages to (after all retries have failed). * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureTransport($value) : static { $this->_usedProperties['failureTransport'] = \true; $this->failureTransport = $value; return $this; } /** * Reset container services after each message. * @default true * @param ParamConfigurator|bool $value * @deprecated Option "reset_on_message" at "messenger" is deprecated. It does nothing and will be removed in version 7.0. * @return $this */ public function resetOnMessage($value) : static { $this->_usedProperties['resetOnMessage'] = \true; $this->resetOnMessage = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function stopWorkerOnSignals(ParamConfigurator|array $value) : static { $this->_usedProperties['stopWorkerOnSignals'] = \true; $this->stopWorkerOnSignals = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function defaultBus($value) : static { $this->_usedProperties['defaultBus'] = \true; $this->defaultBus = $value; return $this; } /** * @default {"messenger.bus.default":{"default_middleware":{"enabled":true,"allow_no_handlers":false,"allow_no_senders":true},"middleware":[]}} */ public function bus(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig { if (!isset($this->buses[$name])) { $this->_usedProperties['buses'] = \true; $this->buses[$name] = new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "bus()" has already been initialized. You cannot pass values the second time you call bus().'); } return $this->buses[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('routing', $value)) { $this->_usedProperties['routing'] = \true; $this->routing = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig($v) : $v, $value['routing']); unset($value['routing']); } if (\array_key_exists('serializer', $value)) { $this->_usedProperties['serializer'] = \true; $this->serializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\SerializerConfig($value['serializer']); unset($value['serializer']); } if (\array_key_exists('transports', $value)) { $this->_usedProperties['transports'] = \true; $this->transports = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig($v) : $v, $value['transports']); unset($value['transports']); } if (\array_key_exists('failure_transport', $value)) { $this->_usedProperties['failureTransport'] = \true; $this->failureTransport = $value['failure_transport']; unset($value['failure_transport']); } if (\array_key_exists('reset_on_message', $value)) { $this->_usedProperties['resetOnMessage'] = \true; $this->resetOnMessage = $value['reset_on_message']; unset($value['reset_on_message']); } if (\array_key_exists('stop_worker_on_signals', $value)) { $this->_usedProperties['stopWorkerOnSignals'] = \true; $this->stopWorkerOnSignals = $value['stop_worker_on_signals']; unset($value['stop_worker_on_signals']); } if (\array_key_exists('default_bus', $value)) { $this->_usedProperties['defaultBus'] = \true; $this->defaultBus = $value['default_bus']; unset($value['default_bus']); } if (\array_key_exists('buses', $value)) { $this->_usedProperties['buses'] = \true; $this->buses = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig($v), $value['buses']); unset($value['buses']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['routing'])) { $output['routing'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\RoutingConfig ? $v->toArray() : $v, $this->routing); } if (isset($this->_usedProperties['serializer'])) { $output['serializer'] = $this->serializer->toArray(); } if (isset($this->_usedProperties['transports'])) { $output['transports'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig ? $v->toArray() : $v, $this->transports); } if (isset($this->_usedProperties['failureTransport'])) { $output['failure_transport'] = $this->failureTransport; } if (isset($this->_usedProperties['resetOnMessage'])) { $output['reset_on_message'] = $this->resetOnMessage; } if (isset($this->_usedProperties['stopWorkerOnSignals'])) { $output['stop_worker_on_signals'] = $this->stopWorkerOnSignals; } if (isset($this->_usedProperties['defaultBus'])) { $output['default_bus'] = $this->defaultBus; } if (isset($this->_usedProperties['buses'])) { $output['buses'] = \array_map(fn($v) => $v->toArray(), $this->buses); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * The message bus to use. * @default 'messenger.default_bus' * @param ParamConfigurator|mixed $value * @return $this */ public function messageBus($value) : static { $this->_usedProperties['messageBus'] = \true; $this->messageBus = $value; return $this; } public function routing(string $type, array $value = []) : \_ContaoManager\Symfony\Config\Framework\Webhook\RoutingConfig { if (!isset($this->routing[$type])) { $this->_usedProperties['routing'] = \true; $this->routing[$type] = new \_ContaoManager\Symfony\Config\Framework\Webhook\RoutingConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "routing()" has already been initialized. You cannot pass values the second time you call routing().'); } return $this->routing[$type]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('message_bus', $value)) { $this->_usedProperties['messageBus'] = \true; $this->messageBus = $value['message_bus']; unset($value['message_bus']); } if (\array_key_exists('routing', $value)) { $this->_usedProperties['routing'] = \true; $this->routing = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Webhook\RoutingConfig($v), $value['routing']); unset($value['routing']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['messageBus'])) { $output['message_bus'] = $this->messageBus; } if (isset($this->_usedProperties['routing'])) { $output['routing'] = \array_map(fn($v) => $v->toArray(), $this->routing); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function resource($value) : static { $this->_usedProperties['resource'] = \true; $this->resource = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function type($value) : static { $this->_usedProperties['type'] = \true; $this->type = $value; return $this; } /** * @default '%kernel.cache_dir%' * @param ParamConfigurator|mixed $value * @return $this */ public function cacheDir($value) : static { $this->_usedProperties['cacheDir'] = \true; $this->cacheDir = $value; return $this; } /** * The default URI used to generate URLs in a non-HTTP context * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function defaultUri($value) : static { $this->_usedProperties['defaultUri'] = \true; $this->defaultUri = $value; return $this; } /** * @default 80 * @param ParamConfigurator|mixed $value * @return $this */ public function httpPort($value) : static { $this->_usedProperties['httpPort'] = \true; $this->httpPort = $value; return $this; } /** * @default 443 * @param ParamConfigurator|mixed $value * @return $this */ public function httpsPort($value) : static { $this->_usedProperties['httpsPort'] = \true; $this->httpsPort = $value; return $this; } /** * set to true to throw an exception when a parameter does not match the requirements set to false to disable exceptions when a parameter does not match the requirements (and return null instead) set to null to disable parameter checks against requirements 'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production * @default true * @param ParamConfigurator|mixed $value * @return $this */ public function strictRequirements($value) : static { $this->_usedProperties['strictRequirements'] = \true; $this->strictRequirements = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function utf8($value) : static { $this->_usedProperties['utf8'] = \true; $this->utf8 = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('resource', $value)) { $this->_usedProperties['resource'] = \true; $this->resource = $value['resource']; unset($value['resource']); } if (\array_key_exists('type', $value)) { $this->_usedProperties['type'] = \true; $this->type = $value['type']; unset($value['type']); } if (\array_key_exists('cache_dir', $value)) { $this->_usedProperties['cacheDir'] = \true; $this->cacheDir = $value['cache_dir']; unset($value['cache_dir']); } if (\array_key_exists('default_uri', $value)) { $this->_usedProperties['defaultUri'] = \true; $this->defaultUri = $value['default_uri']; unset($value['default_uri']); } if (\array_key_exists('http_port', $value)) { $this->_usedProperties['httpPort'] = \true; $this->httpPort = $value['http_port']; unset($value['http_port']); } if (\array_key_exists('https_port', $value)) { $this->_usedProperties['httpsPort'] = \true; $this->httpsPort = $value['https_port']; unset($value['https_port']); } if (\array_key_exists('strict_requirements', $value)) { $this->_usedProperties['strictRequirements'] = \true; $this->strictRequirements = $value['strict_requirements']; unset($value['strict_requirements']); } if (\array_key_exists('utf8', $value)) { $this->_usedProperties['utf8'] = \true; $this->utf8 = $value['utf8']; unset($value['utf8']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['resource'])) { $output['resource'] = $this->resource; } if (isset($this->_usedProperties['type'])) { $output['type'] = $this->type; } if (isset($this->_usedProperties['cacheDir'])) { $output['cache_dir'] = $this->cacheDir; } if (isset($this->_usedProperties['defaultUri'])) { $output['default_uri'] = $this->defaultUri; } if (isset($this->_usedProperties['httpPort'])) { $output['http_port'] = $this->httpPort; } if (isset($this->_usedProperties['httpsPort'])) { $output['https_port'] = $this->httpsPort; } if (isset($this->_usedProperties['strictRequirements'])) { $output['strict_requirements'] = $this->strictRequirements; } if (isset($this->_usedProperties['utf8'])) { $output['utf8'] = $this->utf8; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function fallbacks(ParamConfigurator|string|array $value) : static { $this->_usedProperties['fallbacks'] = \true; $this->fallbacks = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function logging($value) : static { $this->_usedProperties['logging'] = \true; $this->logging = $value; return $this; } /** * @default 'translator.formatter.default' * @param ParamConfigurator|mixed $value * @return $this */ public function formatter($value) : static { $this->_usedProperties['formatter'] = \true; $this->formatter = $value; return $this; } /** * @default '%kernel.cache_dir%/translations' * @param ParamConfigurator|mixed $value * @return $this */ public function cacheDir($value) : static { $this->_usedProperties['cacheDir'] = \true; $this->cacheDir = $value; return $this; } /** * The default path used to load translations * @default '%kernel.project_dir%/translations' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultPath($value) : static { $this->_usedProperties['defaultPath'] = \true; $this->defaultPath = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function paths(ParamConfigurator|array $value) : static { $this->_usedProperties['paths'] = \true; $this->paths = $value; return $this; } /** * @template TValue * @param TValue $value * @default {"enabled":false,"accents":true,"expansion_factor":1,"brackets":true,"parse_html":false,"localizable_html_attributes":[]} * @return \Symfony\Config\Framework\Translator\PseudoLocalizationConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Translator\PseudoLocalizationConfig : static) */ public function pseudoLocalization(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig|static { if (!\is_array($value)) { $this->_usedProperties['pseudoLocalization'] = \true; $this->pseudoLocalization = $value; return $this; } if (!$this->pseudoLocalization instanceof \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig) { $this->_usedProperties['pseudoLocalization'] = \true; $this->pseudoLocalization = new \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "pseudoLocalization()" has already been initialized. You cannot pass values the second time you call pseudoLocalization().'); } return $this->pseudoLocalization; } /** * Translation providers you can read/write your translations from */ public function provider(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Framework\Translator\ProviderConfig { if (!isset($this->providers[$name])) { $this->_usedProperties['providers'] = \true; $this->providers[$name] = new \_ContaoManager\Symfony\Config\Framework\Translator\ProviderConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "provider()" has already been initialized. You cannot pass values the second time you call provider().'); } return $this->providers[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('fallbacks', $value)) { $this->_usedProperties['fallbacks'] = \true; $this->fallbacks = $value['fallbacks']; unset($value['fallbacks']); } if (\array_key_exists('logging', $value)) { $this->_usedProperties['logging'] = \true; $this->logging = $value['logging']; unset($value['logging']); } if (\array_key_exists('formatter', $value)) { $this->_usedProperties['formatter'] = \true; $this->formatter = $value['formatter']; unset($value['formatter']); } if (\array_key_exists('cache_dir', $value)) { $this->_usedProperties['cacheDir'] = \true; $this->cacheDir = $value['cache_dir']; unset($value['cache_dir']); } if (\array_key_exists('default_path', $value)) { $this->_usedProperties['defaultPath'] = \true; $this->defaultPath = $value['default_path']; unset($value['default_path']); } if (\array_key_exists('paths', $value)) { $this->_usedProperties['paths'] = \true; $this->paths = $value['paths']; unset($value['paths']); } if (\array_key_exists('pseudo_localization', $value)) { $this->_usedProperties['pseudoLocalization'] = \true; $this->pseudoLocalization = \is_array($value['pseudo_localization']) ? new \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig($value['pseudo_localization']) : $value['pseudo_localization']; unset($value['pseudo_localization']); } if (\array_key_exists('providers', $value)) { $this->_usedProperties['providers'] = \true; $this->providers = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Translator\ProviderConfig($v), $value['providers']); unset($value['providers']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['fallbacks'])) { $output['fallbacks'] = $this->fallbacks; } if (isset($this->_usedProperties['logging'])) { $output['logging'] = $this->logging; } if (isset($this->_usedProperties['formatter'])) { $output['formatter'] = $this->formatter; } if (isset($this->_usedProperties['cacheDir'])) { $output['cache_dir'] = $this->cacheDir; } if (isset($this->_usedProperties['defaultPath'])) { $output['default_path'] = $this->defaultPath; } if (isset($this->_usedProperties['paths'])) { $output['paths'] = $this->paths; } if (isset($this->_usedProperties['pseudoLocalization'])) { $output['pseudo_localization'] = $this->pseudoLocalization instanceof \_ContaoManager\Symfony\Config\Framework\Translator\PseudoLocalizationConfig ? $this->pseudoLocalization->toArray() : $this->pseudoLocalization; } if (isset($this->_usedProperties['providers'])) { $output['providers'] = \array_map(fn($v) => $v->toArray(), $this->providers); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Workflows\WorkflowsConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Workflows\WorkflowsConfig : static) */ public function workflows(string $name, mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig|static { if (!\is_array($value)) { $this->_usedProperties['workflows'] = \true; $this->workflows[$name] = $value; return $this; } if (!isset($this->workflows[$name]) || !$this->workflows[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig) { $this->_usedProperties['workflows'] = \true; $this->workflows[$name] = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "workflows()" has already been initialized. You cannot pass values the second time you call workflows().'); } return $this->workflows[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('workflows', $value)) { $this->_usedProperties['workflows'] = \true; $this->workflows = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig($v) : $v, $value['workflows']); unset($value['workflows']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['workflows'])) { $output['workflows'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig ? $v->toArray() : $v, $this->workflows); } return $output; } } _usedProperties['auditTrail'] = \true; $this->auditTrail = $value; return $this; } if (!$this->auditTrail instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig) { $this->_usedProperties['auditTrail'] = \true; $this->auditTrail = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "auditTrail()" has already been initialized. You cannot pass values the second time you call auditTrail().'); } return $this->auditTrail; } /** * @default 'state_machine' * @param ParamConfigurator|'workflow'|'state_machine' $value * @return $this */ public function type($value) : static { $this->_usedProperties['type'] = \true; $this->type = $value; return $this; } public function markingStore(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\MarkingStoreConfig { if (null === $this->markingStore) { $this->_usedProperties['markingStore'] = \true; $this->markingStore = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\MarkingStoreConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "markingStore()" has already been initialized. You cannot pass values the second time you call markingStore().'); } return $this->markingStore; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function supports(ParamConfigurator|string|array $value) : static { $this->_usedProperties['supports'] = \true; $this->supports = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function supportStrategy($value) : static { $this->_usedProperties['supportStrategy'] = \true; $this->supportStrategy = $value; return $this; } /** * @param ParamConfigurator|list|mixed $value * * @return $this */ public function initialMarking(mixed $value) : static { $this->_usedProperties['initialMarking'] = \true; $this->initialMarking = $value; return $this; } /** * Select which Transition events should be dispatched for this Workflow * @example workflow.enter * @example workflow.transition * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function eventsToDispatch(mixed $value = NULL) : static { $this->_usedProperties['eventsToDispatch'] = \true; $this->eventsToDispatch = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig : static) */ public function place(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig|static { $this->_usedProperties['places'] = \true; if (!\is_array($value)) { $this->places[] = $value; return $this; } return $this->places[] = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig($value); } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig : static) */ public function transition(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig|static { $this->_usedProperties['transitions'] = \true; if (!\is_array($value)) { $this->transitions[] = $value; return $this; } return $this->transitions[] = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig($value); } /** * @param ParamConfigurator|list $value * * @return $this */ public function metadata(ParamConfigurator|array $value) : static { $this->_usedProperties['metadata'] = \true; $this->metadata = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('audit_trail', $value)) { $this->_usedProperties['auditTrail'] = \true; $this->auditTrail = \is_array($value['audit_trail']) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig($value['audit_trail']) : $value['audit_trail']; unset($value['audit_trail']); } if (\array_key_exists('type', $value)) { $this->_usedProperties['type'] = \true; $this->type = $value['type']; unset($value['type']); } if (\array_key_exists('marking_store', $value)) { $this->_usedProperties['markingStore'] = \true; $this->markingStore = new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\MarkingStoreConfig($value['marking_store']); unset($value['marking_store']); } if (\array_key_exists('supports', $value)) { $this->_usedProperties['supports'] = \true; $this->supports = $value['supports']; unset($value['supports']); } if (\array_key_exists('support_strategy', $value)) { $this->_usedProperties['supportStrategy'] = \true; $this->supportStrategy = $value['support_strategy']; unset($value['support_strategy']); } if (\array_key_exists('initial_marking', $value)) { $this->_usedProperties['initialMarking'] = \true; $this->initialMarking = $value['initial_marking']; unset($value['initial_marking']); } if (\array_key_exists('events_to_dispatch', $value)) { $this->_usedProperties['eventsToDispatch'] = \true; $this->eventsToDispatch = $value['events_to_dispatch']; unset($value['events_to_dispatch']); } if (\array_key_exists('places', $value)) { $this->_usedProperties['places'] = \true; $this->places = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig($v) : $v, $value['places']); unset($value['places']); } if (\array_key_exists('transitions', $value)) { $this->_usedProperties['transitions'] = \true; $this->transitions = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig($v) : $v, $value['transitions']); unset($value['transitions']); } if (\array_key_exists('metadata', $value)) { $this->_usedProperties['metadata'] = \true; $this->metadata = $value['metadata']; unset($value['metadata']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['auditTrail'])) { $output['audit_trail'] = $this->auditTrail instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\AuditTrailConfig ? $this->auditTrail->toArray() : $this->auditTrail; } if (isset($this->_usedProperties['type'])) { $output['type'] = $this->type; } if (isset($this->_usedProperties['markingStore'])) { $output['marking_store'] = $this->markingStore->toArray(); } if (isset($this->_usedProperties['supports'])) { $output['supports'] = $this->supports; } if (isset($this->_usedProperties['supportStrategy'])) { $output['support_strategy'] = $this->supportStrategy; } if (isset($this->_usedProperties['initialMarking'])) { $output['initial_marking'] = $this->initialMarking; } if (isset($this->_usedProperties['eventsToDispatch'])) { $output['events_to_dispatch'] = $this->eventsToDispatch; } if (isset($this->_usedProperties['places'])) { $output['places'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\PlaceConfig ? $v->toArray() : $v, $this->places); } if (isset($this->_usedProperties['transitions'])) { $output['transitions'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Workflows\WorkflowsConfig\TransitionConfig ? $v->toArray() : $v, $this->transitions); } if (isset($this->_usedProperties['metadata'])) { $output['metadata'] = $this->metadata; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['type'] = \true; $this->type = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function property($value) : static { $this->_usedProperties['property'] = \true; $this->property = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function service($value) : static { $this->_usedProperties['service'] = \true; $this->service = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('type', $value)) { $this->_usedProperties['type'] = \true; $this->type = $value['type']; unset($value['type']); } if (\array_key_exists('property', $value)) { $this->_usedProperties['property'] = \true; $this->property = $value['property']; unset($value['property']); } if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['type'])) { $output['type'] = $this->type; } if (isset($this->_usedProperties['property'])) { $output['property'] = $this->property; } if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } return $output; } } _usedProperties['name'] = \true; $this->name = $value; return $this; } /** * An expression to block the transition * @example is_fully_authenticated() and is_granted('ROLE_JOURNALIST') and subject.getTitle() == 'My first article' * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function guard($value) : static { $this->_usedProperties['guard'] = \true; $this->guard = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function from(ParamConfigurator|string|array $value) : static { $this->_usedProperties['from'] = \true; $this->from = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function to(ParamConfigurator|string|array $value) : static { $this->_usedProperties['to'] = \true; $this->to = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function metadata(ParamConfigurator|array $value) : static { $this->_usedProperties['metadata'] = \true; $this->metadata = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('name', $value)) { $this->_usedProperties['name'] = \true; $this->name = $value['name']; unset($value['name']); } if (\array_key_exists('guard', $value)) { $this->_usedProperties['guard'] = \true; $this->guard = $value['guard']; unset($value['guard']); } if (\array_key_exists('from', $value)) { $this->_usedProperties['from'] = \true; $this->from = $value['from']; unset($value['from']); } if (\array_key_exists('to', $value)) { $this->_usedProperties['to'] = \true; $this->to = $value['to']; unset($value['to']); } if (\array_key_exists('metadata', $value)) { $this->_usedProperties['metadata'] = \true; $this->metadata = $value['metadata']; unset($value['metadata']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['name'])) { $output['name'] = $this->name; } if (isset($this->_usedProperties['guard'])) { $output['guard'] = $this->guard; } if (isset($this->_usedProperties['from'])) { $output['from'] = $this->from; } if (isset($this->_usedProperties['to'])) { $output['to'] = $this->to; } if (isset($this->_usedProperties['metadata'])) { $output['metadata'] = $this->metadata; } return $output; } } _usedProperties['name'] = \true; $this->name = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function metadata(ParamConfigurator|array $value) : static { $this->_usedProperties['metadata'] = \true; $this->metadata = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('name', $value)) { $this->_usedProperties['name'] = \true; $this->name = $value['name']; unset($value['name']); } if (\array_key_exists('metadata', $value)) { $this->_usedProperties['metadata'] = \true; $this->metadata = $value['metadata']; unset($value['metadata']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['name'])) { $output['name'] = $this->name; } if (isset($this->_usedProperties['metadata'])) { $output['metadata'] = $this->metadata; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['sender'] = \true; $this->sender = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function recipients(ParamConfigurator|array $value) : static { $this->_usedProperties['recipients'] = \true; $this->recipients = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('sender', $value)) { $this->_usedProperties['sender'] = \true; $this->sender = $value['sender']; unset($value['sender']); } if (\array_key_exists('recipients', $value)) { $this->_usedProperties['recipients'] = \true; $this->recipients = $value['recipients']; unset($value['recipients']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['sender'])) { $output['sender'] = $this->sender; } if (isset($this->_usedProperties['recipients'])) { $output['recipients'] = $this->recipients; } return $output; } } _usedProperties['value'] = \true; $this->value = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('value', $value)) { $this->_usedProperties['value'] = \true; $this->value = $value['value']; unset($value['value']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['value'])) { $output['value'] = $this->value; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function accents($value) : static { $this->_usedProperties['accents'] = \true; $this->accents = $value; return $this; } /** * @default 1.0 * @param ParamConfigurator|float $value * @return $this */ public function expansionFactor($value) : static { $this->_usedProperties['expansionFactor'] = \true; $this->expansionFactor = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function brackets($value) : static { $this->_usedProperties['brackets'] = \true; $this->brackets = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function parseHtml($value) : static { $this->_usedProperties['parseHtml'] = \true; $this->parseHtml = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function localizableHtmlAttributes(ParamConfigurator|array $value) : static { $this->_usedProperties['localizableHtmlAttributes'] = \true; $this->localizableHtmlAttributes = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('accents', $value)) { $this->_usedProperties['accents'] = \true; $this->accents = $value['accents']; unset($value['accents']); } if (\array_key_exists('expansion_factor', $value)) { $this->_usedProperties['expansionFactor'] = \true; $this->expansionFactor = $value['expansion_factor']; unset($value['expansion_factor']); } if (\array_key_exists('brackets', $value)) { $this->_usedProperties['brackets'] = \true; $this->brackets = $value['brackets']; unset($value['brackets']); } if (\array_key_exists('parse_html', $value)) { $this->_usedProperties['parseHtml'] = \true; $this->parseHtml = $value['parse_html']; unset($value['parse_html']); } if (\array_key_exists('localizable_html_attributes', $value)) { $this->_usedProperties['localizableHtmlAttributes'] = \true; $this->localizableHtmlAttributes = $value['localizable_html_attributes']; unset($value['localizable_html_attributes']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['accents'])) { $output['accents'] = $this->accents; } if (isset($this->_usedProperties['expansionFactor'])) { $output['expansion_factor'] = $this->expansionFactor; } if (isset($this->_usedProperties['brackets'])) { $output['brackets'] = $this->brackets; } if (isset($this->_usedProperties['parseHtml'])) { $output['parse_html'] = $this->parseHtml; } if (isset($this->_usedProperties['localizableHtmlAttributes'])) { $output['localizable_html_attributes'] = $this->localizableHtmlAttributes; } return $output; } } _usedProperties['dsn'] = \true; $this->dsn = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function domains(ParamConfigurator|array $value) : static { $this->_usedProperties['domains'] = \true; $this->domains = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function locales(ParamConfigurator|array $value) : static { $this->_usedProperties['locales'] = \true; $this->locales = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('dsn', $value)) { $this->_usedProperties['dsn'] = \true; $this->dsn = $value['dsn']; unset($value['dsn']); } if (\array_key_exists('domains', $value)) { $this->_usedProperties['domains'] = \true; $this->domains = $value['domains']; unset($value['domains']); } if (\array_key_exists('locales', $value)) { $this->_usedProperties['locales'] = \true; $this->locales = $value['locales']; unset($value['locales']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['dsn'])) { $output['dsn'] = $this->dsn; } if (isset($this->_usedProperties['domains'])) { $output['domains'] = $this->domains; } if (isset($this->_usedProperties['locales'])) { $output['locales'] = $this->locales; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function collect($value) : static { $this->_usedProperties['collect'] = \true; $this->collect = $value; return $this; } /** * The name of the parameter to use to enable or disable collection on a per request basis * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function collectParameter($value) : static { $this->_usedProperties['collectParameter'] = \true; $this->collectParameter = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function onlyExceptions($value) : static { $this->_usedProperties['onlyExceptions'] = \true; $this->onlyExceptions = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function onlyMainRequests($value) : static { $this->_usedProperties['onlyMainRequests'] = \true; $this->onlyMainRequests = $value; return $this; } /** * @default 'file:%kernel.cache_dir%/profiler' * @param ParamConfigurator|mixed $value * @return $this */ public function dsn($value) : static { $this->_usedProperties['dsn'] = \true; $this->dsn = $value; return $this; } /** * Enables the serializer data collector and profiler panel * @default false * @param ParamConfigurator|bool $value * @return $this */ public function collectSerializerData($value) : static { $this->_usedProperties['collectSerializerData'] = \true; $this->collectSerializerData = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('collect', $value)) { $this->_usedProperties['collect'] = \true; $this->collect = $value['collect']; unset($value['collect']); } if (\array_key_exists('collect_parameter', $value)) { $this->_usedProperties['collectParameter'] = \true; $this->collectParameter = $value['collect_parameter']; unset($value['collect_parameter']); } if (\array_key_exists('only_exceptions', $value)) { $this->_usedProperties['onlyExceptions'] = \true; $this->onlyExceptions = $value['only_exceptions']; unset($value['only_exceptions']); } if (\array_key_exists('only_main_requests', $value)) { $this->_usedProperties['onlyMainRequests'] = \true; $this->onlyMainRequests = $value['only_main_requests']; unset($value['only_main_requests']); } if (\array_key_exists('dsn', $value)) { $this->_usedProperties['dsn'] = \true; $this->dsn = $value['dsn']; unset($value['dsn']); } if (\array_key_exists('collect_serializer_data', $value)) { $this->_usedProperties['collectSerializerData'] = \true; $this->collectSerializerData = $value['collect_serializer_data']; unset($value['collect_serializer_data']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['collect'])) { $output['collect'] = $this->collect; } if (isset($this->_usedProperties['collectParameter'])) { $output['collect_parameter'] = $this->collectParameter; } if (isset($this->_usedProperties['onlyExceptions'])) { $output['only_exceptions'] = $this->onlyExceptions; } if (isset($this->_usedProperties['onlyMainRequests'])) { $output['only_main_requests'] = $this->onlyMainRequests; } if (isset($this->_usedProperties['dsn'])) { $output['dsn'] = $this->dsn; } if (isset($this->_usedProperties['collectSerializerData'])) { $output['collect_serializer_data'] = $this->collectSerializerData; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @return $this */ public function resource(string $name, mixed $value) : static { $this->_usedProperties['resources'] = \true; $this->resources[$name] = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('resources', $value)) { $this->_usedProperties['resources'] = \true; $this->resources = $value['resources']; unset($value['resources']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['resources'])) { $output['resources'] = $this->resources; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default '%kernel.project_dir%/config/secrets/%kernel.runtime_environment%' * @param ParamConfigurator|mixed $value * @return $this */ public function vaultDirectory($value) : static { $this->_usedProperties['vaultDirectory'] = \true; $this->vaultDirectory = $value; return $this; } /** * @default '%kernel.project_dir%/.env.%kernel.environment%.local' * @param ParamConfigurator|mixed $value * @return $this */ public function localDotenvFile($value) : static { $this->_usedProperties['localDotenvFile'] = \true; $this->localDotenvFile = $value; return $this; } /** * @default 'base64:default::SYMFONY_DECRYPTION_SECRET' * @param ParamConfigurator|mixed $value * @return $this */ public function decryptionEnvVar($value) : static { $this->_usedProperties['decryptionEnvVar'] = \true; $this->decryptionEnvVar = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('vault_directory', $value)) { $this->_usedProperties['vaultDirectory'] = \true; $this->vaultDirectory = $value['vault_directory']; unset($value['vault_directory']); } if (\array_key_exists('local_dotenv_file', $value)) { $this->_usedProperties['localDotenvFile'] = \true; $this->localDotenvFile = $value['local_dotenv_file']; unset($value['local_dotenv_file']); } if (\array_key_exists('decryption_env_var', $value)) { $this->_usedProperties['decryptionEnvVar'] = \true; $this->decryptionEnvVar = $value['decryption_env_var']; unset($value['decryption_env_var']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['vaultDirectory'])) { $output['vault_directory'] = $this->vaultDirectory; } if (isset($this->_usedProperties['localDotenvFile'])) { $output['local_dotenv_file'] = $this->localDotenvFile; } if (isset($this->_usedProperties['decryptionEnvVar'])) { $output['decryption_env_var'] = $this->decryptionEnvVar; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function magicCall($value) : static { $this->_usedProperties['magicCall'] = \true; $this->magicCall = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function magicGet($value) : static { $this->_usedProperties['magicGet'] = \true; $this->magicGet = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function magicSet($value) : static { $this->_usedProperties['magicSet'] = \true; $this->magicSet = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function throwExceptionOnInvalidIndex($value) : static { $this->_usedProperties['throwExceptionOnInvalidIndex'] = \true; $this->throwExceptionOnInvalidIndex = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function throwExceptionOnInvalidPropertyPath($value) : static { $this->_usedProperties['throwExceptionOnInvalidPropertyPath'] = \true; $this->throwExceptionOnInvalidPropertyPath = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('magic_call', $value)) { $this->_usedProperties['magicCall'] = \true; $this->magicCall = $value['magic_call']; unset($value['magic_call']); } if (\array_key_exists('magic_get', $value)) { $this->_usedProperties['magicGet'] = \true; $this->magicGet = $value['magic_get']; unset($value['magic_get']); } if (\array_key_exists('magic_set', $value)) { $this->_usedProperties['magicSet'] = \true; $this->magicSet = $value['magic_set']; unset($value['magic_set']); } if (\array_key_exists('throw_exception_on_invalid_index', $value)) { $this->_usedProperties['throwExceptionOnInvalidIndex'] = \true; $this->throwExceptionOnInvalidIndex = $value['throw_exception_on_invalid_index']; unset($value['throw_exception_on_invalid_index']); } if (\array_key_exists('throw_exception_on_invalid_property_path', $value)) { $this->_usedProperties['throwExceptionOnInvalidPropertyPath'] = \true; $this->throwExceptionOnInvalidPropertyPath = $value['throw_exception_on_invalid_property_path']; unset($value['throw_exception_on_invalid_property_path']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['magicCall'])) { $output['magic_call'] = $this->magicCall; } if (isset($this->_usedProperties['magicGet'])) { $output['magic_get'] = $this->magicGet; } if (isset($this->_usedProperties['magicSet'])) { $output['magic_set'] = $this->magicSet; } if (isset($this->_usedProperties['throwExceptionOnInvalidIndex'])) { $output['throw_exception_on_invalid_index'] = $this->throwExceptionOnInvalidIndex; } if (isset($this->_usedProperties['throwExceptionOnInvalidPropertyPath'])) { $output['throw_exception_on_invalid_property_path'] = $this->throwExceptionOnInvalidPropertyPath; } return $output; } } _usedProperties['dsn'] = \true; $this->dsn = $value; return $this; } /** * Service id of a custom serializer to use. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function serializer($value) : static { $this->_usedProperties['serializer'] = \true; $this->serializer = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function options(ParamConfigurator|array $value) : static { $this->_usedProperties['options'] = \true; $this->options = $value; return $this; } /** * Transport name to send failed messages to (after all retries have failed). * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureTransport($value) : static { $this->_usedProperties['failureTransport'] = \true; $this->failureTransport = $value; return $this; } /** * @template TValue * @param TValue $value * @default {"service":null,"max_retries":3,"delay":1000,"multiplier":2,"max_delay":0} * @return \Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig : static) */ public function retryStrategy(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig|static { if (!\is_array($value)) { $this->_usedProperties['retryStrategy'] = \true; $this->retryStrategy = $value; return $this; } if (!$this->retryStrategy instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig) { $this->_usedProperties['retryStrategy'] = \true; $this->retryStrategy = new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "retryStrategy()" has already been initialized. You cannot pass values the second time you call retryStrategy().'); } return $this->retryStrategy; } /** * Rate limiter name to use when processing messages * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function rateLimiter($value) : static { $this->_usedProperties['rateLimiter'] = \true; $this->rateLimiter = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('dsn', $value)) { $this->_usedProperties['dsn'] = \true; $this->dsn = $value['dsn']; unset($value['dsn']); } if (\array_key_exists('serializer', $value)) { $this->_usedProperties['serializer'] = \true; $this->serializer = $value['serializer']; unset($value['serializer']); } if (\array_key_exists('options', $value)) { $this->_usedProperties['options'] = \true; $this->options = $value['options']; unset($value['options']); } if (\array_key_exists('failure_transport', $value)) { $this->_usedProperties['failureTransport'] = \true; $this->failureTransport = $value['failure_transport']; unset($value['failure_transport']); } if (\array_key_exists('retry_strategy', $value)) { $this->_usedProperties['retryStrategy'] = \true; $this->retryStrategy = \is_array($value['retry_strategy']) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig($value['retry_strategy']) : $value['retry_strategy']; unset($value['retry_strategy']); } if (\array_key_exists('rate_limiter', $value)) { $this->_usedProperties['rateLimiter'] = \true; $this->rateLimiter = $value['rate_limiter']; unset($value['rate_limiter']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['dsn'])) { $output['dsn'] = $this->dsn; } if (isset($this->_usedProperties['serializer'])) { $output['serializer'] = $this->serializer; } if (isset($this->_usedProperties['options'])) { $output['options'] = $this->options; } if (isset($this->_usedProperties['failureTransport'])) { $output['failure_transport'] = $this->failureTransport; } if (isset($this->_usedProperties['retryStrategy'])) { $output['retry_strategy'] = $this->retryStrategy instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\TransportConfig\RetryStrategyConfig ? $this->retryStrategy->toArray() : $this->retryStrategy; } if (isset($this->_usedProperties['rateLimiter'])) { $output['rate_limiter'] = $this->rateLimiter; } return $output; } } _usedProperties['format'] = \true; $this->format = $value; return $this; } /** * @return $this */ public function context(string $name, mixed $value) : static { $this->_usedProperties['context'] = \true; $this->context[$name] = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('format', $value)) { $this->_usedProperties['format'] = \true; $this->format = $value['format']; unset($value['format']); } if (\array_key_exists('context', $value)) { $this->_usedProperties['context'] = \true; $this->context = $value['context']; unset($value['context']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['format'])) { $output['format'] = $this->format; } if (isset($this->_usedProperties['context'])) { $output['context'] = $this->context; } return $output; } } _usedProperties['defaultSerializer'] = \true; $this->defaultSerializer = $value; return $this; } /** * @default {"format":"json","context":[]} */ public function symfonySerializer(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Messenger\Serializer\SymfonySerializerConfig { if (null === $this->symfonySerializer) { $this->_usedProperties['symfonySerializer'] = \true; $this->symfonySerializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\Serializer\SymfonySerializerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "symfonySerializer()" has already been initialized. You cannot pass values the second time you call symfonySerializer().'); } return $this->symfonySerializer; } public function __construct(array $value = []) { if (\array_key_exists('default_serializer', $value)) { $this->_usedProperties['defaultSerializer'] = \true; $this->defaultSerializer = $value['default_serializer']; unset($value['default_serializer']); } if (\array_key_exists('symfony_serializer', $value)) { $this->_usedProperties['symfonySerializer'] = \true; $this->symfonySerializer = new \_ContaoManager\Symfony\Config\Framework\Messenger\Serializer\SymfonySerializerConfig($value['symfony_serializer']); unset($value['symfony_serializer']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['defaultSerializer'])) { $output['default_serializer'] = $this->defaultSerializer; } if (isset($this->_usedProperties['symfonySerializer'])) { $output['symfony_serializer'] = $this->symfonySerializer->toArray(); } return $output; } } _usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @default 3 * @param ParamConfigurator|int $value * @return $this */ public function maxRetries($value) : static { $this->_usedProperties['maxRetries'] = \true; $this->maxRetries = $value; return $this; } /** * Time in ms to delay (or the initial value when multiplier is used) * @default 1000 * @param ParamConfigurator|int $value * @return $this */ public function delay($value) : static { $this->_usedProperties['delay'] = \true; $this->delay = $value; return $this; } /** * If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries)) * @default 2 * @param ParamConfigurator|float $value * @return $this */ public function multiplier($value) : static { $this->_usedProperties['multiplier'] = \true; $this->multiplier = $value; return $this; } /** * Max time in ms that a retry should ever be delayed (0 = infinite) * @default 0 * @param ParamConfigurator|int $value * @return $this */ public function maxDelay($value) : static { $this->_usedProperties['maxDelay'] = \true; $this->maxDelay = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('max_retries', $value)) { $this->_usedProperties['maxRetries'] = \true; $this->maxRetries = $value['max_retries']; unset($value['max_retries']); } if (\array_key_exists('delay', $value)) { $this->_usedProperties['delay'] = \true; $this->delay = $value['delay']; unset($value['delay']); } if (\array_key_exists('multiplier', $value)) { $this->_usedProperties['multiplier'] = \true; $this->multiplier = $value['multiplier']; unset($value['multiplier']); } if (\array_key_exists('max_delay', $value)) { $this->_usedProperties['maxDelay'] = \true; $this->maxDelay = $value['max_delay']; unset($value['max_delay']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['maxRetries'])) { $output['max_retries'] = $this->maxRetries; } if (isset($this->_usedProperties['delay'])) { $output['delay'] = $this->delay; } if (isset($this->_usedProperties['multiplier'])) { $output['multiplier'] = $this->multiplier; } if (isset($this->_usedProperties['maxDelay'])) { $output['max_delay'] = $this->maxDelay; } return $output; } } $value * * @return $this */ public function senders(ParamConfigurator|array $value) : static { $this->_usedProperties['senders'] = \true; $this->senders = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('senders', $value)) { $this->_usedProperties['senders'] = \true; $this->senders = $value['senders']; unset($value['senders']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['senders'])) { $output['senders'] = $this->senders; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function arguments(ParamConfigurator|array $value) : static { $this->_usedProperties['arguments'] = \true; $this->arguments = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('arguments', $value)) { $this->_usedProperties['arguments'] = \true; $this->arguments = $value['arguments']; unset($value['arguments']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['arguments'])) { $output['arguments'] = $this->arguments; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function allowNoHandlers($value) : static { $this->_usedProperties['allowNoHandlers'] = \true; $this->allowNoHandlers = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function allowNoSenders($value) : static { $this->_usedProperties['allowNoSenders'] = \true; $this->allowNoSenders = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('allow_no_handlers', $value)) { $this->_usedProperties['allowNoHandlers'] = \true; $this->allowNoHandlers = $value['allow_no_handlers']; unset($value['allow_no_handlers']); } if (\array_key_exists('allow_no_senders', $value)) { $this->_usedProperties['allowNoSenders'] = \true; $this->allowNoSenders = $value['allow_no_senders']; unset($value['allow_no_senders']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['allowNoHandlers'])) { $output['allow_no_handlers'] = $this->allowNoHandlers; } if (isset($this->_usedProperties['allowNoSenders'])) { $output['allow_no_senders'] = $this->allowNoSenders; } return $output; } } _usedProperties['defaultMiddleware'] = \true; $this->defaultMiddleware = $value; return $this; } if (!$this->defaultMiddleware instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig) { $this->_usedProperties['defaultMiddleware'] = \true; $this->defaultMiddleware = new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "defaultMiddleware()" has already been initialized. You cannot pass values the second time you call defaultMiddleware().'); } return $this->defaultMiddleware; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig : static) */ public function middleware(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig|static { $this->_usedProperties['middleware'] = \true; if (!\is_array($value)) { $this->middleware[] = $value; return $this; } return $this->middleware[] = new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig($value); } public function __construct(array $value = []) { if (\array_key_exists('default_middleware', $value)) { $this->_usedProperties['defaultMiddleware'] = \true; $this->defaultMiddleware = \is_array($value['default_middleware']) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig($value['default_middleware']) : $value['default_middleware']; unset($value['default_middleware']); } if (\array_key_exists('middleware', $value)) { $this->_usedProperties['middleware'] = \true; $this->middleware = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig($v) : $v, $value['middleware']); unset($value['middleware']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['defaultMiddleware'])) { $output['default_middleware'] = $this->defaultMiddleware instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\DefaultMiddlewareConfig ? $this->defaultMiddleware->toArray() : $this->defaultMiddleware; } if (isset($this->_usedProperties['middleware'])) { $output['middleware'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Messenger\BusConfig\MiddlewareConfig ? $v->toArray() : $v, $this->middleware); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * The message bus to use. Defaults to the default bus if the Messenger component is installed. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function messageBus($value) : static { $this->_usedProperties['messageBus'] = \true; $this->messageBus = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function dsn($value) : static { $this->_usedProperties['dsn'] = \true; $this->dsn = $value; return $this; } /** * @return $this */ public function transport(string $name, mixed $value) : static { $this->_usedProperties['transports'] = \true; $this->transports[$name] = $value; return $this; } /** * Mailer Envelope configuration */ public function envelope(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Mailer\EnvelopeConfig { if (null === $this->envelope) { $this->_usedProperties['envelope'] = \true; $this->envelope = new \_ContaoManager\Symfony\Config\Framework\Mailer\EnvelopeConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "envelope()" has already been initialized. You cannot pass values the second time you call envelope().'); } return $this->envelope; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\Mailer\HeaderConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\Mailer\HeaderConfig : static) */ public function header(string $name, mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig|static { if (!\is_array($value)) { $this->_usedProperties['headers'] = \true; $this->headers[$name] = $value; return $this; } if (!isset($this->headers[$name]) || !$this->headers[$name] instanceof \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig) { $this->_usedProperties['headers'] = \true; $this->headers[$name] = new \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "header()" has already been initialized. You cannot pass values the second time you call header().'); } return $this->headers[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('message_bus', $value)) { $this->_usedProperties['messageBus'] = \true; $this->messageBus = $value['message_bus']; unset($value['message_bus']); } if (\array_key_exists('dsn', $value)) { $this->_usedProperties['dsn'] = \true; $this->dsn = $value['dsn']; unset($value['dsn']); } if (\array_key_exists('transports', $value)) { $this->_usedProperties['transports'] = \true; $this->transports = $value['transports']; unset($value['transports']); } if (\array_key_exists('envelope', $value)) { $this->_usedProperties['envelope'] = \true; $this->envelope = new \_ContaoManager\Symfony\Config\Framework\Mailer\EnvelopeConfig($value['envelope']); unset($value['envelope']); } if (\array_key_exists('headers', $value)) { $this->_usedProperties['headers'] = \true; $this->headers = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig($v) : $v, $value['headers']); unset($value['headers']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['messageBus'])) { $output['message_bus'] = $this->messageBus; } if (isset($this->_usedProperties['dsn'])) { $output['dsn'] = $this->dsn; } if (isset($this->_usedProperties['transports'])) { $output['transports'] = $this->transports; } if (isset($this->_usedProperties['envelope'])) { $output['envelope'] = $this->envelope->toArray(); } if (isset($this->_usedProperties['headers'])) { $output['headers'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\Mailer\HeaderConfig ? $v->toArray() : $v, $this->headers); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default null * @param ParamConfigurator|7|6|4|1 $value * @return $this */ public function defaultUuidVersion($value) : static { $this->_usedProperties['defaultUuidVersion'] = \true; $this->defaultUuidVersion = $value; return $this; } /** * @default 5 * @param ParamConfigurator|5|3 $value * @return $this */ public function nameBasedUuidVersion($value) : static { $this->_usedProperties['nameBasedUuidVersion'] = \true; $this->nameBasedUuidVersion = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function nameBasedUuidNamespace($value) : static { $this->_usedProperties['nameBasedUuidNamespace'] = \true; $this->nameBasedUuidNamespace = $value; return $this; } /** * @default null * @param ParamConfigurator|7|6|1 $value * @return $this */ public function timeBasedUuidVersion($value) : static { $this->_usedProperties['timeBasedUuidVersion'] = \true; $this->timeBasedUuidVersion = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function timeBasedUuidNode($value) : static { $this->_usedProperties['timeBasedUuidNode'] = \true; $this->timeBasedUuidNode = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('default_uuid_version', $value)) { $this->_usedProperties['defaultUuidVersion'] = \true; $this->defaultUuidVersion = $value['default_uuid_version']; unset($value['default_uuid_version']); } if (\array_key_exists('name_based_uuid_version', $value)) { $this->_usedProperties['nameBasedUuidVersion'] = \true; $this->nameBasedUuidVersion = $value['name_based_uuid_version']; unset($value['name_based_uuid_version']); } if (\array_key_exists('name_based_uuid_namespace', $value)) { $this->_usedProperties['nameBasedUuidNamespace'] = \true; $this->nameBasedUuidNamespace = $value['name_based_uuid_namespace']; unset($value['name_based_uuid_namespace']); } if (\array_key_exists('time_based_uuid_version', $value)) { $this->_usedProperties['timeBasedUuidVersion'] = \true; $this->timeBasedUuidVersion = $value['time_based_uuid_version']; unset($value['time_based_uuid_version']); } if (\array_key_exists('time_based_uuid_node', $value)) { $this->_usedProperties['timeBasedUuidNode'] = \true; $this->timeBasedUuidNode = $value['time_based_uuid_node']; unset($value['time_based_uuid_node']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['defaultUuidVersion'])) { $output['default_uuid_version'] = $this->defaultUuidVersion; } if (isset($this->_usedProperties['nameBasedUuidVersion'])) { $output['name_based_uuid_version'] = $this->nameBasedUuidVersion; } if (isset($this->_usedProperties['nameBasedUuidNamespace'])) { $output['name_based_uuid_namespace'] = $this->nameBasedUuidNamespace; } if (isset($this->_usedProperties['timeBasedUuidVersion'])) { $output['time_based_uuid_version'] = $this->timeBasedUuidVersion; } if (isset($this->_usedProperties['timeBasedUuidNode'])) { $output['time_based_uuid_node'] = $this->timeBasedUuidNode; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @return $this */ public function path(string $namespace, mixed $value) : static { $this->_usedProperties['paths'] = \true; $this->paths[$namespace] = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function excludedPatterns(ParamConfigurator|array $value) : static { $this->_usedProperties['excludedPatterns'] = \true; $this->excludedPatterns = $value; return $this; } /** * If true, any files starting with "." will be excluded from the asset mapper * @default true * @param ParamConfigurator|bool $value * @return $this */ public function excludeDotfiles($value) : static { $this->_usedProperties['excludeDotfiles'] = \true; $this->excludeDotfiles = $value; return $this; } /** * If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default) * @default false * @param ParamConfigurator|bool $value * @return $this */ public function server($value) : static { $this->_usedProperties['server'] = \true; $this->server = $value; return $this; } /** * The public path where the assets will be written to (and served from when "server" is true) * @default '/assets/' * @param ParamConfigurator|mixed $value * @return $this */ public function publicPrefix($value) : static { $this->_usedProperties['publicPrefix'] = \true; $this->publicPrefix = $value; return $this; } /** * Behavior if an asset cannot be found when imported from JavaScript or CSS files - e.g. "import './non-existent.js'". "strict" means an exception is thrown, "warn" means a warning is logged, "ignore" means the import is left as-is. * @default 'warn' * @param ParamConfigurator|'strict'|'warn'|'ignore' $value * @return $this */ public function missingImportMode($value) : static { $this->_usedProperties['missingImportMode'] = \true; $this->missingImportMode = $value; return $this; } /** * @return $this */ public function extension(string $extension, mixed $value) : static { $this->_usedProperties['extensions'] = \true; $this->extensions[$extension] = $value; return $this; } /** * The path of the importmap.php file. * @default '%kernel.project_dir%/importmap.php' * @param ParamConfigurator|mixed $value * @return $this */ public function importmapPath($value) : static { $this->_usedProperties['importmapPath'] = \true; $this->importmapPath = $value; return $this; } /** * The importmap name that will be used to load the polyfill. Set to false to disable. * @default 'es-module-shims' * @param ParamConfigurator|mixed $value * @return $this */ public function importmapPolyfill($value) : static { $this->_usedProperties['importmapPolyfill'] = \true; $this->importmapPolyfill = $value; return $this; } /** * @return $this */ public function importmapScriptAttribute(string $key, mixed $value) : static { $this->_usedProperties['importmapScriptAttributes'] = \true; $this->importmapScriptAttributes[$key] = $value; return $this; } /** * The directory to store JavaScript vendors. * @default '%kernel.project_dir%/assets/vendor' * @param ParamConfigurator|mixed $value * @return $this */ public function vendorDir($value) : static { $this->_usedProperties['vendorDir'] = \true; $this->vendorDir = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @deprecated Option "provider" at "asset_mapper" is deprecated and does nothing. Remove it. * @return $this */ public function provider($value) : static { $this->_usedProperties['provider'] = \true; $this->provider = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('paths', $value)) { $this->_usedProperties['paths'] = \true; $this->paths = $value['paths']; unset($value['paths']); } if (\array_key_exists('excluded_patterns', $value)) { $this->_usedProperties['excludedPatterns'] = \true; $this->excludedPatterns = $value['excluded_patterns']; unset($value['excluded_patterns']); } if (\array_key_exists('exclude_dotfiles', $value)) { $this->_usedProperties['excludeDotfiles'] = \true; $this->excludeDotfiles = $value['exclude_dotfiles']; unset($value['exclude_dotfiles']); } if (\array_key_exists('server', $value)) { $this->_usedProperties['server'] = \true; $this->server = $value['server']; unset($value['server']); } if (\array_key_exists('public_prefix', $value)) { $this->_usedProperties['publicPrefix'] = \true; $this->publicPrefix = $value['public_prefix']; unset($value['public_prefix']); } if (\array_key_exists('missing_import_mode', $value)) { $this->_usedProperties['missingImportMode'] = \true; $this->missingImportMode = $value['missing_import_mode']; unset($value['missing_import_mode']); } if (\array_key_exists('extensions', $value)) { $this->_usedProperties['extensions'] = \true; $this->extensions = $value['extensions']; unset($value['extensions']); } if (\array_key_exists('importmap_path', $value)) { $this->_usedProperties['importmapPath'] = \true; $this->importmapPath = $value['importmap_path']; unset($value['importmap_path']); } if (\array_key_exists('importmap_polyfill', $value)) { $this->_usedProperties['importmapPolyfill'] = \true; $this->importmapPolyfill = $value['importmap_polyfill']; unset($value['importmap_polyfill']); } if (\array_key_exists('importmap_script_attributes', $value)) { $this->_usedProperties['importmapScriptAttributes'] = \true; $this->importmapScriptAttributes = $value['importmap_script_attributes']; unset($value['importmap_script_attributes']); } if (\array_key_exists('vendor_dir', $value)) { $this->_usedProperties['vendorDir'] = \true; $this->vendorDir = $value['vendor_dir']; unset($value['vendor_dir']); } if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['paths'])) { $output['paths'] = $this->paths; } if (isset($this->_usedProperties['excludedPatterns'])) { $output['excluded_patterns'] = $this->excludedPatterns; } if (isset($this->_usedProperties['excludeDotfiles'])) { $output['exclude_dotfiles'] = $this->excludeDotfiles; } if (isset($this->_usedProperties['server'])) { $output['server'] = $this->server; } if (isset($this->_usedProperties['publicPrefix'])) { $output['public_prefix'] = $this->publicPrefix; } if (isset($this->_usedProperties['missingImportMode'])) { $output['missing_import_mode'] = $this->missingImportMode; } if (isset($this->_usedProperties['extensions'])) { $output['extensions'] = $this->extensions; } if (isset($this->_usedProperties['importmapPath'])) { $output['importmap_path'] = $this->importmapPath; } if (isset($this->_usedProperties['importmapPolyfill'])) { $output['importmap_polyfill'] = $this->importmapPolyfill; } if (isset($this->_usedProperties['importmapScriptAttributes'])) { $output['importmap_script_attributes'] = $this->importmapScriptAttributes; } if (isset($this->_usedProperties['vendorDir'])) { $output['vendor_dir'] = $this->vendorDir; } if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function sanitizer(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Framework\HtmlSanitizer\SanitizerConfig { if (!isset($this->sanitizers[$name])) { $this->_usedProperties['sanitizers'] = \true; $this->sanitizers[$name] = new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizer\SanitizerConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "sanitizer()" has already been initialized. You cannot pass values the second time you call sanitizer().'); } return $this->sanitizers[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('sanitizers', $value)) { $this->_usedProperties['sanitizers'] = \true; $this->sanitizers = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizer\SanitizerConfig($v), $value['sanitizers']); unset($value['sanitizers']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['sanitizers'])) { $output['sanitizers'] = \array_map(fn($v) => $v->toArray(), $this->sanitizers); } return $output; } } _usedProperties['logLevel'] = \true; $this->logLevel = $value; return $this; } /** * The status code of the response. Null or 0 to let Symfony decide. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function statusCode($value) : static { $this->_usedProperties['statusCode'] = \true; $this->statusCode = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('log_level', $value)) { $this->_usedProperties['logLevel'] = \true; $this->logLevel = $value['log_level']; unset($value['log_level']); } if (\array_key_exists('status_code', $value)) { $this->_usedProperties['statusCode'] = \true; $this->statusCode = $value['status_code']; unset($value['status_code']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['logLevel'])) { $output['log_level'] = $this->logLevel; } if (isset($this->_usedProperties['statusCode'])) { $output['status_code'] = $this->statusCode; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default 'session.storage.factory.native' * @param ParamConfigurator|mixed $value * @return $this */ public function storageFactoryId($value) : static { $this->_usedProperties['storageFactoryId'] = \true; $this->storageFactoryId = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function handlerId($value) : static { $this->_usedProperties['handlerId'] = \true; $this->handlerId = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function name($value) : static { $this->_usedProperties['name'] = \true; $this->name = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cookieLifetime($value) : static { $this->_usedProperties['cookieLifetime'] = \true; $this->cookieLifetime = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cookiePath($value) : static { $this->_usedProperties['cookiePath'] = \true; $this->cookiePath = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function cookieDomain($value) : static { $this->_usedProperties['cookieDomain'] = \true; $this->cookieDomain = $value; return $this; } /** * @default null * @param ParamConfigurator|true|false|'auto' $value * @return $this */ public function cookieSecure($value) : static { $this->_usedProperties['cookieSecure'] = \true; $this->cookieSecure = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function cookieHttponly($value) : static { $this->_usedProperties['cookieHttponly'] = \true; $this->cookieHttponly = $value; return $this; } /** * @default null * @param ParamConfigurator|NULL|'lax'|'strict'|'none' $value * @return $this */ public function cookieSamesite($value) : static { $this->_usedProperties['cookieSamesite'] = \true; $this->cookieSamesite = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function useCookies($value) : static { $this->_usedProperties['useCookies'] = \true; $this->useCookies = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function gcDivisor($value) : static { $this->_usedProperties['gcDivisor'] = \true; $this->gcDivisor = $value; return $this; } /** * @default 1 * @param ParamConfigurator|mixed $value * @return $this */ public function gcProbability($value) : static { $this->_usedProperties['gcProbability'] = \true; $this->gcProbability = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function gcMaxlifetime($value) : static { $this->_usedProperties['gcMaxlifetime'] = \true; $this->gcMaxlifetime = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function savePath($value) : static { $this->_usedProperties['savePath'] = \true; $this->savePath = $value; return $this; } /** * seconds to wait between 2 session metadata updates * @default 0 * @param ParamConfigurator|int $value * @return $this */ public function metadataUpdateThreshold($value) : static { $this->_usedProperties['metadataUpdateThreshold'] = \true; $this->metadataUpdateThreshold = $value; return $this; } /** * @default null * @param ParamConfigurator|int $value * @return $this */ public function sidLength($value) : static { $this->_usedProperties['sidLength'] = \true; $this->sidLength = $value; return $this; } /** * @default null * @param ParamConfigurator|int $value * @return $this */ public function sidBitsPerCharacter($value) : static { $this->_usedProperties['sidBitsPerCharacter'] = \true; $this->sidBitsPerCharacter = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('storage_factory_id', $value)) { $this->_usedProperties['storageFactoryId'] = \true; $this->storageFactoryId = $value['storage_factory_id']; unset($value['storage_factory_id']); } if (\array_key_exists('handler_id', $value)) { $this->_usedProperties['handlerId'] = \true; $this->handlerId = $value['handler_id']; unset($value['handler_id']); } if (\array_key_exists('name', $value)) { $this->_usedProperties['name'] = \true; $this->name = $value['name']; unset($value['name']); } if (\array_key_exists('cookie_lifetime', $value)) { $this->_usedProperties['cookieLifetime'] = \true; $this->cookieLifetime = $value['cookie_lifetime']; unset($value['cookie_lifetime']); } if (\array_key_exists('cookie_path', $value)) { $this->_usedProperties['cookiePath'] = \true; $this->cookiePath = $value['cookie_path']; unset($value['cookie_path']); } if (\array_key_exists('cookie_domain', $value)) { $this->_usedProperties['cookieDomain'] = \true; $this->cookieDomain = $value['cookie_domain']; unset($value['cookie_domain']); } if (\array_key_exists('cookie_secure', $value)) { $this->_usedProperties['cookieSecure'] = \true; $this->cookieSecure = $value['cookie_secure']; unset($value['cookie_secure']); } if (\array_key_exists('cookie_httponly', $value)) { $this->_usedProperties['cookieHttponly'] = \true; $this->cookieHttponly = $value['cookie_httponly']; unset($value['cookie_httponly']); } if (\array_key_exists('cookie_samesite', $value)) { $this->_usedProperties['cookieSamesite'] = \true; $this->cookieSamesite = $value['cookie_samesite']; unset($value['cookie_samesite']); } if (\array_key_exists('use_cookies', $value)) { $this->_usedProperties['useCookies'] = \true; $this->useCookies = $value['use_cookies']; unset($value['use_cookies']); } if (\array_key_exists('gc_divisor', $value)) { $this->_usedProperties['gcDivisor'] = \true; $this->gcDivisor = $value['gc_divisor']; unset($value['gc_divisor']); } if (\array_key_exists('gc_probability', $value)) { $this->_usedProperties['gcProbability'] = \true; $this->gcProbability = $value['gc_probability']; unset($value['gc_probability']); } if (\array_key_exists('gc_maxlifetime', $value)) { $this->_usedProperties['gcMaxlifetime'] = \true; $this->gcMaxlifetime = $value['gc_maxlifetime']; unset($value['gc_maxlifetime']); } if (\array_key_exists('save_path', $value)) { $this->_usedProperties['savePath'] = \true; $this->savePath = $value['save_path']; unset($value['save_path']); } if (\array_key_exists('metadata_update_threshold', $value)) { $this->_usedProperties['metadataUpdateThreshold'] = \true; $this->metadataUpdateThreshold = $value['metadata_update_threshold']; unset($value['metadata_update_threshold']); } if (\array_key_exists('sid_length', $value)) { $this->_usedProperties['sidLength'] = \true; $this->sidLength = $value['sid_length']; unset($value['sid_length']); } if (\array_key_exists('sid_bits_per_character', $value)) { $this->_usedProperties['sidBitsPerCharacter'] = \true; $this->sidBitsPerCharacter = $value['sid_bits_per_character']; unset($value['sid_bits_per_character']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['storageFactoryId'])) { $output['storage_factory_id'] = $this->storageFactoryId; } if (isset($this->_usedProperties['handlerId'])) { $output['handler_id'] = $this->handlerId; } if (isset($this->_usedProperties['name'])) { $output['name'] = $this->name; } if (isset($this->_usedProperties['cookieLifetime'])) { $output['cookie_lifetime'] = $this->cookieLifetime; } if (isset($this->_usedProperties['cookiePath'])) { $output['cookie_path'] = $this->cookiePath; } if (isset($this->_usedProperties['cookieDomain'])) { $output['cookie_domain'] = $this->cookieDomain; } if (isset($this->_usedProperties['cookieSecure'])) { $output['cookie_secure'] = $this->cookieSecure; } if (isset($this->_usedProperties['cookieHttponly'])) { $output['cookie_httponly'] = $this->cookieHttponly; } if (isset($this->_usedProperties['cookieSamesite'])) { $output['cookie_samesite'] = $this->cookieSamesite; } if (isset($this->_usedProperties['useCookies'])) { $output['use_cookies'] = $this->useCookies; } if (isset($this->_usedProperties['gcDivisor'])) { $output['gc_divisor'] = $this->gcDivisor; } if (isset($this->_usedProperties['gcProbability'])) { $output['gc_probability'] = $this->gcProbability; } if (isset($this->_usedProperties['gcMaxlifetime'])) { $output['gc_maxlifetime'] = $this->gcMaxlifetime; } if (isset($this->_usedProperties['savePath'])) { $output['save_path'] = $this->savePath; } if (isset($this->_usedProperties['metadataUpdateThreshold'])) { $output['metadata_update_threshold'] = $this->metadataUpdateThreshold; } if (isset($this->_usedProperties['sidLength'])) { $output['sid_length'] = $this->sidLength; } if (isset($this->_usedProperties['sidBitsPerCharacter'])) { $output['sid_bits_per_character'] = $this->sidBitsPerCharacter; } return $output; } } _usedProperties['allowSafeElements'] = \true; $this->allowSafeElements = $value; return $this; } /** * Allows all static elements and attributes from the W3C Sanitizer API standard. * @default false * @param ParamConfigurator|bool $value * @return $this */ public function allowStaticElements($value) : static { $this->_usedProperties['allowStaticElements'] = \true; $this->allowStaticElements = $value; return $this; } /** * @return $this */ public function allowElement(string $name, mixed $value) : static { $this->_usedProperties['allowElements'] = \true; $this->allowElements[$name] = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function blockElements(ParamConfigurator|string|array $value) : static { $this->_usedProperties['blockElements'] = \true; $this->blockElements = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function dropElements(ParamConfigurator|string|array $value) : static { $this->_usedProperties['dropElements'] = \true; $this->dropElements = $value; return $this; } /** * @return $this */ public function allowAttribute(string $name, mixed $value) : static { $this->_usedProperties['allowAttributes'] = \true; $this->allowAttributes[$name] = $value; return $this; } /** * @return $this */ public function dropAttribute(string $name, mixed $value) : static { $this->_usedProperties['dropAttributes'] = \true; $this->dropAttributes[$name] = $value; return $this; } /** * @return $this */ public function forceAttribute(string $name, ParamConfigurator|array $value) : static { $this->_usedProperties['forceAttributes'] = \true; $this->forceAttributes[$name] = $value; return $this; } /** * Transforms URLs using the HTTP scheme to use the HTTPS scheme instead. * @default false * @param ParamConfigurator|bool $value * @return $this */ public function forceHttpsUrls($value) : static { $this->_usedProperties['forceHttpsUrls'] = \true; $this->forceHttpsUrls = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function allowedLinkSchemes(ParamConfigurator|array $value) : static { $this->_usedProperties['allowedLinkSchemes'] = \true; $this->allowedLinkSchemes = $value; return $this; } /** * Allows only a given list of hosts to be used in links href attributes. * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function allowedLinkHosts(mixed $value = NULL) : static { $this->_usedProperties['allowedLinkHosts'] = \true; $this->allowedLinkHosts = $value; return $this; } /** * Allows relative URLs to be used in links href attributes. * @default false * @param ParamConfigurator|bool $value * @return $this */ public function allowRelativeLinks($value) : static { $this->_usedProperties['allowRelativeLinks'] = \true; $this->allowRelativeLinks = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function allowedMediaSchemes(ParamConfigurator|array $value) : static { $this->_usedProperties['allowedMediaSchemes'] = \true; $this->allowedMediaSchemes = $value; return $this; } /** * Allows only a given list of hosts to be used in media source attributes (img, audio, video, ...). * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function allowedMediaHosts(mixed $value = NULL) : static { $this->_usedProperties['allowedMediaHosts'] = \true; $this->allowedMediaHosts = $value; return $this; } /** * Allows relative URLs to be used in media source attributes (img, audio, video, ...). * @default false * @param ParamConfigurator|bool $value * @return $this */ public function allowRelativeMedias($value) : static { $this->_usedProperties['allowRelativeMedias'] = \true; $this->allowRelativeMedias = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function withAttributeSanitizers(ParamConfigurator|array $value) : static { $this->_usedProperties['withAttributeSanitizers'] = \true; $this->withAttributeSanitizers = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function withoutAttributeSanitizers(ParamConfigurator|array $value) : static { $this->_usedProperties['withoutAttributeSanitizers'] = \true; $this->withoutAttributeSanitizers = $value; return $this; } /** * The maximum length allowed for the sanitized input. * @default 0 * @param ParamConfigurator|int $value * @return $this */ public function maxInputLength($value) : static { $this->_usedProperties['maxInputLength'] = \true; $this->maxInputLength = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('allow_safe_elements', $value)) { $this->_usedProperties['allowSafeElements'] = \true; $this->allowSafeElements = $value['allow_safe_elements']; unset($value['allow_safe_elements']); } if (\array_key_exists('allow_static_elements', $value)) { $this->_usedProperties['allowStaticElements'] = \true; $this->allowStaticElements = $value['allow_static_elements']; unset($value['allow_static_elements']); } if (\array_key_exists('allow_elements', $value)) { $this->_usedProperties['allowElements'] = \true; $this->allowElements = $value['allow_elements']; unset($value['allow_elements']); } if (\array_key_exists('block_elements', $value)) { $this->_usedProperties['blockElements'] = \true; $this->blockElements = $value['block_elements']; unset($value['block_elements']); } if (\array_key_exists('drop_elements', $value)) { $this->_usedProperties['dropElements'] = \true; $this->dropElements = $value['drop_elements']; unset($value['drop_elements']); } if (\array_key_exists('allow_attributes', $value)) { $this->_usedProperties['allowAttributes'] = \true; $this->allowAttributes = $value['allow_attributes']; unset($value['allow_attributes']); } if (\array_key_exists('drop_attributes', $value)) { $this->_usedProperties['dropAttributes'] = \true; $this->dropAttributes = $value['drop_attributes']; unset($value['drop_attributes']); } if (\array_key_exists('force_attributes', $value)) { $this->_usedProperties['forceAttributes'] = \true; $this->forceAttributes = $value['force_attributes']; unset($value['force_attributes']); } if (\array_key_exists('force_https_urls', $value)) { $this->_usedProperties['forceHttpsUrls'] = \true; $this->forceHttpsUrls = $value['force_https_urls']; unset($value['force_https_urls']); } if (\array_key_exists('allowed_link_schemes', $value)) { $this->_usedProperties['allowedLinkSchemes'] = \true; $this->allowedLinkSchemes = $value['allowed_link_schemes']; unset($value['allowed_link_schemes']); } if (\array_key_exists('allowed_link_hosts', $value)) { $this->_usedProperties['allowedLinkHosts'] = \true; $this->allowedLinkHosts = $value['allowed_link_hosts']; unset($value['allowed_link_hosts']); } if (\array_key_exists('allow_relative_links', $value)) { $this->_usedProperties['allowRelativeLinks'] = \true; $this->allowRelativeLinks = $value['allow_relative_links']; unset($value['allow_relative_links']); } if (\array_key_exists('allowed_media_schemes', $value)) { $this->_usedProperties['allowedMediaSchemes'] = \true; $this->allowedMediaSchemes = $value['allowed_media_schemes']; unset($value['allowed_media_schemes']); } if (\array_key_exists('allowed_media_hosts', $value)) { $this->_usedProperties['allowedMediaHosts'] = \true; $this->allowedMediaHosts = $value['allowed_media_hosts']; unset($value['allowed_media_hosts']); } if (\array_key_exists('allow_relative_medias', $value)) { $this->_usedProperties['allowRelativeMedias'] = \true; $this->allowRelativeMedias = $value['allow_relative_medias']; unset($value['allow_relative_medias']); } if (\array_key_exists('with_attribute_sanitizers', $value)) { $this->_usedProperties['withAttributeSanitizers'] = \true; $this->withAttributeSanitizers = $value['with_attribute_sanitizers']; unset($value['with_attribute_sanitizers']); } if (\array_key_exists('without_attribute_sanitizers', $value)) { $this->_usedProperties['withoutAttributeSanitizers'] = \true; $this->withoutAttributeSanitizers = $value['without_attribute_sanitizers']; unset($value['without_attribute_sanitizers']); } if (\array_key_exists('max_input_length', $value)) { $this->_usedProperties['maxInputLength'] = \true; $this->maxInputLength = $value['max_input_length']; unset($value['max_input_length']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['allowSafeElements'])) { $output['allow_safe_elements'] = $this->allowSafeElements; } if (isset($this->_usedProperties['allowStaticElements'])) { $output['allow_static_elements'] = $this->allowStaticElements; } if (isset($this->_usedProperties['allowElements'])) { $output['allow_elements'] = $this->allowElements; } if (isset($this->_usedProperties['blockElements'])) { $output['block_elements'] = $this->blockElements; } if (isset($this->_usedProperties['dropElements'])) { $output['drop_elements'] = $this->dropElements; } if (isset($this->_usedProperties['allowAttributes'])) { $output['allow_attributes'] = $this->allowAttributes; } if (isset($this->_usedProperties['dropAttributes'])) { $output['drop_attributes'] = $this->dropAttributes; } if (isset($this->_usedProperties['forceAttributes'])) { $output['force_attributes'] = $this->forceAttributes; } if (isset($this->_usedProperties['forceHttpsUrls'])) { $output['force_https_urls'] = $this->forceHttpsUrls; } if (isset($this->_usedProperties['allowedLinkSchemes'])) { $output['allowed_link_schemes'] = $this->allowedLinkSchemes; } if (isset($this->_usedProperties['allowedLinkHosts'])) { $output['allowed_link_hosts'] = $this->allowedLinkHosts; } if (isset($this->_usedProperties['allowRelativeLinks'])) { $output['allow_relative_links'] = $this->allowRelativeLinks; } if (isset($this->_usedProperties['allowedMediaSchemes'])) { $output['allowed_media_schemes'] = $this->allowedMediaSchemes; } if (isset($this->_usedProperties['allowedMediaHosts'])) { $output['allowed_media_hosts'] = $this->allowedMediaHosts; } if (isset($this->_usedProperties['allowRelativeMedias'])) { $output['allow_relative_medias'] = $this->allowRelativeMedias; } if (isset($this->_usedProperties['withAttributeSanitizers'])) { $output['with_attribute_sanitizers'] = $this->withAttributeSanitizers; } if (isset($this->_usedProperties['withoutAttributeSanitizers'])) { $output['without_attribute_sanitizers'] = $this->withoutAttributeSanitizers; } if (isset($this->_usedProperties['maxInputLength'])) { $output['max_input_length'] = $this->maxInputLength; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * The maximum number of connections to a single host. * @default null * @param ParamConfigurator|int $value * @return $this */ public function maxHostConnections($value) : static { $this->_usedProperties['maxHostConnections'] = \true; $this->maxHostConnections = $value; return $this; } public function defaultOptions(array $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptionsConfig { if (null === $this->defaultOptions) { $this->_usedProperties['defaultOptions'] = \true; $this->defaultOptions = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptionsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "defaultOptions()" has already been initialized. You cannot pass values the second time you call defaultOptions().'); } return $this->defaultOptions; } /** * The id of the service that should generate mock responses. It should be either an invokable or an iterable. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function mockResponseFactory($value) : static { $this->_usedProperties['mockResponseFactory'] = \true; $this->mockResponseFactory = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Framework\HttpClient\ScopedClientConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClient\ScopedClientConfig : static) */ public function scopedClient(string $name, mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig|static { if (!\is_array($value)) { $this->_usedProperties['scopedClients'] = \true; $this->scopedClients[$name] = $value; return $this; } if (!isset($this->scopedClients[$name]) || !$this->scopedClients[$name] instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig) { $this->_usedProperties['scopedClients'] = \true; $this->scopedClients[$name] = new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "scopedClient()" has already been initialized. You cannot pass values the second time you call scopedClient().'); } return $this->scopedClients[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('max_host_connections', $value)) { $this->_usedProperties['maxHostConnections'] = \true; $this->maxHostConnections = $value['max_host_connections']; unset($value['max_host_connections']); } if (\array_key_exists('default_options', $value)) { $this->_usedProperties['defaultOptions'] = \true; $this->defaultOptions = new \_ContaoManager\Symfony\Config\Framework\HttpClient\DefaultOptionsConfig($value['default_options']); unset($value['default_options']); } if (\array_key_exists('mock_response_factory', $value)) { $this->_usedProperties['mockResponseFactory'] = \true; $this->mockResponseFactory = $value['mock_response_factory']; unset($value['mock_response_factory']); } if (\array_key_exists('scoped_clients', $value)) { $this->_usedProperties['scopedClients'] = \true; $this->scopedClients = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig($v) : $v, $value['scoped_clients']); unset($value['scoped_clients']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['maxHostConnections'])) { $output['max_host_connections'] = $this->maxHostConnections; } if (isset($this->_usedProperties['defaultOptions'])) { $output['default_options'] = $this->defaultOptions->toArray(); } if (isset($this->_usedProperties['mockResponseFactory'])) { $output['mock_response_factory'] = $this->mockResponseFactory; } if (isset($this->_usedProperties['scopedClients'])) { $output['scoped_clients'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\HttpClient\ScopedClientConfig ? $v->toArray() : $v, $this->scopedClients); } return $output; } } _usedProperties['log'] = \true; $this->log = $value; return $this; } /** * Throw PHP errors as \ErrorException instances. * @default false * @param ParamConfigurator|bool $value * @return $this */ public function throw($value) : static { $this->_usedProperties['throw'] = \true; $this->throw = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('log', $value)) { $this->_usedProperties['log'] = \true; $this->log = $value['log']; unset($value['log']); } if (\array_key_exists('throw', $value)) { $this->_usedProperties['throw'] = \true; $this->throw = $value['throw']; unset($value['throw']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['log'])) { $output['log'] = $this->log; } if (isset($this->_usedProperties['throw'])) { $output['throw'] = $this->throw; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * The message bus to use. Defaults to the default bus if the Messenger component is installed. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function messageBus($value) : static { $this->_usedProperties['messageBus'] = \true; $this->messageBus = $value; return $this; } /** * @return $this */ public function chatterTransport(string $name, mixed $value) : static { $this->_usedProperties['chatterTransports'] = \true; $this->chatterTransports[$name] = $value; return $this; } /** * @return $this */ public function texterTransport(string $name, mixed $value) : static { $this->_usedProperties['texterTransports'] = \true; $this->texterTransports[$name] = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function notificationOnFailedMessages($value) : static { $this->_usedProperties['notificationOnFailedMessages'] = \true; $this->notificationOnFailedMessages = $value; return $this; } /** * @return $this */ public function channelPolicy(string $name, ParamConfigurator|string|array $value) : static { $this->_usedProperties['channelPolicy'] = \true; $this->channelPolicy[$name] = $value; return $this; } public function adminRecipient(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Notifier\AdminRecipientConfig { $this->_usedProperties['adminRecipients'] = \true; return $this->adminRecipients[] = new \_ContaoManager\Symfony\Config\Framework\Notifier\AdminRecipientConfig($value); } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('message_bus', $value)) { $this->_usedProperties['messageBus'] = \true; $this->messageBus = $value['message_bus']; unset($value['message_bus']); } if (\array_key_exists('chatter_transports', $value)) { $this->_usedProperties['chatterTransports'] = \true; $this->chatterTransports = $value['chatter_transports']; unset($value['chatter_transports']); } if (\array_key_exists('texter_transports', $value)) { $this->_usedProperties['texterTransports'] = \true; $this->texterTransports = $value['texter_transports']; unset($value['texter_transports']); } if (\array_key_exists('notification_on_failed_messages', $value)) { $this->_usedProperties['notificationOnFailedMessages'] = \true; $this->notificationOnFailedMessages = $value['notification_on_failed_messages']; unset($value['notification_on_failed_messages']); } if (\array_key_exists('channel_policy', $value)) { $this->_usedProperties['channelPolicy'] = \true; $this->channelPolicy = $value['channel_policy']; unset($value['channel_policy']); } if (\array_key_exists('admin_recipients', $value)) { $this->_usedProperties['adminRecipients'] = \true; $this->adminRecipients = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Framework\Notifier\AdminRecipientConfig($v), $value['admin_recipients']); unset($value['admin_recipients']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['messageBus'])) { $output['message_bus'] = $this->messageBus; } if (isset($this->_usedProperties['chatterTransports'])) { $output['chatter_transports'] = $this->chatterTransports; } if (isset($this->_usedProperties['texterTransports'])) { $output['texter_transports'] = $this->texterTransports; } if (isset($this->_usedProperties['notificationOnFailedMessages'])) { $output['notification_on_failed_messages'] = $this->notificationOnFailedMessages; } if (isset($this->_usedProperties['channelPolicy'])) { $output['channel_policy'] = $this->channelPolicy; } if (isset($this->_usedProperties['adminRecipients'])) { $output['admin_recipients'] = \array_map(fn($v) => $v->toArray(), $this->adminRecipients); } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @return $this */ public function format(string $name, mixed $value) : static { $this->_usedProperties['formats'] = \true; $this->formats[$name] = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('formats', $value)) { $this->_usedProperties['formats'] = \true; $this->formats = $value['formats']; unset($value['formats']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['formats'])) { $output['formats'] = $this->formats; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default 'php_array' * @param ParamConfigurator|'none'|'php_array'|'file' $value * @return $this */ public function cache($value) : static { $this->_usedProperties['cache'] = \true; $this->cache = $value; return $this; } /** * @default '%kernel.cache_dir%/annotations' * @param ParamConfigurator|mixed $value * @return $this */ public function fileCacheDir($value) : static { $this->_usedProperties['fileCacheDir'] = \true; $this->fileCacheDir = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function debug($value) : static { $this->_usedProperties['debug'] = \true; $this->debug = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('cache', $value)) { $this->_usedProperties['cache'] = \true; $this->cache = $value['cache']; unset($value['cache']); } if (\array_key_exists('file_cache_dir', $value)) { $this->_usedProperties['fileCacheDir'] = \true; $this->fileCacheDir = $value['file_cache_dir']; unset($value['file_cache_dir']); } if (\array_key_exists('debug', $value)) { $this->_usedProperties['debug'] = \true; $this->debug = $value['debug']; unset($value['debug']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['cache'])) { $output['cache'] = $this->cache; } if (isset($this->_usedProperties['fileCacheDir'])) { $output['file_cache_dir'] = $this->fileCacheDir; } if (isset($this->_usedProperties['debug'])) { $output['debug'] = $this->debug; } return $output; } } _usedProperties['strictMode'] = \true; $this->strictMode = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function versionStrategy($value) : static { $this->_usedProperties['versionStrategy'] = \true; $this->versionStrategy = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function version($value) : static { $this->_usedProperties['version'] = \true; $this->version = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function versionFormat($value) : static { $this->_usedProperties['versionFormat'] = \true; $this->versionFormat = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function jsonManifestPath($value) : static { $this->_usedProperties['jsonManifestPath'] = \true; $this->jsonManifestPath = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function basePath($value) : static { $this->_usedProperties['basePath'] = \true; $this->basePath = $value; return $this; } /** * @param ParamConfigurator|list|mixed $value * * @return $this */ public function baseUrls(mixed $value) : static { $this->_usedProperties['baseUrls'] = \true; $this->baseUrls = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('strict_mode', $value)) { $this->_usedProperties['strictMode'] = \true; $this->strictMode = $value['strict_mode']; unset($value['strict_mode']); } if (\array_key_exists('version_strategy', $value)) { $this->_usedProperties['versionStrategy'] = \true; $this->versionStrategy = $value['version_strategy']; unset($value['version_strategy']); } if (\array_key_exists('version', $value)) { $this->_usedProperties['version'] = \true; $this->version = $value['version']; unset($value['version']); } if (\array_key_exists('version_format', $value)) { $this->_usedProperties['versionFormat'] = \true; $this->versionFormat = $value['version_format']; unset($value['version_format']); } if (\array_key_exists('json_manifest_path', $value)) { $this->_usedProperties['jsonManifestPath'] = \true; $this->jsonManifestPath = $value['json_manifest_path']; unset($value['json_manifest_path']); } if (\array_key_exists('base_path', $value)) { $this->_usedProperties['basePath'] = \true; $this->basePath = $value['base_path']; unset($value['base_path']); } if (\array_key_exists('base_urls', $value)) { $this->_usedProperties['baseUrls'] = \true; $this->baseUrls = $value['base_urls']; unset($value['base_urls']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['strictMode'])) { $output['strict_mode'] = $this->strictMode; } if (isset($this->_usedProperties['versionStrategy'])) { $output['version_strategy'] = $this->versionStrategy; } if (isset($this->_usedProperties['version'])) { $output['version'] = $this->version; } if (isset($this->_usedProperties['versionFormat'])) { $output['version_format'] = $this->versionFormat; } if (isset($this->_usedProperties['jsonManifestPath'])) { $output['json_manifest_path'] = $this->jsonManifestPath; } if (isset($this->_usedProperties['basePath'])) { $output['base_path'] = $this->basePath; } if (isset($this->_usedProperties['baseUrls'])) { $output['base_urls'] = $this->baseUrls; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * API endpoint for the NotCompromisedPassword Validator. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function endpoint($value) : static { $this->_usedProperties['endpoint'] = \true; $this->endpoint = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('endpoint', $value)) { $this->_usedProperties['endpoint'] = \true; $this->endpoint = $value['endpoint']; unset($value['endpoint']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['endpoint'])) { $output['endpoint'] = $this->endpoint; } return $output; } } $value * * @return $this */ public function paths(ParamConfigurator|array $value) : static { $this->_usedProperties['paths'] = \true; $this->paths = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('paths', $value)) { $this->_usedProperties['paths'] = \true; $this->paths = $value['paths']; unset($value['paths']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['paths'])) { $output['paths'] = $this->paths; } return $output; } } $value * * @return $this */ public function services(ParamConfigurator|array $value) : static { $this->_usedProperties['services'] = \true; $this->services = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('services', $value)) { $this->_usedProperties['services'] = \true; $this->services = $value['services']; unset($value['services']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['services'])) { $output['services'] = $this->services; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @return $this */ public function resource(string $name, ParamConfigurator|string|array $value) : static { $this->_usedProperties['resources'] = \true; $this->resources[$name] = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('resources', $value)) { $this->_usedProperties['resources'] = \true; $this->resources = $value['resources']; unset($value['resources']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['resources'])) { $output['resources'] = $this->resources; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default {"enabled":null,"field_name":"_token"} */ public function csrfProtection(array $value = []) : \_ContaoManager\Symfony\Config\Framework\Form\CsrfProtectionConfig { if (null === $this->csrfProtection) { $this->_usedProperties['csrfProtection'] = \true; $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\Form\CsrfProtectionConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "csrfProtection()" has already been initialized. You cannot pass values the second time you call csrfProtection().'); } return $this->csrfProtection; } /** * @default null * @param ParamConfigurator|bool $value * @deprecated The child node "legacy_error_messages" at path "form" is deprecated. * @return $this */ public function legacyErrorMessages($value) : static { $this->_usedProperties['legacyErrorMessages'] = \true; $this->legacyErrorMessages = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('csrf_protection', $value)) { $this->_usedProperties['csrfProtection'] = \true; $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\Form\CsrfProtectionConfig($value['csrf_protection']); unset($value['csrf_protection']); } if (\array_key_exists('legacy_error_messages', $value)) { $this->_usedProperties['legacyErrorMessages'] = \true; $this->legacyErrorMessages = $value['legacy_error_messages']; unset($value['legacy_error_messages']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['csrfProtection'])) { $output['csrf_protection'] = $this->csrfProtection->toArray(); } if (isset($this->_usedProperties['legacyErrorMessages'])) { $output['legacy_error_messages'] = $this->legacyErrorMessages; } return $output; } } _usedProperties['password'] = \true; $this->password = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function roles(ParamConfigurator|string|array $value) : static { $this->_usedProperties['roles'] = \true; $this->roles = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('password', $value)) { $this->_usedProperties['password'] = \true; $this->password = $value['password']; unset($value['password']); } if (\array_key_exists('roles', $value)) { $this->_usedProperties['roles'] = \true; $this->roles = $value['roles']; unset($value['roles']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['password'])) { $output['password'] = $this->password; } if (isset($this->_usedProperties['roles'])) { $output['roles'] = $this->roles; } return $output; } } _usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function baseDn($value) : static { $this->_usedProperties['baseDn'] = \true; $this->baseDn = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function searchDn($value) : static { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function searchPassword($value) : static { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function extraFields(ParamConfigurator|array $value) : static { $this->_usedProperties['extraFields'] = \true; $this->extraFields = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function defaultRoles(ParamConfigurator|string|array $value) : static { $this->_usedProperties['defaultRoles'] = \true; $this->defaultRoles = $value; return $this; } /** * @default 'sAMAccountName' * @param ParamConfigurator|mixed $value * @return $this */ public function uidKey($value) : static { $this->_usedProperties['uidKey'] = \true; $this->uidKey = $value; return $this; } /** * @default '({uid_key}={username})' * @param ParamConfigurator|mixed $value * @return $this */ public function filter($value) : static { $this->_usedProperties['filter'] = \true; $this->filter = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function passwordAttribute($value) : static { $this->_usedProperties['passwordAttribute'] = \true; $this->passwordAttribute = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('base_dn', $value)) { $this->_usedProperties['baseDn'] = \true; $this->baseDn = $value['base_dn']; unset($value['base_dn']); } if (\array_key_exists('search_dn', $value)) { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value['search_dn']; unset($value['search_dn']); } if (\array_key_exists('search_password', $value)) { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value['search_password']; unset($value['search_password']); } if (\array_key_exists('extra_fields', $value)) { $this->_usedProperties['extraFields'] = \true; $this->extraFields = $value['extra_fields']; unset($value['extra_fields']); } if (\array_key_exists('default_roles', $value)) { $this->_usedProperties['defaultRoles'] = \true; $this->defaultRoles = $value['default_roles']; unset($value['default_roles']); } if (\array_key_exists('uid_key', $value)) { $this->_usedProperties['uidKey'] = \true; $this->uidKey = $value['uid_key']; unset($value['uid_key']); } if (\array_key_exists('filter', $value)) { $this->_usedProperties['filter'] = \true; $this->filter = $value['filter']; unset($value['filter']); } if (\array_key_exists('password_attribute', $value)) { $this->_usedProperties['passwordAttribute'] = \true; $this->passwordAttribute = $value['password_attribute']; unset($value['password_attribute']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['baseDn'])) { $output['base_dn'] = $this->baseDn; } if (isset($this->_usedProperties['searchDn'])) { $output['search_dn'] = $this->searchDn; } if (isset($this->_usedProperties['searchPassword'])) { $output['search_password'] = $this->searchPassword; } if (isset($this->_usedProperties['extraFields'])) { $output['extra_fields'] = $this->extraFields; } if (isset($this->_usedProperties['defaultRoles'])) { $output['default_roles'] = $this->defaultRoles; } if (isset($this->_usedProperties['uidKey'])) { $output['uid_key'] = $this->uidKey; } if (isset($this->_usedProperties['filter'])) { $output['filter'] = $this->filter; } if (isset($this->_usedProperties['passwordAttribute'])) { $output['password_attribute'] = $this->passwordAttribute; } return $output; } } users[$identifier])) { $this->_usedProperties['users'] = \true; $this->users[$identifier] = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\Memory\UserConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "user()" has already been initialized. You cannot pass values the second time you call user().'); } return $this->users[$identifier]; } public function __construct(array $value = []) { if (\array_key_exists('users', $value)) { $this->_usedProperties['users'] = \true; $this->users = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\ProviderConfig\Memory\UserConfig($v), $value['users']); unset($value['users']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['users'])) { $output['users'] = \array_map(fn($v) => $v->toArray(), $this->users); } return $output; } } |string $value * * @return $this */ public function providers(ParamConfigurator|string|array $value) : static { $this->_usedProperties['providers'] = \true; $this->providers = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('providers', $value)) { $this->_usedProperties['providers'] = \true; $this->providers = $value['providers']; unset($value['providers']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['providers'])) { $output['providers'] = $this->providers; } return $output; } } _usedProperties['algorithm'] = \true; $this->algorithm = $value; return $this; } /** * @param ParamConfigurator|list|mixed $value * * @return $this */ public function migrateFrom(mixed $value) : static { $this->_usedProperties['migrateFrom'] = \true; $this->migrateFrom = $value; return $this; } /** * Name of hashing algorithm for PBKDF2 (i.e. sha256, sha512, etc..) See hash_algos() for a list of supported algorithms. * @default 'sha512' * @param ParamConfigurator|mixed $value * @return $this */ public function hashAlgorithm($value) : static { $this->_usedProperties['hashAlgorithm'] = \true; $this->hashAlgorithm = $value; return $this; } /** * @default 40 * @param ParamConfigurator|mixed $value * @return $this */ public function keyLength($value) : static { $this->_usedProperties['keyLength'] = \true; $this->keyLength = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function ignoreCase($value) : static { $this->_usedProperties['ignoreCase'] = \true; $this->ignoreCase = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function encodeAsBase64($value) : static { $this->_usedProperties['encodeAsBase64'] = \true; $this->encodeAsBase64 = $value; return $this; } /** * @default 5000 * @param ParamConfigurator|mixed $value * @return $this */ public function iterations($value) : static { $this->_usedProperties['iterations'] = \true; $this->iterations = $value; return $this; } /** * @default null * @param ParamConfigurator|int $value * @return $this */ public function cost($value) : static { $this->_usedProperties['cost'] = \true; $this->cost = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function memoryCost($value) : static { $this->_usedProperties['memoryCost'] = \true; $this->memoryCost = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function timeCost($value) : static { $this->_usedProperties['timeCost'] = \true; $this->timeCost = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function id($value) : static { $this->_usedProperties['id'] = \true; $this->id = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('algorithm', $value)) { $this->_usedProperties['algorithm'] = \true; $this->algorithm = $value['algorithm']; unset($value['algorithm']); } if (\array_key_exists('migrate_from', $value)) { $this->_usedProperties['migrateFrom'] = \true; $this->migrateFrom = $value['migrate_from']; unset($value['migrate_from']); } if (\array_key_exists('hash_algorithm', $value)) { $this->_usedProperties['hashAlgorithm'] = \true; $this->hashAlgorithm = $value['hash_algorithm']; unset($value['hash_algorithm']); } if (\array_key_exists('key_length', $value)) { $this->_usedProperties['keyLength'] = \true; $this->keyLength = $value['key_length']; unset($value['key_length']); } if (\array_key_exists('ignore_case', $value)) { $this->_usedProperties['ignoreCase'] = \true; $this->ignoreCase = $value['ignore_case']; unset($value['ignore_case']); } if (\array_key_exists('encode_as_base64', $value)) { $this->_usedProperties['encodeAsBase64'] = \true; $this->encodeAsBase64 = $value['encode_as_base64']; unset($value['encode_as_base64']); } if (\array_key_exists('iterations', $value)) { $this->_usedProperties['iterations'] = \true; $this->iterations = $value['iterations']; unset($value['iterations']); } if (\array_key_exists('cost', $value)) { $this->_usedProperties['cost'] = \true; $this->cost = $value['cost']; unset($value['cost']); } if (\array_key_exists('memory_cost', $value)) { $this->_usedProperties['memoryCost'] = \true; $this->memoryCost = $value['memory_cost']; unset($value['memory_cost']); } if (\array_key_exists('time_cost', $value)) { $this->_usedProperties['timeCost'] = \true; $this->timeCost = $value['time_cost']; unset($value['time_cost']); } if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['algorithm'])) { $output['algorithm'] = $this->algorithm; } if (isset($this->_usedProperties['migrateFrom'])) { $output['migrate_from'] = $this->migrateFrom; } if (isset($this->_usedProperties['hashAlgorithm'])) { $output['hash_algorithm'] = $this->hashAlgorithm; } if (isset($this->_usedProperties['keyLength'])) { $output['key_length'] = $this->keyLength; } if (isset($this->_usedProperties['ignoreCase'])) { $output['ignore_case'] = $this->ignoreCase; } if (isset($this->_usedProperties['encodeAsBase64'])) { $output['encode_as_base64'] = $this->encodeAsBase64; } if (isset($this->_usedProperties['iterations'])) { $output['iterations'] = $this->iterations; } if (isset($this->_usedProperties['cost'])) { $output['cost'] = $this->cost; } if (isset($this->_usedProperties['memoryCost'])) { $output['memory_cost'] = $this->memoryCost; } if (isset($this->_usedProperties['timeCost'])) { $output['time_cost'] = $this->timeCost; } if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } public function chain(array $value = []) : \_ContaoManager\Symfony\Config\Security\ProviderConfig\ChainConfig { if (null === $this->chain) { $this->_usedProperties['chain'] = \true; $this->chain = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\ChainConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "chain()" has already been initialized. You cannot pass values the second time you call chain().'); } return $this->chain; } public function memory(array $value = []) : \_ContaoManager\Symfony\Config\Security\ProviderConfig\MemoryConfig { if (null === $this->memory) { $this->_usedProperties['memory'] = \true; $this->memory = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\MemoryConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "memory()" has already been initialized. You cannot pass values the second time you call memory().'); } return $this->memory; } public function ldap(array $value = []) : \_ContaoManager\Symfony\Config\Security\ProviderConfig\LdapConfig { if (null === $this->ldap) { $this->_usedProperties['ldap'] = \true; $this->ldap = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\LdapConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "ldap()" has already been initialized. You cannot pass values the second time you call ldap().'); } return $this->ldap; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('chain', $value)) { $this->_usedProperties['chain'] = \true; $this->chain = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\ChainConfig($value['chain']); unset($value['chain']); } if (\array_key_exists('memory', $value)) { $this->_usedProperties['memory'] = \true; $this->memory = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\MemoryConfig($value['memory']); unset($value['memory']); } if (\array_key_exists('ldap', $value)) { $this->_usedProperties['ldap'] = \true; $this->ldap = new \_ContaoManager\Symfony\Config\Security\ProviderConfig\LdapConfig($value['ldap']); unset($value['ldap']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['chain'])) { $output['chain'] = $this->chain->toArray(); } if (isset($this->_usedProperties['memory'])) { $output['memory'] = $this->memory->toArray(); } if (isset($this->_usedProperties['ldap'])) { $output['ldap'] = $this->ldap->toArray(); } return $output; } } _usedProperties['pattern'] = \true; $this->pattern = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function host($value) : static { $this->_usedProperties['host'] = \true; $this->host = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function methods(ParamConfigurator|string|array $value) : static { $this->_usedProperties['methods'] = \true; $this->methods = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function security($value) : static { $this->_usedProperties['security'] = \true; $this->security = $value; return $this; } /** * The UserChecker to use when authenticating users in this firewall. * @default 'security.user_checker' * @param ParamConfigurator|mixed $value * @return $this */ public function userChecker($value) : static { $this->_usedProperties['userChecker'] = \true; $this->userChecker = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function requestMatcher($value) : static { $this->_usedProperties['requestMatcher'] = \true; $this->requestMatcher = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function accessDeniedUrl($value) : static { $this->_usedProperties['accessDeniedUrl'] = \true; $this->accessDeniedUrl = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function accessDeniedHandler($value) : static { $this->_usedProperties['accessDeniedHandler'] = \true; $this->accessDeniedHandler = $value; return $this; } /** * An enabled authenticator name or a service id that implements "Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface" * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function entryPoint($value) : static { $this->_usedProperties['entryPoint'] = \true; $this->entryPoint = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function provider($value) : static { $this->_usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function stateless($value) : static { $this->_usedProperties['stateless'] = \true; $this->stateless = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function lazy($value) : static { $this->_usedProperties['lazy'] = \true; $this->lazy = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function context($value) : static { $this->_usedProperties['context'] = \true; $this->context = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Security\FirewallConfig\LogoutConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\LogoutConfig : static) */ public function logout(mixed $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig|static { if (!\is_array($value)) { $this->_usedProperties['logout'] = \true; $this->logout = $value; return $this; } if (!$this->logout instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig) { $this->_usedProperties['logout'] = \true; $this->logout = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "logout()" has already been initialized. You cannot pass values the second time you call logout().'); } return $this->logout; } public function switchUser(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\SwitchUserConfig { if (null === $this->switchUser) { $this->_usedProperties['switchUser'] = \true; $this->switchUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\SwitchUserConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "switchUser()" has already been initialized. You cannot pass values the second time you call switchUser().'); } return $this->switchUser; } /** * @param ParamConfigurator|list $value * * @return $this */ public function requiredBadges(ParamConfigurator|array $value) : static { $this->_usedProperties['requiredBadges'] = \true; $this->requiredBadges = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function customAuthenticators(ParamConfigurator|array $value) : static { $this->_usedProperties['customAuthenticators'] = \true; $this->customAuthenticators = $value; return $this; } public function loginThrottling(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginThrottlingConfig { if (null === $this->loginThrottling) { $this->_usedProperties['loginThrottling'] = \true; $this->loginThrottling = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginThrottlingConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "loginThrottling()" has already been initialized. You cannot pass values the second time you call loginThrottling().'); } return $this->loginThrottling; } public function x509(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\X509Config { if (null === $this->x509) { $this->_usedProperties['x509'] = \true; $this->x509 = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\X509Config($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "x509()" has already been initialized. You cannot pass values the second time you call x509().'); } return $this->x509; } public function remoteUser(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\RemoteUserConfig { if (null === $this->remoteUser) { $this->_usedProperties['remoteUser'] = \true; $this->remoteUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RemoteUserConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "remoteUser()" has already been initialized. You cannot pass values the second time you call remoteUser().'); } return $this->remoteUser; } public function loginLink(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginLinkConfig { if (null === $this->loginLink) { $this->_usedProperties['loginLink'] = \true; $this->loginLink = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginLinkConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "loginLink()" has already been initialized. You cannot pass values the second time you call loginLink().'); } return $this->loginLink; } public function formLogin(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginConfig { if (null === $this->formLogin) { $this->_usedProperties['formLogin'] = \true; $this->formLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "formLogin()" has already been initialized. You cannot pass values the second time you call formLogin().'); } return $this->formLogin; } public function formLoginLdap(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginLdapConfig { if (null === $this->formLoginLdap) { $this->_usedProperties['formLoginLdap'] = \true; $this->formLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginLdapConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "formLoginLdap()" has already been initialized. You cannot pass values the second time you call formLoginLdap().'); } return $this->formLoginLdap; } public function jsonLogin(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginConfig { if (null === $this->jsonLogin) { $this->_usedProperties['jsonLogin'] = \true; $this->jsonLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "jsonLogin()" has already been initialized. You cannot pass values the second time you call jsonLogin().'); } return $this->jsonLogin; } public function jsonLoginLdap(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginLdapConfig { if (null === $this->jsonLoginLdap) { $this->_usedProperties['jsonLoginLdap'] = \true; $this->jsonLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginLdapConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "jsonLoginLdap()" has already been initialized. You cannot pass values the second time you call jsonLoginLdap().'); } return $this->jsonLoginLdap; } public function accessToken(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessTokenConfig { if (null === $this->accessToken) { $this->_usedProperties['accessToken'] = \true; $this->accessToken = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessTokenConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "accessToken()" has already been initialized. You cannot pass values the second time you call accessToken().'); } return $this->accessToken; } public function httpBasic(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicConfig { if (null === $this->httpBasic) { $this->_usedProperties['httpBasic'] = \true; $this->httpBasic = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "httpBasic()" has already been initialized. You cannot pass values the second time you call httpBasic().'); } return $this->httpBasic; } public function httpBasicLdap(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicLdapConfig { if (null === $this->httpBasicLdap) { $this->_usedProperties['httpBasicLdap'] = \true; $this->httpBasicLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicLdapConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "httpBasicLdap()" has already been initialized. You cannot pass values the second time you call httpBasicLdap().'); } return $this->httpBasicLdap; } public function rememberMe(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMeConfig { if (null === $this->rememberMe) { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMeConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "rememberMe()" has already been initialized. You cannot pass values the second time you call rememberMe().'); } return $this->rememberMe; } public function __construct(array $value = []) { if (\array_key_exists('pattern', $value)) { $this->_usedProperties['pattern'] = \true; $this->pattern = $value['pattern']; unset($value['pattern']); } if (\array_key_exists('host', $value)) { $this->_usedProperties['host'] = \true; $this->host = $value['host']; unset($value['host']); } if (\array_key_exists('methods', $value)) { $this->_usedProperties['methods'] = \true; $this->methods = $value['methods']; unset($value['methods']); } if (\array_key_exists('security', $value)) { $this->_usedProperties['security'] = \true; $this->security = $value['security']; unset($value['security']); } if (\array_key_exists('user_checker', $value)) { $this->_usedProperties['userChecker'] = \true; $this->userChecker = $value['user_checker']; unset($value['user_checker']); } if (\array_key_exists('request_matcher', $value)) { $this->_usedProperties['requestMatcher'] = \true; $this->requestMatcher = $value['request_matcher']; unset($value['request_matcher']); } if (\array_key_exists('access_denied_url', $value)) { $this->_usedProperties['accessDeniedUrl'] = \true; $this->accessDeniedUrl = $value['access_denied_url']; unset($value['access_denied_url']); } if (\array_key_exists('access_denied_handler', $value)) { $this->_usedProperties['accessDeniedHandler'] = \true; $this->accessDeniedHandler = $value['access_denied_handler']; unset($value['access_denied_handler']); } if (\array_key_exists('entry_point', $value)) { $this->_usedProperties['entryPoint'] = \true; $this->entryPoint = $value['entry_point']; unset($value['entry_point']); } if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('stateless', $value)) { $this->_usedProperties['stateless'] = \true; $this->stateless = $value['stateless']; unset($value['stateless']); } if (\array_key_exists('lazy', $value)) { $this->_usedProperties['lazy'] = \true; $this->lazy = $value['lazy']; unset($value['lazy']); } if (\array_key_exists('context', $value)) { $this->_usedProperties['context'] = \true; $this->context = $value['context']; unset($value['context']); } if (\array_key_exists('logout', $value)) { $this->_usedProperties['logout'] = \true; $this->logout = \is_array($value['logout']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig($value['logout']) : $value['logout']; unset($value['logout']); } if (\array_key_exists('switch_user', $value)) { $this->_usedProperties['switchUser'] = \true; $this->switchUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\SwitchUserConfig($value['switch_user']); unset($value['switch_user']); } if (\array_key_exists('required_badges', $value)) { $this->_usedProperties['requiredBadges'] = \true; $this->requiredBadges = $value['required_badges']; unset($value['required_badges']); } if (\array_key_exists('custom_authenticators', $value)) { $this->_usedProperties['customAuthenticators'] = \true; $this->customAuthenticators = $value['custom_authenticators']; unset($value['custom_authenticators']); } if (\array_key_exists('login_throttling', $value)) { $this->_usedProperties['loginThrottling'] = \true; $this->loginThrottling = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginThrottlingConfig($value['login_throttling']); unset($value['login_throttling']); } if (\array_key_exists('x509', $value)) { $this->_usedProperties['x509'] = \true; $this->x509 = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\X509Config($value['x509']); unset($value['x509']); } if (\array_key_exists('remote_user', $value)) { $this->_usedProperties['remoteUser'] = \true; $this->remoteUser = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RemoteUserConfig($value['remote_user']); unset($value['remote_user']); } if (\array_key_exists('login_link', $value)) { $this->_usedProperties['loginLink'] = \true; $this->loginLink = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\LoginLinkConfig($value['login_link']); unset($value['login_link']); } if (\array_key_exists('form_login', $value)) { $this->_usedProperties['formLogin'] = \true; $this->formLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginConfig($value['form_login']); unset($value['form_login']); } if (\array_key_exists('form_login_ldap', $value)) { $this->_usedProperties['formLoginLdap'] = \true; $this->formLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\FormLoginLdapConfig($value['form_login_ldap']); unset($value['form_login_ldap']); } if (\array_key_exists('json_login', $value)) { $this->_usedProperties['jsonLogin'] = \true; $this->jsonLogin = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginConfig($value['json_login']); unset($value['json_login']); } if (\array_key_exists('json_login_ldap', $value)) { $this->_usedProperties['jsonLoginLdap'] = \true; $this->jsonLoginLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\JsonLoginLdapConfig($value['json_login_ldap']); unset($value['json_login_ldap']); } if (\array_key_exists('access_token', $value)) { $this->_usedProperties['accessToken'] = \true; $this->accessToken = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessTokenConfig($value['access_token']); unset($value['access_token']); } if (\array_key_exists('http_basic', $value)) { $this->_usedProperties['httpBasic'] = \true; $this->httpBasic = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicConfig($value['http_basic']); unset($value['http_basic']); } if (\array_key_exists('http_basic_ldap', $value)) { $this->_usedProperties['httpBasicLdap'] = \true; $this->httpBasicLdap = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\HttpBasicLdapConfig($value['http_basic_ldap']); unset($value['http_basic_ldap']); } if (\array_key_exists('remember_me', $value)) { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMeConfig($value['remember_me']); unset($value['remember_me']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['pattern'])) { $output['pattern'] = $this->pattern; } if (isset($this->_usedProperties['host'])) { $output['host'] = $this->host; } if (isset($this->_usedProperties['methods'])) { $output['methods'] = $this->methods; } if (isset($this->_usedProperties['security'])) { $output['security'] = $this->security; } if (isset($this->_usedProperties['userChecker'])) { $output['user_checker'] = $this->userChecker; } if (isset($this->_usedProperties['requestMatcher'])) { $output['request_matcher'] = $this->requestMatcher; } if (isset($this->_usedProperties['accessDeniedUrl'])) { $output['access_denied_url'] = $this->accessDeniedUrl; } if (isset($this->_usedProperties['accessDeniedHandler'])) { $output['access_denied_handler'] = $this->accessDeniedHandler; } if (isset($this->_usedProperties['entryPoint'])) { $output['entry_point'] = $this->entryPoint; } if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['stateless'])) { $output['stateless'] = $this->stateless; } if (isset($this->_usedProperties['lazy'])) { $output['lazy'] = $this->lazy; } if (isset($this->_usedProperties['context'])) { $output['context'] = $this->context; } if (isset($this->_usedProperties['logout'])) { $output['logout'] = $this->logout instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\LogoutConfig ? $this->logout->toArray() : $this->logout; } if (isset($this->_usedProperties['switchUser'])) { $output['switch_user'] = $this->switchUser->toArray(); } if (isset($this->_usedProperties['requiredBadges'])) { $output['required_badges'] = $this->requiredBadges; } if (isset($this->_usedProperties['customAuthenticators'])) { $output['custom_authenticators'] = $this->customAuthenticators; } if (isset($this->_usedProperties['loginThrottling'])) { $output['login_throttling'] = $this->loginThrottling->toArray(); } if (isset($this->_usedProperties['x509'])) { $output['x509'] = $this->x509->toArray(); } if (isset($this->_usedProperties['remoteUser'])) { $output['remote_user'] = $this->remoteUser->toArray(); } if (isset($this->_usedProperties['loginLink'])) { $output['login_link'] = $this->loginLink->toArray(); } if (isset($this->_usedProperties['formLogin'])) { $output['form_login'] = $this->formLogin->toArray(); } if (isset($this->_usedProperties['formLoginLdap'])) { $output['form_login_ldap'] = $this->formLoginLdap->toArray(); } if (isset($this->_usedProperties['jsonLogin'])) { $output['json_login'] = $this->jsonLogin->toArray(); } if (isset($this->_usedProperties['jsonLoginLdap'])) { $output['json_login_ldap'] = $this->jsonLoginLdap->toArray(); } if (isset($this->_usedProperties['accessToken'])) { $output['access_token'] = $this->accessToken->toArray(); } if (isset($this->_usedProperties['httpBasic'])) { $output['http_basic'] = $this->httpBasic->toArray(); } if (isset($this->_usedProperties['httpBasicLdap'])) { $output['http_basic_ldap'] = $this->httpBasicLdap->toArray(); } if (isset($this->_usedProperties['rememberMe'])) { $output['remember_me'] = $this->rememberMe->toArray(); } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function rememberMe($value) : static { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function successHandler($value) : static { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureHandler($value) : static { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function realm($value) : static { $this->_usedProperties['realm'] = \true; $this->realm = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function tokenExtractors(ParamConfigurator|string|array $value) : static { $this->_usedProperties['tokenExtractors'] = \true; $this->tokenExtractors = $value; return $this; } /** * @template TValue * @param TValue $value * @example "App\\Security\\CustomTokenHandler" * @return \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig : static) */ public function tokenHandler(mixed $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig|static { if (!\is_array($value)) { $this->_usedProperties['tokenHandler'] = \true; $this->tokenHandler = $value; return $this; } if (!$this->tokenHandler instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig) { $this->_usedProperties['tokenHandler'] = \true; $this->tokenHandler = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "tokenHandler()" has already been initialized. You cannot pass values the second time you call tokenHandler().'); } return $this->tokenHandler; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('remember_me', $value)) { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value['remember_me']; unset($value['remember_me']); } if (\array_key_exists('success_handler', $value)) { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value['success_handler']; unset($value['success_handler']); } if (\array_key_exists('failure_handler', $value)) { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value['failure_handler']; unset($value['failure_handler']); } if (\array_key_exists('realm', $value)) { $this->_usedProperties['realm'] = \true; $this->realm = $value['realm']; unset($value['realm']); } if (\array_key_exists('token_extractors', $value)) { $this->_usedProperties['tokenExtractors'] = \true; $this->tokenExtractors = $value['token_extractors']; unset($value['token_extractors']); } if (\array_key_exists('token_handler', $value)) { $this->_usedProperties['tokenHandler'] = \true; $this->tokenHandler = \is_array($value['token_handler']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig($value['token_handler']) : $value['token_handler']; unset($value['token_handler']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['rememberMe'])) { $output['remember_me'] = $this->rememberMe; } if (isset($this->_usedProperties['successHandler'])) { $output['success_handler'] = $this->successHandler; } if (isset($this->_usedProperties['failureHandler'])) { $output['failure_handler'] = $this->failureHandler; } if (isset($this->_usedProperties['realm'])) { $output['realm'] = $this->realm; } if (isset($this->_usedProperties['tokenExtractors'])) { $output['token_extractors'] = $this->tokenExtractors; } if (isset($this->_usedProperties['tokenHandler'])) { $output['token_handler'] = $this->tokenHandler instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandlerConfig ? $this->tokenHandler->toArray() : $this->tokenHandler; } return $output; } } _usedProperties['secret'] = \true; $this->secret = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function service($value) : static { $this->_usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function userProviders(ParamConfigurator|string|array $value) : static { $this->_usedProperties['userProviders'] = \true; $this->userProviders = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function catchExceptions($value) : static { $this->_usedProperties['catchExceptions'] = \true; $this->catchExceptions = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function signatureProperties(ParamConfigurator|array $value) : static { $this->_usedProperties['signatureProperties'] = \true; $this->signatureProperties = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig : static) */ public function tokenProvider(string|array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig|static { if (!\is_array($value)) { $this->_usedProperties['tokenProvider'] = \true; $this->tokenProvider = $value; return $this; } if (!$this->tokenProvider instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig) { $this->_usedProperties['tokenProvider'] = \true; $this->tokenProvider = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "tokenProvider()" has already been initialized. You cannot pass values the second time you call tokenProvider().'); } return $this->tokenProvider; } /** * The service ID of a custom rememberme token verifier. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function tokenVerifier($value) : static { $this->_usedProperties['tokenVerifier'] = \true; $this->tokenVerifier = $value; return $this; } /** * @default 'REMEMBERME' * @param ParamConfigurator|mixed $value * @return $this */ public function name($value) : static { $this->_usedProperties['name'] = \true; $this->name = $value; return $this; } /** * @default 31536000 * @param ParamConfigurator|int $value * @return $this */ public function lifetime($value) : static { $this->_usedProperties['lifetime'] = \true; $this->lifetime = $value; return $this; } /** * @default '/' * @param ParamConfigurator|mixed $value * @return $this */ public function path($value) : static { $this->_usedProperties['path'] = \true; $this->path = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function domain($value) : static { $this->_usedProperties['domain'] = \true; $this->domain = $value; return $this; } /** * @default false * @param ParamConfigurator|true|false|'auto' $value * @return $this */ public function secure($value) : static { $this->_usedProperties['secure'] = \true; $this->secure = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function httponly($value) : static { $this->_usedProperties['httponly'] = \true; $this->httponly = $value; return $this; } /** * @default null * @param ParamConfigurator|NULL|'lax'|'strict'|'none' $value * @return $this */ public function samesite($value) : static { $this->_usedProperties['samesite'] = \true; $this->samesite = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function alwaysRememberMe($value) : static { $this->_usedProperties['alwaysRememberMe'] = \true; $this->alwaysRememberMe = $value; return $this; } /** * @default '_remember_me' * @param ParamConfigurator|mixed $value * @return $this */ public function rememberMeParameter($value) : static { $this->_usedProperties['rememberMeParameter'] = \true; $this->rememberMeParameter = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('secret', $value)) { $this->_usedProperties['secret'] = \true; $this->secret = $value['secret']; unset($value['secret']); } if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('user_providers', $value)) { $this->_usedProperties['userProviders'] = \true; $this->userProviders = $value['user_providers']; unset($value['user_providers']); } if (\array_key_exists('catch_exceptions', $value)) { $this->_usedProperties['catchExceptions'] = \true; $this->catchExceptions = $value['catch_exceptions']; unset($value['catch_exceptions']); } if (\array_key_exists('signature_properties', $value)) { $this->_usedProperties['signatureProperties'] = \true; $this->signatureProperties = $value['signature_properties']; unset($value['signature_properties']); } if (\array_key_exists('token_provider', $value)) { $this->_usedProperties['tokenProvider'] = \true; $this->tokenProvider = \is_array($value['token_provider']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig($value['token_provider']) : $value['token_provider']; unset($value['token_provider']); } if (\array_key_exists('token_verifier', $value)) { $this->_usedProperties['tokenVerifier'] = \true; $this->tokenVerifier = $value['token_verifier']; unset($value['token_verifier']); } if (\array_key_exists('name', $value)) { $this->_usedProperties['name'] = \true; $this->name = $value['name']; unset($value['name']); } if (\array_key_exists('lifetime', $value)) { $this->_usedProperties['lifetime'] = \true; $this->lifetime = $value['lifetime']; unset($value['lifetime']); } if (\array_key_exists('path', $value)) { $this->_usedProperties['path'] = \true; $this->path = $value['path']; unset($value['path']); } if (\array_key_exists('domain', $value)) { $this->_usedProperties['domain'] = \true; $this->domain = $value['domain']; unset($value['domain']); } if (\array_key_exists('secure', $value)) { $this->_usedProperties['secure'] = \true; $this->secure = $value['secure']; unset($value['secure']); } if (\array_key_exists('httponly', $value)) { $this->_usedProperties['httponly'] = \true; $this->httponly = $value['httponly']; unset($value['httponly']); } if (\array_key_exists('samesite', $value)) { $this->_usedProperties['samesite'] = \true; $this->samesite = $value['samesite']; unset($value['samesite']); } if (\array_key_exists('always_remember_me', $value)) { $this->_usedProperties['alwaysRememberMe'] = \true; $this->alwaysRememberMe = $value['always_remember_me']; unset($value['always_remember_me']); } if (\array_key_exists('remember_me_parameter', $value)) { $this->_usedProperties['rememberMeParameter'] = \true; $this->rememberMeParameter = $value['remember_me_parameter']; unset($value['remember_me_parameter']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['secret'])) { $output['secret'] = $this->secret; } if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['userProviders'])) { $output['user_providers'] = $this->userProviders; } if (isset($this->_usedProperties['catchExceptions'])) { $output['catch_exceptions'] = $this->catchExceptions; } if (isset($this->_usedProperties['signatureProperties'])) { $output['signature_properties'] = $this->signatureProperties; } if (isset($this->_usedProperties['tokenProvider'])) { $output['token_provider'] = $this->tokenProvider instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProviderConfig ? $this->tokenProvider->toArray() : $this->tokenProvider; } if (isset($this->_usedProperties['tokenVerifier'])) { $output['token_verifier'] = $this->tokenVerifier; } if (isset($this->_usedProperties['name'])) { $output['name'] = $this->name; } if (isset($this->_usedProperties['lifetime'])) { $output['lifetime'] = $this->lifetime; } if (isset($this->_usedProperties['path'])) { $output['path'] = $this->path; } if (isset($this->_usedProperties['domain'])) { $output['domain'] = $this->domain; } if (isset($this->_usedProperties['secure'])) { $output['secure'] = $this->secure; } if (isset($this->_usedProperties['httponly'])) { $output['httponly'] = $this->httponly; } if (isset($this->_usedProperties['samesite'])) { $output['samesite'] = $this->samesite; } if (isset($this->_usedProperties['alwaysRememberMe'])) { $output['always_remember_me'] = $this->alwaysRememberMe; } if (isset($this->_usedProperties['rememberMeParameter'])) { $output['remember_me_parameter'] = $this->rememberMeParameter; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function rememberMe($value) : static { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function successHandler($value) : static { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureHandler($value) : static { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value; return $this; } /** * @default '/login_check' * @param ParamConfigurator|mixed $value * @return $this */ public function checkPath($value) : static { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useForward($value) : static { $this->_usedProperties['useForward'] = \true; $this->useForward = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @deprecated Option "require_previous_session" at "form_login" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore. * @return $this */ public function requirePreviousSession($value) : static { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value; return $this; } /** * @default '/login' * @param ParamConfigurator|mixed $value * @return $this */ public function loginPath($value) : static { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value; return $this; } /** * @default '_username' * @param ParamConfigurator|mixed $value * @return $this */ public function usernameParameter($value) : static { $this->_usedProperties['usernameParameter'] = \true; $this->usernameParameter = $value; return $this; } /** * @default '_password' * @param ParamConfigurator|mixed $value * @return $this */ public function passwordParameter($value) : static { $this->_usedProperties['passwordParameter'] = \true; $this->passwordParameter = $value; return $this; } /** * @default '_csrf_token' * @param ParamConfigurator|mixed $value * @return $this */ public function csrfParameter($value) : static { $this->_usedProperties['csrfParameter'] = \true; $this->csrfParameter = $value; return $this; } /** * @default 'authenticate' * @param ParamConfigurator|mixed $value * @return $this */ public function csrfTokenId($value) : static { $this->_usedProperties['csrfTokenId'] = \true; $this->csrfTokenId = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function enableCsrf($value) : static { $this->_usedProperties['enableCsrf'] = \true; $this->enableCsrf = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function postOnly($value) : static { $this->_usedProperties['postOnly'] = \true; $this->postOnly = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function formOnly($value) : static { $this->_usedProperties['formOnly'] = \true; $this->formOnly = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function alwaysUseDefaultTargetPath($value) : static { $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true; $this->alwaysUseDefaultTargetPath = $value; return $this; } /** * @default '/' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultTargetPath($value) : static { $this->_usedProperties['defaultTargetPath'] = \true; $this->defaultTargetPath = $value; return $this; } /** * @default '_target_path' * @param ParamConfigurator|mixed $value * @return $this */ public function targetPathParameter($value) : static { $this->_usedProperties['targetPathParameter'] = \true; $this->targetPathParameter = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useReferer($value) : static { $this->_usedProperties['useReferer'] = \true; $this->useReferer = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failurePath($value) : static { $this->_usedProperties['failurePath'] = \true; $this->failurePath = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function failureForward($value) : static { $this->_usedProperties['failureForward'] = \true; $this->failureForward = $value; return $this; } /** * @default '_failure_path' * @param ParamConfigurator|mixed $value * @return $this */ public function failurePathParameter($value) : static { $this->_usedProperties['failurePathParameter'] = \true; $this->failurePathParameter = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function csrfTokenGenerator($value) : static { $this->_usedProperties['csrfTokenGenerator'] = \true; $this->csrfTokenGenerator = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('remember_me', $value)) { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value['remember_me']; unset($value['remember_me']); } if (\array_key_exists('success_handler', $value)) { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value['success_handler']; unset($value['success_handler']); } if (\array_key_exists('failure_handler', $value)) { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value['failure_handler']; unset($value['failure_handler']); } if (\array_key_exists('check_path', $value)) { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value['check_path']; unset($value['check_path']); } if (\array_key_exists('use_forward', $value)) { $this->_usedProperties['useForward'] = \true; $this->useForward = $value['use_forward']; unset($value['use_forward']); } if (\array_key_exists('require_previous_session', $value)) { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value['require_previous_session']; unset($value['require_previous_session']); } if (\array_key_exists('login_path', $value)) { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value['login_path']; unset($value['login_path']); } if (\array_key_exists('username_parameter', $value)) { $this->_usedProperties['usernameParameter'] = \true; $this->usernameParameter = $value['username_parameter']; unset($value['username_parameter']); } if (\array_key_exists('password_parameter', $value)) { $this->_usedProperties['passwordParameter'] = \true; $this->passwordParameter = $value['password_parameter']; unset($value['password_parameter']); } if (\array_key_exists('csrf_parameter', $value)) { $this->_usedProperties['csrfParameter'] = \true; $this->csrfParameter = $value['csrf_parameter']; unset($value['csrf_parameter']); } if (\array_key_exists('csrf_token_id', $value)) { $this->_usedProperties['csrfTokenId'] = \true; $this->csrfTokenId = $value['csrf_token_id']; unset($value['csrf_token_id']); } if (\array_key_exists('enable_csrf', $value)) { $this->_usedProperties['enableCsrf'] = \true; $this->enableCsrf = $value['enable_csrf']; unset($value['enable_csrf']); } if (\array_key_exists('post_only', $value)) { $this->_usedProperties['postOnly'] = \true; $this->postOnly = $value['post_only']; unset($value['post_only']); } if (\array_key_exists('form_only', $value)) { $this->_usedProperties['formOnly'] = \true; $this->formOnly = $value['form_only']; unset($value['form_only']); } if (\array_key_exists('always_use_default_target_path', $value)) { $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true; $this->alwaysUseDefaultTargetPath = $value['always_use_default_target_path']; unset($value['always_use_default_target_path']); } if (\array_key_exists('default_target_path', $value)) { $this->_usedProperties['defaultTargetPath'] = \true; $this->defaultTargetPath = $value['default_target_path']; unset($value['default_target_path']); } if (\array_key_exists('target_path_parameter', $value)) { $this->_usedProperties['targetPathParameter'] = \true; $this->targetPathParameter = $value['target_path_parameter']; unset($value['target_path_parameter']); } if (\array_key_exists('use_referer', $value)) { $this->_usedProperties['useReferer'] = \true; $this->useReferer = $value['use_referer']; unset($value['use_referer']); } if (\array_key_exists('failure_path', $value)) { $this->_usedProperties['failurePath'] = \true; $this->failurePath = $value['failure_path']; unset($value['failure_path']); } if (\array_key_exists('failure_forward', $value)) { $this->_usedProperties['failureForward'] = \true; $this->failureForward = $value['failure_forward']; unset($value['failure_forward']); } if (\array_key_exists('failure_path_parameter', $value)) { $this->_usedProperties['failurePathParameter'] = \true; $this->failurePathParameter = $value['failure_path_parameter']; unset($value['failure_path_parameter']); } if (\array_key_exists('csrf_token_generator', $value)) { $this->_usedProperties['csrfTokenGenerator'] = \true; $this->csrfTokenGenerator = $value['csrf_token_generator']; unset($value['csrf_token_generator']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['rememberMe'])) { $output['remember_me'] = $this->rememberMe; } if (isset($this->_usedProperties['successHandler'])) { $output['success_handler'] = $this->successHandler; } if (isset($this->_usedProperties['failureHandler'])) { $output['failure_handler'] = $this->failureHandler; } if (isset($this->_usedProperties['checkPath'])) { $output['check_path'] = $this->checkPath; } if (isset($this->_usedProperties['useForward'])) { $output['use_forward'] = $this->useForward; } if (isset($this->_usedProperties['requirePreviousSession'])) { $output['require_previous_session'] = $this->requirePreviousSession; } if (isset($this->_usedProperties['loginPath'])) { $output['login_path'] = $this->loginPath; } if (isset($this->_usedProperties['usernameParameter'])) { $output['username_parameter'] = $this->usernameParameter; } if (isset($this->_usedProperties['passwordParameter'])) { $output['password_parameter'] = $this->passwordParameter; } if (isset($this->_usedProperties['csrfParameter'])) { $output['csrf_parameter'] = $this->csrfParameter; } if (isset($this->_usedProperties['csrfTokenId'])) { $output['csrf_token_id'] = $this->csrfTokenId; } if (isset($this->_usedProperties['enableCsrf'])) { $output['enable_csrf'] = $this->enableCsrf; } if (isset($this->_usedProperties['postOnly'])) { $output['post_only'] = $this->postOnly; } if (isset($this->_usedProperties['formOnly'])) { $output['form_only'] = $this->formOnly; } if (isset($this->_usedProperties['alwaysUseDefaultTargetPath'])) { $output['always_use_default_target_path'] = $this->alwaysUseDefaultTargetPath; } if (isset($this->_usedProperties['defaultTargetPath'])) { $output['default_target_path'] = $this->defaultTargetPath; } if (isset($this->_usedProperties['targetPathParameter'])) { $output['target_path_parameter'] = $this->targetPathParameter; } if (isset($this->_usedProperties['useReferer'])) { $output['use_referer'] = $this->useReferer; } if (isset($this->_usedProperties['failurePath'])) { $output['failure_path'] = $this->failurePath; } if (isset($this->_usedProperties['failureForward'])) { $output['failure_forward'] = $this->failureForward; } if (isset($this->_usedProperties['failurePathParameter'])) { $output['failure_path_parameter'] = $this->failurePathParameter; } if (isset($this->_usedProperties['csrfTokenGenerator'])) { $output['csrf_token_generator'] = $this->csrfTokenGenerator; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function rememberMe($value) : static { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function successHandler($value) : static { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureHandler($value) : static { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value; return $this; } /** * @default '/login_check' * @param ParamConfigurator|mixed $value * @return $this */ public function checkPath($value) : static { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useForward($value) : static { $this->_usedProperties['useForward'] = \true; $this->useForward = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @deprecated Option "require_previous_session" at "json_login_ldap" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore. * @return $this */ public function requirePreviousSession($value) : static { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value; return $this; } /** * @default '/login' * @param ParamConfigurator|mixed $value * @return $this */ public function loginPath($value) : static { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value; return $this; } /** * @default 'username' * @param ParamConfigurator|mixed $value * @return $this */ public function usernamePath($value) : static { $this->_usedProperties['usernamePath'] = \true; $this->usernamePath = $value; return $this; } /** * @default 'password' * @param ParamConfigurator|mixed $value * @return $this */ public function passwordPath($value) : static { $this->_usedProperties['passwordPath'] = \true; $this->passwordPath = $value; return $this; } /** * @default 'ldap' * @param ParamConfigurator|mixed $value * @return $this */ public function service($value) : static { $this->_usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @default '{username}' * @param ParamConfigurator|mixed $value * @return $this */ public function dnString($value) : static { $this->_usedProperties['dnString'] = \true; $this->dnString = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function queryString($value) : static { $this->_usedProperties['queryString'] = \true; $this->queryString = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function searchDn($value) : static { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function searchPassword($value) : static { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('remember_me', $value)) { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value['remember_me']; unset($value['remember_me']); } if (\array_key_exists('success_handler', $value)) { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value['success_handler']; unset($value['success_handler']); } if (\array_key_exists('failure_handler', $value)) { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value['failure_handler']; unset($value['failure_handler']); } if (\array_key_exists('check_path', $value)) { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value['check_path']; unset($value['check_path']); } if (\array_key_exists('use_forward', $value)) { $this->_usedProperties['useForward'] = \true; $this->useForward = $value['use_forward']; unset($value['use_forward']); } if (\array_key_exists('require_previous_session', $value)) { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value['require_previous_session']; unset($value['require_previous_session']); } if (\array_key_exists('login_path', $value)) { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value['login_path']; unset($value['login_path']); } if (\array_key_exists('username_path', $value)) { $this->_usedProperties['usernamePath'] = \true; $this->usernamePath = $value['username_path']; unset($value['username_path']); } if (\array_key_exists('password_path', $value)) { $this->_usedProperties['passwordPath'] = \true; $this->passwordPath = $value['password_path']; unset($value['password_path']); } if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('dn_string', $value)) { $this->_usedProperties['dnString'] = \true; $this->dnString = $value['dn_string']; unset($value['dn_string']); } if (\array_key_exists('query_string', $value)) { $this->_usedProperties['queryString'] = \true; $this->queryString = $value['query_string']; unset($value['query_string']); } if (\array_key_exists('search_dn', $value)) { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value['search_dn']; unset($value['search_dn']); } if (\array_key_exists('search_password', $value)) { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value['search_password']; unset($value['search_password']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['rememberMe'])) { $output['remember_me'] = $this->rememberMe; } if (isset($this->_usedProperties['successHandler'])) { $output['success_handler'] = $this->successHandler; } if (isset($this->_usedProperties['failureHandler'])) { $output['failure_handler'] = $this->failureHandler; } if (isset($this->_usedProperties['checkPath'])) { $output['check_path'] = $this->checkPath; } if (isset($this->_usedProperties['useForward'])) { $output['use_forward'] = $this->useForward; } if (isset($this->_usedProperties['requirePreviousSession'])) { $output['require_previous_session'] = $this->requirePreviousSession; } if (isset($this->_usedProperties['loginPath'])) { $output['login_path'] = $this->loginPath; } if (isset($this->_usedProperties['usernamePath'])) { $output['username_path'] = $this->usernamePath; } if (isset($this->_usedProperties['passwordPath'])) { $output['password_path'] = $this->passwordPath; } if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['dnString'])) { $output['dn_string'] = $this->dnString; } if (isset($this->_usedProperties['queryString'])) { $output['query_string'] = $this->queryString; } if (isset($this->_usedProperties['searchDn'])) { $output['search_dn'] = $this->searchDn; } if (isset($this->_usedProperties['searchPassword'])) { $output['search_password'] = $this->searchPassword; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default 'Secured Area' * @param ParamConfigurator|mixed $value * @return $this */ public function realm($value) : static { $this->_usedProperties['realm'] = \true; $this->realm = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('realm', $value)) { $this->_usedProperties['realm'] = \true; $this->realm = $value['realm']; unset($value['realm']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['realm'])) { $output['realm'] = $this->realm; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig : static) */ public function oidcUserInfo(string|array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig|static { if (!\is_array($value)) { $this->_usedProperties['oidcUserInfo'] = \true; $this->oidcUserInfo = $value; return $this; } if (!$this->oidcUserInfo instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig) { $this->_usedProperties['oidcUserInfo'] = \true; $this->oidcUserInfo = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "oidcUserInfo()" has already been initialized. You cannot pass values the second time you call oidcUserInfo().'); } return $this->oidcUserInfo; } public function oidc(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcConfig { if (null === $this->oidc) { $this->_usedProperties['oidc'] = \true; $this->oidc = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "oidc()" has already been initialized. You cannot pass values the second time you call oidc().'); } return $this->oidc; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('oidc_user_info', $value)) { $this->_usedProperties['oidcUserInfo'] = \true; $this->oidcUserInfo = \is_array($value['oidc_user_info']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig($value['oidc_user_info']) : $value['oidc_user_info']; unset($value['oidc_user_info']); } if (\array_key_exists('oidc', $value)) { $this->_usedProperties['oidc'] = \true; $this->oidc = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcConfig($value['oidc']); unset($value['oidc']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['oidcUserInfo'])) { $output['oidc_user_info'] = $this->oidcUserInfo instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\AccessToken\TokenHandler\OidcUserInfoConfig ? $this->oidcUserInfo->toArray() : $this->oidcUserInfo; } if (isset($this->_usedProperties['oidc'])) { $output['oidc'] = $this->oidc->toArray(); } return $output; } } _usedProperties['baseUri'] = \true; $this->baseUri = $value; return $this; } /** * Claim which contains the user identifier (e.g. sub, email, etc.). * @default 'sub' * @param ParamConfigurator|mixed $value * @return $this */ public function claim($value) : static { $this->_usedProperties['claim'] = \true; $this->claim = $value; return $this; } /** * HttpClient service id to use to call the OIDC server. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function client($value) : static { $this->_usedProperties['client'] = \true; $this->client = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('base_uri', $value)) { $this->_usedProperties['baseUri'] = \true; $this->baseUri = $value['base_uri']; unset($value['base_uri']); } if (\array_key_exists('claim', $value)) { $this->_usedProperties['claim'] = \true; $this->claim = $value['claim']; unset($value['claim']); } if (\array_key_exists('client', $value)) { $this->_usedProperties['client'] = \true; $this->client = $value['client']; unset($value['client']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['baseUri'])) { $output['base_uri'] = $this->baseUri; } if (isset($this->_usedProperties['claim'])) { $output['claim'] = $this->claim; } if (isset($this->_usedProperties['client'])) { $output['client'] = $this->client; } return $output; } } _usedProperties['claim'] = \true; $this->claim = $value; return $this; } /** * Audience set in the token, for validation purpose. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function audience($value) : static { $this->_usedProperties['audience'] = \true; $this->audience = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function issuers(ParamConfigurator|array $value) : static { $this->_usedProperties['issuers'] = \true; $this->issuers = $value; return $this; } /** * Algorithm used to sign the token. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function algorithm($value) : static { $this->_usedProperties['algorithm'] = \true; $this->algorithm = $value; return $this; } /** * JSON-encoded JWK used to sign the token (must contain a "kty" key). * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function key($value) : static { $this->_usedProperties['key'] = \true; $this->key = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('claim', $value)) { $this->_usedProperties['claim'] = \true; $this->claim = $value['claim']; unset($value['claim']); } if (\array_key_exists('audience', $value)) { $this->_usedProperties['audience'] = \true; $this->audience = $value['audience']; unset($value['audience']); } if (\array_key_exists('issuers', $value)) { $this->_usedProperties['issuers'] = \true; $this->issuers = $value['issuers']; unset($value['issuers']); } if (\array_key_exists('algorithm', $value)) { $this->_usedProperties['algorithm'] = \true; $this->algorithm = $value['algorithm']; unset($value['algorithm']); } if (\array_key_exists('key', $value)) { $this->_usedProperties['key'] = \true; $this->key = $value['key']; unset($value['key']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['claim'])) { $output['claim'] = $this->claim; } if (isset($this->_usedProperties['audience'])) { $output['audience'] = $this->audience; } if (isset($this->_usedProperties['issuers'])) { $output['issuers'] = $this->issuers; } if (isset($this->_usedProperties['algorithm'])) { $output['algorithm'] = $this->algorithm; } if (isset($this->_usedProperties['key'])) { $output['key'] = $this->key; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function rememberMe($value) : static { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function successHandler($value) : static { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureHandler($value) : static { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value; return $this; } /** * @default '/login_check' * @param ParamConfigurator|mixed $value * @return $this */ public function checkPath($value) : static { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useForward($value) : static { $this->_usedProperties['useForward'] = \true; $this->useForward = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @deprecated Option "require_previous_session" at "json_login" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore. * @return $this */ public function requirePreviousSession($value) : static { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value; return $this; } /** * @default '/login' * @param ParamConfigurator|mixed $value * @return $this */ public function loginPath($value) : static { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value; return $this; } /** * @default 'username' * @param ParamConfigurator|mixed $value * @return $this */ public function usernamePath($value) : static { $this->_usedProperties['usernamePath'] = \true; $this->usernamePath = $value; return $this; } /** * @default 'password' * @param ParamConfigurator|mixed $value * @return $this */ public function passwordPath($value) : static { $this->_usedProperties['passwordPath'] = \true; $this->passwordPath = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('remember_me', $value)) { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value['remember_me']; unset($value['remember_me']); } if (\array_key_exists('success_handler', $value)) { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value['success_handler']; unset($value['success_handler']); } if (\array_key_exists('failure_handler', $value)) { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value['failure_handler']; unset($value['failure_handler']); } if (\array_key_exists('check_path', $value)) { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value['check_path']; unset($value['check_path']); } if (\array_key_exists('use_forward', $value)) { $this->_usedProperties['useForward'] = \true; $this->useForward = $value['use_forward']; unset($value['use_forward']); } if (\array_key_exists('require_previous_session', $value)) { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value['require_previous_session']; unset($value['require_previous_session']); } if (\array_key_exists('login_path', $value)) { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value['login_path']; unset($value['login_path']); } if (\array_key_exists('username_path', $value)) { $this->_usedProperties['usernamePath'] = \true; $this->usernamePath = $value['username_path']; unset($value['username_path']); } if (\array_key_exists('password_path', $value)) { $this->_usedProperties['passwordPath'] = \true; $this->passwordPath = $value['password_path']; unset($value['password_path']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['rememberMe'])) { $output['remember_me'] = $this->rememberMe; } if (isset($this->_usedProperties['successHandler'])) { $output['success_handler'] = $this->successHandler; } if (isset($this->_usedProperties['failureHandler'])) { $output['failure_handler'] = $this->failureHandler; } if (isset($this->_usedProperties['checkPath'])) { $output['check_path'] = $this->checkPath; } if (isset($this->_usedProperties['useForward'])) { $output['use_forward'] = $this->useForward; } if (isset($this->_usedProperties['requirePreviousSession'])) { $output['require_previous_session'] = $this->requirePreviousSession; } if (isset($this->_usedProperties['loginPath'])) { $output['login_path'] = $this->loginPath; } if (isset($this->_usedProperties['usernamePath'])) { $output['username_path'] = $this->usernamePath; } if (isset($this->_usedProperties['passwordPath'])) { $output['password_path'] = $this->passwordPath; } return $output; } } _usedProperties['path'] = \true; $this->path = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function domain($value) : static { $this->_usedProperties['domain'] = \true; $this->domain = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function secure($value) : static { $this->_usedProperties['secure'] = \true; $this->secure = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function samesite($value) : static { $this->_usedProperties['samesite'] = \true; $this->samesite = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function partitioned($value) : static { $this->_usedProperties['partitioned'] = \true; $this->partitioned = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('path', $value)) { $this->_usedProperties['path'] = \true; $this->path = $value['path']; unset($value['path']); } if (\array_key_exists('domain', $value)) { $this->_usedProperties['domain'] = \true; $this->domain = $value['domain']; unset($value['domain']); } if (\array_key_exists('secure', $value)) { $this->_usedProperties['secure'] = \true; $this->secure = $value['secure']; unset($value['secure']); } if (\array_key_exists('samesite', $value)) { $this->_usedProperties['samesite'] = \true; $this->samesite = $value['samesite']; unset($value['samesite']); } if (\array_key_exists('partitioned', $value)) { $this->_usedProperties['partitioned'] = \true; $this->partitioned = $value['partitioned']; unset($value['partitioned']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['path'])) { $output['path'] = $this->path; } if (isset($this->_usedProperties['domain'])) { $output['domain'] = $this->domain; } if (isset($this->_usedProperties['secure'])) { $output['secure'] = $this->secure; } if (isset($this->_usedProperties['samesite'])) { $output['samesite'] = $this->samesite; } if (isset($this->_usedProperties['partitioned'])) { $output['partitioned'] = $this->partitioned; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default '_switch_user' * @param ParamConfigurator|mixed $value * @return $this */ public function parameter($value) : static { $this->_usedProperties['parameter'] = \true; $this->parameter = $value; return $this; } /** * @default 'ROLE_ALLOWED_TO_SWITCH' * @param ParamConfigurator|mixed $value * @return $this */ public function role($value) : static { $this->_usedProperties['role'] = \true; $this->role = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function targetRoute($value) : static { $this->_usedProperties['targetRoute'] = \true; $this->targetRoute = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('parameter', $value)) { $this->_usedProperties['parameter'] = \true; $this->parameter = $value['parameter']; unset($value['parameter']); } if (\array_key_exists('role', $value)) { $this->_usedProperties['role'] = \true; $this->role = $value['role']; unset($value['role']); } if (\array_key_exists('target_route', $value)) { $this->_usedProperties['targetRoute'] = \true; $this->targetRoute = $value['target_route']; unset($value['target_route']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['parameter'])) { $output['parameter'] = $this->parameter; } if (isset($this->_usedProperties['role'])) { $output['role'] = $this->role; } if (isset($this->_usedProperties['targetRoute'])) { $output['target_route'] = $this->targetRoute; } return $output; } } _usedProperties['limiter'] = \true; $this->limiter = $value; return $this; } /** * @default 5 * @param ParamConfigurator|int $value * @return $this */ public function maxAttempts($value) : static { $this->_usedProperties['maxAttempts'] = \true; $this->maxAttempts = $value; return $this; } /** * @default '1 minute' * @param ParamConfigurator|mixed $value * @return $this */ public function interval($value) : static { $this->_usedProperties['interval'] = \true; $this->interval = $value; return $this; } /** * The service ID of the lock factory used by the login rate limiter (or null to disable locking) * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function lockFactory($value) : static { $this->_usedProperties['lockFactory'] = \true; $this->lockFactory = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('limiter', $value)) { $this->_usedProperties['limiter'] = \true; $this->limiter = $value['limiter']; unset($value['limiter']); } if (\array_key_exists('max_attempts', $value)) { $this->_usedProperties['maxAttempts'] = \true; $this->maxAttempts = $value['max_attempts']; unset($value['max_attempts']); } if (\array_key_exists('interval', $value)) { $this->_usedProperties['interval'] = \true; $this->interval = $value['interval']; unset($value['interval']); } if (\array_key_exists('lock_factory', $value)) { $this->_usedProperties['lockFactory'] = \true; $this->lockFactory = $value['lock_factory']; unset($value['lock_factory']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['limiter'])) { $output['limiter'] = $this->limiter; } if (isset($this->_usedProperties['maxAttempts'])) { $output['max_attempts'] = $this->maxAttempts; } if (isset($this->_usedProperties['interval'])) { $output['interval'] = $this->interval; } if (isset($this->_usedProperties['lockFactory'])) { $output['lock_factory'] = $this->lockFactory; } return $output; } } _usedProperties['checkRoute'] = \true; $this->checkRoute = $value; return $this; } /** * If true, only HTTP POST requests to "check_route" will be handled by the authenticator. * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function checkPostOnly($value) : static { $this->_usedProperties['checkPostOnly'] = \true; $this->checkPostOnly = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function signatureProperties(ParamConfigurator|array $value) : static { $this->_usedProperties['signatureProperties'] = \true; $this->signatureProperties = $value; return $this; } /** * The lifetime of the login link in seconds. * @default 600 * @param ParamConfigurator|int $value * @return $this */ public function lifetime($value) : static { $this->_usedProperties['lifetime'] = \true; $this->lifetime = $value; return $this; } /** * Max number of times a login link can be used - null means unlimited within lifetime. * @default null * @param ParamConfigurator|int $value * @return $this */ public function maxUses($value) : static { $this->_usedProperties['maxUses'] = \true; $this->maxUses = $value; return $this; } /** * Cache service id used to expired links of max_uses is set. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function usedLinkCache($value) : static { $this->_usedProperties['usedLinkCache'] = \true; $this->usedLinkCache = $value; return $this; } /** * A service id that implements Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function successHandler($value) : static { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value; return $this; } /** * A service id that implements Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureHandler($value) : static { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value; return $this; } /** * The user provider to load users from. * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function provider($value) : static { $this->_usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function alwaysUseDefaultTargetPath($value) : static { $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true; $this->alwaysUseDefaultTargetPath = $value; return $this; } /** * @default '/' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultTargetPath($value) : static { $this->_usedProperties['defaultTargetPath'] = \true; $this->defaultTargetPath = $value; return $this; } /** * @default '/login' * @param ParamConfigurator|mixed $value * @return $this */ public function loginPath($value) : static { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value; return $this; } /** * @default '_target_path' * @param ParamConfigurator|mixed $value * @return $this */ public function targetPathParameter($value) : static { $this->_usedProperties['targetPathParameter'] = \true; $this->targetPathParameter = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useReferer($value) : static { $this->_usedProperties['useReferer'] = \true; $this->useReferer = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failurePath($value) : static { $this->_usedProperties['failurePath'] = \true; $this->failurePath = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function failureForward($value) : static { $this->_usedProperties['failureForward'] = \true; $this->failureForward = $value; return $this; } /** * @default '_failure_path' * @param ParamConfigurator|mixed $value * @return $this */ public function failurePathParameter($value) : static { $this->_usedProperties['failurePathParameter'] = \true; $this->failurePathParameter = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('check_route', $value)) { $this->_usedProperties['checkRoute'] = \true; $this->checkRoute = $value['check_route']; unset($value['check_route']); } if (\array_key_exists('check_post_only', $value)) { $this->_usedProperties['checkPostOnly'] = \true; $this->checkPostOnly = $value['check_post_only']; unset($value['check_post_only']); } if (\array_key_exists('signature_properties', $value)) { $this->_usedProperties['signatureProperties'] = \true; $this->signatureProperties = $value['signature_properties']; unset($value['signature_properties']); } if (\array_key_exists('lifetime', $value)) { $this->_usedProperties['lifetime'] = \true; $this->lifetime = $value['lifetime']; unset($value['lifetime']); } if (\array_key_exists('max_uses', $value)) { $this->_usedProperties['maxUses'] = \true; $this->maxUses = $value['max_uses']; unset($value['max_uses']); } if (\array_key_exists('used_link_cache', $value)) { $this->_usedProperties['usedLinkCache'] = \true; $this->usedLinkCache = $value['used_link_cache']; unset($value['used_link_cache']); } if (\array_key_exists('success_handler', $value)) { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value['success_handler']; unset($value['success_handler']); } if (\array_key_exists('failure_handler', $value)) { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value['failure_handler']; unset($value['failure_handler']); } if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('always_use_default_target_path', $value)) { $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true; $this->alwaysUseDefaultTargetPath = $value['always_use_default_target_path']; unset($value['always_use_default_target_path']); } if (\array_key_exists('default_target_path', $value)) { $this->_usedProperties['defaultTargetPath'] = \true; $this->defaultTargetPath = $value['default_target_path']; unset($value['default_target_path']); } if (\array_key_exists('login_path', $value)) { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value['login_path']; unset($value['login_path']); } if (\array_key_exists('target_path_parameter', $value)) { $this->_usedProperties['targetPathParameter'] = \true; $this->targetPathParameter = $value['target_path_parameter']; unset($value['target_path_parameter']); } if (\array_key_exists('use_referer', $value)) { $this->_usedProperties['useReferer'] = \true; $this->useReferer = $value['use_referer']; unset($value['use_referer']); } if (\array_key_exists('failure_path', $value)) { $this->_usedProperties['failurePath'] = \true; $this->failurePath = $value['failure_path']; unset($value['failure_path']); } if (\array_key_exists('failure_forward', $value)) { $this->_usedProperties['failureForward'] = \true; $this->failureForward = $value['failure_forward']; unset($value['failure_forward']); } if (\array_key_exists('failure_path_parameter', $value)) { $this->_usedProperties['failurePathParameter'] = \true; $this->failurePathParameter = $value['failure_path_parameter']; unset($value['failure_path_parameter']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['checkRoute'])) { $output['check_route'] = $this->checkRoute; } if (isset($this->_usedProperties['checkPostOnly'])) { $output['check_post_only'] = $this->checkPostOnly; } if (isset($this->_usedProperties['signatureProperties'])) { $output['signature_properties'] = $this->signatureProperties; } if (isset($this->_usedProperties['lifetime'])) { $output['lifetime'] = $this->lifetime; } if (isset($this->_usedProperties['maxUses'])) { $output['max_uses'] = $this->maxUses; } if (isset($this->_usedProperties['usedLinkCache'])) { $output['used_link_cache'] = $this->usedLinkCache; } if (isset($this->_usedProperties['successHandler'])) { $output['success_handler'] = $this->successHandler; } if (isset($this->_usedProperties['failureHandler'])) { $output['failure_handler'] = $this->failureHandler; } if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['alwaysUseDefaultTargetPath'])) { $output['always_use_default_target_path'] = $this->alwaysUseDefaultTargetPath; } if (isset($this->_usedProperties['defaultTargetPath'])) { $output['default_target_path'] = $this->defaultTargetPath; } if (isset($this->_usedProperties['loginPath'])) { $output['login_path'] = $this->loginPath; } if (isset($this->_usedProperties['targetPathParameter'])) { $output['target_path_parameter'] = $this->targetPathParameter; } if (isset($this->_usedProperties['useReferer'])) { $output['use_referer'] = $this->useReferer; } if (isset($this->_usedProperties['failurePath'])) { $output['failure_path'] = $this->failurePath; } if (isset($this->_usedProperties['failureForward'])) { $output['failure_forward'] = $this->failureForward; } if (isset($this->_usedProperties['failurePathParameter'])) { $output['failure_path_parameter'] = $this->failurePathParameter; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function connection($value) : static { $this->_usedProperties['connection'] = \true; $this->connection = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('connection', $value)) { $this->_usedProperties['connection'] = \true; $this->connection = $value['connection']; unset($value['connection']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['connection'])) { $output['connection'] = $this->connection; } return $output; } } _usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @template TValue * @param TValue $value * @default {"enabled":false,"connection":null} * @return \Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig : static) */ public function doctrine(array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig|static { if (!\is_array($value)) { $this->_usedProperties['doctrine'] = \true; $this->doctrine = $value; return $this; } if (!$this->doctrine instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig) { $this->_usedProperties['doctrine'] = \true; $this->doctrine = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "doctrine()" has already been initialized. You cannot pass values the second time you call doctrine().'); } return $this->doctrine; } public function __construct(array $value = []) { if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('doctrine', $value)) { $this->_usedProperties['doctrine'] = \true; $this->doctrine = \is_array($value['doctrine']) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig($value['doctrine']) : $value['doctrine']; unset($value['doctrine']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['doctrine'])) { $output['doctrine'] = $this->doctrine instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\RememberMe\TokenProvider\DoctrineConfig ? $this->doctrine->toArray() : $this->doctrine; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function rememberMe($value) : static { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function successHandler($value) : static { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failureHandler($value) : static { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value; return $this; } /** * @default '/login_check' * @param ParamConfigurator|mixed $value * @return $this */ public function checkPath($value) : static { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useForward($value) : static { $this->_usedProperties['useForward'] = \true; $this->useForward = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @deprecated Option "require_previous_session" at "form_login_ldap" is deprecated, it will be removed in version 7.0. Setting it has no effect anymore. * @return $this */ public function requirePreviousSession($value) : static { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value; return $this; } /** * @default '/login' * @param ParamConfigurator|mixed $value * @return $this */ public function loginPath($value) : static { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value; return $this; } /** * @default '_username' * @param ParamConfigurator|mixed $value * @return $this */ public function usernameParameter($value) : static { $this->_usedProperties['usernameParameter'] = \true; $this->usernameParameter = $value; return $this; } /** * @default '_password' * @param ParamConfigurator|mixed $value * @return $this */ public function passwordParameter($value) : static { $this->_usedProperties['passwordParameter'] = \true; $this->passwordParameter = $value; return $this; } /** * @default '_csrf_token' * @param ParamConfigurator|mixed $value * @return $this */ public function csrfParameter($value) : static { $this->_usedProperties['csrfParameter'] = \true; $this->csrfParameter = $value; return $this; } /** * @default 'authenticate' * @param ParamConfigurator|mixed $value * @return $this */ public function csrfTokenId($value) : static { $this->_usedProperties['csrfTokenId'] = \true; $this->csrfTokenId = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function enableCsrf($value) : static { $this->_usedProperties['enableCsrf'] = \true; $this->enableCsrf = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function postOnly($value) : static { $this->_usedProperties['postOnly'] = \true; $this->postOnly = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function formOnly($value) : static { $this->_usedProperties['formOnly'] = \true; $this->formOnly = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function alwaysUseDefaultTargetPath($value) : static { $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true; $this->alwaysUseDefaultTargetPath = $value; return $this; } /** * @default '/' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultTargetPath($value) : static { $this->_usedProperties['defaultTargetPath'] = \true; $this->defaultTargetPath = $value; return $this; } /** * @default '_target_path' * @param ParamConfigurator|mixed $value * @return $this */ public function targetPathParameter($value) : static { $this->_usedProperties['targetPathParameter'] = \true; $this->targetPathParameter = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useReferer($value) : static { $this->_usedProperties['useReferer'] = \true; $this->useReferer = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function failurePath($value) : static { $this->_usedProperties['failurePath'] = \true; $this->failurePath = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function failureForward($value) : static { $this->_usedProperties['failureForward'] = \true; $this->failureForward = $value; return $this; } /** * @default '_failure_path' * @param ParamConfigurator|mixed $value * @return $this */ public function failurePathParameter($value) : static { $this->_usedProperties['failurePathParameter'] = \true; $this->failurePathParameter = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function csrfTokenGenerator($value) : static { $this->_usedProperties['csrfTokenGenerator'] = \true; $this->csrfTokenGenerator = $value; return $this; } /** * @default 'ldap' * @param ParamConfigurator|mixed $value * @return $this */ public function service($value) : static { $this->_usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @default '{username}' * @param ParamConfigurator|mixed $value * @return $this */ public function dnString($value) : static { $this->_usedProperties['dnString'] = \true; $this->dnString = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function queryString($value) : static { $this->_usedProperties['queryString'] = \true; $this->queryString = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function searchDn($value) : static { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function searchPassword($value) : static { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('remember_me', $value)) { $this->_usedProperties['rememberMe'] = \true; $this->rememberMe = $value['remember_me']; unset($value['remember_me']); } if (\array_key_exists('success_handler', $value)) { $this->_usedProperties['successHandler'] = \true; $this->successHandler = $value['success_handler']; unset($value['success_handler']); } if (\array_key_exists('failure_handler', $value)) { $this->_usedProperties['failureHandler'] = \true; $this->failureHandler = $value['failure_handler']; unset($value['failure_handler']); } if (\array_key_exists('check_path', $value)) { $this->_usedProperties['checkPath'] = \true; $this->checkPath = $value['check_path']; unset($value['check_path']); } if (\array_key_exists('use_forward', $value)) { $this->_usedProperties['useForward'] = \true; $this->useForward = $value['use_forward']; unset($value['use_forward']); } if (\array_key_exists('require_previous_session', $value)) { $this->_usedProperties['requirePreviousSession'] = \true; $this->requirePreviousSession = $value['require_previous_session']; unset($value['require_previous_session']); } if (\array_key_exists('login_path', $value)) { $this->_usedProperties['loginPath'] = \true; $this->loginPath = $value['login_path']; unset($value['login_path']); } if (\array_key_exists('username_parameter', $value)) { $this->_usedProperties['usernameParameter'] = \true; $this->usernameParameter = $value['username_parameter']; unset($value['username_parameter']); } if (\array_key_exists('password_parameter', $value)) { $this->_usedProperties['passwordParameter'] = \true; $this->passwordParameter = $value['password_parameter']; unset($value['password_parameter']); } if (\array_key_exists('csrf_parameter', $value)) { $this->_usedProperties['csrfParameter'] = \true; $this->csrfParameter = $value['csrf_parameter']; unset($value['csrf_parameter']); } if (\array_key_exists('csrf_token_id', $value)) { $this->_usedProperties['csrfTokenId'] = \true; $this->csrfTokenId = $value['csrf_token_id']; unset($value['csrf_token_id']); } if (\array_key_exists('enable_csrf', $value)) { $this->_usedProperties['enableCsrf'] = \true; $this->enableCsrf = $value['enable_csrf']; unset($value['enable_csrf']); } if (\array_key_exists('post_only', $value)) { $this->_usedProperties['postOnly'] = \true; $this->postOnly = $value['post_only']; unset($value['post_only']); } if (\array_key_exists('form_only', $value)) { $this->_usedProperties['formOnly'] = \true; $this->formOnly = $value['form_only']; unset($value['form_only']); } if (\array_key_exists('always_use_default_target_path', $value)) { $this->_usedProperties['alwaysUseDefaultTargetPath'] = \true; $this->alwaysUseDefaultTargetPath = $value['always_use_default_target_path']; unset($value['always_use_default_target_path']); } if (\array_key_exists('default_target_path', $value)) { $this->_usedProperties['defaultTargetPath'] = \true; $this->defaultTargetPath = $value['default_target_path']; unset($value['default_target_path']); } if (\array_key_exists('target_path_parameter', $value)) { $this->_usedProperties['targetPathParameter'] = \true; $this->targetPathParameter = $value['target_path_parameter']; unset($value['target_path_parameter']); } if (\array_key_exists('use_referer', $value)) { $this->_usedProperties['useReferer'] = \true; $this->useReferer = $value['use_referer']; unset($value['use_referer']); } if (\array_key_exists('failure_path', $value)) { $this->_usedProperties['failurePath'] = \true; $this->failurePath = $value['failure_path']; unset($value['failure_path']); } if (\array_key_exists('failure_forward', $value)) { $this->_usedProperties['failureForward'] = \true; $this->failureForward = $value['failure_forward']; unset($value['failure_forward']); } if (\array_key_exists('failure_path_parameter', $value)) { $this->_usedProperties['failurePathParameter'] = \true; $this->failurePathParameter = $value['failure_path_parameter']; unset($value['failure_path_parameter']); } if (\array_key_exists('csrf_token_generator', $value)) { $this->_usedProperties['csrfTokenGenerator'] = \true; $this->csrfTokenGenerator = $value['csrf_token_generator']; unset($value['csrf_token_generator']); } if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('dn_string', $value)) { $this->_usedProperties['dnString'] = \true; $this->dnString = $value['dn_string']; unset($value['dn_string']); } if (\array_key_exists('query_string', $value)) { $this->_usedProperties['queryString'] = \true; $this->queryString = $value['query_string']; unset($value['query_string']); } if (\array_key_exists('search_dn', $value)) { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value['search_dn']; unset($value['search_dn']); } if (\array_key_exists('search_password', $value)) { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value['search_password']; unset($value['search_password']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['rememberMe'])) { $output['remember_me'] = $this->rememberMe; } if (isset($this->_usedProperties['successHandler'])) { $output['success_handler'] = $this->successHandler; } if (isset($this->_usedProperties['failureHandler'])) { $output['failure_handler'] = $this->failureHandler; } if (isset($this->_usedProperties['checkPath'])) { $output['check_path'] = $this->checkPath; } if (isset($this->_usedProperties['useForward'])) { $output['use_forward'] = $this->useForward; } if (isset($this->_usedProperties['requirePreviousSession'])) { $output['require_previous_session'] = $this->requirePreviousSession; } if (isset($this->_usedProperties['loginPath'])) { $output['login_path'] = $this->loginPath; } if (isset($this->_usedProperties['usernameParameter'])) { $output['username_parameter'] = $this->usernameParameter; } if (isset($this->_usedProperties['passwordParameter'])) { $output['password_parameter'] = $this->passwordParameter; } if (isset($this->_usedProperties['csrfParameter'])) { $output['csrf_parameter'] = $this->csrfParameter; } if (isset($this->_usedProperties['csrfTokenId'])) { $output['csrf_token_id'] = $this->csrfTokenId; } if (isset($this->_usedProperties['enableCsrf'])) { $output['enable_csrf'] = $this->enableCsrf; } if (isset($this->_usedProperties['postOnly'])) { $output['post_only'] = $this->postOnly; } if (isset($this->_usedProperties['formOnly'])) { $output['form_only'] = $this->formOnly; } if (isset($this->_usedProperties['alwaysUseDefaultTargetPath'])) { $output['always_use_default_target_path'] = $this->alwaysUseDefaultTargetPath; } if (isset($this->_usedProperties['defaultTargetPath'])) { $output['default_target_path'] = $this->defaultTargetPath; } if (isset($this->_usedProperties['targetPathParameter'])) { $output['target_path_parameter'] = $this->targetPathParameter; } if (isset($this->_usedProperties['useReferer'])) { $output['use_referer'] = $this->useReferer; } if (isset($this->_usedProperties['failurePath'])) { $output['failure_path'] = $this->failurePath; } if (isset($this->_usedProperties['failureForward'])) { $output['failure_forward'] = $this->failureForward; } if (isset($this->_usedProperties['failurePathParameter'])) { $output['failure_path_parameter'] = $this->failurePathParameter; } if (isset($this->_usedProperties['csrfTokenGenerator'])) { $output['csrf_token_generator'] = $this->csrfTokenGenerator; } if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['dnString'])) { $output['dn_string'] = $this->dnString; } if (isset($this->_usedProperties['queryString'])) { $output['query_string'] = $this->queryString; } if (isset($this->_usedProperties['searchDn'])) { $output['search_dn'] = $this->searchDn; } if (isset($this->_usedProperties['searchPassword'])) { $output['search_password'] = $this->searchPassword; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default 'Secured Area' * @param ParamConfigurator|mixed $value * @return $this */ public function realm($value) : static { $this->_usedProperties['realm'] = \true; $this->realm = $value; return $this; } /** * @default 'ldap' * @param ParamConfigurator|mixed $value * @return $this */ public function service($value) : static { $this->_usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @default '{username}' * @param ParamConfigurator|mixed $value * @return $this */ public function dnString($value) : static { $this->_usedProperties['dnString'] = \true; $this->dnString = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function queryString($value) : static { $this->_usedProperties['queryString'] = \true; $this->queryString = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function searchDn($value) : static { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value; return $this; } /** * @param ParamConfigurator|mixed $value * @return $this */ public function searchPassword($value) : static { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('realm', $value)) { $this->_usedProperties['realm'] = \true; $this->realm = $value['realm']; unset($value['realm']); } if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('dn_string', $value)) { $this->_usedProperties['dnString'] = \true; $this->dnString = $value['dn_string']; unset($value['dn_string']); } if (\array_key_exists('query_string', $value)) { $this->_usedProperties['queryString'] = \true; $this->queryString = $value['query_string']; unset($value['query_string']); } if (\array_key_exists('search_dn', $value)) { $this->_usedProperties['searchDn'] = \true; $this->searchDn = $value['search_dn']; unset($value['search_dn']); } if (\array_key_exists('search_password', $value)) { $this->_usedProperties['searchPassword'] = \true; $this->searchPassword = $value['search_password']; unset($value['search_password']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['realm'])) { $output['realm'] = $this->realm; } if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['dnString'])) { $output['dn_string'] = $this->dnString; } if (isset($this->_usedProperties['queryString'])) { $output['query_string'] = $this->queryString; } if (isset($this->_usedProperties['searchDn'])) { $output['search_dn'] = $this->searchDn; } if (isset($this->_usedProperties['searchPassword'])) { $output['search_password'] = $this->searchPassword; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default 'SSL_CLIENT_S_DN_Email' * @param ParamConfigurator|mixed $value * @return $this */ public function user($value) : static { $this->_usedProperties['user'] = \true; $this->user = $value; return $this; } /** * @default 'SSL_CLIENT_S_DN' * @param ParamConfigurator|mixed $value * @return $this */ public function credentials($value) : static { $this->_usedProperties['credentials'] = \true; $this->credentials = $value; return $this; } /** * @default 'emailAddress' * @param ParamConfigurator|mixed $value * @return $this */ public function userIdentifier($value) : static { $this->_usedProperties['userIdentifier'] = \true; $this->userIdentifier = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('user', $value)) { $this->_usedProperties['user'] = \true; $this->user = $value['user']; unset($value['user']); } if (\array_key_exists('credentials', $value)) { $this->_usedProperties['credentials'] = \true; $this->credentials = $value['credentials']; unset($value['credentials']); } if (\array_key_exists('user_identifier', $value)) { $this->_usedProperties['userIdentifier'] = \true; $this->userIdentifier = $value['user_identifier']; unset($value['user_identifier']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['user'])) { $output['user'] = $this->user; } if (isset($this->_usedProperties['credentials'])) { $output['credentials'] = $this->credentials; } if (isset($this->_usedProperties['userIdentifier'])) { $output['user_identifier'] = $this->userIdentifier; } return $output; } } _usedProperties['provider'] = \true; $this->provider = $value; return $this; } /** * @default 'REMOTE_USER' * @param ParamConfigurator|mixed $value * @return $this */ public function user($value) : static { $this->_usedProperties['user'] = \true; $this->user = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('provider', $value)) { $this->_usedProperties['provider'] = \true; $this->provider = $value['provider']; unset($value['provider']); } if (\array_key_exists('user', $value)) { $this->_usedProperties['user'] = \true; $this->user = $value['user']; unset($value['user']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['provider'])) { $output['provider'] = $this->provider; } if (isset($this->_usedProperties['user'])) { $output['user'] = $this->user; } return $output; } } _usedProperties['enableCsrf'] = \true; $this->enableCsrf = $value; return $this; } /** * @default 'logout' * @param ParamConfigurator|mixed $value * @return $this */ public function csrfTokenId($value) : static { $this->_usedProperties['csrfTokenId'] = \true; $this->csrfTokenId = $value; return $this; } /** * @default '_csrf_token' * @param ParamConfigurator|mixed $value * @return $this */ public function csrfParameter($value) : static { $this->_usedProperties['csrfParameter'] = \true; $this->csrfParameter = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @deprecated The "csrf_token_generator" option is deprecated. Use "csrf_token_manager" instead. * @return $this */ public function csrfTokenGenerator($value) : static { $this->_usedProperties['csrfTokenGenerator'] = \true; $this->csrfTokenGenerator = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function csrfTokenManager($value) : static { $this->_usedProperties['csrfTokenManager'] = \true; $this->csrfTokenManager = $value; return $this; } /** * @default '/logout' * @param ParamConfigurator|mixed $value * @return $this */ public function path($value) : static { $this->_usedProperties['path'] = \true; $this->path = $value; return $this; } /** * @default '/' * @param ParamConfigurator|mixed $value * @return $this */ public function target($value) : static { $this->_usedProperties['target'] = \true; $this->target = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function invalidateSession($value) : static { $this->_usedProperties['invalidateSession'] = \true; $this->invalidateSession = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function clearSiteData(ParamConfigurator|string|array $value) : static { $this->_usedProperties['clearSiteData'] = \true; $this->clearSiteData = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig : static) */ public function deleteCookie(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig|static { if (!\is_array($value)) { $this->_usedProperties['deleteCookies'] = \true; $this->deleteCookies[$name] = $value; return $this; } if (!isset($this->deleteCookies[$name]) || !$this->deleteCookies[$name] instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig) { $this->_usedProperties['deleteCookies'] = \true; $this->deleteCookies[$name] = new \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "deleteCookie()" has already been initialized. You cannot pass values the second time you call deleteCookie().'); } return $this->deleteCookies[$name]; } public function __construct(array $value = []) { if (\array_key_exists('enable_csrf', $value)) { $this->_usedProperties['enableCsrf'] = \true; $this->enableCsrf = $value['enable_csrf']; unset($value['enable_csrf']); } if (\array_key_exists('csrf_token_id', $value)) { $this->_usedProperties['csrfTokenId'] = \true; $this->csrfTokenId = $value['csrf_token_id']; unset($value['csrf_token_id']); } if (\array_key_exists('csrf_parameter', $value)) { $this->_usedProperties['csrfParameter'] = \true; $this->csrfParameter = $value['csrf_parameter']; unset($value['csrf_parameter']); } if (\array_key_exists('csrf_token_generator', $value)) { $this->_usedProperties['csrfTokenGenerator'] = \true; $this->csrfTokenGenerator = $value['csrf_token_generator']; unset($value['csrf_token_generator']); } if (\array_key_exists('csrf_token_manager', $value)) { $this->_usedProperties['csrfTokenManager'] = \true; $this->csrfTokenManager = $value['csrf_token_manager']; unset($value['csrf_token_manager']); } if (\array_key_exists('path', $value)) { $this->_usedProperties['path'] = \true; $this->path = $value['path']; unset($value['path']); } if (\array_key_exists('target', $value)) { $this->_usedProperties['target'] = \true; $this->target = $value['target']; unset($value['target']); } if (\array_key_exists('invalidate_session', $value)) { $this->_usedProperties['invalidateSession'] = \true; $this->invalidateSession = $value['invalidate_session']; unset($value['invalidate_session']); } if (\array_key_exists('clear_site_data', $value)) { $this->_usedProperties['clearSiteData'] = \true; $this->clearSiteData = $value['clear_site_data']; unset($value['clear_site_data']); } if (\array_key_exists('delete_cookies', $value)) { $this->_usedProperties['deleteCookies'] = \true; $this->deleteCookies = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig($v) : $v, $value['delete_cookies']); unset($value['delete_cookies']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enableCsrf'])) { $output['enable_csrf'] = $this->enableCsrf; } if (isset($this->_usedProperties['csrfTokenId'])) { $output['csrf_token_id'] = $this->csrfTokenId; } if (isset($this->_usedProperties['csrfParameter'])) { $output['csrf_parameter'] = $this->csrfParameter; } if (isset($this->_usedProperties['csrfTokenGenerator'])) { $output['csrf_token_generator'] = $this->csrfTokenGenerator; } if (isset($this->_usedProperties['csrfTokenManager'])) { $output['csrf_token_manager'] = $this->csrfTokenManager; } if (isset($this->_usedProperties['path'])) { $output['path'] = $this->path; } if (isset($this->_usedProperties['target'])) { $output['target'] = $this->target; } if (isset($this->_usedProperties['invalidateSession'])) { $output['invalidate_session'] = $this->invalidateSession; } if (isset($this->_usedProperties['clearSiteData'])) { $output['clear_site_data'] = $this->clearSiteData; } if (isset($this->_usedProperties['deleteCookies'])) { $output['delete_cookies'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Security\FirewallConfig\Logout\DeleteCookieConfig ? $v->toArray() : $v, $this->deleteCookies); } return $output; } } _usedProperties['strategy'] = \true; $this->strategy = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function service($value) : static { $this->_usedProperties['service'] = \true; $this->service = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function strategyService($value) : static { $this->_usedProperties['strategyService'] = \true; $this->strategyService = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function allowIfAllAbstain($value) : static { $this->_usedProperties['allowIfAllAbstain'] = \true; $this->allowIfAllAbstain = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function allowIfEqualGrantedDenied($value) : static { $this->_usedProperties['allowIfEqualGrantedDenied'] = \true; $this->allowIfEqualGrantedDenied = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('strategy', $value)) { $this->_usedProperties['strategy'] = \true; $this->strategy = $value['strategy']; unset($value['strategy']); } if (\array_key_exists('service', $value)) { $this->_usedProperties['service'] = \true; $this->service = $value['service']; unset($value['service']); } if (\array_key_exists('strategy_service', $value)) { $this->_usedProperties['strategyService'] = \true; $this->strategyService = $value['strategy_service']; unset($value['strategy_service']); } if (\array_key_exists('allow_if_all_abstain', $value)) { $this->_usedProperties['allowIfAllAbstain'] = \true; $this->allowIfAllAbstain = $value['allow_if_all_abstain']; unset($value['allow_if_all_abstain']); } if (\array_key_exists('allow_if_equal_granted_denied', $value)) { $this->_usedProperties['allowIfEqualGrantedDenied'] = \true; $this->allowIfEqualGrantedDenied = $value['allow_if_equal_granted_denied']; unset($value['allow_if_equal_granted_denied']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['strategy'])) { $output['strategy'] = $this->strategy; } if (isset($this->_usedProperties['service'])) { $output['service'] = $this->service; } if (isset($this->_usedProperties['strategyService'])) { $output['strategy_service'] = $this->strategyService; } if (isset($this->_usedProperties['allowIfAllAbstain'])) { $output['allow_if_all_abstain'] = $this->allowIfAllAbstain; } if (isset($this->_usedProperties['allowIfEqualGrantedDenied'])) { $output['allow_if_equal_granted_denied'] = $this->allowIfEqualGrantedDenied; } return $output; } } _usedProperties['requestMatcher'] = \true; $this->requestMatcher = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function requiresChannel($value) : static { $this->_usedProperties['requiresChannel'] = \true; $this->requiresChannel = $value; return $this; } /** * use the urldecoded format * @example ^/path to resource/ * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function path($value) : static { $this->_usedProperties['path'] = \true; $this->path = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function host($value) : static { $this->_usedProperties['host'] = \true; $this->host = $value; return $this; } /** * @default null * @param ParamConfigurator|int $value * @return $this */ public function port($value) : static { $this->_usedProperties['port'] = \true; $this->port = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function ips(ParamConfigurator|string|array $value) : static { $this->_usedProperties['ips'] = \true; $this->ips = $value; return $this; } /** * @return $this */ public function attribute(string $key, mixed $value) : static { $this->_usedProperties['attributes'] = \true; $this->attributes[$key] = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function route($value) : static { $this->_usedProperties['route'] = \true; $this->route = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function methods(ParamConfigurator|string|array $value) : static { $this->_usedProperties['methods'] = \true; $this->methods = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function allowIf($value) : static { $this->_usedProperties['allowIf'] = \true; $this->allowIf = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function roles(ParamConfigurator|string|array $value) : static { $this->_usedProperties['roles'] = \true; $this->roles = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('request_matcher', $value)) { $this->_usedProperties['requestMatcher'] = \true; $this->requestMatcher = $value['request_matcher']; unset($value['request_matcher']); } if (\array_key_exists('requires_channel', $value)) { $this->_usedProperties['requiresChannel'] = \true; $this->requiresChannel = $value['requires_channel']; unset($value['requires_channel']); } if (\array_key_exists('path', $value)) { $this->_usedProperties['path'] = \true; $this->path = $value['path']; unset($value['path']); } if (\array_key_exists('host', $value)) { $this->_usedProperties['host'] = \true; $this->host = $value['host']; unset($value['host']); } if (\array_key_exists('port', $value)) { $this->_usedProperties['port'] = \true; $this->port = $value['port']; unset($value['port']); } if (\array_key_exists('ips', $value)) { $this->_usedProperties['ips'] = \true; $this->ips = $value['ips']; unset($value['ips']); } if (\array_key_exists('attributes', $value)) { $this->_usedProperties['attributes'] = \true; $this->attributes = $value['attributes']; unset($value['attributes']); } if (\array_key_exists('route', $value)) { $this->_usedProperties['route'] = \true; $this->route = $value['route']; unset($value['route']); } if (\array_key_exists('methods', $value)) { $this->_usedProperties['methods'] = \true; $this->methods = $value['methods']; unset($value['methods']); } if (\array_key_exists('allow_if', $value)) { $this->_usedProperties['allowIf'] = \true; $this->allowIf = $value['allow_if']; unset($value['allow_if']); } if (\array_key_exists('roles', $value)) { $this->_usedProperties['roles'] = \true; $this->roles = $value['roles']; unset($value['roles']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['requestMatcher'])) { $output['request_matcher'] = $this->requestMatcher; } if (isset($this->_usedProperties['requiresChannel'])) { $output['requires_channel'] = $this->requiresChannel; } if (isset($this->_usedProperties['path'])) { $output['path'] = $this->path; } if (isset($this->_usedProperties['host'])) { $output['host'] = $this->host; } if (isset($this->_usedProperties['port'])) { $output['port'] = $this->port; } if (isset($this->_usedProperties['ips'])) { $output['ips'] = $this->ips; } if (isset($this->_usedProperties['attributes'])) { $output['attributes'] = $this->attributes; } if (isset($this->_usedProperties['route'])) { $output['route'] = $this->route; } if (isset($this->_usedProperties['methods'])) { $output['methods'] = $this->methods; } if (isset($this->_usedProperties['allowIf'])) { $output['allow_if'] = $this->allowIf; } if (isset($this->_usedProperties['roles'])) { $output['roles'] = $this->roles; } return $output; } } _usedProperties['accessDeniedUrl'] = \true; $this->accessDeniedUrl = $value; return $this; } /** * @default 'migrate' * @param ParamConfigurator|'none'|'migrate'|'invalidate' $value * @return $this */ public function sessionFixationStrategy($value) : static { $this->_usedProperties['sessionFixationStrategy'] = \true; $this->sessionFixationStrategy = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function hideUserNotFound($value) : static { $this->_usedProperties['hideUserNotFound'] = \true; $this->hideUserNotFound = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function eraseCredentials($value) : static { $this->_usedProperties['eraseCredentials'] = \true; $this->eraseCredentials = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @deprecated The "enable_authenticator_manager" option at "security" is deprecated. * @return $this */ public function enableAuthenticatorManager($value) : static { $this->_usedProperties['enableAuthenticatorManager'] = \true; $this->enableAuthenticatorManager = $value; return $this; } /** * @default {"allow_if_all_abstain":false,"allow_if_equal_granted_denied":true} */ public function accessDecisionManager(array $value = []) : \_ContaoManager\Symfony\Config\Security\AccessDecisionManagerConfig { if (null === $this->accessDecisionManager) { $this->_usedProperties['accessDecisionManager'] = \true; $this->accessDecisionManager = new \_ContaoManager\Symfony\Config\Security\AccessDecisionManagerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "accessDecisionManager()" has already been initialized. You cannot pass values the second time you call accessDecisionManager().'); } return $this->accessDecisionManager; } /** * @template TValue * @param TValue $value * @example "auto" * @example {"algorithm":"auto","time_cost":8,"cost":13} * @return \Symfony\Config\Security\PasswordHasherConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Security\PasswordHasherConfig : static) */ public function passwordHasher(string $class, string|array $value = []) : \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig|static { if (!\is_array($value)) { $this->_usedProperties['passwordHashers'] = \true; $this->passwordHashers[$class] = $value; return $this; } if (!isset($this->passwordHashers[$class]) || !$this->passwordHashers[$class] instanceof \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig) { $this->_usedProperties['passwordHashers'] = \true; $this->passwordHashers[$class] = new \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "passwordHasher()" has already been initialized. You cannot pass values the second time you call passwordHasher().'); } return $this->passwordHashers[$class]; } /** * @example {"memory":{"users":{"foo":{"password":"foo","roles":"ROLE_USER"},"bar":{"password":"bar","roles":"[ROLE_USER, ROLE_ADMIN]"}}}} * @example {"entity":{"class":"SecurityBundle:User","property":"username"}} */ public function provider(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Security\ProviderConfig { if (!isset($this->providers[$name])) { $this->_usedProperties['providers'] = \true; $this->providers[$name] = new \_ContaoManager\Symfony\Config\Security\ProviderConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "provider()" has already been initialized. You cannot pass values the second time you call provider().'); } return $this->providers[$name]; } public function firewall(string $name, array $value = []) : \_ContaoManager\Symfony\Config\Security\FirewallConfig { if (!isset($this->firewalls[$name])) { $this->_usedProperties['firewalls'] = \true; $this->firewalls[$name] = new \_ContaoManager\Symfony\Config\Security\FirewallConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "firewall()" has already been initialized. You cannot pass values the second time you call firewall().'); } return $this->firewalls[$name]; } public function accessControl(array $value = []) : \_ContaoManager\Symfony\Config\Security\AccessControlConfig { $this->_usedProperties['accessControl'] = \true; return $this->accessControl[] = new \_ContaoManager\Symfony\Config\Security\AccessControlConfig($value); } /** * @return $this */ public function roleHierarchy(string $id, mixed $value) : static { $this->_usedProperties['roleHierarchy'] = \true; $this->roleHierarchy[$id] = $value; return $this; } public function getExtensionAlias() : string { return 'security'; } public function __construct(array $value = []) { if (\array_key_exists('access_denied_url', $value)) { $this->_usedProperties['accessDeniedUrl'] = \true; $this->accessDeniedUrl = $value['access_denied_url']; unset($value['access_denied_url']); } if (\array_key_exists('session_fixation_strategy', $value)) { $this->_usedProperties['sessionFixationStrategy'] = \true; $this->sessionFixationStrategy = $value['session_fixation_strategy']; unset($value['session_fixation_strategy']); } if (\array_key_exists('hide_user_not_found', $value)) { $this->_usedProperties['hideUserNotFound'] = \true; $this->hideUserNotFound = $value['hide_user_not_found']; unset($value['hide_user_not_found']); } if (\array_key_exists('erase_credentials', $value)) { $this->_usedProperties['eraseCredentials'] = \true; $this->eraseCredentials = $value['erase_credentials']; unset($value['erase_credentials']); } if (\array_key_exists('enable_authenticator_manager', $value)) { $this->_usedProperties['enableAuthenticatorManager'] = \true; $this->enableAuthenticatorManager = $value['enable_authenticator_manager']; unset($value['enable_authenticator_manager']); } if (\array_key_exists('access_decision_manager', $value)) { $this->_usedProperties['accessDecisionManager'] = \true; $this->accessDecisionManager = new \_ContaoManager\Symfony\Config\Security\AccessDecisionManagerConfig($value['access_decision_manager']); unset($value['access_decision_manager']); } if (\array_key_exists('password_hashers', $value)) { $this->_usedProperties['passwordHashers'] = \true; $this->passwordHashers = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig($v) : $v, $value['password_hashers']); unset($value['password_hashers']); } if (\array_key_exists('providers', $value)) { $this->_usedProperties['providers'] = \true; $this->providers = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\ProviderConfig($v), $value['providers']); unset($value['providers']); } if (\array_key_exists('firewalls', $value)) { $this->_usedProperties['firewalls'] = \true; $this->firewalls = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\FirewallConfig($v), $value['firewalls']); unset($value['firewalls']); } if (\array_key_exists('access_control', $value)) { $this->_usedProperties['accessControl'] = \true; $this->accessControl = \array_map(fn($v) => new \_ContaoManager\Symfony\Config\Security\AccessControlConfig($v), $value['access_control']); unset($value['access_control']); } if (\array_key_exists('role_hierarchy', $value)) { $this->_usedProperties['roleHierarchy'] = \true; $this->roleHierarchy = $value['role_hierarchy']; unset($value['role_hierarchy']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['accessDeniedUrl'])) { $output['access_denied_url'] = $this->accessDeniedUrl; } if (isset($this->_usedProperties['sessionFixationStrategy'])) { $output['session_fixation_strategy'] = $this->sessionFixationStrategy; } if (isset($this->_usedProperties['hideUserNotFound'])) { $output['hide_user_not_found'] = $this->hideUserNotFound; } if (isset($this->_usedProperties['eraseCredentials'])) { $output['erase_credentials'] = $this->eraseCredentials; } if (isset($this->_usedProperties['enableAuthenticatorManager'])) { $output['enable_authenticator_manager'] = $this->enableAuthenticatorManager; } if (isset($this->_usedProperties['accessDecisionManager'])) { $output['access_decision_manager'] = $this->accessDecisionManager->toArray(); } if (isset($this->_usedProperties['passwordHashers'])) { $output['password_hashers'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Security\PasswordHasherConfig ? $v->toArray() : $v, $this->passwordHashers); } if (isset($this->_usedProperties['providers'])) { $output['providers'] = \array_map(fn($v) => $v->toArray(), $this->providers); } if (isset($this->_usedProperties['firewalls'])) { $output['firewalls'] = \array_map(fn($v) => $v->toArray(), $this->firewalls); } if (isset($this->_usedProperties['accessControl'])) { $output['access_control'] = \array_map(fn($v) => $v->toArray(), $this->accessControl); } if (isset($this->_usedProperties['roleHierarchy'])) { $output['role_hierarchy'] = $this->roleHierarchy; } return $output; } } _usedProperties['useMicroseconds'] = \true; $this->useMicroseconds = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function channels(ParamConfigurator|array $value) : static { $this->_usedProperties['channels'] = \true; $this->channels = $value; return $this; } /** * @template TValue * @param TValue $value * @example {"type":"stream","path":"\/var\/log\/symfony.log","level":"ERROR","bubble":"false","formatter":"my_formatter"} * @example {"type":"fingers_crossed","action_level":"WARNING","buffer_size":30,"handler":"custom"} * @example {"type":"service","id":"my_handler"} * @return \Symfony\Config\Monolog\HandlerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig : static) */ public function handler(string $name, mixed $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig|static { if (!\is_array($value)) { $this->_usedProperties['handlers'] = \true; $this->handlers[$name] = $value; return $this; } if (!isset($this->handlers[$name]) || !$this->handlers[$name] instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig) { $this->_usedProperties['handlers'] = \true; $this->handlers[$name] = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "handler()" has already been initialized. You cannot pass values the second time you call handler().'); } return $this->handlers[$name]; } public function getExtensionAlias() : string { return 'monolog'; } public function __construct(array $value = []) { if (\array_key_exists('use_microseconds', $value)) { $this->_usedProperties['useMicroseconds'] = \true; $this->useMicroseconds = $value['use_microseconds']; unset($value['use_microseconds']); } if (\array_key_exists('channels', $value)) { $this->_usedProperties['channels'] = \true; $this->channels = $value['channels']; unset($value['channels']); } if (\array_key_exists('handlers', $value)) { $this->_usedProperties['handlers'] = \true; $this->handlers = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig($v) : $v, $value['handlers']); unset($value['handlers']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['useMicroseconds'])) { $output['use_microseconds'] = $this->useMicroseconds; } if (isset($this->_usedProperties['channels'])) { $output['channels'] = $this->channels; } if (isset($this->_usedProperties['handlers'])) { $output['handlers'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig ? $v->toArray() : $v, $this->handlers); } return $output; } } _usedProperties['type'] = \true; $this->type = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function id($value) : static { $this->_usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @default 0 * @param ParamConfigurator|mixed $value * @return $this */ public function priority($value) : static { $this->_usedProperties['priority'] = \true; $this->priority = $value; return $this; } /** * @default 'DEBUG' * @param ParamConfigurator|mixed $value * @return $this */ public function level($value) : static { $this->_usedProperties['level'] = \true; $this->level = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function bubble($value) : static { $this->_usedProperties['bubble'] = \true; $this->bubble = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function appName($value) : static { $this->_usedProperties['appName'] = \true; $this->appName = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function fillExtraContext($value) : static { $this->_usedProperties['fillExtraContext'] = \true; $this->fillExtraContext = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function includeStacktraces($value) : static { $this->_usedProperties['includeStacktraces'] = \true; $this->includeStacktraces = $value; return $this; } /** * @template TValue * @param TValue $value * @default {"enabled":null} * @return \Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig : static) */ public function processPsr3Messages(mixed $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig|static { if (!\is_array($value)) { $this->_usedProperties['processPsr3Messages'] = \true; $this->processPsr3Messages = $value; return $this; } if (!$this->processPsr3Messages instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig) { $this->_usedProperties['processPsr3Messages'] = \true; $this->processPsr3Messages = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "processPsr3Messages()" has already been initialized. You cannot pass values the second time you call processPsr3Messages().'); } return $this->processPsr3Messages; } /** * @default '%kernel.logs_dir%/%kernel.environment%.log' * @param ParamConfigurator|mixed $value * @return $this */ public function path($value) : static { $this->_usedProperties['path'] = \true; $this->path = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function filePermission($value) : static { $this->_usedProperties['filePermission'] = \true; $this->filePermission = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function useLocking($value) : static { $this->_usedProperties['useLocking'] = \true; $this->useLocking = $value; return $this; } /** * @default '{filename}-{date}' * @param ParamConfigurator|mixed $value * @return $this */ public function filenameFormat($value) : static { $this->_usedProperties['filenameFormat'] = \true; $this->filenameFormat = $value; return $this; } /** * @default 'Y-m-d' * @param ParamConfigurator|mixed $value * @return $this */ public function dateFormat($value) : static { $this->_usedProperties['dateFormat'] = \true; $this->dateFormat = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function ident($value) : static { $this->_usedProperties['ident'] = \true; $this->ident = $value; return $this; } /** * @default 1 * @param ParamConfigurator|mixed $value * @return $this */ public function logopts($value) : static { $this->_usedProperties['logopts'] = \true; $this->logopts = $value; return $this; } /** * @default 'user' * @param ParamConfigurator|mixed $value * @return $this */ public function facility($value) : static { $this->_usedProperties['facility'] = \true; $this->facility = $value; return $this; } /** * @default 0 * @param ParamConfigurator|mixed $value * @return $this */ public function maxFiles($value) : static { $this->_usedProperties['maxFiles'] = \true; $this->maxFiles = $value; return $this; } /** * @default 'WARNING' * @param ParamConfigurator|mixed $value * @return $this */ public function actionLevel($value) : static { $this->_usedProperties['actionLevel'] = \true; $this->actionLevel = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function activationStrategy($value) : static { $this->_usedProperties['activationStrategy'] = \true; $this->activationStrategy = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function stopBuffering($value) : static { $this->_usedProperties['stopBuffering'] = \true; $this->stopBuffering = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function passthruLevel($value) : static { $this->_usedProperties['passthruLevel'] = \true; $this->passthruLevel = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function excluded404s(ParamConfigurator|array $value) : static { $this->_usedProperties['excluded404s'] = \true; $this->excluded404s = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig : static) */ public function excludedHttpCode(mixed $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig|static { $this->_usedProperties['excludedHttpCodes'] = \true; if (!\is_array($value)) { $this->excludedHttpCodes[] = $value; return $this; } return $this->excludedHttpCodes[] = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig($value); } /** * @param ParamConfigurator|list $value * * @return $this */ public function acceptedLevels(ParamConfigurator|array $value) : static { $this->_usedProperties['acceptedLevels'] = \true; $this->acceptedLevels = $value; return $this; } /** * @default 'DEBUG' * @param ParamConfigurator|mixed $value * @return $this */ public function minLevel($value) : static { $this->_usedProperties['minLevel'] = \true; $this->minLevel = $value; return $this; } /** * @default 'EMERGENCY' * @param ParamConfigurator|mixed $value * @return $this */ public function maxLevel($value) : static { $this->_usedProperties['maxLevel'] = \true; $this->maxLevel = $value; return $this; } /** * @default 0 * @param ParamConfigurator|mixed $value * @return $this */ public function bufferSize($value) : static { $this->_usedProperties['bufferSize'] = \true; $this->bufferSize = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function flushOnOverflow($value) : static { $this->_usedProperties['flushOnOverflow'] = \true; $this->flushOnOverflow = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function handler($value) : static { $this->_usedProperties['handler'] = \true; $this->handler = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function url($value) : static { $this->_usedProperties['url'] = \true; $this->url = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function exchange($value) : static { $this->_usedProperties['exchange'] = \true; $this->exchange = $value; return $this; } /** * @default 'log' * @param ParamConfigurator|mixed $value * @return $this */ public function exchangeName($value) : static { $this->_usedProperties['exchangeName'] = \true; $this->exchangeName = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function room($value) : static { $this->_usedProperties['room'] = \true; $this->room = $value; return $this; } /** * @default 'text' * @param ParamConfigurator|mixed $value * @return $this */ public function messageFormat($value) : static { $this->_usedProperties['messageFormat'] = \true; $this->messageFormat = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function apiVersion($value) : static { $this->_usedProperties['apiVersion'] = \true; $this->apiVersion = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function channel($value) : static { $this->_usedProperties['channel'] = \true; $this->channel = $value; return $this; } /** * @default 'Monolog' * @param ParamConfigurator|mixed $value * @return $this */ public function botName($value) : static { $this->_usedProperties['botName'] = \true; $this->botName = $value; return $this; } /** * @default true * @param ParamConfigurator|mixed $value * @return $this */ public function useAttachment($value) : static { $this->_usedProperties['useAttachment'] = \true; $this->useAttachment = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function useShortAttachment($value) : static { $this->_usedProperties['useShortAttachment'] = \true; $this->useShortAttachment = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function includeExtra($value) : static { $this->_usedProperties['includeExtra'] = \true; $this->includeExtra = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function iconEmoji($value) : static { $this->_usedProperties['iconEmoji'] = \true; $this->iconEmoji = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function webhookUrl($value) : static { $this->_usedProperties['webhookUrl'] = \true; $this->webhookUrl = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function team($value) : static { $this->_usedProperties['team'] = \true; $this->team = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function notify($value) : static { $this->_usedProperties['notify'] = \true; $this->notify = $value; return $this; } /** * @default 'Monolog' * @param ParamConfigurator|mixed $value * @return $this */ public function nickname($value) : static { $this->_usedProperties['nickname'] = \true; $this->nickname = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function token($value) : static { $this->_usedProperties['token'] = \true; $this->token = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function region($value) : static { $this->_usedProperties['region'] = \true; $this->region = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function source($value) : static { $this->_usedProperties['source'] = \true; $this->source = $value; return $this; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function useSsl($value) : static { $this->_usedProperties['useSsl'] = \true; $this->useSsl = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * * @return $this */ public function user(mixed $value) : static { $this->_usedProperties['user'] = \true; $this->user = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function title($value) : static { $this->_usedProperties['title'] = \true; $this->title = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function host($value) : static { $this->_usedProperties['host'] = \true; $this->host = $value; return $this; } /** * @default 514 * @param ParamConfigurator|mixed $value * @return $this */ public function port($value) : static { $this->_usedProperties['port'] = \true; $this->port = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function config(ParamConfigurator|array $value) : static { $this->_usedProperties['config'] = \true; $this->config = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function members(ParamConfigurator|array $value) : static { $this->_usedProperties['members'] = \true; $this->members = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function connectionString($value) : static { $this->_usedProperties['connectionString'] = \true; $this->connectionString = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function timeout($value) : static { $this->_usedProperties['timeout'] = \true; $this->timeout = $value; return $this; } /** * @default 60 * @param ParamConfigurator|mixed $value * @return $this */ public function time($value) : static { $this->_usedProperties['time'] = \true; $this->time = $value; return $this; } /** * @default 400 * @param ParamConfigurator|mixed $value * @return $this */ public function deduplicationLevel($value) : static { $this->_usedProperties['deduplicationLevel'] = \true; $this->deduplicationLevel = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function store($value) : static { $this->_usedProperties['store'] = \true; $this->store = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function connectionTimeout($value) : static { $this->_usedProperties['connectionTimeout'] = \true; $this->connectionTimeout = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function persistent($value) : static { $this->_usedProperties['persistent'] = \true; $this->persistent = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function dsn($value) : static { $this->_usedProperties['dsn'] = \true; $this->dsn = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function hubId($value) : static { $this->_usedProperties['hubId'] = \true; $this->hubId = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function clientId($value) : static { $this->_usedProperties['clientId'] = \true; $this->clientId = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function autoLogStacks($value) : static { $this->_usedProperties['autoLogStacks'] = \true; $this->autoLogStacks = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function release($value) : static { $this->_usedProperties['release'] = \true; $this->release = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function environment($value) : static { $this->_usedProperties['environment'] = \true; $this->environment = $value; return $this; } /** * @default 0 * @param ParamConfigurator|mixed $value * @return $this */ public function messageType($value) : static { $this->_usedProperties['messageType'] = \true; $this->messageType = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function parseMode($value) : static { $this->_usedProperties['parseMode'] = \true; $this->parseMode = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function disableWebpagePreview($value) : static { $this->_usedProperties['disableWebpagePreview'] = \true; $this->disableWebpagePreview = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function disableNotification($value) : static { $this->_usedProperties['disableNotification'] = \true; $this->disableNotification = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function splitLongMessages($value) : static { $this->_usedProperties['splitLongMessages'] = \true; $this->splitLongMessages = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function delayBetweenMessages($value) : static { $this->_usedProperties['delayBetweenMessages'] = \true; $this->delayBetweenMessages = $value; return $this; } /** * @default 1 * @param ParamConfigurator|int $value * @return $this */ public function factor($value) : static { $this->_usedProperties['factor'] = \true; $this->factor = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function tags(ParamConfigurator|string|array $value) : static { $this->_usedProperties['tags'] = \true; $this->tags = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @deprecated ".console_formater_options" is deprecated, use ".console_formatter_options" instead. * * @return $this */ public function consoleFormaterOptions(mixed $value) : static { $this->_usedProperties['consoleFormaterOptions'] = \true; $this->consoleFormaterOptions = $value; return $this; } /** * @default array ( ) * @param ParamConfigurator|mixed $value * * @return $this */ public function consoleFormatterOptions(mixed $value = array()) : static { $this->_usedProperties['consoleFormatterOptions'] = \true; $this->consoleFormatterOptions = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function formatter($value) : static { $this->_usedProperties['formatter'] = \true; $this->formatter = $value; return $this; } /** * @default false * @param ParamConfigurator|bool $value * @return $this */ public function nested($value) : static { $this->_usedProperties['nested'] = \true; $this->nested = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\PublisherConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\PublisherConfig : static) */ public function publisher(string|array $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig|static { if (!\is_array($value)) { $this->_usedProperties['publisher'] = \true; $this->publisher = $value; return $this; } if (!$this->publisher instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig) { $this->_usedProperties['publisher'] = \true; $this->publisher = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "publisher()" has already been initialized. You cannot pass values the second time you call publisher().'); } return $this->publisher; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\MongoConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\MongoConfig : static) */ public function mongo(string|array $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig|static { if (!\is_array($value)) { $this->_usedProperties['mongo'] = \true; $this->mongo = $value; return $this; } if (!$this->mongo instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig) { $this->_usedProperties['mongo'] = \true; $this->mongo = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "mongo()" has already been initialized. You cannot pass values the second time you call mongo().'); } return $this->mongo; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig : static) */ public function elasticsearch(string|array $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig|static { if (!\is_array($value)) { $this->_usedProperties['elasticsearch'] = \true; $this->elasticsearch = $value; return $this; } if (!$this->elasticsearch instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig) { $this->_usedProperties['elasticsearch'] = \true; $this->elasticsearch = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "elasticsearch()" has already been initialized. You cannot pass values the second time you call elasticsearch().'); } return $this->elasticsearch; } /** * @default 'monolog' * @param ParamConfigurator|mixed $value * @return $this */ public function index($value) : static { $this->_usedProperties['index'] = \true; $this->index = $value; return $this; } /** * @default 'logs' * @param ParamConfigurator|mixed $value * @return $this */ public function documentType($value) : static { $this->_usedProperties['documentType'] = \true; $this->documentType = $value; return $this; } /** * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function ignoreError($value) : static { $this->_usedProperties['ignoreError'] = \true; $this->ignoreError = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\RedisConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\RedisConfig : static) */ public function redis(string|array $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig|static { if (!\is_array($value)) { $this->_usedProperties['redis'] = \true; $this->redis = $value; return $this; } if (!$this->redis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig) { $this->_usedProperties['redis'] = \true; $this->redis = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "redis()" has already been initialized. You cannot pass values the second time you call redis().'); } return $this->redis; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\PredisConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\PredisConfig : static) */ public function predis(string|array $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig|static { if (!\is_array($value)) { $this->_usedProperties['predis'] = \true; $this->predis = $value; return $this; } if (!$this->predis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig) { $this->_usedProperties['predis'] = \true; $this->predis = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "predis()" has already been initialized. You cannot pass values the second time you call predis().'); } return $this->predis; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function fromEmail($value) : static { $this->_usedProperties['fromEmail'] = \true; $this->fromEmail = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function toEmail(ParamConfigurator|string|array $value) : static { $this->_usedProperties['toEmail'] = \true; $this->toEmail = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function subject($value) : static { $this->_usedProperties['subject'] = \true; $this->subject = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function contentType($value) : static { $this->_usedProperties['contentType'] = \true; $this->contentType = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function headers(ParamConfigurator|array $value) : static { $this->_usedProperties['headers'] = \true; $this->headers = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function mailer($value) : static { $this->_usedProperties['mailer'] = \true; $this->mailer = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig : static) */ public function emailPrototype(string|array $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig|static { if (!\is_array($value)) { $this->_usedProperties['emailPrototype'] = \true; $this->emailPrototype = $value; return $this; } if (!$this->emailPrototype instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig) { $this->_usedProperties['emailPrototype'] = \true; $this->emailPrototype = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "emailPrototype()" has already been initialized. You cannot pass values the second time you call emailPrototype().'); } return $this->emailPrototype; } /** * @default true * @param ParamConfigurator|bool $value * @return $this */ public function lazy($value) : static { $this->_usedProperties['lazy'] = \true; $this->lazy = $value; return $this; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig : static) */ public function verbosityLevels(array $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig|static { if (!\is_array($value)) { $this->_usedProperties['verbosityLevels'] = \true; $this->verbosityLevels = $value; return $this; } if (!$this->verbosityLevels instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig) { $this->_usedProperties['verbosityLevels'] = \true; $this->verbosityLevels = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "verbosityLevels()" has already been initialized. You cannot pass values the second time you call verbosityLevels().'); } return $this->verbosityLevels; } /** * @template TValue * @param TValue $value * @return \Symfony\Config\Monolog\HandlerConfig\ChannelsConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Monolog\HandlerConfig\ChannelsConfig : static) */ public function channels(mixed $value = []) : \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig|static { if (!\is_array($value)) { $this->_usedProperties['channels'] = \true; $this->channels = $value; return $this; } if (!$this->channels instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig) { $this->_usedProperties['channels'] = \true; $this->channels = new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "channels()" has already been initialized. You cannot pass values the second time you call channels().'); } return $this->channels; } public function __construct(array $value = []) { if (\array_key_exists('type', $value)) { $this->_usedProperties['type'] = \true; $this->type = $value['type']; unset($value['type']); } if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('priority', $value)) { $this->_usedProperties['priority'] = \true; $this->priority = $value['priority']; unset($value['priority']); } if (\array_key_exists('level', $value)) { $this->_usedProperties['level'] = \true; $this->level = $value['level']; unset($value['level']); } if (\array_key_exists('bubble', $value)) { $this->_usedProperties['bubble'] = \true; $this->bubble = $value['bubble']; unset($value['bubble']); } if (\array_key_exists('app_name', $value)) { $this->_usedProperties['appName'] = \true; $this->appName = $value['app_name']; unset($value['app_name']); } if (\array_key_exists('fill_extra_context', $value)) { $this->_usedProperties['fillExtraContext'] = \true; $this->fillExtraContext = $value['fill_extra_context']; unset($value['fill_extra_context']); } if (\array_key_exists('include_stacktraces', $value)) { $this->_usedProperties['includeStacktraces'] = \true; $this->includeStacktraces = $value['include_stacktraces']; unset($value['include_stacktraces']); } if (\array_key_exists('process_psr_3_messages', $value)) { $this->_usedProperties['processPsr3Messages'] = \true; $this->processPsr3Messages = \is_array($value['process_psr_3_messages']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig($value['process_psr_3_messages']) : $value['process_psr_3_messages']; unset($value['process_psr_3_messages']); } if (\array_key_exists('path', $value)) { $this->_usedProperties['path'] = \true; $this->path = $value['path']; unset($value['path']); } if (\array_key_exists('file_permission', $value)) { $this->_usedProperties['filePermission'] = \true; $this->filePermission = $value['file_permission']; unset($value['file_permission']); } if (\array_key_exists('use_locking', $value)) { $this->_usedProperties['useLocking'] = \true; $this->useLocking = $value['use_locking']; unset($value['use_locking']); } if (\array_key_exists('filename_format', $value)) { $this->_usedProperties['filenameFormat'] = \true; $this->filenameFormat = $value['filename_format']; unset($value['filename_format']); } if (\array_key_exists('date_format', $value)) { $this->_usedProperties['dateFormat'] = \true; $this->dateFormat = $value['date_format']; unset($value['date_format']); } if (\array_key_exists('ident', $value)) { $this->_usedProperties['ident'] = \true; $this->ident = $value['ident']; unset($value['ident']); } if (\array_key_exists('logopts', $value)) { $this->_usedProperties['logopts'] = \true; $this->logopts = $value['logopts']; unset($value['logopts']); } if (\array_key_exists('facility', $value)) { $this->_usedProperties['facility'] = \true; $this->facility = $value['facility']; unset($value['facility']); } if (\array_key_exists('max_files', $value)) { $this->_usedProperties['maxFiles'] = \true; $this->maxFiles = $value['max_files']; unset($value['max_files']); } if (\array_key_exists('action_level', $value)) { $this->_usedProperties['actionLevel'] = \true; $this->actionLevel = $value['action_level']; unset($value['action_level']); } if (\array_key_exists('activation_strategy', $value)) { $this->_usedProperties['activationStrategy'] = \true; $this->activationStrategy = $value['activation_strategy']; unset($value['activation_strategy']); } if (\array_key_exists('stop_buffering', $value)) { $this->_usedProperties['stopBuffering'] = \true; $this->stopBuffering = $value['stop_buffering']; unset($value['stop_buffering']); } if (\array_key_exists('passthru_level', $value)) { $this->_usedProperties['passthruLevel'] = \true; $this->passthruLevel = $value['passthru_level']; unset($value['passthru_level']); } if (\array_key_exists('excluded_404s', $value)) { $this->_usedProperties['excluded404s'] = \true; $this->excluded404s = $value['excluded_404s']; unset($value['excluded_404s']); } if (\array_key_exists('excluded_http_codes', $value)) { $this->_usedProperties['excludedHttpCodes'] = \true; $this->excludedHttpCodes = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig($v) : $v, $value['excluded_http_codes']); unset($value['excluded_http_codes']); } if (\array_key_exists('accepted_levels', $value)) { $this->_usedProperties['acceptedLevels'] = \true; $this->acceptedLevels = $value['accepted_levels']; unset($value['accepted_levels']); } if (\array_key_exists('min_level', $value)) { $this->_usedProperties['minLevel'] = \true; $this->minLevel = $value['min_level']; unset($value['min_level']); } if (\array_key_exists('max_level', $value)) { $this->_usedProperties['maxLevel'] = \true; $this->maxLevel = $value['max_level']; unset($value['max_level']); } if (\array_key_exists('buffer_size', $value)) { $this->_usedProperties['bufferSize'] = \true; $this->bufferSize = $value['buffer_size']; unset($value['buffer_size']); } if (\array_key_exists('flush_on_overflow', $value)) { $this->_usedProperties['flushOnOverflow'] = \true; $this->flushOnOverflow = $value['flush_on_overflow']; unset($value['flush_on_overflow']); } if (\array_key_exists('handler', $value)) { $this->_usedProperties['handler'] = \true; $this->handler = $value['handler']; unset($value['handler']); } if (\array_key_exists('url', $value)) { $this->_usedProperties['url'] = \true; $this->url = $value['url']; unset($value['url']); } if (\array_key_exists('exchange', $value)) { $this->_usedProperties['exchange'] = \true; $this->exchange = $value['exchange']; unset($value['exchange']); } if (\array_key_exists('exchange_name', $value)) { $this->_usedProperties['exchangeName'] = \true; $this->exchangeName = $value['exchange_name']; unset($value['exchange_name']); } if (\array_key_exists('room', $value)) { $this->_usedProperties['room'] = \true; $this->room = $value['room']; unset($value['room']); } if (\array_key_exists('message_format', $value)) { $this->_usedProperties['messageFormat'] = \true; $this->messageFormat = $value['message_format']; unset($value['message_format']); } if (\array_key_exists('api_version', $value)) { $this->_usedProperties['apiVersion'] = \true; $this->apiVersion = $value['api_version']; unset($value['api_version']); } if (\array_key_exists('channel', $value)) { $this->_usedProperties['channel'] = \true; $this->channel = $value['channel']; unset($value['channel']); } if (\array_key_exists('bot_name', $value)) { $this->_usedProperties['botName'] = \true; $this->botName = $value['bot_name']; unset($value['bot_name']); } if (\array_key_exists('use_attachment', $value)) { $this->_usedProperties['useAttachment'] = \true; $this->useAttachment = $value['use_attachment']; unset($value['use_attachment']); } if (\array_key_exists('use_short_attachment', $value)) { $this->_usedProperties['useShortAttachment'] = \true; $this->useShortAttachment = $value['use_short_attachment']; unset($value['use_short_attachment']); } if (\array_key_exists('include_extra', $value)) { $this->_usedProperties['includeExtra'] = \true; $this->includeExtra = $value['include_extra']; unset($value['include_extra']); } if (\array_key_exists('icon_emoji', $value)) { $this->_usedProperties['iconEmoji'] = \true; $this->iconEmoji = $value['icon_emoji']; unset($value['icon_emoji']); } if (\array_key_exists('webhook_url', $value)) { $this->_usedProperties['webhookUrl'] = \true; $this->webhookUrl = $value['webhook_url']; unset($value['webhook_url']); } if (\array_key_exists('team', $value)) { $this->_usedProperties['team'] = \true; $this->team = $value['team']; unset($value['team']); } if (\array_key_exists('notify', $value)) { $this->_usedProperties['notify'] = \true; $this->notify = $value['notify']; unset($value['notify']); } if (\array_key_exists('nickname', $value)) { $this->_usedProperties['nickname'] = \true; $this->nickname = $value['nickname']; unset($value['nickname']); } if (\array_key_exists('token', $value)) { $this->_usedProperties['token'] = \true; $this->token = $value['token']; unset($value['token']); } if (\array_key_exists('region', $value)) { $this->_usedProperties['region'] = \true; $this->region = $value['region']; unset($value['region']); } if (\array_key_exists('source', $value)) { $this->_usedProperties['source'] = \true; $this->source = $value['source']; unset($value['source']); } if (\array_key_exists('use_ssl', $value)) { $this->_usedProperties['useSsl'] = \true; $this->useSsl = $value['use_ssl']; unset($value['use_ssl']); } if (\array_key_exists('user', $value)) { $this->_usedProperties['user'] = \true; $this->user = $value['user']; unset($value['user']); } if (\array_key_exists('title', $value)) { $this->_usedProperties['title'] = \true; $this->title = $value['title']; unset($value['title']); } if (\array_key_exists('host', $value)) { $this->_usedProperties['host'] = \true; $this->host = $value['host']; unset($value['host']); } if (\array_key_exists('port', $value)) { $this->_usedProperties['port'] = \true; $this->port = $value['port']; unset($value['port']); } if (\array_key_exists('config', $value)) { $this->_usedProperties['config'] = \true; $this->config = $value['config']; unset($value['config']); } if (\array_key_exists('members', $value)) { $this->_usedProperties['members'] = \true; $this->members = $value['members']; unset($value['members']); } if (\array_key_exists('connection_string', $value)) { $this->_usedProperties['connectionString'] = \true; $this->connectionString = $value['connection_string']; unset($value['connection_string']); } if (\array_key_exists('timeout', $value)) { $this->_usedProperties['timeout'] = \true; $this->timeout = $value['timeout']; unset($value['timeout']); } if (\array_key_exists('time', $value)) { $this->_usedProperties['time'] = \true; $this->time = $value['time']; unset($value['time']); } if (\array_key_exists('deduplication_level', $value)) { $this->_usedProperties['deduplicationLevel'] = \true; $this->deduplicationLevel = $value['deduplication_level']; unset($value['deduplication_level']); } if (\array_key_exists('store', $value)) { $this->_usedProperties['store'] = \true; $this->store = $value['store']; unset($value['store']); } if (\array_key_exists('connection_timeout', $value)) { $this->_usedProperties['connectionTimeout'] = \true; $this->connectionTimeout = $value['connection_timeout']; unset($value['connection_timeout']); } if (\array_key_exists('persistent', $value)) { $this->_usedProperties['persistent'] = \true; $this->persistent = $value['persistent']; unset($value['persistent']); } if (\array_key_exists('dsn', $value)) { $this->_usedProperties['dsn'] = \true; $this->dsn = $value['dsn']; unset($value['dsn']); } if (\array_key_exists('hub_id', $value)) { $this->_usedProperties['hubId'] = \true; $this->hubId = $value['hub_id']; unset($value['hub_id']); } if (\array_key_exists('client_id', $value)) { $this->_usedProperties['clientId'] = \true; $this->clientId = $value['client_id']; unset($value['client_id']); } if (\array_key_exists('auto_log_stacks', $value)) { $this->_usedProperties['autoLogStacks'] = \true; $this->autoLogStacks = $value['auto_log_stacks']; unset($value['auto_log_stacks']); } if (\array_key_exists('release', $value)) { $this->_usedProperties['release'] = \true; $this->release = $value['release']; unset($value['release']); } if (\array_key_exists('environment', $value)) { $this->_usedProperties['environment'] = \true; $this->environment = $value['environment']; unset($value['environment']); } if (\array_key_exists('message_type', $value)) { $this->_usedProperties['messageType'] = \true; $this->messageType = $value['message_type']; unset($value['message_type']); } if (\array_key_exists('parse_mode', $value)) { $this->_usedProperties['parseMode'] = \true; $this->parseMode = $value['parse_mode']; unset($value['parse_mode']); } if (\array_key_exists('disable_webpage_preview', $value)) { $this->_usedProperties['disableWebpagePreview'] = \true; $this->disableWebpagePreview = $value['disable_webpage_preview']; unset($value['disable_webpage_preview']); } if (\array_key_exists('disable_notification', $value)) { $this->_usedProperties['disableNotification'] = \true; $this->disableNotification = $value['disable_notification']; unset($value['disable_notification']); } if (\array_key_exists('split_long_messages', $value)) { $this->_usedProperties['splitLongMessages'] = \true; $this->splitLongMessages = $value['split_long_messages']; unset($value['split_long_messages']); } if (\array_key_exists('delay_between_messages', $value)) { $this->_usedProperties['delayBetweenMessages'] = \true; $this->delayBetweenMessages = $value['delay_between_messages']; unset($value['delay_between_messages']); } if (\array_key_exists('factor', $value)) { $this->_usedProperties['factor'] = \true; $this->factor = $value['factor']; unset($value['factor']); } if (\array_key_exists('tags', $value)) { $this->_usedProperties['tags'] = \true; $this->tags = $value['tags']; unset($value['tags']); } if (\array_key_exists('console_formater_options', $value)) { $this->_usedProperties['consoleFormaterOptions'] = \true; $this->consoleFormaterOptions = $value['console_formater_options']; unset($value['console_formater_options']); } if (\array_key_exists('console_formatter_options', $value)) { $this->_usedProperties['consoleFormatterOptions'] = \true; $this->consoleFormatterOptions = $value['console_formatter_options']; unset($value['console_formatter_options']); } if (\array_key_exists('formatter', $value)) { $this->_usedProperties['formatter'] = \true; $this->formatter = $value['formatter']; unset($value['formatter']); } if (\array_key_exists('nested', $value)) { $this->_usedProperties['nested'] = \true; $this->nested = $value['nested']; unset($value['nested']); } if (\array_key_exists('publisher', $value)) { $this->_usedProperties['publisher'] = \true; $this->publisher = \is_array($value['publisher']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig($value['publisher']) : $value['publisher']; unset($value['publisher']); } if (\array_key_exists('mongo', $value)) { $this->_usedProperties['mongo'] = \true; $this->mongo = \is_array($value['mongo']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig($value['mongo']) : $value['mongo']; unset($value['mongo']); } if (\array_key_exists('elasticsearch', $value)) { $this->_usedProperties['elasticsearch'] = \true; $this->elasticsearch = \is_array($value['elasticsearch']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig($value['elasticsearch']) : $value['elasticsearch']; unset($value['elasticsearch']); } if (\array_key_exists('index', $value)) { $this->_usedProperties['index'] = \true; $this->index = $value['index']; unset($value['index']); } if (\array_key_exists('document_type', $value)) { $this->_usedProperties['documentType'] = \true; $this->documentType = $value['document_type']; unset($value['document_type']); } if (\array_key_exists('ignore_error', $value)) { $this->_usedProperties['ignoreError'] = \true; $this->ignoreError = $value['ignore_error']; unset($value['ignore_error']); } if (\array_key_exists('redis', $value)) { $this->_usedProperties['redis'] = \true; $this->redis = \is_array($value['redis']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig($value['redis']) : $value['redis']; unset($value['redis']); } if (\array_key_exists('predis', $value)) { $this->_usedProperties['predis'] = \true; $this->predis = \is_array($value['predis']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig($value['predis']) : $value['predis']; unset($value['predis']); } if (\array_key_exists('from_email', $value)) { $this->_usedProperties['fromEmail'] = \true; $this->fromEmail = $value['from_email']; unset($value['from_email']); } if (\array_key_exists('to_email', $value)) { $this->_usedProperties['toEmail'] = \true; $this->toEmail = $value['to_email']; unset($value['to_email']); } if (\array_key_exists('subject', $value)) { $this->_usedProperties['subject'] = \true; $this->subject = $value['subject']; unset($value['subject']); } if (\array_key_exists('content_type', $value)) { $this->_usedProperties['contentType'] = \true; $this->contentType = $value['content_type']; unset($value['content_type']); } if (\array_key_exists('headers', $value)) { $this->_usedProperties['headers'] = \true; $this->headers = $value['headers']; unset($value['headers']); } if (\array_key_exists('mailer', $value)) { $this->_usedProperties['mailer'] = \true; $this->mailer = $value['mailer']; unset($value['mailer']); } if (\array_key_exists('email_prototype', $value)) { $this->_usedProperties['emailPrototype'] = \true; $this->emailPrototype = \is_array($value['email_prototype']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig($value['email_prototype']) : $value['email_prototype']; unset($value['email_prototype']); } if (\array_key_exists('lazy', $value)) { $this->_usedProperties['lazy'] = \true; $this->lazy = $value['lazy']; unset($value['lazy']); } if (\array_key_exists('verbosity_levels', $value)) { $this->_usedProperties['verbosityLevels'] = \true; $this->verbosityLevels = \is_array($value['verbosity_levels']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig($value['verbosity_levels']) : $value['verbosity_levels']; unset($value['verbosity_levels']); } if (\array_key_exists('channels', $value)) { $this->_usedProperties['channels'] = \true; $this->channels = \is_array($value['channels']) ? new \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig($value['channels']) : $value['channels']; unset($value['channels']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['type'])) { $output['type'] = $this->type; } if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['priority'])) { $output['priority'] = $this->priority; } if (isset($this->_usedProperties['level'])) { $output['level'] = $this->level; } if (isset($this->_usedProperties['bubble'])) { $output['bubble'] = $this->bubble; } if (isset($this->_usedProperties['appName'])) { $output['app_name'] = $this->appName; } if (isset($this->_usedProperties['fillExtraContext'])) { $output['fill_extra_context'] = $this->fillExtraContext; } if (isset($this->_usedProperties['includeStacktraces'])) { $output['include_stacktraces'] = $this->includeStacktraces; } if (isset($this->_usedProperties['processPsr3Messages'])) { $output['process_psr_3_messages'] = $this->processPsr3Messages instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ProcessPsr3MessagesConfig ? $this->processPsr3Messages->toArray() : $this->processPsr3Messages; } if (isset($this->_usedProperties['path'])) { $output['path'] = $this->path; } if (isset($this->_usedProperties['filePermission'])) { $output['file_permission'] = $this->filePermission; } if (isset($this->_usedProperties['useLocking'])) { $output['use_locking'] = $this->useLocking; } if (isset($this->_usedProperties['filenameFormat'])) { $output['filename_format'] = $this->filenameFormat; } if (isset($this->_usedProperties['dateFormat'])) { $output['date_format'] = $this->dateFormat; } if (isset($this->_usedProperties['ident'])) { $output['ident'] = $this->ident; } if (isset($this->_usedProperties['logopts'])) { $output['logopts'] = $this->logopts; } if (isset($this->_usedProperties['facility'])) { $output['facility'] = $this->facility; } if (isset($this->_usedProperties['maxFiles'])) { $output['max_files'] = $this->maxFiles; } if (isset($this->_usedProperties['actionLevel'])) { $output['action_level'] = $this->actionLevel; } if (isset($this->_usedProperties['activationStrategy'])) { $output['activation_strategy'] = $this->activationStrategy; } if (isset($this->_usedProperties['stopBuffering'])) { $output['stop_buffering'] = $this->stopBuffering; } if (isset($this->_usedProperties['passthruLevel'])) { $output['passthru_level'] = $this->passthruLevel; } if (isset($this->_usedProperties['excluded404s'])) { $output['excluded_404s'] = $this->excluded404s; } if (isset($this->_usedProperties['excludedHttpCodes'])) { $output['excluded_http_codes'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ExcludedHttpCodeConfig ? $v->toArray() : $v, $this->excludedHttpCodes); } if (isset($this->_usedProperties['acceptedLevels'])) { $output['accepted_levels'] = $this->acceptedLevels; } if (isset($this->_usedProperties['minLevel'])) { $output['min_level'] = $this->minLevel; } if (isset($this->_usedProperties['maxLevel'])) { $output['max_level'] = $this->maxLevel; } if (isset($this->_usedProperties['bufferSize'])) { $output['buffer_size'] = $this->bufferSize; } if (isset($this->_usedProperties['flushOnOverflow'])) { $output['flush_on_overflow'] = $this->flushOnOverflow; } if (isset($this->_usedProperties['handler'])) { $output['handler'] = $this->handler; } if (isset($this->_usedProperties['url'])) { $output['url'] = $this->url; } if (isset($this->_usedProperties['exchange'])) { $output['exchange'] = $this->exchange; } if (isset($this->_usedProperties['exchangeName'])) { $output['exchange_name'] = $this->exchangeName; } if (isset($this->_usedProperties['room'])) { $output['room'] = $this->room; } if (isset($this->_usedProperties['messageFormat'])) { $output['message_format'] = $this->messageFormat; } if (isset($this->_usedProperties['apiVersion'])) { $output['api_version'] = $this->apiVersion; } if (isset($this->_usedProperties['channel'])) { $output['channel'] = $this->channel; } if (isset($this->_usedProperties['botName'])) { $output['bot_name'] = $this->botName; } if (isset($this->_usedProperties['useAttachment'])) { $output['use_attachment'] = $this->useAttachment; } if (isset($this->_usedProperties['useShortAttachment'])) { $output['use_short_attachment'] = $this->useShortAttachment; } if (isset($this->_usedProperties['includeExtra'])) { $output['include_extra'] = $this->includeExtra; } if (isset($this->_usedProperties['iconEmoji'])) { $output['icon_emoji'] = $this->iconEmoji; } if (isset($this->_usedProperties['webhookUrl'])) { $output['webhook_url'] = $this->webhookUrl; } if (isset($this->_usedProperties['team'])) { $output['team'] = $this->team; } if (isset($this->_usedProperties['notify'])) { $output['notify'] = $this->notify; } if (isset($this->_usedProperties['nickname'])) { $output['nickname'] = $this->nickname; } if (isset($this->_usedProperties['token'])) { $output['token'] = $this->token; } if (isset($this->_usedProperties['region'])) { $output['region'] = $this->region; } if (isset($this->_usedProperties['source'])) { $output['source'] = $this->source; } if (isset($this->_usedProperties['useSsl'])) { $output['use_ssl'] = $this->useSsl; } if (isset($this->_usedProperties['user'])) { $output['user'] = $this->user; } if (isset($this->_usedProperties['title'])) { $output['title'] = $this->title; } if (isset($this->_usedProperties['host'])) { $output['host'] = $this->host; } if (isset($this->_usedProperties['port'])) { $output['port'] = $this->port; } if (isset($this->_usedProperties['config'])) { $output['config'] = $this->config; } if (isset($this->_usedProperties['members'])) { $output['members'] = $this->members; } if (isset($this->_usedProperties['connectionString'])) { $output['connection_string'] = $this->connectionString; } if (isset($this->_usedProperties['timeout'])) { $output['timeout'] = $this->timeout; } if (isset($this->_usedProperties['time'])) { $output['time'] = $this->time; } if (isset($this->_usedProperties['deduplicationLevel'])) { $output['deduplication_level'] = $this->deduplicationLevel; } if (isset($this->_usedProperties['store'])) { $output['store'] = $this->store; } if (isset($this->_usedProperties['connectionTimeout'])) { $output['connection_timeout'] = $this->connectionTimeout; } if (isset($this->_usedProperties['persistent'])) { $output['persistent'] = $this->persistent; } if (isset($this->_usedProperties['dsn'])) { $output['dsn'] = $this->dsn; } if (isset($this->_usedProperties['hubId'])) { $output['hub_id'] = $this->hubId; } if (isset($this->_usedProperties['clientId'])) { $output['client_id'] = $this->clientId; } if (isset($this->_usedProperties['autoLogStacks'])) { $output['auto_log_stacks'] = $this->autoLogStacks; } if (isset($this->_usedProperties['release'])) { $output['release'] = $this->release; } if (isset($this->_usedProperties['environment'])) { $output['environment'] = $this->environment; } if (isset($this->_usedProperties['messageType'])) { $output['message_type'] = $this->messageType; } if (isset($this->_usedProperties['parseMode'])) { $output['parse_mode'] = $this->parseMode; } if (isset($this->_usedProperties['disableWebpagePreview'])) { $output['disable_webpage_preview'] = $this->disableWebpagePreview; } if (isset($this->_usedProperties['disableNotification'])) { $output['disable_notification'] = $this->disableNotification; } if (isset($this->_usedProperties['splitLongMessages'])) { $output['split_long_messages'] = $this->splitLongMessages; } if (isset($this->_usedProperties['delayBetweenMessages'])) { $output['delay_between_messages'] = $this->delayBetweenMessages; } if (isset($this->_usedProperties['factor'])) { $output['factor'] = $this->factor; } if (isset($this->_usedProperties['tags'])) { $output['tags'] = $this->tags; } if (isset($this->_usedProperties['consoleFormaterOptions'])) { $output['console_formater_options'] = $this->consoleFormaterOptions; } if (isset($this->_usedProperties['consoleFormatterOptions'])) { $output['console_formatter_options'] = $this->consoleFormatterOptions; } if (isset($this->_usedProperties['formatter'])) { $output['formatter'] = $this->formatter; } if (isset($this->_usedProperties['nested'])) { $output['nested'] = $this->nested; } if (isset($this->_usedProperties['publisher'])) { $output['publisher'] = $this->publisher instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PublisherConfig ? $this->publisher->toArray() : $this->publisher; } if (isset($this->_usedProperties['mongo'])) { $output['mongo'] = $this->mongo instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\MongoConfig ? $this->mongo->toArray() : $this->mongo; } if (isset($this->_usedProperties['elasticsearch'])) { $output['elasticsearch'] = $this->elasticsearch instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ElasticsearchConfig ? $this->elasticsearch->toArray() : $this->elasticsearch; } if (isset($this->_usedProperties['index'])) { $output['index'] = $this->index; } if (isset($this->_usedProperties['documentType'])) { $output['document_type'] = $this->documentType; } if (isset($this->_usedProperties['ignoreError'])) { $output['ignore_error'] = $this->ignoreError; } if (isset($this->_usedProperties['redis'])) { $output['redis'] = $this->redis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\RedisConfig ? $this->redis->toArray() : $this->redis; } if (isset($this->_usedProperties['predis'])) { $output['predis'] = $this->predis instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\PredisConfig ? $this->predis->toArray() : $this->predis; } if (isset($this->_usedProperties['fromEmail'])) { $output['from_email'] = $this->fromEmail; } if (isset($this->_usedProperties['toEmail'])) { $output['to_email'] = $this->toEmail; } if (isset($this->_usedProperties['subject'])) { $output['subject'] = $this->subject; } if (isset($this->_usedProperties['contentType'])) { $output['content_type'] = $this->contentType; } if (isset($this->_usedProperties['headers'])) { $output['headers'] = $this->headers; } if (isset($this->_usedProperties['mailer'])) { $output['mailer'] = $this->mailer; } if (isset($this->_usedProperties['emailPrototype'])) { $output['email_prototype'] = $this->emailPrototype instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\EmailPrototypeConfig ? $this->emailPrototype->toArray() : $this->emailPrototype; } if (isset($this->_usedProperties['lazy'])) { $output['lazy'] = $this->lazy; } if (isset($this->_usedProperties['verbosityLevels'])) { $output['verbosity_levels'] = $this->verbosityLevels instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\VerbosityLevelsConfig ? $this->verbosityLevels->toArray() : $this->verbosityLevels; } if (isset($this->_usedProperties['channels'])) { $output['channels'] = $this->channels instanceof \_ContaoManager\Symfony\Config\Monolog\HandlerConfig\ChannelsConfig ? $this->channels->toArray() : $this->channels; } return $output; } } _usedProperties['enabled'] = \true; $this->enabled = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function dateFormat($value) : static { $this->_usedProperties['dateFormat'] = \true; $this->dateFormat = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function removeUsedContextFields($value) : static { $this->_usedProperties['removeUsedContextFields'] = \true; $this->removeUsedContextFields = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('enabled', $value)) { $this->_usedProperties['enabled'] = \true; $this->enabled = $value['enabled']; unset($value['enabled']); } if (\array_key_exists('date_format', $value)) { $this->_usedProperties['dateFormat'] = \true; $this->dateFormat = $value['date_format']; unset($value['date_format']); } if (\array_key_exists('remove_used_context_fields', $value)) { $this->_usedProperties['removeUsedContextFields'] = \true; $this->removeUsedContextFields = $value['remove_used_context_fields']; unset($value['remove_used_context_fields']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['enabled'])) { $output['enabled'] = $this->enabled; } if (isset($this->_usedProperties['dateFormat'])) { $output['date_format'] = $this->dateFormat; } if (isset($this->_usedProperties['removeUsedContextFields'])) { $output['remove_used_context_fields'] = $this->removeUsedContextFields; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function hostname($value) : static { $this->_usedProperties['hostname'] = \true; $this->hostname = $value; return $this; } /** * @default 12201 * @param ParamConfigurator|mixed $value * @return $this */ public function port($value) : static { $this->_usedProperties['port'] = \true; $this->port = $value; return $this; } /** * @default 1420 * @param ParamConfigurator|mixed $value * @return $this */ public function chunkSize($value) : static { $this->_usedProperties['chunkSize'] = \true; $this->chunkSize = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('hostname', $value)) { $this->_usedProperties['hostname'] = \true; $this->hostname = $value['hostname']; unset($value['hostname']); } if (\array_key_exists('port', $value)) { $this->_usedProperties['port'] = \true; $this->port = $value['port']; unset($value['port']); } if (\array_key_exists('chunk_size', $value)) { $this->_usedProperties['chunkSize'] = \true; $this->chunkSize = $value['chunk_size']; unset($value['chunk_size']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['hostname'])) { $output['hostname'] = $this->hostname; } if (isset($this->_usedProperties['port'])) { $output['port'] = $this->port; } if (isset($this->_usedProperties['chunkSize'])) { $output['chunk_size'] = $this->chunkSize; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function host($value) : static { $this->_usedProperties['host'] = \true; $this->host = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function password($value) : static { $this->_usedProperties['password'] = \true; $this->password = $value; return $this; } /** * @default 6379 * @param ParamConfigurator|mixed $value * @return $this */ public function port($value) : static { $this->_usedProperties['port'] = \true; $this->port = $value; return $this; } /** * @default 0 * @param ParamConfigurator|mixed $value * @return $this */ public function database($value) : static { $this->_usedProperties['database'] = \true; $this->database = $value; return $this; } /** * @default 'monolog_redis' * @param ParamConfigurator|mixed $value * @return $this */ public function keyName($value) : static { $this->_usedProperties['keyName'] = \true; $this->keyName = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('host', $value)) { $this->_usedProperties['host'] = \true; $this->host = $value['host']; unset($value['host']); } if (\array_key_exists('password', $value)) { $this->_usedProperties['password'] = \true; $this->password = $value['password']; unset($value['password']); } if (\array_key_exists('port', $value)) { $this->_usedProperties['port'] = \true; $this->port = $value['port']; unset($value['port']); } if (\array_key_exists('database', $value)) { $this->_usedProperties['database'] = \true; $this->database = $value['database']; unset($value['database']); } if (\array_key_exists('key_name', $value)) { $this->_usedProperties['keyName'] = \true; $this->keyName = $value['key_name']; unset($value['key_name']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['host'])) { $output['host'] = $this->host; } if (isset($this->_usedProperties['password'])) { $output['password'] = $this->password; } if (isset($this->_usedProperties['port'])) { $output['port'] = $this->port; } if (isset($this->_usedProperties['database'])) { $output['database'] = $this->database; } if (isset($this->_usedProperties['keyName'])) { $output['key_name'] = $this->keyName; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function host($value) : static { $this->_usedProperties['host'] = \true; $this->host = $value; return $this; } /** * @default 9200 * @param ParamConfigurator|mixed $value * @return $this */ public function port($value) : static { $this->_usedProperties['port'] = \true; $this->port = $value; return $this; } /** * @default 'Http' * @param ParamConfigurator|mixed $value * @return $this */ public function transport($value) : static { $this->_usedProperties['transport'] = \true; $this->transport = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function user($value) : static { $this->_usedProperties['user'] = \true; $this->user = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function password($value) : static { $this->_usedProperties['password'] = \true; $this->password = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('host', $value)) { $this->_usedProperties['host'] = \true; $this->host = $value['host']; unset($value['host']); } if (\array_key_exists('port', $value)) { $this->_usedProperties['port'] = \true; $this->port = $value['port']; unset($value['port']); } if (\array_key_exists('transport', $value)) { $this->_usedProperties['transport'] = \true; $this->transport = $value['transport']; unset($value['transport']); } if (\array_key_exists('user', $value)) { $this->_usedProperties['user'] = \true; $this->user = $value['user']; unset($value['user']); } if (\array_key_exists('password', $value)) { $this->_usedProperties['password'] = \true; $this->password = $value['password']; unset($value['password']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['host'])) { $output['host'] = $this->host; } if (isset($this->_usedProperties['port'])) { $output['port'] = $this->port; } if (isset($this->_usedProperties['transport'])) { $output['transport'] = $this->transport; } if (isset($this->_usedProperties['user'])) { $output['user'] = $this->user; } if (isset($this->_usedProperties['password'])) { $output['password'] = $this->password; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function method($value) : static { $this->_usedProperties['method'] = \true; $this->method = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('method', $value)) { $this->_usedProperties['method'] = \true; $this->method = $value['method']; unset($value['method']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['method'])) { $output['method'] = $this->method; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function host($value) : static { $this->_usedProperties['host'] = \true; $this->host = $value; return $this; } /** * @default 27017 * @param ParamConfigurator|mixed $value * @return $this */ public function port($value) : static { $this->_usedProperties['port'] = \true; $this->port = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function user($value) : static { $this->_usedProperties['user'] = \true; $this->user = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function pass($value) : static { $this->_usedProperties['pass'] = \true; $this->pass = $value; return $this; } /** * @default 'monolog' * @param ParamConfigurator|mixed $value * @return $this */ public function database($value) : static { $this->_usedProperties['database'] = \true; $this->database = $value; return $this; } /** * @default 'logs' * @param ParamConfigurator|mixed $value * @return $this */ public function collection($value) : static { $this->_usedProperties['collection'] = \true; $this->collection = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('host', $value)) { $this->_usedProperties['host'] = \true; $this->host = $value['host']; unset($value['host']); } if (\array_key_exists('port', $value)) { $this->_usedProperties['port'] = \true; $this->port = $value['port']; unset($value['port']); } if (\array_key_exists('user', $value)) { $this->_usedProperties['user'] = \true; $this->user = $value['user']; unset($value['user']); } if (\array_key_exists('pass', $value)) { $this->_usedProperties['pass'] = \true; $this->pass = $value['pass']; unset($value['pass']); } if (\array_key_exists('database', $value)) { $this->_usedProperties['database'] = \true; $this->database = $value['database']; unset($value['database']); } if (\array_key_exists('collection', $value)) { $this->_usedProperties['collection'] = \true; $this->collection = $value['collection']; unset($value['collection']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['host'])) { $output['host'] = $this->host; } if (isset($this->_usedProperties['port'])) { $output['port'] = $this->port; } if (isset($this->_usedProperties['user'])) { $output['user'] = $this->user; } if (isset($this->_usedProperties['pass'])) { $output['pass'] = $this->pass; } if (isset($this->_usedProperties['database'])) { $output['database'] = $this->database; } if (isset($this->_usedProperties['collection'])) { $output['collection'] = $this->collection; } return $output; } } _usedProperties['vERBOSITYQUIET'] = \true; $this->vERBOSITYQUIET = $value; return $this; } /** * @default 'WARNING' * @param ParamConfigurator|mixed $value * @return $this */ public function vERBOSITYNORMAL($value) : static { $this->_usedProperties['vERBOSITYNORMAL'] = \true; $this->vERBOSITYNORMAL = $value; return $this; } /** * @default 'NOTICE' * @param ParamConfigurator|mixed $value * @return $this */ public function vERBOSITYVERBOSE($value) : static { $this->_usedProperties['vERBOSITYVERBOSE'] = \true; $this->vERBOSITYVERBOSE = $value; return $this; } /** * @default 'INFO' * @param ParamConfigurator|mixed $value * @return $this */ public function vERBOSITYVERYVERBOSE($value) : static { $this->_usedProperties['vERBOSITYVERYVERBOSE'] = \true; $this->vERBOSITYVERYVERBOSE = $value; return $this; } /** * @default 'DEBUG' * @param ParamConfigurator|mixed $value * @return $this */ public function vERBOSITYDEBUG($value) : static { $this->_usedProperties['vERBOSITYDEBUG'] = \true; $this->vERBOSITYDEBUG = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('VERBOSITY_QUIET', $value)) { $this->_usedProperties['vERBOSITYQUIET'] = \true; $this->vERBOSITYQUIET = $value['VERBOSITY_QUIET']; unset($value['VERBOSITY_QUIET']); } if (\array_key_exists('VERBOSITY_NORMAL', $value)) { $this->_usedProperties['vERBOSITYNORMAL'] = \true; $this->vERBOSITYNORMAL = $value['VERBOSITY_NORMAL']; unset($value['VERBOSITY_NORMAL']); } if (\array_key_exists('VERBOSITY_VERBOSE', $value)) { $this->_usedProperties['vERBOSITYVERBOSE'] = \true; $this->vERBOSITYVERBOSE = $value['VERBOSITY_VERBOSE']; unset($value['VERBOSITY_VERBOSE']); } if (\array_key_exists('VERBOSITY_VERY_VERBOSE', $value)) { $this->_usedProperties['vERBOSITYVERYVERBOSE'] = \true; $this->vERBOSITYVERYVERBOSE = $value['VERBOSITY_VERY_VERBOSE']; unset($value['VERBOSITY_VERY_VERBOSE']); } if (\array_key_exists('VERBOSITY_DEBUG', $value)) { $this->_usedProperties['vERBOSITYDEBUG'] = \true; $this->vERBOSITYDEBUG = $value['VERBOSITY_DEBUG']; unset($value['VERBOSITY_DEBUG']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['vERBOSITYQUIET'])) { $output['VERBOSITY_QUIET'] = $this->vERBOSITYQUIET; } if (isset($this->_usedProperties['vERBOSITYNORMAL'])) { $output['VERBOSITY_NORMAL'] = $this->vERBOSITYNORMAL; } if (isset($this->_usedProperties['vERBOSITYVERBOSE'])) { $output['VERBOSITY_VERBOSE'] = $this->vERBOSITYVERBOSE; } if (isset($this->_usedProperties['vERBOSITYVERYVERBOSE'])) { $output['VERBOSITY_VERY_VERBOSE'] = $this->vERBOSITYVERYVERBOSE; } if (isset($this->_usedProperties['vERBOSITYDEBUG'])) { $output['VERBOSITY_DEBUG'] = $this->vERBOSITYDEBUG; } return $output; } } _usedProperties['id'] = \true; $this->id = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function host($value) : static { $this->_usedProperties['host'] = \true; $this->host = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('id', $value)) { $this->_usedProperties['id'] = \true; $this->id = $value['id']; unset($value['id']); } if (\array_key_exists('host', $value)) { $this->_usedProperties['host'] = \true; $this->host = $value['host']; unset($value['host']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['id'])) { $output['id'] = $this->id; } if (isset($this->_usedProperties['host'])) { $output['host'] = $this->host; } return $output; } } _usedProperties['code'] = \true; $this->code = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function urls(ParamConfigurator|array $value) : static { $this->_usedProperties['urls'] = \true; $this->urls = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('code', $value)) { $this->_usedProperties['code'] = \true; $this->code = $value['code']; unset($value['code']); } if (\array_key_exists('urls', $value)) { $this->_usedProperties['urls'] = \true; $this->urls = $value['urls']; unset($value['urls']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['code'])) { $output['code'] = $this->code; } if (isset($this->_usedProperties['urls'])) { $output['urls'] = $this->urls; } return $output; } } _usedProperties['type'] = \true; $this->type = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function elements(ParamConfigurator|array $value) : static { $this->_usedProperties['elements'] = \true; $this->elements = $value; return $this; } public function __construct(array $value = []) { if (\array_key_exists('type', $value)) { $this->_usedProperties['type'] = \true; $this->type = $value['type']; unset($value['type']); } if (\array_key_exists('elements', $value)) { $this->_usedProperties['elements'] = \true; $this->elements = $value['elements']; unset($value['elements']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['type'])) { $output['type'] = $this->type; } if (isset($this->_usedProperties['elements'])) { $output['elements'] = $this->elements; } return $output; } } _usedProperties['secret'] = \true; $this->secret = $value; return $this; } /** * Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead * @default null * @param ParamConfigurator|bool $value * @return $this */ public function httpMethodOverride($value) : static { $this->_usedProperties['httpMethodOverride'] = \true; $this->httpMethodOverride = $value; return $this; } /** * Set true to enable support for xsendfile in binary file responses. * @default false * @param ParamConfigurator|mixed $value * @return $this */ public function trustXSendfileTypeHeader($value) : static { $this->_usedProperties['trustXSendfileTypeHeader'] = \true; $this->trustXSendfileTypeHeader = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function ide($value) : static { $this->_usedProperties['ide'] = \true; $this->ide = $value; return $this; } /** * @default null * @param ParamConfigurator|bool $value * @return $this */ public function test($value) : static { $this->_usedProperties['test'] = \true; $this->test = $value; return $this; } /** * @default 'en' * @param ParamConfigurator|mixed $value * @return $this */ public function defaultLocale($value) : static { $this->_usedProperties['defaultLocale'] = \true; $this->defaultLocale = $value; return $this; } /** * Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed). * @default false * @param ParamConfigurator|bool $value * @return $this */ public function setLocaleFromAcceptLanguage($value) : static { $this->_usedProperties['setLocaleFromAcceptLanguage'] = \true; $this->setLocaleFromAcceptLanguage = $value; return $this; } /** * Whether to set the Content-Language HTTP header on the Response using the Request locale. * @default false * @param ParamConfigurator|bool $value * @return $this */ public function setContentLanguageFromLocale($value) : static { $this->_usedProperties['setContentLanguageFromLocale'] = \true; $this->setContentLanguageFromLocale = $value; return $this; } /** * @param ParamConfigurator|list $value * * @return $this */ public function enabledLocales(ParamConfigurator|array $value) : static { $this->_usedProperties['enabledLocales'] = \true; $this->enabledLocales = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function trustedHosts(ParamConfigurator|string|array $value) : static { $this->_usedProperties['trustedHosts'] = \true; $this->trustedHosts = $value; return $this; } /** * @default null * @param ParamConfigurator|mixed $value * @return $this */ public function trustedProxies($value) : static { $this->_usedProperties['trustedProxies'] = \true; $this->trustedProxies = $value; return $this; } /** * @param ParamConfigurator|list|string $value * * @return $this */ public function trustedHeaders(ParamConfigurator|string|array $value) : static { $this->_usedProperties['trustedHeaders'] = \true; $this->trustedHeaders = $value; return $this; } /** * @default 'error_controller' * @param ParamConfigurator|mixed $value * @return $this */ public function errorController($value) : static { $this->_usedProperties['errorController'] = \true; $this->errorController = $value; return $this; } /** * HttpKernel will handle all kinds of \Throwable * @default null * @param ParamConfigurator|bool $value * @return $this */ public function handleAllThrowables($value) : static { $this->_usedProperties['handleAllThrowables'] = \true; $this->handleAllThrowables = $value; return $this; } /** * @default {"enabled":null} */ public function csrfProtection(array $value = []) : \_ContaoManager\Symfony\Config\Framework\CsrfProtectionConfig { if (null === $this->csrfProtection) { $this->_usedProperties['csrfProtection'] = \true; $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\CsrfProtectionConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "csrfProtection()" has already been initialized. You cannot pass values the second time you call csrfProtection().'); } return $this->csrfProtection; } /** * @template TValue * @param TValue $value * form configuration * @default {"enabled":false,"csrf_protection":{"enabled":null,"field_name":"_token"}} * @return \Symfony\Config\Framework\FormConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\FormConfig : static) */ public function form(array $value = []) : \_ContaoManager\Symfony\Config\Framework\FormConfig|static { if (!\is_array($value)) { $this->_usedProperties['form'] = \true; $this->form = $value; return $this; } if (!$this->form instanceof \_ContaoManager\Symfony\Config\Framework\FormConfig) { $this->_usedProperties['form'] = \true; $this->form = new \_ContaoManager\Symfony\Config\Framework\FormConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "form()" has already been initialized. You cannot pass values the second time you call form().'); } return $this->form; } /** * @template TValue * @param TValue $value * HTTP cache configuration * @default {"enabled":false,"debug":"%kernel.debug%","private_headers":[],"skip_response_headers":[]} * @return \Symfony\Config\Framework\HttpCacheConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpCacheConfig : static) */ public function httpCache(array $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig|static { if (!\is_array($value)) { $this->_usedProperties['httpCache'] = \true; $this->httpCache = $value; return $this; } if (!$this->httpCache instanceof \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig) { $this->_usedProperties['httpCache'] = \true; $this->httpCache = new \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "httpCache()" has already been initialized. You cannot pass values the second time you call httpCache().'); } return $this->httpCache; } /** * @template TValue * @param TValue $value * esi configuration * @default {"enabled":false} * @return \Symfony\Config\Framework\EsiConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\EsiConfig : static) */ public function esi(array $value = []) : \_ContaoManager\Symfony\Config\Framework\EsiConfig|static { if (!\is_array($value)) { $this->_usedProperties['esi'] = \true; $this->esi = $value; return $this; } if (!$this->esi instanceof \_ContaoManager\Symfony\Config\Framework\EsiConfig) { $this->_usedProperties['esi'] = \true; $this->esi = new \_ContaoManager\Symfony\Config\Framework\EsiConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "esi()" has already been initialized. You cannot pass values the second time you call esi().'); } return $this->esi; } /** * @template TValue * @param TValue $value * ssi configuration * @default {"enabled":false} * @return \Symfony\Config\Framework\SsiConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\SsiConfig : static) */ public function ssi(array $value = []) : \_ContaoManager\Symfony\Config\Framework\SsiConfig|static { if (!\is_array($value)) { $this->_usedProperties['ssi'] = \true; $this->ssi = $value; return $this; } if (!$this->ssi instanceof \_ContaoManager\Symfony\Config\Framework\SsiConfig) { $this->_usedProperties['ssi'] = \true; $this->ssi = new \_ContaoManager\Symfony\Config\Framework\SsiConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "ssi()" has already been initialized. You cannot pass values the second time you call ssi().'); } return $this->ssi; } /** * @template TValue * @param TValue $value * fragments configuration * @default {"enabled":false,"hinclude_default_template":null,"path":"\/_fragment"} * @return \Symfony\Config\Framework\FragmentsConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\FragmentsConfig : static) */ public function fragments(array $value = []) : \_ContaoManager\Symfony\Config\Framework\FragmentsConfig|static { if (!\is_array($value)) { $this->_usedProperties['fragments'] = \true; $this->fragments = $value; return $this; } if (!$this->fragments instanceof \_ContaoManager\Symfony\Config\Framework\FragmentsConfig) { $this->_usedProperties['fragments'] = \true; $this->fragments = new \_ContaoManager\Symfony\Config\Framework\FragmentsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "fragments()" has already been initialized. You cannot pass values the second time you call fragments().'); } return $this->fragments; } /** * @template TValue * @param TValue $value * profiler configuration * @default {"enabled":false,"collect":true,"collect_parameter":null,"only_exceptions":false,"only_main_requests":false,"dsn":"file:%kernel.cache_dir%\/profiler","collect_serializer_data":false} * @return \Symfony\Config\Framework\ProfilerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\ProfilerConfig : static) */ public function profiler(array $value = []) : \_ContaoManager\Symfony\Config\Framework\ProfilerConfig|static { if (!\is_array($value)) { $this->_usedProperties['profiler'] = \true; $this->profiler = $value; return $this; } if (!$this->profiler instanceof \_ContaoManager\Symfony\Config\Framework\ProfilerConfig) { $this->_usedProperties['profiler'] = \true; $this->profiler = new \_ContaoManager\Symfony\Config\Framework\ProfilerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "profiler()" has already been initialized. You cannot pass values the second time you call profiler().'); } return $this->profiler; } /** * @template TValue * @param TValue $value * @default {"enabled":false,"workflows":[]} * @return \Symfony\Config\Framework\WorkflowsConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\WorkflowsConfig : static) */ public function workflows(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig|static { if (!\is_array($value)) { $this->_usedProperties['workflows'] = \true; $this->workflows = $value; return $this; } if (!$this->workflows instanceof \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig) { $this->_usedProperties['workflows'] = \true; $this->workflows = new \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "workflows()" has already been initialized. You cannot pass values the second time you call workflows().'); } return $this->workflows; } /** * @template TValue * @param TValue $value * router configuration * @default {"enabled":false,"cache_dir":"%kernel.cache_dir%","default_uri":null,"http_port":80,"https_port":443,"strict_requirements":true,"utf8":true} * @return \Symfony\Config\Framework\RouterConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\RouterConfig : static) */ public function router(array $value = []) : \_ContaoManager\Symfony\Config\Framework\RouterConfig|static { if (!\is_array($value)) { $this->_usedProperties['router'] = \true; $this->router = $value; return $this; } if (!$this->router instanceof \_ContaoManager\Symfony\Config\Framework\RouterConfig) { $this->_usedProperties['router'] = \true; $this->router = new \_ContaoManager\Symfony\Config\Framework\RouterConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "router()" has already been initialized. You cannot pass values the second time you call router().'); } return $this->router; } /** * @template TValue * @param TValue $value * session configuration * @default {"enabled":false,"storage_factory_id":"session.storage.factory.native","cookie_httponly":true,"gc_probability":1,"metadata_update_threshold":0} * @return \Symfony\Config\Framework\SessionConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\SessionConfig : static) */ public function session(array $value = []) : \_ContaoManager\Symfony\Config\Framework\SessionConfig|static { if (!\is_array($value)) { $this->_usedProperties['session'] = \true; $this->session = $value; return $this; } if (!$this->session instanceof \_ContaoManager\Symfony\Config\Framework\SessionConfig) { $this->_usedProperties['session'] = \true; $this->session = new \_ContaoManager\Symfony\Config\Framework\SessionConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "session()" has already been initialized. You cannot pass values the second time you call session().'); } return $this->session; } /** * @template TValue * @param TValue $value * request configuration * @default {"enabled":false,"formats":[]} * @return \Symfony\Config\Framework\RequestConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\RequestConfig : static) */ public function request(array $value = []) : \_ContaoManager\Symfony\Config\Framework\RequestConfig|static { if (!\is_array($value)) { $this->_usedProperties['request'] = \true; $this->request = $value; return $this; } if (!$this->request instanceof \_ContaoManager\Symfony\Config\Framework\RequestConfig) { $this->_usedProperties['request'] = \true; $this->request = new \_ContaoManager\Symfony\Config\Framework\RequestConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "request()" has already been initialized. You cannot pass values the second time you call request().'); } return $this->request; } /** * @template TValue * @param TValue $value * assets configuration * @default {"enabled":false,"strict_mode":false,"version_strategy":null,"version":null,"version_format":"%%s?%%s","json_manifest_path":null,"base_path":"","base_urls":[],"packages":[]} * @return \Symfony\Config\Framework\AssetsConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\AssetsConfig : static) */ public function assets(array $value = []) : \_ContaoManager\Symfony\Config\Framework\AssetsConfig|static { if (!\is_array($value)) { $this->_usedProperties['assets'] = \true; $this->assets = $value; return $this; } if (!$this->assets instanceof \_ContaoManager\Symfony\Config\Framework\AssetsConfig) { $this->_usedProperties['assets'] = \true; $this->assets = new \_ContaoManager\Symfony\Config\Framework\AssetsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "assets()" has already been initialized. You cannot pass values the second time you call assets().'); } return $this->assets; } /** * @template TValue * @param TValue $value * Asset Mapper configuration * @default {"enabled":false,"paths":[],"excluded_patterns":[],"exclude_dotfiles":true,"server":false,"public_prefix":"\/assets\/","missing_import_mode":"warn","extensions":[],"importmap_path":"%kernel.project_dir%\/importmap.php","importmap_polyfill":"es-module-shims","importmap_script_attributes":[],"vendor_dir":"%kernel.project_dir%\/assets\/vendor"} * @return \Symfony\Config\Framework\AssetMapperConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\AssetMapperConfig : static) */ public function assetMapper(array $value = []) : \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig|static { if (!\is_array($value)) { $this->_usedProperties['assetMapper'] = \true; $this->assetMapper = $value; return $this; } if (!$this->assetMapper instanceof \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig) { $this->_usedProperties['assetMapper'] = \true; $this->assetMapper = new \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "assetMapper()" has already been initialized. You cannot pass values the second time you call assetMapper().'); } return $this->assetMapper; } /** * @template TValue * @param TValue $value * translator configuration * @default {"enabled":false,"fallbacks":[],"logging":false,"formatter":"translator.formatter.default","cache_dir":"%kernel.cache_dir%\/translations","default_path":"%kernel.project_dir%\/translations","paths":[],"pseudo_localization":{"enabled":false,"accents":true,"expansion_factor":1,"brackets":true,"parse_html":false,"localizable_html_attributes":[]},"providers":[]} * @return \Symfony\Config\Framework\TranslatorConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\TranslatorConfig : static) */ public function translator(array $value = []) : \_ContaoManager\Symfony\Config\Framework\TranslatorConfig|static { if (!\is_array($value)) { $this->_usedProperties['translator'] = \true; $this->translator = $value; return $this; } if (!$this->translator instanceof \_ContaoManager\Symfony\Config\Framework\TranslatorConfig) { $this->_usedProperties['translator'] = \true; $this->translator = new \_ContaoManager\Symfony\Config\Framework\TranslatorConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "translator()" has already been initialized. You cannot pass values the second time you call translator().'); } return $this->translator; } /** * @template TValue * @param TValue $value * validation configuration * @default {"enabled":false,"enable_attributes":true,"static_method":["loadValidatorMetadata"],"translation_domain":"validators","mapping":{"paths":[]},"not_compromised_password":{"enabled":true,"endpoint":null},"auto_mapping":[]} * @return \Symfony\Config\Framework\ValidationConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\ValidationConfig : static) */ public function validation(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\ValidationConfig|static { if (!\is_array($value)) { $this->_usedProperties['validation'] = \true; $this->validation = $value; return $this; } if (!$this->validation instanceof \_ContaoManager\Symfony\Config\Framework\ValidationConfig) { $this->_usedProperties['validation'] = \true; $this->validation = new \_ContaoManager\Symfony\Config\Framework\ValidationConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "validation()" has already been initialized. You cannot pass values the second time you call validation().'); } return $this->validation; } /** * @template TValue * @param TValue $value * annotation configuration * @default {"enabled":false,"cache":"php_array","file_cache_dir":"%kernel.cache_dir%\/annotations","debug":false} * @return \Symfony\Config\Framework\AnnotationsConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\AnnotationsConfig : static) */ public function annotations(array $value = []) : \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig|static { if (!\is_array($value)) { $this->_usedProperties['annotations'] = \true; $this->annotations = $value; return $this; } if (!$this->annotations instanceof \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig) { $this->_usedProperties['annotations'] = \true; $this->annotations = new \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "annotations()" has already been initialized. You cannot pass values the second time you call annotations().'); } return $this->annotations; } /** * @template TValue * @param TValue $value * serializer configuration * @default {"enabled":true,"enable_attributes":true,"mapping":{"paths":[]},"default_context":[]} * @return \Symfony\Config\Framework\SerializerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\SerializerConfig : static) */ public function serializer(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\SerializerConfig|static { if (!\is_array($value)) { $this->_usedProperties['serializer'] = \true; $this->serializer = $value; return $this; } if (!$this->serializer instanceof \_ContaoManager\Symfony\Config\Framework\SerializerConfig) { $this->_usedProperties['serializer'] = \true; $this->serializer = new \_ContaoManager\Symfony\Config\Framework\SerializerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "serializer()" has already been initialized. You cannot pass values the second time you call serializer().'); } return $this->serializer; } /** * Property access configuration * @default {"enabled":true,"magic_call":false,"magic_get":true,"magic_set":true,"throw_exception_on_invalid_index":false,"throw_exception_on_invalid_property_path":true} */ public function propertyAccess(array $value = []) : \_ContaoManager\Symfony\Config\Framework\PropertyAccessConfig { if (null === $this->propertyAccess) { $this->_usedProperties['propertyAccess'] = \true; $this->propertyAccess = new \_ContaoManager\Symfony\Config\Framework\PropertyAccessConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "propertyAccess()" has already been initialized. You cannot pass values the second time you call propertyAccess().'); } return $this->propertyAccess; } /** * Property info configuration * @default {"enabled":true} */ public function propertyInfo(array $value = []) : \_ContaoManager\Symfony\Config\Framework\PropertyInfoConfig { if (null === $this->propertyInfo) { $this->_usedProperties['propertyInfo'] = \true; $this->propertyInfo = new \_ContaoManager\Symfony\Config\Framework\PropertyInfoConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "propertyInfo()" has already been initialized. You cannot pass values the second time you call propertyInfo().'); } return $this->propertyInfo; } /** * Cache configuration * @default {"prefix_seed":"_%kernel.project_dir%.%kernel.container_class%","app":"cache.adapter.filesystem","system":"cache.adapter.system","directory":"%kernel.cache_dir%\/pools\/app","default_redis_provider":"redis:\/\/localhost","default_memcached_provider":"memcached:\/\/localhost","default_doctrine_dbal_provider":"database_connection","default_pdo_provider":null,"pools":[]} */ public function cache(array $value = []) : \_ContaoManager\Symfony\Config\Framework\CacheConfig { if (null === $this->cache) { $this->_usedProperties['cache'] = \true; $this->cache = new \_ContaoManager\Symfony\Config\Framework\CacheConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "cache()" has already been initialized. You cannot pass values the second time you call cache().'); } return $this->cache; } /** * PHP errors handling configuration * @default {"throw":false} */ public function phpErrors(array $value = []) : \_ContaoManager\Symfony\Config\Framework\PhpErrorsConfig { if (null === $this->phpErrors) { $this->_usedProperties['phpErrors'] = \true; $this->phpErrors = new \_ContaoManager\Symfony\Config\Framework\PhpErrorsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "phpErrors()" has already been initialized. You cannot pass values the second time you call phpErrors().'); } return $this->phpErrors; } /** * @template TValue * @param TValue $value * Exception handling configuration * @return \Symfony\Config\Framework\ExceptionConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\ExceptionConfig : static) */ public function exception(string $class, array $value = []) : \_ContaoManager\Symfony\Config\Framework\ExceptionConfig|static { if (!\is_array($value)) { $this->_usedProperties['exceptions'] = \true; $this->exceptions[$class] = $value; return $this; } if (!isset($this->exceptions[$class]) || !$this->exceptions[$class] instanceof \_ContaoManager\Symfony\Config\Framework\ExceptionConfig) { $this->_usedProperties['exceptions'] = \true; $this->exceptions[$class] = new \_ContaoManager\Symfony\Config\Framework\ExceptionConfig($value); } elseif (1 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "exception()" has already been initialized. You cannot pass values the second time you call exception().'); } return $this->exceptions[$class]; } /** * @template TValue * @param TValue $value * web links configuration * @default {"enabled":false} * @return \Symfony\Config\Framework\WebLinkConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\WebLinkConfig : static) */ public function webLink(array $value = []) : \_ContaoManager\Symfony\Config\Framework\WebLinkConfig|static { if (!\is_array($value)) { $this->_usedProperties['webLink'] = \true; $this->webLink = $value; return $this; } if (!$this->webLink instanceof \_ContaoManager\Symfony\Config\Framework\WebLinkConfig) { $this->_usedProperties['webLink'] = \true; $this->webLink = new \_ContaoManager\Symfony\Config\Framework\WebLinkConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "webLink()" has already been initialized. You cannot pass values the second time you call webLink().'); } return $this->webLink; } /** * @template TValue * @param TValue $value * Lock configuration * @default {"enabled":false,"resources":{"default":["flock"]}} * @return \Symfony\Config\Framework\LockConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\LockConfig : static) */ public function lock(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\LockConfig|static { if (!\is_array($value)) { $this->_usedProperties['lock'] = \true; $this->lock = $value; return $this; } if (!$this->lock instanceof \_ContaoManager\Symfony\Config\Framework\LockConfig) { $this->_usedProperties['lock'] = \true; $this->lock = new \_ContaoManager\Symfony\Config\Framework\LockConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "lock()" has already been initialized. You cannot pass values the second time you call lock().'); } return $this->lock; } /** * @template TValue * @param TValue $value * Semaphore configuration * @default {"enabled":false,"resources":[]} * @return \Symfony\Config\Framework\SemaphoreConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\SemaphoreConfig : static) */ public function semaphore(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig|static { if (!\is_array($value)) { $this->_usedProperties['semaphore'] = \true; $this->semaphore = $value; return $this; } if (!$this->semaphore instanceof \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig) { $this->_usedProperties['semaphore'] = \true; $this->semaphore = new \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "semaphore()" has already been initialized. You cannot pass values the second time you call semaphore().'); } return $this->semaphore; } /** * @template TValue * @param TValue $value * Messenger configuration * @default {"enabled":false,"routing":[],"serializer":{"default_serializer":"messenger.transport.native_php_serializer","symfony_serializer":{"format":"json","context":[]}},"transports":[],"failure_transport":null,"reset_on_message":true,"stop_worker_on_signals":[],"default_bus":null,"buses":{"messenger.bus.default":{"default_middleware":{"enabled":true,"allow_no_handlers":false,"allow_no_senders":true},"middleware":[]}}} * @return \Symfony\Config\Framework\MessengerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\MessengerConfig : static) */ public function messenger(array $value = []) : \_ContaoManager\Symfony\Config\Framework\MessengerConfig|static { if (!\is_array($value)) { $this->_usedProperties['messenger'] = \true; $this->messenger = $value; return $this; } if (!$this->messenger instanceof \_ContaoManager\Symfony\Config\Framework\MessengerConfig) { $this->_usedProperties['messenger'] = \true; $this->messenger = new \_ContaoManager\Symfony\Config\Framework\MessengerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "messenger()" has already been initialized. You cannot pass values the second time you call messenger().'); } return $this->messenger; } /** * @template TValue * @param TValue $value * Scheduler configuration * @default {"enabled":false} * @return \Symfony\Config\Framework\SchedulerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\SchedulerConfig : static) */ public function scheduler(array $value = []) : \_ContaoManager\Symfony\Config\Framework\SchedulerConfig|static { if (!\is_array($value)) { $this->_usedProperties['scheduler'] = \true; $this->scheduler = $value; return $this; } if (!$this->scheduler instanceof \_ContaoManager\Symfony\Config\Framework\SchedulerConfig) { $this->_usedProperties['scheduler'] = \true; $this->scheduler = new \_ContaoManager\Symfony\Config\Framework\SchedulerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "scheduler()" has already been initialized. You cannot pass values the second time you call scheduler().'); } return $this->scheduler; } /** * Enabled by default when debug is enabled. * @default false * @param ParamConfigurator|bool $value * @return $this */ public function disallowSearchEngineIndex($value) : static { $this->_usedProperties['disallowSearchEngineIndex'] = \true; $this->disallowSearchEngineIndex = $value; return $this; } /** * @template TValue * @param TValue $value * HTTP Client configuration * @default {"enabled":false,"scoped_clients":[]} * @return \Symfony\Config\Framework\HttpClientConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HttpClientConfig : static) */ public function httpClient(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\HttpClientConfig|static { if (!\is_array($value)) { $this->_usedProperties['httpClient'] = \true; $this->httpClient = $value; return $this; } if (!$this->httpClient instanceof \_ContaoManager\Symfony\Config\Framework\HttpClientConfig) { $this->_usedProperties['httpClient'] = \true; $this->httpClient = new \_ContaoManager\Symfony\Config\Framework\HttpClientConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "httpClient()" has already been initialized. You cannot pass values the second time you call httpClient().'); } return $this->httpClient; } /** * @template TValue * @param TValue $value * Mailer configuration * @default {"enabled":false,"message_bus":null,"dsn":null,"transports":[],"headers":[]} * @return \Symfony\Config\Framework\MailerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\MailerConfig : static) */ public function mailer(array $value = []) : \_ContaoManager\Symfony\Config\Framework\MailerConfig|static { if (!\is_array($value)) { $this->_usedProperties['mailer'] = \true; $this->mailer = $value; return $this; } if (!$this->mailer instanceof \_ContaoManager\Symfony\Config\Framework\MailerConfig) { $this->_usedProperties['mailer'] = \true; $this->mailer = new \_ContaoManager\Symfony\Config\Framework\MailerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "mailer()" has already been initialized. You cannot pass values the second time you call mailer().'); } return $this->mailer; } /** * @default {"enabled":true,"vault_directory":"%kernel.project_dir%\/config\/secrets\/%kernel.runtime_environment%","local_dotenv_file":"%kernel.project_dir%\/.env.%kernel.environment%.local","decryption_env_var":"base64:default::SYMFONY_DECRYPTION_SECRET"} */ public function secrets(array $value = []) : \_ContaoManager\Symfony\Config\Framework\SecretsConfig { if (null === $this->secrets) { $this->_usedProperties['secrets'] = \true; $this->secrets = new \_ContaoManager\Symfony\Config\Framework\SecretsConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "secrets()" has already been initialized. You cannot pass values the second time you call secrets().'); } return $this->secrets; } /** * @template TValue * @param TValue $value * Notifier configuration * @default {"enabled":false,"message_bus":null,"chatter_transports":[],"texter_transports":[],"notification_on_failed_messages":false,"channel_policy":[],"admin_recipients":[]} * @return \Symfony\Config\Framework\NotifierConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\NotifierConfig : static) */ public function notifier(array $value = []) : \_ContaoManager\Symfony\Config\Framework\NotifierConfig|static { if (!\is_array($value)) { $this->_usedProperties['notifier'] = \true; $this->notifier = $value; return $this; } if (!$this->notifier instanceof \_ContaoManager\Symfony\Config\Framework\NotifierConfig) { $this->_usedProperties['notifier'] = \true; $this->notifier = new \_ContaoManager\Symfony\Config\Framework\NotifierConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "notifier()" has already been initialized. You cannot pass values the second time you call notifier().'); } return $this->notifier; } /** * @template TValue * @param TValue $value * Rate limiter configuration * @default {"enabled":false,"limiters":[]} * @return \Symfony\Config\Framework\RateLimiterConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\RateLimiterConfig : static) */ public function rateLimiter(mixed $value = []) : \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig|static { if (!\is_array($value)) { $this->_usedProperties['rateLimiter'] = \true; $this->rateLimiter = $value; return $this; } if (!$this->rateLimiter instanceof \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig) { $this->_usedProperties['rateLimiter'] = \true; $this->rateLimiter = new \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "rateLimiter()" has already been initialized. You cannot pass values the second time you call rateLimiter().'); } return $this->rateLimiter; } /** * Uid configuration * @default {"enabled":true,"name_based_uuid_version":5} */ public function uid(array $value = []) : \_ContaoManager\Symfony\Config\Framework\UidConfig { if (null === $this->uid) { $this->_usedProperties['uid'] = \true; $this->uid = new \_ContaoManager\Symfony\Config\Framework\UidConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "uid()" has already been initialized. You cannot pass values the second time you call uid().'); } return $this->uid; } /** * @template TValue * @param TValue $value * HtmlSanitizer configuration * @default {"enabled":false,"sanitizers":[]} * @return \Symfony\Config\Framework\HtmlSanitizerConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\HtmlSanitizerConfig : static) */ public function htmlSanitizer(array $value = []) : \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig|static { if (!\is_array($value)) { $this->_usedProperties['htmlSanitizer'] = \true; $this->htmlSanitizer = $value; return $this; } if (!$this->htmlSanitizer instanceof \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig) { $this->_usedProperties['htmlSanitizer'] = \true; $this->htmlSanitizer = new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "htmlSanitizer()" has already been initialized. You cannot pass values the second time you call htmlSanitizer().'); } return $this->htmlSanitizer; } /** * @template TValue * @param TValue $value * Webhook configuration * @default {"enabled":false,"message_bus":"messenger.default_bus","routing":[]} * @return \Symfony\Config\Framework\WebhookConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\WebhookConfig : static) */ public function webhook(array $value = []) : \_ContaoManager\Symfony\Config\Framework\WebhookConfig|static { if (!\is_array($value)) { $this->_usedProperties['webhook'] = \true; $this->webhook = $value; return $this; } if (!$this->webhook instanceof \_ContaoManager\Symfony\Config\Framework\WebhookConfig) { $this->_usedProperties['webhook'] = \true; $this->webhook = new \_ContaoManager\Symfony\Config\Framework\WebhookConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "webhook()" has already been initialized. You cannot pass values the second time you call webhook().'); } return $this->webhook; } /** * @template TValue * @param TValue $value * RemoteEvent configuration * @default {"enabled":false} * @return \Symfony\Config\Framework\RemoteeventConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\Framework\RemoteeventConfig : static) */ public function remoteevent(array $value = []) : \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig|static { if (!\is_array($value)) { $this->_usedProperties['remoteevent'] = \true; $this->remoteevent = $value; return $this; } if (!$this->remoteevent instanceof \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig) { $this->_usedProperties['remoteevent'] = \true; $this->remoteevent = new \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig($value); } elseif (0 < \func_num_args()) { throw new InvalidConfigurationException('The node created by "remoteevent()" has already been initialized. You cannot pass values the second time you call remoteevent().'); } return $this->remoteevent; } public function getExtensionAlias() : string { return 'framework'; } public function __construct(array $value = []) { if (\array_key_exists('secret', $value)) { $this->_usedProperties['secret'] = \true; $this->secret = $value['secret']; unset($value['secret']); } if (\array_key_exists('http_method_override', $value)) { $this->_usedProperties['httpMethodOverride'] = \true; $this->httpMethodOverride = $value['http_method_override']; unset($value['http_method_override']); } if (\array_key_exists('trust_x_sendfile_type_header', $value)) { $this->_usedProperties['trustXSendfileTypeHeader'] = \true; $this->trustXSendfileTypeHeader = $value['trust_x_sendfile_type_header']; unset($value['trust_x_sendfile_type_header']); } if (\array_key_exists('ide', $value)) { $this->_usedProperties['ide'] = \true; $this->ide = $value['ide']; unset($value['ide']); } if (\array_key_exists('test', $value)) { $this->_usedProperties['test'] = \true; $this->test = $value['test']; unset($value['test']); } if (\array_key_exists('default_locale', $value)) { $this->_usedProperties['defaultLocale'] = \true; $this->defaultLocale = $value['default_locale']; unset($value['default_locale']); } if (\array_key_exists('set_locale_from_accept_language', $value)) { $this->_usedProperties['setLocaleFromAcceptLanguage'] = \true; $this->setLocaleFromAcceptLanguage = $value['set_locale_from_accept_language']; unset($value['set_locale_from_accept_language']); } if (\array_key_exists('set_content_language_from_locale', $value)) { $this->_usedProperties['setContentLanguageFromLocale'] = \true; $this->setContentLanguageFromLocale = $value['set_content_language_from_locale']; unset($value['set_content_language_from_locale']); } if (\array_key_exists('enabled_locales', $value)) { $this->_usedProperties['enabledLocales'] = \true; $this->enabledLocales = $value['enabled_locales']; unset($value['enabled_locales']); } if (\array_key_exists('trusted_hosts', $value)) { $this->_usedProperties['trustedHosts'] = \true; $this->trustedHosts = $value['trusted_hosts']; unset($value['trusted_hosts']); } if (\array_key_exists('trusted_proxies', $value)) { $this->_usedProperties['trustedProxies'] = \true; $this->trustedProxies = $value['trusted_proxies']; unset($value['trusted_proxies']); } if (\array_key_exists('trusted_headers', $value)) { $this->_usedProperties['trustedHeaders'] = \true; $this->trustedHeaders = $value['trusted_headers']; unset($value['trusted_headers']); } if (\array_key_exists('error_controller', $value)) { $this->_usedProperties['errorController'] = \true; $this->errorController = $value['error_controller']; unset($value['error_controller']); } if (\array_key_exists('handle_all_throwables', $value)) { $this->_usedProperties['handleAllThrowables'] = \true; $this->handleAllThrowables = $value['handle_all_throwables']; unset($value['handle_all_throwables']); } if (\array_key_exists('csrf_protection', $value)) { $this->_usedProperties['csrfProtection'] = \true; $this->csrfProtection = new \_ContaoManager\Symfony\Config\Framework\CsrfProtectionConfig($value['csrf_protection']); unset($value['csrf_protection']); } if (\array_key_exists('form', $value)) { $this->_usedProperties['form'] = \true; $this->form = \is_array($value['form']) ? new \_ContaoManager\Symfony\Config\Framework\FormConfig($value['form']) : $value['form']; unset($value['form']); } if (\array_key_exists('http_cache', $value)) { $this->_usedProperties['httpCache'] = \true; $this->httpCache = \is_array($value['http_cache']) ? new \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig($value['http_cache']) : $value['http_cache']; unset($value['http_cache']); } if (\array_key_exists('esi', $value)) { $this->_usedProperties['esi'] = \true; $this->esi = \is_array($value['esi']) ? new \_ContaoManager\Symfony\Config\Framework\EsiConfig($value['esi']) : $value['esi']; unset($value['esi']); } if (\array_key_exists('ssi', $value)) { $this->_usedProperties['ssi'] = \true; $this->ssi = \is_array($value['ssi']) ? new \_ContaoManager\Symfony\Config\Framework\SsiConfig($value['ssi']) : $value['ssi']; unset($value['ssi']); } if (\array_key_exists('fragments', $value)) { $this->_usedProperties['fragments'] = \true; $this->fragments = \is_array($value['fragments']) ? new \_ContaoManager\Symfony\Config\Framework\FragmentsConfig($value['fragments']) : $value['fragments']; unset($value['fragments']); } if (\array_key_exists('profiler', $value)) { $this->_usedProperties['profiler'] = \true; $this->profiler = \is_array($value['profiler']) ? new \_ContaoManager\Symfony\Config\Framework\ProfilerConfig($value['profiler']) : $value['profiler']; unset($value['profiler']); } if (\array_key_exists('workflows', $value)) { $this->_usedProperties['workflows'] = \true; $this->workflows = \is_array($value['workflows']) ? new \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig($value['workflows']) : $value['workflows']; unset($value['workflows']); } if (\array_key_exists('router', $value)) { $this->_usedProperties['router'] = \true; $this->router = \is_array($value['router']) ? new \_ContaoManager\Symfony\Config\Framework\RouterConfig($value['router']) : $value['router']; unset($value['router']); } if (\array_key_exists('session', $value)) { $this->_usedProperties['session'] = \true; $this->session = \is_array($value['session']) ? new \_ContaoManager\Symfony\Config\Framework\SessionConfig($value['session']) : $value['session']; unset($value['session']); } if (\array_key_exists('request', $value)) { $this->_usedProperties['request'] = \true; $this->request = \is_array($value['request']) ? new \_ContaoManager\Symfony\Config\Framework\RequestConfig($value['request']) : $value['request']; unset($value['request']); } if (\array_key_exists('assets', $value)) { $this->_usedProperties['assets'] = \true; $this->assets = \is_array($value['assets']) ? new \_ContaoManager\Symfony\Config\Framework\AssetsConfig($value['assets']) : $value['assets']; unset($value['assets']); } if (\array_key_exists('asset_mapper', $value)) { $this->_usedProperties['assetMapper'] = \true; $this->assetMapper = \is_array($value['asset_mapper']) ? new \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig($value['asset_mapper']) : $value['asset_mapper']; unset($value['asset_mapper']); } if (\array_key_exists('translator', $value)) { $this->_usedProperties['translator'] = \true; $this->translator = \is_array($value['translator']) ? new \_ContaoManager\Symfony\Config\Framework\TranslatorConfig($value['translator']) : $value['translator']; unset($value['translator']); } if (\array_key_exists('validation', $value)) { $this->_usedProperties['validation'] = \true; $this->validation = \is_array($value['validation']) ? new \_ContaoManager\Symfony\Config\Framework\ValidationConfig($value['validation']) : $value['validation']; unset($value['validation']); } if (\array_key_exists('annotations', $value)) { $this->_usedProperties['annotations'] = \true; $this->annotations = \is_array($value['annotations']) ? new \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig($value['annotations']) : $value['annotations']; unset($value['annotations']); } if (\array_key_exists('serializer', $value)) { $this->_usedProperties['serializer'] = \true; $this->serializer = \is_array($value['serializer']) ? new \_ContaoManager\Symfony\Config\Framework\SerializerConfig($value['serializer']) : $value['serializer']; unset($value['serializer']); } if (\array_key_exists('property_access', $value)) { $this->_usedProperties['propertyAccess'] = \true; $this->propertyAccess = new \_ContaoManager\Symfony\Config\Framework\PropertyAccessConfig($value['property_access']); unset($value['property_access']); } if (\array_key_exists('property_info', $value)) { $this->_usedProperties['propertyInfo'] = \true; $this->propertyInfo = new \_ContaoManager\Symfony\Config\Framework\PropertyInfoConfig($value['property_info']); unset($value['property_info']); } if (\array_key_exists('cache', $value)) { $this->_usedProperties['cache'] = \true; $this->cache = new \_ContaoManager\Symfony\Config\Framework\CacheConfig($value['cache']); unset($value['cache']); } if (\array_key_exists('php_errors', $value)) { $this->_usedProperties['phpErrors'] = \true; $this->phpErrors = new \_ContaoManager\Symfony\Config\Framework\PhpErrorsConfig($value['php_errors']); unset($value['php_errors']); } if (\array_key_exists('exceptions', $value)) { $this->_usedProperties['exceptions'] = \true; $this->exceptions = \array_map(fn($v) => \is_array($v) ? new \_ContaoManager\Symfony\Config\Framework\ExceptionConfig($v) : $v, $value['exceptions']); unset($value['exceptions']); } if (\array_key_exists('web_link', $value)) { $this->_usedProperties['webLink'] = \true; $this->webLink = \is_array($value['web_link']) ? new \_ContaoManager\Symfony\Config\Framework\WebLinkConfig($value['web_link']) : $value['web_link']; unset($value['web_link']); } if (\array_key_exists('lock', $value)) { $this->_usedProperties['lock'] = \true; $this->lock = \is_array($value['lock']) ? new \_ContaoManager\Symfony\Config\Framework\LockConfig($value['lock']) : $value['lock']; unset($value['lock']); } if (\array_key_exists('semaphore', $value)) { $this->_usedProperties['semaphore'] = \true; $this->semaphore = \is_array($value['semaphore']) ? new \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig($value['semaphore']) : $value['semaphore']; unset($value['semaphore']); } if (\array_key_exists('messenger', $value)) { $this->_usedProperties['messenger'] = \true; $this->messenger = \is_array($value['messenger']) ? new \_ContaoManager\Symfony\Config\Framework\MessengerConfig($value['messenger']) : $value['messenger']; unset($value['messenger']); } if (\array_key_exists('scheduler', $value)) { $this->_usedProperties['scheduler'] = \true; $this->scheduler = \is_array($value['scheduler']) ? new \_ContaoManager\Symfony\Config\Framework\SchedulerConfig($value['scheduler']) : $value['scheduler']; unset($value['scheduler']); } if (\array_key_exists('disallow_search_engine_index', $value)) { $this->_usedProperties['disallowSearchEngineIndex'] = \true; $this->disallowSearchEngineIndex = $value['disallow_search_engine_index']; unset($value['disallow_search_engine_index']); } if (\array_key_exists('http_client', $value)) { $this->_usedProperties['httpClient'] = \true; $this->httpClient = \is_array($value['http_client']) ? new \_ContaoManager\Symfony\Config\Framework\HttpClientConfig($value['http_client']) : $value['http_client']; unset($value['http_client']); } if (\array_key_exists('mailer', $value)) { $this->_usedProperties['mailer'] = \true; $this->mailer = \is_array($value['mailer']) ? new \_ContaoManager\Symfony\Config\Framework\MailerConfig($value['mailer']) : $value['mailer']; unset($value['mailer']); } if (\array_key_exists('secrets', $value)) { $this->_usedProperties['secrets'] = \true; $this->secrets = new \_ContaoManager\Symfony\Config\Framework\SecretsConfig($value['secrets']); unset($value['secrets']); } if (\array_key_exists('notifier', $value)) { $this->_usedProperties['notifier'] = \true; $this->notifier = \is_array($value['notifier']) ? new \_ContaoManager\Symfony\Config\Framework\NotifierConfig($value['notifier']) : $value['notifier']; unset($value['notifier']); } if (\array_key_exists('rate_limiter', $value)) { $this->_usedProperties['rateLimiter'] = \true; $this->rateLimiter = \is_array($value['rate_limiter']) ? new \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig($value['rate_limiter']) : $value['rate_limiter']; unset($value['rate_limiter']); } if (\array_key_exists('uid', $value)) { $this->_usedProperties['uid'] = \true; $this->uid = new \_ContaoManager\Symfony\Config\Framework\UidConfig($value['uid']); unset($value['uid']); } if (\array_key_exists('html_sanitizer', $value)) { $this->_usedProperties['htmlSanitizer'] = \true; $this->htmlSanitizer = \is_array($value['html_sanitizer']) ? new \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig($value['html_sanitizer']) : $value['html_sanitizer']; unset($value['html_sanitizer']); } if (\array_key_exists('webhook', $value)) { $this->_usedProperties['webhook'] = \true; $this->webhook = \is_array($value['webhook']) ? new \_ContaoManager\Symfony\Config\Framework\WebhookConfig($value['webhook']) : $value['webhook']; unset($value['webhook']); } if (\array_key_exists('remote-event', $value)) { $this->_usedProperties['remoteevent'] = \true; $this->remoteevent = \is_array($value['remote-event']) ? new \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig($value['remote-event']) : $value['remote-event']; unset($value['remote-event']); } if ([] !== $value) { throw new InvalidConfigurationException(\sprintf('The following keys are not supported by "%s": ', __CLASS__) . \implode(', ', \array_keys($value))); } } public function toArray() : array { $output = []; if (isset($this->_usedProperties['secret'])) { $output['secret'] = $this->secret; } if (isset($this->_usedProperties['httpMethodOverride'])) { $output['http_method_override'] = $this->httpMethodOverride; } if (isset($this->_usedProperties['trustXSendfileTypeHeader'])) { $output['trust_x_sendfile_type_header'] = $this->trustXSendfileTypeHeader; } if (isset($this->_usedProperties['ide'])) { $output['ide'] = $this->ide; } if (isset($this->_usedProperties['test'])) { $output['test'] = $this->test; } if (isset($this->_usedProperties['defaultLocale'])) { $output['default_locale'] = $this->defaultLocale; } if (isset($this->_usedProperties['setLocaleFromAcceptLanguage'])) { $output['set_locale_from_accept_language'] = $this->setLocaleFromAcceptLanguage; } if (isset($this->_usedProperties['setContentLanguageFromLocale'])) { $output['set_content_language_from_locale'] = $this->setContentLanguageFromLocale; } if (isset($this->_usedProperties['enabledLocales'])) { $output['enabled_locales'] = $this->enabledLocales; } if (isset($this->_usedProperties['trustedHosts'])) { $output['trusted_hosts'] = $this->trustedHosts; } if (isset($this->_usedProperties['trustedProxies'])) { $output['trusted_proxies'] = $this->trustedProxies; } if (isset($this->_usedProperties['trustedHeaders'])) { $output['trusted_headers'] = $this->trustedHeaders; } if (isset($this->_usedProperties['errorController'])) { $output['error_controller'] = $this->errorController; } if (isset($this->_usedProperties['handleAllThrowables'])) { $output['handle_all_throwables'] = $this->handleAllThrowables; } if (isset($this->_usedProperties['csrfProtection'])) { $output['csrf_protection'] = $this->csrfProtection->toArray(); } if (isset($this->_usedProperties['form'])) { $output['form'] = $this->form instanceof \_ContaoManager\Symfony\Config\Framework\FormConfig ? $this->form->toArray() : $this->form; } if (isset($this->_usedProperties['httpCache'])) { $output['http_cache'] = $this->httpCache instanceof \_ContaoManager\Symfony\Config\Framework\HttpCacheConfig ? $this->httpCache->toArray() : $this->httpCache; } if (isset($this->_usedProperties['esi'])) { $output['esi'] = $this->esi instanceof \_ContaoManager\Symfony\Config\Framework\EsiConfig ? $this->esi->toArray() : $this->esi; } if (isset($this->_usedProperties['ssi'])) { $output['ssi'] = $this->ssi instanceof \_ContaoManager\Symfony\Config\Framework\SsiConfig ? $this->ssi->toArray() : $this->ssi; } if (isset($this->_usedProperties['fragments'])) { $output['fragments'] = $this->fragments instanceof \_ContaoManager\Symfony\Config\Framework\FragmentsConfig ? $this->fragments->toArray() : $this->fragments; } if (isset($this->_usedProperties['profiler'])) { $output['profiler'] = $this->profiler instanceof \_ContaoManager\Symfony\Config\Framework\ProfilerConfig ? $this->profiler->toArray() : $this->profiler; } if (isset($this->_usedProperties['workflows'])) { $output['workflows'] = $this->workflows instanceof \_ContaoManager\Symfony\Config\Framework\WorkflowsConfig ? $this->workflows->toArray() : $this->workflows; } if (isset($this->_usedProperties['router'])) { $output['router'] = $this->router instanceof \_ContaoManager\Symfony\Config\Framework\RouterConfig ? $this->router->toArray() : $this->router; } if (isset($this->_usedProperties['session'])) { $output['session'] = $this->session instanceof \_ContaoManager\Symfony\Config\Framework\SessionConfig ? $this->session->toArray() : $this->session; } if (isset($this->_usedProperties['request'])) { $output['request'] = $this->request instanceof \_ContaoManager\Symfony\Config\Framework\RequestConfig ? $this->request->toArray() : $this->request; } if (isset($this->_usedProperties['assets'])) { $output['assets'] = $this->assets instanceof \_ContaoManager\Symfony\Config\Framework\AssetsConfig ? $this->assets->toArray() : $this->assets; } if (isset($this->_usedProperties['assetMapper'])) { $output['asset_mapper'] = $this->assetMapper instanceof \_ContaoManager\Symfony\Config\Framework\AssetMapperConfig ? $this->assetMapper->toArray() : $this->assetMapper; } if (isset($this->_usedProperties['translator'])) { $output['translator'] = $this->translator instanceof \_ContaoManager\Symfony\Config\Framework\TranslatorConfig ? $this->translator->toArray() : $this->translator; } if (isset($this->_usedProperties['validation'])) { $output['validation'] = $this->validation instanceof \_ContaoManager\Symfony\Config\Framework\ValidationConfig ? $this->validation->toArray() : $this->validation; } if (isset($this->_usedProperties['annotations'])) { $output['annotations'] = $this->annotations instanceof \_ContaoManager\Symfony\Config\Framework\AnnotationsConfig ? $this->annotations->toArray() : $this->annotations; } if (isset($this->_usedProperties['serializer'])) { $output['serializer'] = $this->serializer instanceof \_ContaoManager\Symfony\Config\Framework\SerializerConfig ? $this->serializer->toArray() : $this->serializer; } if (isset($this->_usedProperties['propertyAccess'])) { $output['property_access'] = $this->propertyAccess->toArray(); } if (isset($this->_usedProperties['propertyInfo'])) { $output['property_info'] = $this->propertyInfo->toArray(); } if (isset($this->_usedProperties['cache'])) { $output['cache'] = $this->cache->toArray(); } if (isset($this->_usedProperties['phpErrors'])) { $output['php_errors'] = $this->phpErrors->toArray(); } if (isset($this->_usedProperties['exceptions'])) { $output['exceptions'] = \array_map(fn($v) => $v instanceof \_ContaoManager\Symfony\Config\Framework\ExceptionConfig ? $v->toArray() : $v, $this->exceptions); } if (isset($this->_usedProperties['webLink'])) { $output['web_link'] = $this->webLink instanceof \_ContaoManager\Symfony\Config\Framework\WebLinkConfig ? $this->webLink->toArray() : $this->webLink; } if (isset($this->_usedProperties['lock'])) { $output['lock'] = $this->lock instanceof \_ContaoManager\Symfony\Config\Framework\LockConfig ? $this->lock->toArray() : $this->lock; } if (isset($this->_usedProperties['semaphore'])) { $output['semaphore'] = $this->semaphore instanceof \_ContaoManager\Symfony\Config\Framework\SemaphoreConfig ? $this->semaphore->toArray() : $this->semaphore; } if (isset($this->_usedProperties['messenger'])) { $output['messenger'] = $this->messenger instanceof \_ContaoManager\Symfony\Config\Framework\MessengerConfig ? $this->messenger->toArray() : $this->messenger; } if (isset($this->_usedProperties['scheduler'])) { $output['scheduler'] = $this->scheduler instanceof \_ContaoManager\Symfony\Config\Framework\SchedulerConfig ? $this->scheduler->toArray() : $this->scheduler; } if (isset($this->_usedProperties['disallowSearchEngineIndex'])) { $output['disallow_search_engine_index'] = $this->disallowSearchEngineIndex; } if (isset($this->_usedProperties['httpClient'])) { $output['http_client'] = $this->httpClient instanceof \_ContaoManager\Symfony\Config\Framework\HttpClientConfig ? $this->httpClient->toArray() : $this->httpClient; } if (isset($this->_usedProperties['mailer'])) { $output['mailer'] = $this->mailer instanceof \_ContaoManager\Symfony\Config\Framework\MailerConfig ? $this->mailer->toArray() : $this->mailer; } if (isset($this->_usedProperties['secrets'])) { $output['secrets'] = $this->secrets->toArray(); } if (isset($this->_usedProperties['notifier'])) { $output['notifier'] = $this->notifier instanceof \_ContaoManager\Symfony\Config\Framework\NotifierConfig ? $this->notifier->toArray() : $this->notifier; } if (isset($this->_usedProperties['rateLimiter'])) { $output['rate_limiter'] = $this->rateLimiter instanceof \_ContaoManager\Symfony\Config\Framework\RateLimiterConfig ? $this->rateLimiter->toArray() : $this->rateLimiter; } if (isset($this->_usedProperties['uid'])) { $output['uid'] = $this->uid->toArray(); } if (isset($this->_usedProperties['htmlSanitizer'])) { $output['html_sanitizer'] = $this->htmlSanitizer instanceof \_ContaoManager\Symfony\Config\Framework\HtmlSanitizerConfig ? $this->htmlSanitizer->toArray() : $this->htmlSanitizer; } if (isset($this->_usedProperties['webhook'])) { $output['webhook'] = $this->webhook instanceof \_ContaoManager\Symfony\Config\Framework\WebhookConfig ? $this->webhook->toArray() : $this->webhook; } if (isset($this->_usedProperties['remoteevent'])) { $output['remote-event'] = $this->remoteevent instanceof \_ContaoManager\Symfony\Config\Framework\RemoteeventConfig ? $this->remoteevent->toArray() : $this->remoteevent; } return $output; } } services['router'] ?? self::getRouterService($container); return $container->privates['security.firewall.map.context.api'] = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallContext(new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['security.channel_listener'] ?? $container->load('getSecurity_ChannelListenerService')); (yield 1 => $container->privates['security.firewall.authenticator.api'] ?? $container->load('getSecurity_Firewall_Authenticator_ApiService')); (yield 2 => $container->privates['security.access_listener'] ?? $container->load('getSecurity_AccessListenerService')); }, 3), new \_ContaoManager\Symfony\Component\Security\Http\Firewall\ExceptionListener($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.authentication.trust_resolver'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver(), new \_ContaoManager\Symfony\Component\Security\Http\HttpUtils($a, $a), 'api', NULL, NULL, NULL, $container->privates['monolog.logger.security'] ?? $container->load('getMonolog_Logger_SecurityService'), \true), NULL, new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallConfig('api', 'security.user_checker', NULL, \true, \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider', NULL, NULL, NULL, NULL, ['_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator', '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator', '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator', '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator', '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator'], NULL, NULL)); } } services['container.get_routing_condition_service'] = (new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), [], []))->get(...); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\ComposerController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['security.user_checker_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator(['api' => #[\Closure(name: 'security.user_checker', class: '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserChecker')] fn() => $container->privates['security.user_checker'] ??= new \_ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserChecker()]); } } privates['console.command.secrets_list'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local')); $instance->setName('secrets:list'); $instance->setDescription('List all secrets'); return $instance; } } privates['console.command.secrets_remove'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local')); $instance->setName('secrets:remove'); $instance->setDescription('Remove a secret from the vault'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\GraphicsLibCheck($container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\PhpCliController(); } } privates['security.authenticator.managers_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator(['api' => #[\Closure(name: 'security.authenticator.manager.api', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManager')] fn() => $container->privates['security.authenticator.manager.api'] ?? $container->load('getSecurity_Authenticator_Manager_ApiService')]); } } services['_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand($container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager'] ?? $container->load('getTaskManagerService')); $instance->setName('task:delete'); $instance->setDescription('Deletes the current task if it is not active.'); return $instance; } } privates['.console.command.secrets_encrypt_from_local.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:encrypt-from-local', [], 'Encrypt all local secrets to the vault', \false, #[\Closure(name: 'console.command.secrets_encrypt_from_local', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsEncryptFromLocalCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand => $container->privates['console.command.secrets_encrypt_from_local'] ?? $container->load('getConsole_Command_SecretsEncryptFromLocalService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController'] = new \_ContaoManager\Contao\ManagerApi\Controller\ConstraintController(); } } privates['argument_resolver.backed_enum_resolver'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver(); } } \true, '.Contao\\ManagerApi\\Command\\AboutCommand.lazy' => \true, '.Contao\\ManagerApi\\Command\\IntegrityCheckCommand.lazy' => \true, '.Contao\\ManagerApi\\Command\\ProcessRunnerCommand.lazy' => \true, '.Contao\\ManagerApi\\Command\\TaskAbortCommand.lazy' => \true, '.Contao\\ManagerApi\\Command\\TaskDeleteCommand.lazy' => \true, '.Contao\\ManagerApi\\Command\\TaskUpdateCommand.lazy' => \true, '.Contao\\ManagerApi\\Command\\UpdateCommand.lazy' => \true, '.Psr\\Container\\ContainerInterface $parameter_bag' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\ApiApplication' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Command\\AboutCommand' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Command\\TaskAbortCommand' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Command\\TaskDeleteCommand' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Command\\TaskUpdateCommand' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Command\\UpdateCommand' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Composer\\CloudResolver' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Controller\\FileController' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\EventListener\\CheckTotpListener' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\EventListener\\ExceptionListener' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\EventListener\\JsonRequestListener' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\EventListener\\LocaleListener' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\EventListener\\SecurityListener' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Composer\\ClearCacheOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Composer\\CreateProjectOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Composer\\DumpAutoloadOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Composer\\InstallOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Composer\\RemoveOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Composer\\RequireOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Composer\\UpdateOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Contao\\BackupCreateOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Contao\\BackupRestoreOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Contao\\CacheClearOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Contao\\CacheWarmupOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Contao\\CreateContaoOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Contao\\MaintenanceModeOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Filesystem\\InstallUploadsOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveCacheOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveUploadsOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveVendorOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\TaskOperation\\Manager\\SelfUpdateOperation' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Packages\\InstallTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Packages\\SetupTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => \true, '_ContaoManager\\.abstract.instanceof.Contao\\ManagerApi\\Task\\TaskManager' => \true, '.abstract.instanceof.locale_listener' => \true, '.cache_connection.GD_MSZC' => \true, '.cache_connection.JKE6keX' => \true, '.console.command.about.lazy' => \true, '.console.command.assets_install.lazy' => \true, '.console.command.cache_clear.lazy' => \true, '.console.command.cache_pool_clear.lazy' => \true, '.console.command.cache_pool_delete.lazy' => \true, '.console.command.cache_pool_invalidate_tags.lazy' => \true, '.console.command.cache_pool_list.lazy' => \true, '.console.command.cache_pool_prune.lazy' => \true, '.console.command.cache_warmup.lazy' => \true, '.console.command.config_debug.lazy' => \true, '.console.command.config_dump_reference.lazy' => \true, '.console.command.container_debug.lazy' => \true, '.console.command.container_lint.lazy' => \true, '.console.command.debug_autowiring.lazy' => \true, '.console.command.event_dispatcher_debug.lazy' => \true, '.console.command.router_debug.lazy' => \true, '.console.command.router_match.lazy' => \true, '.console.command.secrets_decrypt_to_local.lazy' => \true, '.console.command.secrets_encrypt_from_local.lazy' => \true, '.console.command.secrets_generate_key.lazy' => \true, '.console.command.secrets_list.lazy' => \true, '.console.command.secrets_remove.lazy' => \true, '.console.command.secrets_set.lazy' => \true, '.console.command.serializer_debug.lazy' => \true, '.console.command.yaml_lint.lazy' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Composer\\CloudResolver.0.Contao\\ManagerApi\\Composer\\CloudResolver' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\EventListener\\CheckTotpListener.0.Contao\\ManagerApi\\EventListener\\CheckTotpListener' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\EventListener\\ExceptionListener.0.Contao\\ManagerApi\\EventListener\\ExceptionListener' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\EventListener\\JsonRequestListener.0.Contao\\ManagerApi\\EventListener\\JsonRequestListener' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\EventListener\\SecurityListener.0.Contao\\ManagerApi\\EventListener\\SecurityListener' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Process\\ConsoleProcessFactory.0.Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Security\\WebauthnAuthenticator.0.Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Packages\\InstallTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Packages\\SetupTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskInterface.0.Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => \true, '_ContaoManager\\.instanceof.Contao\\ManagerApi\\Task\\TaskManager.0.Contao\\ManagerApi\\Task\\TaskManager' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Composer\\CloudResolver' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Composer\\ClearCacheOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Composer\\CreateProjectOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Composer\\DumpAutoloadOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Composer\\InstallOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Composer\\RemoveOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Composer\\RequireOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Composer\\UpdateOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Contao\\BackupCreateOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Contao\\BackupRestoreOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Contao\\CacheClearOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Contao\\CacheWarmupOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Contao\\CreateContaoOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Contao\\MaintenanceModeOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Filesystem\\InstallUploadsOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveCacheOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveUploadsOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveVendorOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\TaskOperation\\Manager\\SelfUpdateOperation' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Packages\\InstallTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Packages\\SetupTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => \true, '_ContaoManager\\.instanceof.Psr\\Log\\LoggerAwareInterface.0.Contao\\ManagerApi\\Task\\TaskManager' => \true, '_ContaoManager\\.instanceof.Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController.0.Contao\\ManagerApi\\Controller\\FileController' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\Console\\Command\\Command.0.Contao\\ManagerApi\\Command\\AboutCommand' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\Console\\Command\\Command.0.Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\Console\\Command\\Command.0.Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\Console\\Command\\Command.0.Contao\\ManagerApi\\Command\\TaskAbortCommand' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\Console\\Command\\Command.0.Contao\\ManagerApi\\Command\\TaskDeleteCommand' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\Console\\Command\\Command.0.Contao\\ManagerApi\\Command\\TaskUpdateCommand' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\Console\\Command\\Command.0.Contao\\ManagerApi\\Command\\UpdateCommand' => \true, '_ContaoManager\\.instanceof.Symfony\\Component\\EventDispatcher\\EventSubscriberInterface.0.Contao\\ManagerApi\\EventListener\\LocaleListener' => \true, '.instanceof.Symfony\\Component\\EventDispatcher\\EventSubscriberInterface.0.locale_listener' => \true, '_ContaoManager\\.instanceof.Symfony\\Contracts\\Service\\ResetInterface.0.Contao\\ManagerApi\\ApiApplication' => \true, '_ContaoManager\\.instanceof.Symfony\\Contracts\\Service\\ServiceSubscriberInterface.0.Contao\\ManagerApi\\Controller\\FileController' => \true, '_ContaoManager\\.instanceof.Symfony\\Contracts\\Service\\ServiceSubscriberInterface.0.Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => \true, '.security.command.debug_firewall.lazy' => \true, '.security.command.user_password_hash.lazy' => \true, '.security.request_matcher.AMZT15Y' => \true, '.security.request_matcher.LBzTDsp' => \true, '.security.request_matcher.gjnNpJn' => \true, '.security.request_matcher.j_9S1dW' => \true, '.service_locator..Fs8Kd7' => \true, '.service_locator.7ILhJfy' => \true, '.service_locator.7clGYzp' => \true, '.service_locator.9gXQpqd' => \true, '.service_locator.9gXQpqd.router.default' => \true, '.service_locator.BUTPlx4' => \true, '.service_locator.BvkMlPl' => \true, '.service_locator.Ct6lrWe' => \true, '.service_locator.EZsc.DO' => \true, '.service_locator.H.Zsu_s' => \true, '.service_locator.IMte7nJ' => \true, '.service_locator.JkQTEiI' => \true, '.service_locator.MlbgBlB' => \true, '.service_locator.NBUFN6A' => \true, '.service_locator.QRKZpFh' => \true, '.service_locator.VdCFd8p' => \true, '.service_locator.WxpRori' => \true, '.service_locator.XXv1IfR' => \true, '.service_locator.XZyI1uB' => \true, '_ContaoManager\\.service_locator.XZyI1uB.Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => \true, '.service_locator.Xbsa8iG' => \true, '.service_locator.aH5O6Sd' => \true, '.service_locator.bJ.4HC5' => \true, '.service_locator.cUcW89y' => \true, '.service_locator.cUcW89y.router.cache_warmer' => \true, '.service_locator.e_.xxAP' => \true, '.service_locator.jK0HQn2' => \true, '.service_locator.lLv4pWF' => \true, '.service_locator.spTGjxd' => \true, '.service_locator.tpD_zef' => \true, '.service_locator.uOz8uDJ' => \true, '_ContaoManager\\.service_locator.uOz8uDJ.Contao\\ManagerApi\\Controller\\FileController' => \true, '.service_locator.uPlitoC' => \true, '.service_locator.w7.f4fT' => \true, '.service_locator.y.Xs7Mw' => \true, '_ContaoManager\\Contao\\ManagerApi\\ApiApplication' => \true, '_ContaoManager\\Contao\\ManagerApi\\ApiKernel' => \true, '_ContaoManager\\Contao\\ManagerApi\\Command' => \true, '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudChanges' => \true, '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudException' => \true, '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudJob' => \true, '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver' => \true, '_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment' => \true, '_ContaoManager\\Contao\\ManagerApi\\Config\\AuthConfig' => \true, '_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig' => \true, '_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig' => \true, '_ContaoManager\\Contao\\ManagerApi\\Config\\PartialConfig' => \true, '_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig' => \true, '_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig' => \true, '_ContaoManager\\Contao\\ManagerApi\\Controller' => \true, '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener' => \true, '_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener' => \true, '_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener' => \true, '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener' => \true, '_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener' => \true, '_ContaoManager\\Contao\\ManagerApi\\Exception\\ApiProblemException' => \true, '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidJsonException' => \true, '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidTotpException' => \true, '_ContaoManager\\Contao\\ManagerApi\\Exception\\ProcessOutputException' => \true, '_ContaoManager\\Contao\\ManagerApi\\Exception\\RequestException' => \true, '_ContaoManager\\Contao\\ManagerApi\\HttpKernel\\ApiProblemResponse' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ZipCheck' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\DisownForker' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\InlineForker' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\NohupForker' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\WindowsStartForker' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\PhpExecutableFinder' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessController' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessRunner' => \true, '_ContaoManager\\Contao\\ManagerApi\\Process\\Utf8Process' => \true, '_ContaoManager\\Contao\\ManagerApi\\Resources' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\TotpBadge' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\User' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider' => \true, '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => \true, '_ContaoManager\\Contao\\ManagerApi\\System\\Request' => \true, '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate' => \true, '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\ClearCacheOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CloudOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CreateProjectOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\DumpAutoloadOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\InstallOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RemoveOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RequireOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\UpdateOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\ConsoleOutput' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupCreateOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupRestoreOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheClearOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheWarmupOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CreateContaoOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\MaintenanceModeOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\InstallUploadsOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveCacheOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveUploadsOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveVendorOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Manager\\SelfUpdateOperation' => \true, '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\SponsoredOperationInterface' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskConfig' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager' => \true, '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskStatus' => \true, '_ContaoManager\\Contao\\ManagerApi\\Tests' => \true, '_ContaoManager\\Psr\\Cache\\CacheItemPoolInterface' => \true, '_ContaoManager\\Psr\\Clock\\ClockInterface' => \true, 'Psr\\Container\\ContainerInterface $parameterBag' => \true, '_ContaoManager\\Psr\\EventDispatcher\\EventDispatcherInterface' => \true, '_ContaoManager\\Psr\\Log\\LoggerInterface' => \true, 'Psr\\Log\\LoggerInterface $cacheLogger' => \true, 'Psr\\Log\\LoggerInterface $consoleLogger' => \true, 'Psr\\Log\\LoggerInterface $phpLogger' => \true, 'Psr\\Log\\LoggerInterface $requestLogger' => \true, 'Psr\\Log\\LoggerInterface $routerLogger' => \true, 'Psr\\Log\\LoggerInterface $securityLogger' => \true, 'Psr\\Log\\LoggerInterface $tasksLogger' => \true, '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security' => \true, '_ContaoManager\\Symfony\\Component\\Clock\\ClockInterface' => \true, '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderInterface' => \true, '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBagInterface' => \true, '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => \true, '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ReverseContainer' => \true, '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter' => \true, '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => \true, '_ContaoManager\\Symfony\\Component\\Filesystem\\Filesystem' => \true, '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Request' => \true, '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestStack' => \true, '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Response' => \true, '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionInterface' => \true, '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UriSigner' => \true, '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UrlHelper' => \true, '_ContaoManager\\Symfony\\Component\\HttpKernel\\Config\\FileLocator' => \true, '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGeneratorInterface' => \true, '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface' => \true, '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelInterface' => \true, '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelInterface' => \true, '_ContaoManager\\Symfony\\Component\\HttpKernel\\UriSigner' => \true, '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactoryInterface' => \true, '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasherInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => \true, '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface' => \true, '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface' => \true, '_ContaoManager\\Symfony\\Component\\Routing\\RequestContext' => \true, '_ContaoManager\\Symfony\\Component\\Routing\\RequestContextAwareInterface' => \true, '_ContaoManager\\Symfony\\Component\\Routing\\RouterInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationCheckerInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchyInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Core\\Security' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserProviderInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationUtils' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\UserAuthenticatorInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMapInterface' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Http\\HttpUtils' => \true, '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategyInterface' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\DecoderInterface' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\EncoderInterface' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorResolverInterface' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryInterface' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer' => \true, '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerInterface' => \true, '_ContaoManager\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => \true, '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\NameBasedUuidFactory' => \true, '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\RandomBasedUuidFactory' => \true, '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\TimeBasedUuidFactory' => \true, '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UlidFactory' => \true, '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UuidFactory' => \true, '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheInterface' => \true, '_ContaoManager\\Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => \true, '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => \true, 'argument_metadata_factory' => \true, 'argument_resolver' => \true, 'argument_resolver.backed_enum_resolver' => \true, 'argument_resolver.controller_locator' => \true, 'argument_resolver.datetime' => \true, 'argument_resolver.default' => \true, 'argument_resolver.query_parameter_value_resolver' => \true, 'argument_resolver.request' => \true, 'argument_resolver.request_attribute' => \true, 'argument_resolver.request_payload' => \true, 'argument_resolver.service' => \true, 'argument_resolver.session' => \true, 'argument_resolver.uid' => \true, 'argument_resolver.variadic' => \true, 'cache.adapter.apcu' => \true, 'cache.adapter.array' => \true, 'cache.adapter.doctrine_dbal' => \true, 'cache.adapter.filesystem' => \true, 'cache.adapter.memcached' => \true, 'cache.adapter.pdo' => \true, 'cache.adapter.psr6' => \true, 'cache.adapter.redis' => \true, 'cache.adapter.redis_tag_aware' => \true, 'cache.adapter.system' => \true, 'cache.annotations' => \true, 'cache.app.taggable' => \true, 'cache.default_clearer' => \true, 'cache.default_doctrine_dbal_provider' => \true, 'cache.default_marshaller' => \true, 'cache.default_memcached_provider' => \true, 'cache.default_redis_provider' => \true, 'cache.early_expiration_handler' => \true, 'cache.property_access' => \true, 'cache.property_info' => \true, 'cache.security_expression_language' => \true, 'cache.serializer' => \true, 'cache.validator' => \true, 'cache_clearer' => \true, 'clock' => \true, 'config.resource.self_checking_resource_checker' => \true, 'config_builder.warmer' => \true, 'config_cache_factory' => \true, 'console.command.about' => \true, 'console.command.assets_install' => \true, 'console.command.cache_clear' => \true, 'console.command.cache_pool_clear' => \true, 'console.command.cache_pool_delete' => \true, 'console.command.cache_pool_invalidate_tags' => \true, 'console.command.cache_pool_list' => \true, 'console.command.cache_pool_prune' => \true, 'console.command.cache_warmup' => \true, 'console.command.config_debug' => \true, 'console.command.config_dump_reference' => \true, 'console.command.container_debug' => \true, 'console.command.container_lint' => \true, 'console.command.debug_autowiring' => \true, 'console.command.event_dispatcher_debug' => \true, 'console.command.router_debug' => \true, 'console.command.router_match' => \true, 'console.command.secrets_decrypt_to_local' => \true, 'console.command.secrets_encrypt_from_local' => \true, 'console.command.secrets_generate_key' => \true, 'console.command.secrets_list' => \true, 'console.command.secrets_remove' => \true, 'console.command.secrets_set' => \true, 'console.command.serializer_debug' => \true, 'console.command.yaml_lint' => \true, 'console.error_listener' => \true, 'console.messenger.application' => \true, 'console.messenger.execute_command_handler' => \true, 'console.suggest_missing_package_subscriber' => \true, 'container.env' => \true, 'container.env_var_processor' => \true, 'container.getenv' => \true, 'contao_manager.webauthn.authenticator_assertion_response_validator' => \true, 'contao_manager.webauthn.authenticator_attestation_response_validator' => \true, 'contao_manager.webauthn.ceremony_step_manager_factory' => \true, 'contao_manager.webauthn.creation_ceremony' => \true, 'contao_manager.webauthn.request_ceremony' => \true, 'contao_manager.webauthn.serializer' => \true, 'contao_manager.webauthn.serializer_factory' => \true, 'controller.cache_attribute_listener' => \true, 'controller.is_granted_attribute_listener' => \true, 'controller_resolver' => \true, 'data_collector.security' => \true, 'debug.debug_handlers_listener' => \true, 'debug.file_link_formatter' => \true, 'dependency_injection.config.container_parameters_resource_checker' => \true, 'error_handler.error_renderer.html' => \true, 'error_handler.error_renderer.serializer' => \true, 'error_renderer' => \true, 'error_renderer.html' => \true, 'error_renderer.serializer' => \true, 'exception_listener' => \true, 'file_locator' => \true, 'filesystem' => \true, 'fragment.handler' => \true, 'fragment.renderer.inline' => \true, 'fragment.uri_generator' => \true, 'http_cache' => \true, 'http_cache.store' => \true, 'locale_aware_listener' => \true, 'locale_listener' => \true, 'logger' => \true, 'monolog.activation_strategy.not_found' => \true, 'monolog.formatter.chrome_php' => \true, 'monolog.formatter.gelf_message' => \true, 'monolog.formatter.html' => \true, 'monolog.formatter.json' => \true, 'monolog.formatter.line' => \true, 'monolog.formatter.loggly' => \true, 'monolog.formatter.logstash' => \true, 'monolog.formatter.normalizer' => \true, 'monolog.formatter.scalar' => \true, 'monolog.formatter.wildfire' => \true, 'monolog.handler.file' => \true, 'monolog.handler.fingers_crossed.error_level_activation_strategy' => \true, 'monolog.handler.main' => \true, 'monolog.handler.null_internal' => \true, 'monolog.http_client' => \true, 'monolog.logger' => \true, 'monolog.logger.cache' => \true, 'monolog.logger.console' => \true, 'monolog.logger.php' => \true, 'monolog.logger.request' => \true, 'monolog.logger.router' => \true, 'monolog.logger.security' => \true, 'monolog.logger.tasks' => \true, 'monolog.logger_prototype' => \true, 'monolog.processor.psr_log_message' => \true, 'name_based_uuid.factory' => \true, 'parameter_bag' => \true, 'process.messenger.process_message_handler' => \true, 'property_accessor' => \true, 'property_info' => \true, 'property_info.cache' => \true, 'property_info.cache.inner' => \true, 'property_info.php_doc_extractor' => \true, 'property_info.phpstan_extractor' => \true, 'property_info.reflection_extractor' => \true, 'property_info.serializer_extractor' => \true, 'random_based_uuid.factory' => \true, 'response_listener' => \true, 'reverse_container' => \true, 'router.cache_warmer' => \true, 'router.default' => \true, 'router.request_context' => \true, 'router_listener' => \true, 'routing.loader.annotation' => \true, 'routing.loader.annotation.directory' => \true, 'routing.loader.annotation.file' => \true, 'routing.loader.attribute' => \true, 'routing.loader.attribute.directory' => \true, 'routing.loader.attribute.file' => \true, 'routing.loader.container' => \true, 'routing.loader.directory' => \true, 'routing.loader.glob' => \true, 'routing.loader.php' => \true, 'routing.loader.psr4' => \true, 'routing.loader.xml' => \true, 'routing.loader.yml' => \true, 'routing.resolver' => \true, 'secrets.decryption_key' => \true, 'secrets.local_vault' => \true, 'secrets.vault' => \true, 'security.access.authenticated_voter' => \true, 'security.access.decision_manager' => \true, 'security.access.role_hierarchy_voter' => \true, 'security.access_listener' => \true, 'security.access_map' => \true, 'security.access_token_extractor.header' => \true, 'security.access_token_extractor.query_string' => \true, 'security.access_token_extractor.request_body' => \true, 'security.access_token_handler.oidc' => \true, 'security.access_token_handler.oidc.jwk' => \true, 'security.access_token_handler.oidc.signature' => \true, 'security.access_token_handler.oidc.signature.ES256' => \true, 'security.access_token_handler.oidc.signature.ES384' => \true, 'security.access_token_handler.oidc.signature.ES512' => \true, 'security.access_token_handler.oidc_user_info' => \true, 'security.access_token_handler.oidc_user_info.http_client' => \true, 'security.authentication.custom_failure_handler' => \true, 'security.authentication.custom_success_handler' => \true, 'security.authentication.failure_handler' => \true, 'security.authentication.listener.abstract' => \true, 'security.authentication.session_strategy' => \true, 'security.authentication.session_strategy.api' => \true, 'security.authentication.session_strategy_noop' => \true, 'security.authentication.success_handler' => \true, 'security.authentication.switchuser_listener' => \true, 'security.authentication.trust_resolver' => \true, 'security.authentication_utils' => \true, 'security.authenticator.access_token' => \true, 'security.authenticator.access_token.chain_extractor' => \true, 'security.authenticator.form_login' => \true, 'security.authenticator.http_basic' => \true, 'security.authenticator.json_login' => \true, 'security.authenticator.manager' => \true, 'security.authenticator.manager.api' => \true, 'security.authenticator.managers_locator' => \true, 'security.authenticator.remote_user' => \true, 'security.authenticator.x509' => \true, 'security.authorization_checker' => \true, 'security.channel_listener' => \true, 'security.command.debug_firewall' => \true, 'security.command.user_password_hash' => \true, 'security.context_listener' => \true, 'security.event_dispatcher.api' => \true, 'security.exception_listener' => \true, 'security.exception_listener.api' => \true, 'security.firewall' => \true, 'security.firewall.authenticator' => \true, 'security.firewall.authenticator.api' => \true, 'security.firewall.config' => \true, 'security.firewall.context' => \true, 'security.firewall.context_locator' => \true, 'security.firewall.event_dispatcher_locator' => \true, 'security.firewall.lazy_context' => \true, 'security.firewall.map' => \true, 'security.firewall.map.config.api' => \true, 'security.firewall.map.context.api' => \true, 'security.helper' => \true, 'security.http_utils' => \true, 'security.impersonate_url_generator' => \true, 'security.ldap_locator' => \true, 'security.listener.api.user_provider' => \true, 'security.listener.check_authenticator_credentials' => \true, 'security.listener.login_throttling' => \true, 'security.listener.password_migrating' => \true, 'security.listener.session' => \true, 'security.listener.user_checker' => \true, 'security.listener.user_checker.api' => \true, 'security.listener.user_provider' => \true, 'security.listener.user_provider.abstract' => \true, 'security.logout.listener.clear_site_data' => \true, 'security.logout.listener.cookie_clearing' => \true, 'security.logout.listener.default' => \true, 'security.logout.listener.session' => \true, 'security.logout_listener' => \true, 'security.logout_url_generator' => \true, 'security.password_hasher' => \true, 'security.password_hasher_factory' => \true, 'security.role_hierarchy' => \true, 'security.route_loader.logout' => \true, 'security.security_token_value_resolver' => \true, 'security.untracked_token_storage' => \true, 'security.user.provider.chain' => \true, 'security.user.provider.concrete.contao_manager_user_provider' => \true, 'security.user.provider.in_memory' => \true, 'security.user.provider.ldap' => \true, 'security.user.provider.missing' => \true, 'security.user_authenticator' => \true, 'security.user_checker' => \true, 'security.user_checker.api' => \true, 'security.user_checker.chain.api' => \true, 'security.user_checker_locator' => \true, 'security.user_password_hasher' => \true, 'security.user_providers' => \true, 'security.user_value_resolver' => \true, 'security.validator.user_password' => \true, 'serializer' => \true, 'serializer.denormalizer.array' => \true, 'serializer.denormalizer.unwrapping' => \true, 'serializer.encoder.csv' => \true, 'serializer.encoder.json' => \true, 'serializer.encoder.xml' => \true, 'serializer.encoder.yaml' => \true, 'serializer.mapping.cache.symfony' => \true, 'serializer.mapping.cache_class_metadata_factory' => \true, 'serializer.mapping.cache_class_metadata_factory.inner' => \true, 'serializer.mapping.cache_warmer' => \true, 'serializer.mapping.chain_loader' => \true, 'serializer.mapping.class_discriminator_resolver' => \true, 'serializer.mapping.class_metadata_factory' => \true, 'serializer.name_converter.camel_case_to_snake_case' => \true, 'serializer.name_converter.metadata_aware' => \true, 'serializer.normalizer.backed_enum' => \true, 'serializer.normalizer.constraint_violation_list' => \true, 'serializer.normalizer.data_uri' => \true, 'serializer.normalizer.dateinterval' => \true, 'serializer.normalizer.datetime' => \true, 'serializer.normalizer.datetimezone' => \true, 'serializer.normalizer.form_error' => \true, 'serializer.normalizer.json_serializable' => \true, 'serializer.normalizer.object' => \true, 'serializer.normalizer.problem' => \true, 'serializer.normalizer.property' => \true, 'serializer.normalizer.uid' => \true, 'serializer.property_accessor' => \true, 'slugger' => \true, 'time_based_uuid.factory' => \true, 'ulid.factory' => \true, 'uri_signer' => \true, 'url_helper' => \true, 'uuid.factory' => \true, 'validate_request_listener' => \true]; services['_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand(); $instance->setName('background-task:run'); $instance->setDescription('Execute a background task'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'] ?? self::getJwtManagerService($container)); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\ContaoController($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi'] ?? $container->load('getContaoApiService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['security.access_map'] = $instance = new \_ContaoManager\Symfony\Component\Security\Http\AccessMap(); $instance->add(new \_ContaoManager\Symfony\Component\HttpFoundation\ChainRequestMatcher([new \_ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher('^/api/session(/options)?$')]), ['PUBLIC_ACCESS'], NULL); $instance->add(new \_ContaoManager\Symfony\Component\HttpFoundation\ChainRequestMatcher([new \_ContaoManager\Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher('^/api')]), ['ROLE_USER'], NULL); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\IntegrityCheckFactory((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck', 'getAllowUrlFopenCheckService', \true], '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck', 'getGraphicsLibCheckService', \true], '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck', 'getMemoryLimitCheckService', \true], '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck', 'getPhpExtensionsCheckService', \true], '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck', 'getProcessCheckService', \true], '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck', 'getSessionCheckService', \true], '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck', 'getSymlinkCheckService', \true], '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck', 'getSysTempDirCheckService', \true]], ['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck' => '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck']))->withContext('_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory', $container)); } } privates['console.command.container_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand(); $instance->setName('debug:container'); $instance->setDescription('Display current services for an application'); return $instance; } } privates['.console.command.container_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:container', [], 'Display current services for an application', \false, #[\Closure(name: 'console.command.container_debug', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand => $container->privates['console.command.container_debug'] ?? $container->load('getConsole_Command_ContainerDebugService')); } } services['event_dispatcher'] ?? self::getEventDispatcherService($container); if (isset($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator'])) { return $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator']; } $b = new \_ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory(); $c = new \_ContaoManager\Webauthn\AuthenticatorAttestationResponseValidator(NULL, NULL, NULL, NULL, $a, $b->creationCeremony()); $d = $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'); $c->setLogger($d); $e = new \_ContaoManager\Webauthn\AuthenticatorAssertionResponseValidator(NULL, NULL, NULL, NULL, $a, $b->requestCeremony()); $e->setLogger($d); return $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator((new \_ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory(new \_ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager()))->create(), $c, $e, $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'] ?? self::getJwtManagerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['kernel'] ?? $container->get('kernel', 1)); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\JwtCookieController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi'] ?? $container->load('getContaoApiService')); } } privates['router.cache_warmer'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['router' => ['services', 'router', 'getRouterService', \false]], ['router' => '?']))->withContext('router.cache_warmer', $container)); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Contao\BackupRestoreTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } services['console.command_loader'] = new \_ContaoManager\Symfony\Component\Console\CommandLoader\ContainerCommandLoader(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand' => ['privates', '.Contao\\ManagerApi\\Command\\AboutCommand.lazy', 'getAboutCommand_LazyService', \true], '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => ['privates', '.Contao\\ManagerApi\\Command\\IntegrityCheckCommand.lazy', 'getIntegrityCheckCommand_LazyService', \true], '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => ['privates', '.Contao\\ManagerApi\\Command\\ProcessRunnerCommand.lazy', 'getProcessRunnerCommand_LazyService', \true], '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand' => ['privates', '.Contao\\ManagerApi\\Command\\TaskAbortCommand.lazy', 'getTaskAbortCommand_LazyService', \true], '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand' => ['privates', '.Contao\\ManagerApi\\Command\\TaskDeleteCommand.lazy', 'getTaskDeleteCommand_LazyService', \true], '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand' => ['privates', '.Contao\\ManagerApi\\Command\\TaskUpdateCommand.lazy', 'getTaskUpdateCommand_LazyService', \true], '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand' => ['privates', '.Contao\\ManagerApi\\Command\\UpdateCommand.lazy', 'getUpdateCommand_LazyService', \true], 'console.command.about' => ['privates', '.console.command.about.lazy', 'get_Console_Command_About_LazyService', \true], 'console.command.assets_install' => ['privates', '.console.command.assets_install.lazy', 'get_Console_Command_AssetsInstall_LazyService', \true], 'console.command.cache_clear' => ['privates', '.console.command.cache_clear.lazy', 'get_Console_Command_CacheClear_LazyService', \true], 'console.command.cache_pool_clear' => ['privates', '.console.command.cache_pool_clear.lazy', 'get_Console_Command_CachePoolClear_LazyService', \true], 'console.command.cache_pool_prune' => ['privates', '.console.command.cache_pool_prune.lazy', 'get_Console_Command_CachePoolPrune_LazyService', \true], 'console.command.cache_pool_invalidate_tags' => ['privates', '.console.command.cache_pool_invalidate_tags.lazy', 'get_Console_Command_CachePoolInvalidateTags_LazyService', \true], 'console.command.cache_pool_delete' => ['privates', '.console.command.cache_pool_delete.lazy', 'get_Console_Command_CachePoolDelete_LazyService', \true], 'console.command.cache_pool_list' => ['privates', '.console.command.cache_pool_list.lazy', 'get_Console_Command_CachePoolList_LazyService', \true], 'console.command.cache_warmup' => ['privates', '.console.command.cache_warmup.lazy', 'get_Console_Command_CacheWarmup_LazyService', \true], 'console.command.config_debug' => ['privates', '.console.command.config_debug.lazy', 'get_Console_Command_ConfigDebug_LazyService', \true], 'console.command.config_dump_reference' => ['privates', '.console.command.config_dump_reference.lazy', 'get_Console_Command_ConfigDumpReference_LazyService', \true], 'console.command.container_debug' => ['privates', '.console.command.container_debug.lazy', 'get_Console_Command_ContainerDebug_LazyService', \true], 'console.command.container_lint' => ['privates', '.console.command.container_lint.lazy', 'get_Console_Command_ContainerLint_LazyService', \true], 'console.command.debug_autowiring' => ['privates', '.console.command.debug_autowiring.lazy', 'get_Console_Command_DebugAutowiring_LazyService', \true], 'console.command.event_dispatcher_debug' => ['privates', '.console.command.event_dispatcher_debug.lazy', 'get_Console_Command_EventDispatcherDebug_LazyService', \true], 'console.command.router_debug' => ['privates', '.console.command.router_debug.lazy', 'get_Console_Command_RouterDebug_LazyService', \true], 'console.command.router_match' => ['privates', '.console.command.router_match.lazy', 'get_Console_Command_RouterMatch_LazyService', \true], 'console.command.serializer_debug' => ['privates', '.console.command.serializer_debug.lazy', 'get_Console_Command_SerializerDebug_LazyService', \true], 'console.command.yaml_lint' => ['privates', '.console.command.yaml_lint.lazy', 'get_Console_Command_YamlLint_LazyService', \true], 'console.command.secrets_set' => ['privates', '.console.command.secrets_set.lazy', 'get_Console_Command_SecretsSet_LazyService', \true], 'console.command.secrets_remove' => ['privates', '.console.command.secrets_remove.lazy', 'get_Console_Command_SecretsRemove_LazyService', \true], 'console.command.secrets_generate_key' => ['privates', '.console.command.secrets_generate_key.lazy', 'get_Console_Command_SecretsGenerateKey_LazyService', \true], 'console.command.secrets_list' => ['privates', '.console.command.secrets_list.lazy', 'get_Console_Command_SecretsList_LazyService', \true], 'console.command.secrets_decrypt_to_local' => ['privates', '.console.command.secrets_decrypt_to_local.lazy', 'get_Console_Command_SecretsDecryptToLocal_LazyService', \true], 'console.command.secrets_encrypt_from_local' => ['privates', '.console.command.secrets_encrypt_from_local.lazy', 'get_Console_Command_SecretsEncryptFromLocal_LazyService', \true], 'security.command.debug_firewall' => ['privates', '.security.command.debug_firewall.lazy', 'get_Security_Command_DebugFirewall_LazyService', \true], 'security.command.user_password_hash' => ['privates', '.security.command.user_password_hash.lazy', 'get_Security_Command_UserPasswordHash_LazyService', \true]], ['_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand' => '?', '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => '?', '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => '?', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand' => '?', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand' => '?', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand' => '?', '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand' => '?', 'console.command.about' => '?', 'console.command.assets_install' => '?', 'console.command.cache_clear' => '?', 'console.command.cache_pool_clear' => '?', 'console.command.cache_pool_prune' => '?', 'console.command.cache_pool_invalidate_tags' => '?', 'console.command.cache_pool_delete' => '?', 'console.command.cache_pool_list' => '?', 'console.command.cache_warmup' => '?', 'console.command.config_debug' => '?', 'console.command.config_dump_reference' => '?', 'console.command.container_debug' => '?', 'console.command.container_lint' => '?', 'console.command.debug_autowiring' => '?', 'console.command.event_dispatcher_debug' => '?', 'console.command.router_debug' => '?', 'console.command.router_match' => '?', 'console.command.serializer_debug' => '?', 'console.command.yaml_lint' => '?', 'console.command.secrets_set' => '?', 'console.command.secrets_remove' => '?', 'console.command.secrets_generate_key' => '?', 'console.command.secrets_list' => '?', 'console.command.secrets_decrypt_to_local' => '?', 'console.command.secrets_encrypt_from_local' => '?', 'security.command.debug_firewall' => '?', 'security.command.user_password_hash' => '?']), ['about' => 'console.command.about', 'integrity-check' => '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand', 'background-task:run' => '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand', 'task:abort' => '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand', 'task:delete' => '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand', 'task:update' => '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand', 'self-update' => '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand', 'assets:install' => 'console.command.assets_install', 'cache:clear' => 'console.command.cache_clear', 'cache:pool:clear' => 'console.command.cache_pool_clear', 'cache:pool:prune' => 'console.command.cache_pool_prune', 'cache:pool:invalidate-tags' => 'console.command.cache_pool_invalidate_tags', 'cache:pool:delete' => 'console.command.cache_pool_delete', 'cache:pool:list' => 'console.command.cache_pool_list', 'cache:warmup' => 'console.command.cache_warmup', 'debug:config' => 'console.command.config_debug', 'config:dump-reference' => 'console.command.config_dump_reference', 'debug:container' => 'console.command.container_debug', 'lint:container' => 'console.command.container_lint', 'debug:autowiring' => 'console.command.debug_autowiring', 'debug:event-dispatcher' => 'console.command.event_dispatcher_debug', 'debug:router' => 'console.command.router_debug', 'router:match' => 'console.command.router_match', 'debug:serializer' => 'console.command.serializer_debug', 'lint:yaml' => 'console.command.yaml_lint', 'secrets:set' => 'console.command.secrets_set', 'secrets:remove' => 'console.command.secrets_remove', 'secrets:generate-keys' => 'console.command.secrets_generate_key', 'secrets:list' => 'console.command.secrets_list', 'secrets:decrypt-to-local' => 'console.command.secrets_decrypt_to_local', 'secrets:encrypt-from-local' => 'console.command.secrets_encrypt_from_local', 'debug:firewall' => 'security.command.debug_firewall', 'security:hash-password' => 'security.command.user_password_hash']); } } services['cache.app'] = $instance = new \_ContaoManager\Symfony\Component\Cache\Adapter\FilesystemAdapter('oir3ScyWr8', 0, $container->targetDir . '' . '/pools/app', new \_ContaoManager\Symfony\Component\Cache\Marshaller\DefaultMarshaller(NULL, \false)); $instance->setLogger($container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container)); return $instance; } } privates['console.command.secrets_set'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local')); $instance->setName('secrets:set'); $instance->setDescription('Set a secret in the vault'); return $instance; } } privates['security.command.user_password_hash'] = $instance = new \_ContaoManager\Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container), ['_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordAuthenticatedUserInterface']); $instance->setName('security:hash-password'); $instance->setDescription('Hash a user password'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] = $instance = new \_ContaoManager\Contao\ManagerApi\Process\ConsoleProcessFactory($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo'] ?? $container->load('getServerInfoService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['.console.command.config_dump_reference.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('config:dump-reference', [], 'Dump the default configuration for an extension', \false, #[\Closure(name: 'console.command.config_dump_reference', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDumpReferenceCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand => $container->privates['console.command.config_dump_reference'] ?? $container->load('getConsole_Command_ConfigDumpReferenceService')); } } services['cache.app_clearer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer(['cache.app' => $container->services['cache.app'] ?? $container->load('getCache_AppService')]); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController'] = new \_ContaoManager\Contao\ManagerApi\Controller\UserController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container), $container->services['router'] ?? self::getRouterService($container), $container->privates['security.helper'] ?? $container->load('getSecurity_HelperService'), $container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container)); } } privates['console.command.router_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand($container->services['router'] ?? self::getRouterService($container), $container->privates['debug.file_link_formatter'] ??= new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter(NULL)); $instance->setName('debug:router'); $instance->setDescription('Display current routes for an application'); return $instance; } } targetDir = \dirname($containerDir); $this->parameters = $this->getDefaultParameters(); $this->services = $this->privates = []; $this->syntheticIds = ['kernel' => \true]; $this->methodMap = ['event_dispatcher' => 'getEventDispatcherService', 'http_kernel' => 'getHttpKernelService', 'request_stack' => 'getRequestStackService', 'router' => 'getRouterService', 'security.token_storage' => 'getSecurity_TokenStorageService']; $this->fileMap = ['_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand' => 'getAboutCommandService', '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => 'getIntegrityCheckCommandService', '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => 'getProcessRunnerCommandService', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand' => 'getTaskAbortCommandService', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand' => 'getTaskDeleteCommandService', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand' => 'getTaskUpdateCommandService', '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand' => 'getUpdateCommandService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController' => 'getAuthControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController' => 'getComposerControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController' => 'getManagerControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController' => 'getConstraintControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController' => 'getAccessKeyControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController' => 'getBackupControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController' => 'getDatabaseMigrationControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController' => 'getInstallToolLockControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController' => 'getJwtCookieControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController' => 'getMaintenanceModeControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController' => 'getFileControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController' => 'getLogControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController' => 'getCloudControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController' => 'getLocalPackagesControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController' => 'getMissingPackagesControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController' => 'getRootPackageControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController' => 'getUploadPackagesControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => 'getAdminUserControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => 'getComposerController2Service', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController' => 'getConfigControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController' => 'getContaoControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController' => 'getDatabaseControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController' => 'getOpcacheControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => 'getPhpCliControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => 'getPhpWebControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController' => 'getPhpinfoControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => 'getSelfUpdateControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController' => 'getSessionControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController' => 'getTaskControllerService', '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController' => 'getUserControllerService', '_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator' => 'getTranslatorService', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController' => 'getRedirectControllerService', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController' => 'getTemplateControllerService', 'cache.app' => 'getCache_AppService', 'cache.app_clearer' => 'getCache_AppClearerService', 'cache.global_clearer' => 'getCache_GlobalClearerService', 'cache.security_is_granted_attribute_expression_language' => 'getCache_SecurityIsGrantedAttributeExpressionLanguageService', 'cache.system' => 'getCache_SystemService', 'cache.system_clearer' => 'getCache_SystemClearerService', 'cache_warmer' => 'getCacheWarmerService', 'console.command_loader' => 'getConsole_CommandLoaderService', 'container.env_var_processors_locator' => 'getContainer_EnvVarProcessorsLocatorService', 'container.get_routing_condition_service' => 'getContainer_GetRoutingConditionServiceService', 'debug.error_handler_configurator' => 'getDebug_ErrorHandlerConfiguratorService', 'error_controller' => 'getErrorControllerService', 'routing.loader' => 'getRouting_LoaderService', 'services_resetter' => 'getServicesResetterService']; $this->aliases = []; } public function compile() : void { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } public function isCompiled() : bool { return \true; } public function getRemovedIds() : array { return require $this->containerDir . \DIRECTORY_SEPARATOR . 'removed-ids.php'; } protected function load($file, $lazyLoad = \true) : mixed { if (\class_exists($class = __NAMESPACE__ . '\\' . $file, \false)) { return $class::do($this, $lazyLoad); } if ('.' === $file[-4]) { $class = \substr($class, 0, -4); } else { $file .= '.php'; } $service = (require $this->containerDir . \DIRECTORY_SEPARATOR . $file); return \class_exists($class, \false) ? $class::do($this, $lazyLoad) : $service; } protected function createProxy($class, \Closure $factory) { \class_exists($class, \false) || (require __DIR__ . '/' . $class . '.php'); return $factory(); } /* * Gets the public 'event_dispatcher' shared service. * * @return \Symfony\Component\EventDispatcher\EventDispatcher */ protected static function getEventDispatcherService($container) { $container->services['event_dispatcher'] = $instance = new \_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher(); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener'] ??= new \_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener(), '__invoke'], 0); $instance->addListener('kernel.exception', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener'] ?? $container->load('getExceptionListenerService'), '__invoke'], 10); $instance->addListener('kernel.request', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener'] ??= new \_ContaoManager\Contao\ManagerApi\EventListener\JsonRequestListener(), '__invoke'], 20); $instance->addListener('kernel.response', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener'] ?? self::getSecurityListenerService($container), '__invoke'], 0); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: 'security.listener.user_provider', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener')] fn() => $container->privates['security.listener.user_provider'] ?? $container->load('getSecurity_Listener_UserProviderService'), 'checkPassport'], 1024); $instance->addListener('kernel.request', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener'] ?? self::getLocaleListenerService($container), 'setDefaultLocale'], 100); $instance->addListener('kernel.request', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener'] ?? self::getLocaleListenerService($container), 'onKernelRequest'], 16); $instance->addListener('kernel.finish_request', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener'] ?? self::getLocaleListenerService($container), 'onKernelFinishRequest'], 0); $instance->addListener('kernel.request', [#[\Closure(name: 'locale_listener', class: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener')] fn() => $container->privates['locale_listener'] ?? self::getLocaleListener2Service($container), 'setDefaultLocale'], 100); $instance->addListener('kernel.request', [#[\Closure(name: 'locale_listener', class: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener')] fn() => $container->privates['locale_listener'] ?? self::getLocaleListener2Service($container), 'onKernelRequest'], 16); $instance->addListener('kernel.finish_request', [#[\Closure(name: 'locale_listener', class: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener')] fn() => $container->privates['locale_listener'] ?? self::getLocaleListener2Service($container), 'onKernelFinishRequest'], 0); $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'argument_resolver.request_payload', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver')] fn() => $container->privates['argument_resolver.request_payload'] ?? self::getArgumentResolver_RequestPayloadService($container), 'onKernelControllerArguments'], 0); $instance->addListener('kernel.response', [#[\Closure(name: 'response_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener')] fn() => $container->privates['response_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\ResponseListener('UTF-8', \false), 'onKernelResponse'], 0); $instance->addListener('kernel.request', [#[\Closure(name: 'validate_request_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener')] fn() => $container->privates['validate_request_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\ValidateRequestListener(), 'onKernelRequest'], 256); $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'onControllerArguments'], 0); $instance->addListener('kernel.exception', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'logKernelException'], 0); $instance->addListener('kernel.exception', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'onKernelException'], -128); $instance->addListener('kernel.response', [#[\Closure(name: 'exception_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener')] fn() => $container->privates['exception_listener'] ?? self::getExceptionListener2Service($container), 'removeCspHeader'], -128); $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'controller.cache_attribute_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\CacheAttributeListener')] fn() => $container->privates['controller.cache_attribute_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener(), 'onKernelControllerArguments'], 10); $instance->addListener('kernel.response', [#[\Closure(name: 'controller.cache_attribute_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\CacheAttributeListener')] fn() => $container->privates['controller.cache_attribute_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\CacheAttributeListener(), 'onKernelResponse'], -10); $instance->addListener('console.error', [#[\Closure(name: 'console.error_listener', class: '_ContaoManager\\Symfony\\Component\\Console\\EventListener\\ErrorListener')] fn() => $container->privates['console.error_listener'] ?? $container->load('getConsole_ErrorListenerService'), 'onConsoleError'], -128); $instance->addListener('console.terminate', [#[\Closure(name: 'console.error_listener', class: '_ContaoManager\\Symfony\\Component\\Console\\EventListener\\ErrorListener')] fn() => $container->privates['console.error_listener'] ?? $container->load('getConsole_ErrorListenerService'), 'onConsoleTerminate'], -128); $instance->addListener('console.error', [#[\Closure(name: 'console.suggest_missing_package_subscriber', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\SuggestMissingPackageSubscriber')] fn() => $container->privates['console.suggest_missing_package_subscriber'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber(), 'onConsoleError'], 0); $instance->addListener('kernel.request', [#[\Closure(name: 'debug.debug_handlers_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener')] fn() => $container->privates['debug.debug_handlers_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener(NULL, $container->getEnv('bool:default::key:web:default:kernel.runtime_mode:')), 'configure'], 2048); $instance->addListener('console.command', [#[\Closure(name: 'debug.debug_handlers_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener')] fn() => $container->privates['debug.debug_handlers_listener'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\DebugHandlersListener(NULL, $container->getEnv('bool:default::key:web:default:kernel.runtime_mode:')), 'configure'], 2048); $instance->addListener('kernel.request', [#[\Closure(name: 'router_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener')] fn() => $container->privates['router_listener'] ?? self::getRouterListenerService($container), 'onKernelRequest'], 32); $instance->addListener('kernel.finish_request', [#[\Closure(name: 'router_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener')] fn() => $container->privates['router_listener'] ?? self::getRouterListenerService($container), 'onKernelFinishRequest'], 0); $instance->addListener('kernel.exception', [#[\Closure(name: 'router_listener', class: '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener')] fn() => $container->privates['router_listener'] ?? self::getRouterListenerService($container), 'onKernelException'], -64); $instance->addListener('kernel.request', [#[\Closure(name: 'security.firewall', class: '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener')] fn() => $container->privates['security.firewall'] ?? self::getSecurity_FirewallService($container), 'configureLogoutUrlGenerator'], 8); $instance->addListener('kernel.request', [#[\Closure(name: 'security.firewall', class: '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener')] fn() => $container->privates['security.firewall'] ?? self::getSecurity_FirewallService($container), 'onKernelRequest'], 8); $instance->addListener('kernel.finish_request', [#[\Closure(name: 'security.firewall', class: '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener')] fn() => $container->privates['security.firewall'] ?? self::getSecurity_FirewallService($container), 'onKernelFinishRequest'], 0); $instance->addListener('kernel.controller_arguments', [#[\Closure(name: 'controller.is_granted_attribute_listener', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\IsGrantedAttributeListener')] fn() => $container->privates['controller.is_granted_attribute_listener'] ?? self::getController_IsGrantedAttributeListenerService($container), 'onKernelControllerArguments'], 20); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: 'security.listener.check_authenticator_credentials', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckCredentialsListener')] fn() => $container->privates['security.listener.check_authenticator_credentials'] ?? $container->load('getSecurity_Listener_CheckAuthenticatorCredentialsService'), 'checkPassport'], 0); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent', [#[\Closure(name: 'security.listener.password_migrating', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener')] fn() => $container->privates['security.listener.password_migrating'] ?? $container->load('getSecurity_Listener_PasswordMigratingService'), 'onLoginSuccess'], 0); return $instance; } /* * Gets the public 'http_kernel' shared service. * * @return \Symfony\Component\HttpKernel\HttpKernel */ protected static function getHttpKernelService($container) { $a = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver($container, $container->privates['monolog.logger.request'] ?? self::getMonolog_Logger_RequestService($container)); $a->allowControllers(['_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController']); $a->allowControllers(['_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController', '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController']); return $container->services['http_kernel'] = new \_ContaoManager\Symfony\Component\HttpKernel\HttpKernel($container->services['event_dispatcher'] ?? self::getEventDispatcherService($container), $a, $container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver(new \_ContaoManager\Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory(), new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['security.user_value_resolver'] ?? $container->load('getSecurity_UserValueResolverService')); (yield 1 => $container->privates['security.security_token_value_resolver'] ?? $container->load('getSecurity_SecurityTokenValueResolverService')); (yield 2 => $container->privates['argument_resolver.backed_enum_resolver'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver()); (yield 3 => $container->privates['argument_resolver.uid'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver()); (yield 4 => $container->privates['argument_resolver.datetime'] ?? $container->load('getArgumentResolver_DatetimeService')); (yield 5 => $container->privates['argument_resolver.request_attribute'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver()); (yield 6 => $container->privates['argument_resolver.request'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver()); (yield 7 => $container->privates['argument_resolver.session'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver()); (yield 8 => $container->privates['argument_resolver.service'] ?? $container->load('getArgumentResolver_ServiceService')); (yield 9 => $container->privates['argument_resolver.default'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver()); (yield 10 => $container->privates['argument_resolver.variadic'] ??= new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver()); }, 11), new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver' => ['privates', 'argument_resolver.backed_enum_resolver', 'getArgumentResolver_BackedEnumResolverService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver' => ['privates', 'argument_resolver.datetime', 'getArgumentResolver_DatetimeService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => ['privates', 'argument_resolver.default', 'getArgumentResolver_DefaultService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver' => ['privates', 'argument_resolver.query_parameter_value_resolver', 'getArgumentResolver_QueryParameterValueResolverService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => ['privates', 'argument_resolver.request_attribute', 'getArgumentResolver_RequestAttributeService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver' => ['privates', 'argument_resolver.request_payload', 'getArgumentResolver_RequestPayloadService', \false], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => ['privates', 'argument_resolver.request', 'getArgumentResolver_RequestService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => ['privates', 'argument_resolver.service', 'getArgumentResolver_ServiceService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => ['privates', 'argument_resolver.session', 'getArgumentResolver_SessionService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver' => ['privates', 'argument_resolver.uid', 'getArgumentResolver_UidService', \true], '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => ['privates', 'argument_resolver.variadic', 'getArgumentResolver_VariadicService', \true], '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver' => ['privates', 'security.security_token_value_resolver', 'getSecurity_SecurityTokenValueResolverService', \true], '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver' => ['privates', 'security.user_value_resolver', 'getSecurity_UserValueResolverService', \true]], ['_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver' => '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver' => '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver'])), \false); } /* * Gets the public 'request_stack' shared service. * * @return \Symfony\Component\HttpFoundation\RequestStack */ protected static function getRequestStackService($container) { return $container->services['request_stack'] = new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(); } /* * Gets the public 'router' shared service. * * @return \Symfony\Bundle\FrameworkBundle\Routing\Router */ protected static function getRouterService($container) { $a = new \_ContaoManager\Monolog\Logger('router'); $a->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); $container->services['router'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\Router((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['routing.loader' => ['services', 'routing.loader', 'getRouting_LoaderService', \true]], ['routing.loader' => '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderInterface']))->withContext('router.default', $container), 'kernel::loadRoutes', ['cache_dir' => $container->targetDir . '', 'debug' => \false, 'generator_class' => '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator', 'generator_dumper_class' => '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper', 'matcher_class' => '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher', 'matcher_dumper_class' => '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper', 'strict_requirements' => \true, 'resource_type' => 'service'], $container->privates['router.request_context'] ?? self::getRouter_RequestContextService($container), $container->privates['parameter_bag'] ??= new \_ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBag($container), $a, 'en'); $instance->setConfigCacheFactory(new \_ContaoManager\Symfony\Component\Config\ResourceCheckerConfigCacheFactory()); return $instance; } /* * Gets the public 'security.token_storage' shared service. * * @return \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage */ protected static function getSecurity_TokenStorageService($container) { return $container->services['security.token_storage'] = new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(); } /* * Gets the private '.service_locator.tpD_zef' shared service. * * @return \Symfony\Component\DependencyInjection\ServiceLocator */ protected static function get_ServiceLocator_TpDZefService($container) { return $container->privates['.service_locator.tpD_zef'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['security.firewall.map.context.api' => ['privates', 'security.firewall.map.context.api', 'getSecurity_Firewall_Map_Context_ApiService', \true]], ['security.firewall.map.context.api' => '?']); } /* * Gets the private 'Contao\ManagerApi\Config\UserConfig' shared autowired service. * * @return \Contao\ManagerApi\Config\UserConfig */ protected static function getUserConfigService($container) { return $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\UserConfig($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } /* * Gets the private 'Contao\ManagerApi\EventListener\LocaleListener' shared autowired service. * * @return \Contao\ManagerApi\EventListener\LocaleListener */ protected static function getLocaleListenerService($container) { return $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener'] = new \_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener($container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), 'en', $container->services['router'] ?? self::getRouterService($container)); } /* * Gets the private 'Contao\ManagerApi\EventListener\SecurityListener' shared autowired service. * * @return \Contao\ManagerApi\EventListener\SecurityListener */ protected static function getSecurityListenerService($container) { return $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener'] = new \_ContaoManager\Contao\ManagerApi\EventListener\SecurityListener($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'] ?? self::getJwtManagerService($container), $container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.authorization_checker'] ?? self::getSecurity_AuthorizationCheckerService($container)); } /* * Gets the private 'Contao\ManagerApi\Security\JwtManager' shared autowired service. * * @return \Contao\ManagerApi\Security\JwtManager */ protected static function getJwtManagerService($container) { return $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'] = new \_ContaoManager\Contao\ManagerApi\Security\JwtManager($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container)); } /* * Gets the private 'argument_resolver.request_payload' shared service. * * @return \Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver */ protected static function getArgumentResolver_RequestPayloadService($container, $lazyLoad = \true) { if (\true === $lazyLoad) { return $container->privates['argument_resolver.request_payload'] = $container->createProxy('RequestPayloadValueResolverGhost8d82153', static fn() => \_ContaoManager\RequestPayloadValueResolverGhost8d82153::createLazyGhost(static fn($proxy) => self::getArgumentResolver_RequestPayloadService($container, $proxy))); } return $lazyLoad->__construct($container->privates['serializer'] ?? self::getSerializerService($container), NULL, NULL) && \false ?: $lazyLoad; } /* * Gets the private 'cache.property_access' shared service. * * @return \Symfony\Component\Cache\Adapter\AdapterInterface */ protected static function getCache_PropertyAccessService($container) { return $container->privates['cache.property_access'] = \_ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor::createCache('rx3ZD3v2JT', 0, $container->getParameter('container.build_id'), $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container)); } /* * Gets the private 'cache.property_info' shared service. * * @return \Symfony\Component\Cache\Adapter\AdapterInterface */ protected static function getCache_PropertyInfoService($container) { return $container->privates['cache.property_info'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('MdxUZfqldb', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container)); } /* * Gets the private 'cache.serializer' shared service. * * @return \Symfony\Component\Cache\Adapter\AdapterInterface */ protected static function getCache_SerializerService($container) { return $container->privates['cache.serializer'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('hYZs-Zg53G', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container)); } /* * Gets the private 'controller.is_granted_attribute_listener' shared service. * * @return \Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener */ protected static function getController_IsGrantedAttributeListenerService($container) { return $container->privates['controller.is_granted_attribute_listener'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener($container->privates['security.authorization_checker'] ?? self::getSecurity_AuthorizationCheckerService($container), NULL); } /* * Gets the private 'exception_listener' shared service. * * @return \Symfony\Component\HttpKernel\EventListener\ErrorListener */ protected static function getExceptionListener2Service($container) { return $container->privates['exception_listener'] = new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\ErrorListener('error_controller', $container->privates['monolog.logger.request'] ?? self::getMonolog_Logger_RequestService($container), \false, []); } /* * Gets the private 'locale_listener' shared autowired service. * * @return \Contao\ManagerApi\EventListener\LocaleListener */ protected static function getLocaleListener2Service($container) { return $container->privates['locale_listener'] = new \_ContaoManager\Contao\ManagerApi\EventListener\LocaleListener($container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), 'en', $container->services['router'] ?? self::getRouterService($container)); } /* * Gets the private 'monolog.handler.main' shared service. * * @return \Monolog\Handler\FingersCrossedHandler */ protected static function getMonolog_Handler_MainService($container) { $a = new \_ContaoManager\Monolog\Handler\ErrorLogHandler(0, 'DEBUG', \true); $a->pushProcessor(new \_ContaoManager\Monolog\Processor\PsrLogMessageProcessor()); return $container->privates['monolog.handler.main'] = new \_ContaoManager\Monolog\Handler\FingersCrossedHandler($a, new \_ContaoManager\Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy('error'), 0, \true, \true, NULL); } /* * Gets the private 'monolog.logger.cache' shared service. * * @return \Monolog\Logger */ protected static function getMonolog_Logger_CacheService($container) { $container->privates['monolog.logger.cache'] = $instance = new \_ContaoManager\Monolog\Logger('cache'); $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); return $instance; } /* * Gets the private 'monolog.logger.request' shared service. * * @return \Monolog\Logger */ protected static function getMonolog_Logger_RequestService($container) { $container->privates['monolog.logger.request'] = $instance = new \_ContaoManager\Monolog\Logger('request'); $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); return $instance; } /* * Gets the private 'parameter_bag' shared service. * * @return \Symfony\Component\DependencyInjection\ParameterBag\ContainerBag */ protected static function getParameterBagService($container) { return $container->privates['parameter_bag'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ParameterBag\ContainerBag($container); } /* * Gets the private 'router.request_context' shared service. * * @return \Symfony\Component\Routing\RequestContext */ protected static function getRouter_RequestContextService($container) { return $container->privates['router.request_context'] = \_ContaoManager\Symfony\Component\Routing\RequestContext::fromUri('', 'localhost', 'http', 80, 443); } /* * Gets the private 'router_listener' shared service. * * @return \Symfony\Component\HttpKernel\EventListener\RouterListener */ protected static function getRouterListenerService($container) { return $container->privates['router_listener'] = new \_ContaoManager\Symfony\Component\HttpKernel\EventListener\RouterListener($container->services['router'] ?? self::getRouterService($container), $container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), $container->privates['router.request_context'] ?? self::getRouter_RequestContextService($container), $container->privates['monolog.logger.request'] ?? self::getMonolog_Logger_RequestService($container), \dirname(__DIR__, 4) . '/test-dir', \false); } /* * Gets the private 'security.access.decision_manager' shared service. * * @return \Symfony\Component\Security\Core\Authorization\AccessDecisionManager */ protected static function getSecurity_Access_DecisionManagerService($container) { return $container->privates['security.access.decision_manager'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\AccessDecisionManager(new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['security.access.authenticated_voter'] ?? $container->load('getSecurity_Access_AuthenticatedVoterService')); (yield 1 => $container->privates['security.access.role_hierarchy_voter'] ?? $container->load('getSecurity_Access_RoleHierarchyVoterService')); }, 2), new \_ContaoManager\Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy(\false)); } /* * Gets the private 'security.authorization_checker' shared service. * * @return \Symfony\Component\Security\Core\Authorization\AuthorizationChecker */ protected static function getSecurity_AuthorizationCheckerService($container) { return $container->privates['security.authorization_checker'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\AuthorizationChecker($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.access.decision_manager'] ?? self::getSecurity_Access_DecisionManagerService($container), \false, \false); } /* * Gets the private 'security.firewall' shared service. * * @return \Symfony\Bundle\SecurityBundle\EventListener\FirewallListener */ protected static function getSecurity_FirewallService($container) { $a = $container->privates['security.firewall.map'] ?? self::getSecurity_Firewall_MapService($container); if (isset($container->privates['security.firewall'])) { return $container->privates['security.firewall']; } $b = $container->services['event_dispatcher'] ?? self::getEventDispatcherService($container); if (isset($container->privates['security.firewall'])) { return $container->privates['security.firewall']; } return $container->privates['security.firewall'] = new \_ContaoManager\Symfony\Bundle\SecurityBundle\EventListener\FirewallListener($a, $b, new \_ContaoManager\Symfony\Component\Security\Http\Logout\LogoutUrlGenerator($container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(), $container->services['router'] ?? self::getRouterService($container), $container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage())); } /* * Gets the private 'security.firewall.map' shared service. * * @return \Symfony\Bundle\SecurityBundle\Security\FirewallMap */ protected static function getSecurity_Firewall_MapService($container) { $a = $container->privates['.service_locator.tpD_zef'] ?? self::get_ServiceLocator_TpDZefService($container); if (isset($container->privates['security.firewall.map'])) { return $container->privates['security.firewall.map']; } return $container->privates['security.firewall.map'] = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security\FirewallMap($a, new RewindableGenerator(function () use($container) { (yield 'security.firewall.map.context.api' => NULL); }, 1)); } /* * Gets the private 'security.password_hasher_factory' shared service. * * @return \Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory */ protected static function getSecurity_PasswordHasherFactoryService($container) { return $container->privates['security.password_hasher_factory'] = new \_ContaoManager\Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory(['_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordAuthenticatedUserInterface' => ['algorithm' => 'auto', 'migrate_from' => [], 'hash_algorithm' => 'sha512', 'key_length' => 40, 'ignore_case' => \false, 'encode_as_base64' => \true, 'iterations' => 5000, 'cost' => NULL, 'memory_cost' => NULL, 'time_cost' => NULL]]); } /* * Gets the private 'serializer' shared service. * * @return \Symfony\Component\Serializer\Serializer */ protected static function getSerializerService($container) { $a = $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor(); $b = new \_ContaoManager\Symfony\Component\PropertyAccess\PropertyAccessor(3, 2, $container->privates['cache.property_access'] ?? self::getCache_PropertyAccessService($container), $a, $a); $c = $container->privates['serializer.mapping.cache_class_metadata_factory'] ?? self::getSerializer_Mapping_CacheClassMetadataFactoryService($container); $d = new \_ContaoManager\Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter($c); $e = new \_ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor(new \_ContaoManager\Symfony\Component\PropertyInfo\PropertyInfoExtractor(new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['property_info.serializer_extractor'] ?? $container->load('getPropertyInfo_SerializerExtractorService')); (yield 1 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor()); }, 2), new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['property_info.phpstan_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor()); (yield 1 => $container->privates['property_info.php_doc_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor()); (yield 2 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor()); }, 3), new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['property_info.php_doc_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor()); }, 1), new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor()); }, 1), new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['property_info.reflection_extractor'] ??= new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor()); }, 1)), $container->privates['cache.property_info'] ?? self::getCache_PropertyInfoService($container)); return $container->privates['serializer'] = new \_ContaoManager\Symfony\Component\Serializer\Serializer([new \_ContaoManager\Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer($b), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ProblemNormalizer(\false, translator: NULL), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\UidNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer([], $d), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\FormErrorNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\DataUriNormalizer(NULL), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer(NULL, NULL), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ArrayDenormalizer(), new \_ContaoManager\Symfony\Component\Serializer\Normalizer\ObjectNormalizer($c, $d, $b, $e, new \_ContaoManager\Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata($c), NULL, [], $e)], [new \_ContaoManager\Symfony\Component\Serializer\Encoder\XmlEncoder(), new \_ContaoManager\Symfony\Component\Serializer\Encoder\JsonEncoder(NULL, NULL), new \_ContaoManager\Symfony\Component\Serializer\Encoder\YamlEncoder(NULL, NULL), new \_ContaoManager\Symfony\Component\Serializer\Encoder\CsvEncoder()], []); } /* * Gets the private 'serializer.mapping.cache_class_metadata_factory' shared service. * * @return \Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory */ protected static function getSerializer_Mapping_CacheClassMetadataFactoryService($container) { return $container->privates['serializer.mapping.cache_class_metadata_factory'] = new \_ContaoManager\Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory(new \_ContaoManager\Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory(new \_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\LoaderChain([new \_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\AttributeLoader(NULL)])), \_ContaoManager\Symfony\Component\Cache\Adapter\PhpArrayAdapter::create($container->targetDir . '' . '/serialization.php', $container->privates['cache.serializer'] ?? self::getCache_SerializerService($container))); } public function getParameter(string $name) : array|bool|string|int|float|\UnitEnum|null { if (isset($this->buildParameters[$name])) { return $this->buildParameters[$name]; } if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || \array_key_exists($name, $this->parameters))) { throw new ParameterNotFoundException($name); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); } return $this->parameters[$name]; } public function hasParameter(string $name) : bool { if (isset($this->buildParameters[$name])) { return \true; } return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || \array_key_exists($name, $this->parameters); } public function setParameter(string $name, $value) : void { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } public function getParameterBag() : ParameterBagInterface { if (!isset($this->parameterBag)) { $parameters = $this->parameters; foreach ($this->loadedDynamicParameters as $name => $loaded) { $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); } foreach ($this->buildParameters as $name => $value) { $parameters[$name] = $value; } $this->parameterBag = new FrozenParameterBag($parameters); } return $this->parameterBag; } private $loadedDynamicParameters = ['kernel.runtime_environment' => \false, 'kernel.runtime_mode' => \false, 'kernel.runtime_mode.web' => \false, 'kernel.runtime_mode.cli' => \false, 'kernel.runtime_mode.worker' => \false, 'kernel.build_dir' => \false, 'kernel.cache_dir' => \false, 'router.cache_dir' => \false, 'serializer.mapping.cache.file' => \false]; private $dynamicParameters = []; private function getDynamicParameter(string $name) { $container = $this; $value = match ($name) { 'kernel.runtime_environment' => $container->getEnv('default:kernel.environment:APP_RUNTIME_ENV'), 'kernel.runtime_mode' => $container->getEnv('query_string:default:container.runtime_mode:APP_RUNTIME_MODE'), 'kernel.runtime_mode.web' => $container->getEnv('bool:default::key:web:default:kernel.runtime_mode:'), 'kernel.runtime_mode.cli' => $container->getEnv('not:default:kernel.runtime_mode.web:'), 'kernel.runtime_mode.worker' => $container->getEnv('bool:default::key:worker:default:kernel.runtime_mode:'), 'kernel.build_dir' => $container->targetDir . '', 'kernel.cache_dir' => $container->targetDir . '', 'router.cache_dir' => $container->targetDir . '', 'serializer.mapping.cache.file' => $container->targetDir . '' . '/serialization.php', default => throw new ParameterNotFoundException($name), }; $this->loadedDynamicParameters[$name] = \true; return $this->dynamicParameters[$name] = $value; } protected function getDefaultParameters() : array { return ['kernel.project_dir' => \dirname(__DIR__, 4) . '/test-dir', 'kernel.environment' => 'prod', 'kernel.debug' => \false, 'kernel.logs_dir' => \dirname(__DIR__, 4) . '/test-dir/contao-manager/logs', 'kernel.bundles' => ['FrameworkBundle' => '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle', 'SecurityBundle' => '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\SecurityBundle', 'MonologBundle' => '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\MonologBundle'], 'kernel.bundles_metadata' => ['FrameworkBundle' => ['path' => \dirname(__DIR__, 4) . '/vendor/symfony/framework-bundle', 'namespace' => '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle'], 'SecurityBundle' => ['path' => \dirname(__DIR__, 4) . '/vendor/symfony/security-bundle', 'namespace' => '_ContaoManager\\Symfony\\Bundle\\SecurityBundle'], 'MonologBundle' => ['path' => \dirname(__DIR__, 4) . '/vendor/symfony/monolog-bundle', 'namespace' => '_ContaoManager\\Symfony\\Bundle\\MonologBundle']], 'kernel.charset' => 'UTF-8', 'kernel.container_class' => 'Contao_ManagerApi_ApiKernelProdContainer', 'event_dispatcher.event_aliases' => ['_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => 'console.command', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => 'console.error', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => 'console.signal', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => 'console.terminate', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerArgumentsEvent' => 'kernel.controller_arguments', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerEvent' => 'kernel.controller', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ResponseEvent' => 'kernel.response', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent' => 'kernel.finish_request', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\RequestEvent' => 'kernel.request', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ViewEvent' => 'kernel.view', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ExceptionEvent' => 'kernel.exception', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\TerminateEvent' => 'kernel.terminate', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationSuccessEvent' => 'security.authentication.success', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\InteractiveLoginEvent' => 'security.interactive_login', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\SwitchUserEvent' => 'security.switch_user'], 'fragment.renderer.hinclude.global_template' => NULL, 'fragment.path' => '/_fragment', 'kernel.secret' => '', 'kernel.http_method_override' => \true, 'kernel.trust_x_sendfile_type_header' => \false, 'kernel.trusted_hosts' => [], 'kernel.default_locale' => 'en', 'kernel.enabled_locales' => [], 'kernel.error_controller' => 'error_controller', 'debug.file_link_format' => NULL, 'debug.error_handler.throw_at' => 0, 'router.request_context.host' => 'localhost', 'router.request_context.scheme' => 'http', 'router.request_context.base_url' => '', 'router.resource' => 'kernel::loadRoutes', 'request_listener.http_port' => 80, 'request_listener.https_port' => 443, 'data_collector.templates' => [], 'security.role_hierarchy.roles' => ['ROLE_ADMIN' => [0 => 'ROLE_INSTALL'], 'ROLE_INSTALL' => [0 => 'ROLE_UPDATE'], 'ROLE_UPDATE' => [0 => 'ROLE_READ'], 'ROLE_READ' => [0 => 'ROLE_USER']], 'security.access.denied_url' => NULL, 'security.authentication.manager.erase_credentials' => \true, 'security.authentication.session_strategy.strategy' => 'migrate', 'security.authentication.hide_user_not_found' => \true, 'security.firewalls' => [0 => 'api'], 'security.logout_uris' => [], 'monolog.use_microseconds' => \true, 'monolog.swift_mailer.handlers' => [], 'monolog.handlers_to_channels' => ['monolog.handler.main' => NULL], 'console.command.ids' => []]; } } privates['.console.command.cache_pool_prune.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:prune', [], 'Prune cache pools', \false, #[\Closure(name: 'console.command.cache_pool_prune', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolPruneCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand => $container->privates['console.command.cache_pool_prune'] ?? $container->load('getConsole_Command_CachePoolPruneService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand($container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager'] ?? $container->load('getTaskManagerService')); $instance->setName('task:update'); $instance->setDescription('Updates the current task and returns the status information.'); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController'] = new \_ContaoManager\Contao\ManagerApi\Controller\TaskController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager'] ?? $container->load('getTaskManagerService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\MaintenanceModeController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController'] = $instance = new \_ContaoManager\Contao\ManagerApi\Controller\FileController($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); $instance->setContainer((new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['http_kernel' => ['services', 'http_kernel', 'getHttpKernelService', \false], 'parameter_bag' => ['privates', 'parameter_bag', 'getParameterBagService', \false], 'request_stack' => ['services', 'request_stack', 'getRequestStackService', \false], 'router' => ['services', 'router', 'getRouterService', \false], 'security.authorization_checker' => ['privates', 'security.authorization_checker', 'getSecurity_AuthorizationCheckerService', \false], 'security.token_storage' => ['services', 'security.token_storage', 'getSecurity_TokenStorageService', \false], 'serializer' => ['privates', 'serializer', 'getSerializerService', \false]], ['http_kernel' => '?', 'parameter_bag' => '?', 'request_stack' => '?', 'router' => '?', 'security.authorization_checker' => '?', 'security.token_storage' => '?', 'serializer' => '?']))->withContext('_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController', $container)); return $instance; } } privates['.service_locator.y.Xs7Mw'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['processFactory' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory', 'getConsoleProcessFactoryService', \true], 'serverInfo' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo', 'getServerInfoService', \true]], ['processFactory' => '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory', 'serverInfo' => '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo']); } } services['kernel'] ?? $container->get('kernel', 1)); $c = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\AttributeRouteControllerLoader('prod'); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\XmlFileLoader($b, 'prod')); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\YamlFileLoader($b, 'prod')); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\PhpFileLoader($b, 'prod')); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\GlobFileLoader($b, 'prod')); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\DirectoryLoader($b, 'prod')); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\ContainerLoader(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['kernel' => ['services', 'kernel', 'getKernelService', \false], 'security.route_loader.logout' => ['privates', 'security.route_loader.logout', 'getSecurity_RouteLoader_LogoutService', \true]], ['kernel' => '?', 'security.route_loader.logout' => '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Routing\\LogoutRouteLoader']), 'prod')); $a->addLoader($c); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\AttributeDirectoryLoader($b, $c)); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\AttributeFileLoader($b, $c)); $a->addLoader(new \_ContaoManager\Symfony\Component\Routing\Loader\Psr4DirectoryLoader($b)); return $container->services['routing.loader'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader($a, ['utf8' => \true], []); } } privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] = new \_ContaoManager\Contao\ManagerApi\Composer\Environment($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig'] ?? $container->load('getManagerConfigService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig'] ?? $container->load('getComposerConfigService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\Request'] ?? $container->load('getRequestService')); } } privates['security.listener.user_checker.api'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\UserCheckerListener($container->privates['security.user_checker'] ??= new \_ContaoManager\Symfony\Component\Security\Core\User\InMemoryUserChecker()); } } services['services_resetter'] = new \_ContaoManager\Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter(new RewindableGenerator(function () use($container) { if (\false) { (yield '_ContaoManager\\Contao\\ManagerApi\\ApiApplication' => null); } if (isset($container->services['request_stack'])) { (yield 'request_stack' => $container->services['request_stack'] ?? null); } if (isset($container->services['cache.app'])) { (yield 'cache.app' => $container->services['cache.app'] ?? null); } if (isset($container->services['cache.system'])) { (yield 'cache.system' => $container->services['cache.system'] ?? null); } if (\false) { (yield 'cache.validator' => null); } if (isset($container->privates['cache.serializer'])) { (yield 'cache.serializer' => $container->privates['cache.serializer'] ?? null); } if (\false) { (yield 'cache.annotations' => null); } if (isset($container->privates['cache.property_info'])) { (yield 'cache.property_info' => $container->privates['cache.property_info'] ?? null); } if (isset($container->services['security.token_storage'])) { (yield 'security.untracked_token_storage' => $container->services['security.token_storage'] ?? null); } if (\false) { (yield 'cache.security_expression_language' => null); } if (isset($container->services['cache.security_is_granted_attribute_expression_language'])) { (yield 'cache.security_is_granted_attribute_expression_language' => $container->services['cache.security_is_granted_attribute_expression_language'] ?? null); } if (isset($container->privates['monolog.handler.main'])) { (yield 'monolog.handler.main' => $container->privates['monolog.handler.main'] ?? null); } }, fn() => 0 + (int) \false + (int) isset($container->services['request_stack']) + (int) isset($container->services['cache.app']) + (int) isset($container->services['cache.system']) + (int) \false + (int) isset($container->privates['cache.serializer']) + (int) \false + (int) isset($container->privates['cache.property_info']) + (int) isset($container->services['security.token_storage']) + (int) \false + (int) isset($container->services['cache.security_is_granted_attribute_expression_language']) + (int) isset($container->privates['monolog.handler.main'])), ['_ContaoManager\\Contao\\ManagerApi\\ApiApplication' => ['reset'], 'request_stack' => ['?resetRequestFormats'], 'cache.app' => ['reset'], 'cache.system' => ['reset'], 'cache.validator' => ['reset'], 'cache.serializer' => ['reset'], 'cache.annotations' => ['reset'], 'cache.property_info' => ['reset'], 'security.untracked_token_storage' => ['reset'], 'cache.security_expression_language' => ['reset'], 'cache.security_is_granted_attribute_expression_language' => ['reset'], 'monolog.handler.main' => ['reset']]); } } services['cache.security_is_granted_attribute_expression_language'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('-VUU5Zp3Of', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container)); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\OpcacheController(); } } privates['console.command.assets_install'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand($container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), \dirname(__DIR__, 4) . '/test-dir'); $instance->setName('assets:install'); $instance->setDescription('Install bundle\'s web assets under a public directory'); return $instance; } } privates['serializer.mapping.cache_warmer'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\SerializerCacheWarmer([new \_ContaoManager\Symfony\Component\Serializer\Mapping\Loader\AttributeLoader(NULL)], $container->targetDir . '' . '/serialization.php'); } } privates['_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'] ?? self::getJwtManagerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['kernel'] ?? $container->get('kernel', 1)); } } privates['security.event_dispatcher.api'] = $instance = new \_ContaoManager\Symfony\Component\EventDispatcher\EventDispatcher(); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: 'security.listener.api.user_provider', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener')] fn() => $container->privates['security.listener.api.user_provider'] ?? $container->load('getSecurity_Listener_Api_UserProviderService'), 'checkPassport'], 2048); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: 'security.listener.user_checker.api', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserCheckerListener')] fn() => $container->privates['security.listener.user_checker.api'] ?? $container->load('getSecurity_Listener_UserChecker_ApiService'), 'preCheckCredentials'], 256); $instance->addListener('security.authentication.success', [#[\Closure(name: 'security.listener.user_checker.api', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserCheckerListener')] fn() => $container->privates['security.listener.user_checker.api'] ?? $container->load('getSecurity_Listener_UserChecker_ApiService'), 'postCheckCredentials'], 256); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener')] fn() => $container->privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener'] ??= new \_ContaoManager\Contao\ManagerApi\EventListener\CheckTotpListener(), '__invoke'], 0); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: 'security.listener.user_provider', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener')] fn() => $container->privates['security.listener.user_provider'] ?? $container->load('getSecurity_Listener_UserProviderService'), 'checkPassport'], 1024); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent', [#[\Closure(name: 'security.listener.check_authenticator_credentials', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckCredentialsListener')] fn() => $container->privates['security.listener.check_authenticator_credentials'] ?? $container->load('getSecurity_Listener_CheckAuthenticatorCredentialsService'), 'checkPassport'], 0); $instance->addListener('_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent', [#[\Closure(name: 'security.listener.password_migrating', class: '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener')] fn() => $container->privates['security.listener.password_migrating'] ?? $container->load('getSecurity_Listener_PasswordMigratingService'), 'onLoginSuccess'], 0); return $instance; } } services['cache.system'] = \_ContaoManager\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache('IUGL952q0t', 0, $container->getParameter('container.build_id'), $container->targetDir . '' . '/pools/system', $container->privates['monolog.logger.cache'] ?? self::getMonolog_Logger_CacheService($container)); } } privates['monolog.logger'] = $instance = new \_ContaoManager\Monolog\Logger('app'); $instance->useMicrosecondTimestamps(\true); $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); return $instance; } } privates['.console.command.cache_pool_delete.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:delete', [], 'Delete an item from a cache pool', \false, #[\Closure(name: 'console.command.cache_pool_delete', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolDeleteCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand => $container->privates['console.command.cache_pool_delete'] ?? $container->load('getConsole_Command_CachePoolDeleteService')); } } privates['monolog.logger.security'] = $instance = new \_ContaoManager\Monolog\Logger('security'); $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\UpdateCommand($container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate'] ?? $container->load('getSelfUpdateService')); $instance->setName('self-update'); $instance->setDescription('Updates Contao Manager to the latest version'); return $instance; } } pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); return $container->services['debug.error_handler_configurator'] = new \_ContaoManager\Symfony\Component\HttpKernel\Debug\ErrorHandlerConfigurator($a, NULL, 0, \false, \false, NULL); } } privates['.Contao\\ManagerApi\\Command\\TaskDeleteCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('task:delete', [], 'Deletes the current task if it is not active.', \false, #[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\TaskDeleteCommand => $container->services['_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand'] ?? $container->load('getTaskDeleteCommandService')); } } privates['security.access.authenticated_voter'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter($container->privates['security.authentication.trust_resolver'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver()); } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\ProcessCheck($container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController'] = new \_ContaoManager\Contao\ManagerApi\Controller\SessionController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container), $container->privates['security.helper'] ?? $container->load('getSecurity_HelperService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'] ?? self::getJwtManagerService($container), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator'] ?? $container->load('getWebauthnAuthenticatorService')); } } privates['security.listener.password_migrating'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\PasswordMigratingListener($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container)); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Manager\SelfUpdateTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate'] ?? $container->load('getSelfUpdateService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['.console.command.serializer_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:serializer', [], 'Display serialization information for classes', \false, #[\Closure(name: 'console.command.serializer_debug', class: '_ContaoManager\\Symfony\\Component\\Serializer\\Command\\DebugCommand')] fn(): \_ContaoManager\Symfony\Component\Serializer\Command\DebugCommand => $container->privates['console.command.serializer_debug'] ?? $container->load('getConsole_Command_SerializerDebugService')); } } services['cache.global_clearer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer(['cache.app' => $container->services['cache.app'] ?? $container->load('getCache_AppService'), 'cache.system' => $container->services['cache.system'] ?? $container->load('getCache_SystemService'), 'cache.serializer' => $container->privates['cache.serializer'] ?? self::getCache_SerializerService($container), 'cache.property_info' => $container->privates['cache.property_info'] ?? self::getCache_PropertyInfoService($container), 'cache.property_access' => $container->privates['cache.property_access'] ?? self::getCache_PropertyAccessService($container), 'cache.security_is_granted_attribute_expression_language' => $container->services['cache.security_is_granted_attribute_expression_language'] ?? $container->load('getCache_SecurityIsGrantedAttributeExpressionLanguageService')]); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\TaskManager(new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask'] ?? $container->load('getClearCacheTaskService')); (yield 1 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask'] ?? $container->load('getDumpAutoloadTaskService')); (yield 2 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask'] ?? $container->load('getBackupCreateTaskService')); (yield 3 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask'] ?? $container->load('getBackupRestoreTaskService')); (yield 4 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask'] ?? $container->load('getRebuildCacheTaskService')); (yield 5 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask'] ?? $container->load('getSelfUpdateTaskService')); (yield 6 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask'] ?? $container->load('getInstallTaskService')); (yield 7 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask'] ?? $container->load('getSetupTaskService')); (yield 8 => $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask'] ?? $container->load('getUpdateTaskService')); }, 9), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['security.authorization_checker'] ?? self::getSecurity_AuthorizationCheckerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); return $container->privates['console.error_listener'] = new \_ContaoManager\Symfony\Component\Console\EventListener\ErrorListener($a); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\UploadPackagesController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig'] ?? $container->load('getUploadsConfigService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi'] = new \_ContaoManager\Contao\ManagerApi\Process\ContaoApi($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\MemoryLimitCheck($container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } privates['.security.command.debug_firewall.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:firewall', [], 'Display information about your security firewall(s)', \false, #[\Closure(name: 'security.command.debug_firewall', class: '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Command\\DebugFirewallCommand')] fn(): \_ContaoManager\Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand => $container->privates['security.command.debug_firewall'] ?? $container->load('getSecurity_Command_DebugFirewallService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\SysTempDirCheck($container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } privates['.console.command.secrets_remove.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:remove', [], 'Remove a secret from the vault', \false, #[\Closure(name: 'console.command.secrets_remove', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsRemoveCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand => $container->privates['console.command.secrets_remove'] ?? $container->load('getConsole_Command_SecretsRemoveService')); } } privates['argument_resolver.query_parameter_value_resolver'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValueResolver(); } } privates['.Contao\\ManagerApi\\Command\\TaskUpdateCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('task:update', [], 'Updates the current task and returns the status information.', \false, #[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\TaskUpdateCommand => $container->services['_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand'] ?? $container->load('getTaskUpdateCommandService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\ConfigController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig'] ?? $container->load('getManagerConfigService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo'] ?? $container->load('getServerInfoService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate'] = new \_ContaoManager\Contao\ManagerApi\System\SelfUpdate($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig'] ?? $container->load('getManagerConfigService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\Request'] ?? $container->load('getRequestService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } services['_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand($container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager'] ?? $container->load('getTaskManagerService')); $instance->setName('task:abort'); $instance->setDescription('Aborts the current task and returns the status information.'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver'] = $instance = new \_ContaoManager\Contao\ManagerApi\Composer\CloudResolver($container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\Request'] ?? $container->load('getRequestService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['.console.command.secrets_decrypt_to_local.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:decrypt-to-local', [], 'Decrypt all secrets and stores them in the local vault', \false, #[\Closure(name: 'console.command.secrets_decrypt_to_local', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsDecryptToLocalCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand => $container->privates['console.command.secrets_decrypt_to_local'] ?? $container->load('getConsole_Command_SecretsDecryptToLocalService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\AccessKeyController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi'] ?? $container->load('getContaoApiService')); } } privates['property_info.serializer_extractor'] = new \_ContaoManager\Symfony\Component\PropertyInfo\Extractor\SerializerExtractor($container->privates['serializer.mapping.cache_class_metadata_factory'] ?? self::getSerializer_Mapping_CacheClassMetadataFactoryService($container)); } } privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] = new \_ContaoManager\Contao\ManagerApi\Security\UserProvider($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container)); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\PhpWebController($container->privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory'] ?? $container->load('getIntegrityCheckFactoryService')); } } privates['.Contao\\ManagerApi\\Command\\AboutCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('about', [], 'Displays information about Contao Manager and the current server', \false, #[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\AboutCommand => $container->services['_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand'] ?? $container->load('getAboutCommandService')); } } privates['console.command.container_lint'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand(); $instance->setName('lint:container'); $instance->setDescription('Ensure that arguments injected into services match type declarations'); return $instance; } } privates['.console.command.about.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('about', [], 'Display information about the current project', \false, #[\Closure(name: 'console.command.about', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AboutCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AboutCommand => $container->privates['console.command.about'] ?? $container->load('getConsole_Command_AboutService')); } } privates['.console.command.router_match.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('router:match', [], 'Help debug routes by simulating a path info match', \false, #[\Closure(name: 'console.command.router_match', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterMatchCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand => $container->privates['console.command.router_match'] ?? $container->load('getConsole_Command_RouterMatchService')); } } services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] = new \_ContaoManager\Contao\ManagerApi\I18n\Translator($container->services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack()); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\SelfUpdateController(); } } privates['router.request_context'] ?? self::getRouter_RequestContextService($container); return $container->privates['security.channel_listener'] = new \_ContaoManager\Symfony\Component\Security\Http\Firewall\ChannelListener($container->privates['security.access_map'] ?? $container->load('getSecurity_AccessMapService'), $container->privates['monolog.logger.security'] ?? $container->load('getMonolog_Logger_SecurityService'), $a->getHttpPort(), $a->getHttpsPort()); } } privates['argument_resolver.variadic'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver(); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Config\ManagerController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig'] ?? $container->load('getManagerConfigService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\BackupController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService')); } } privates['security.helper'] = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Security(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['request_stack' => ['services', 'request_stack', 'getRequestStackService', \false], 'security.authenticator.managers_locator' => ['privates', 'security.authenticator.managers_locator', 'getSecurity_Authenticator_ManagersLocatorService', \true], 'security.authorization_checker' => ['privates', 'security.authorization_checker', 'getSecurity_AuthorizationCheckerService', \false], 'security.firewall.event_dispatcher_locator' => ['privates', 'security.firewall.event_dispatcher_locator', 'getSecurity_Firewall_EventDispatcherLocatorService', \true], 'security.firewall.map' => ['privates', 'security.firewall.map', 'getSecurity_Firewall_MapService', \false], 'security.token_storage' => ['services', 'security.token_storage', 'getSecurity_TokenStorageService', \false], 'security.user_checker_locator' => ['privates', 'security.user_checker_locator', 'getSecurity_UserCheckerLocatorService', \true]], ['request_stack' => '?', 'security.authenticator.managers_locator' => '?', 'security.authorization_checker' => '?', 'security.firewall.event_dispatcher_locator' => '?', 'security.firewall.map' => '?', 'security.token_storage' => '?', 'security.user_checker_locator' => '?']), ['api' => new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator', 'getJwtAuthenticatorService', \true], '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator', 'getLoginAuthenticatorService', \true], '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator', 'getPasswordlessAuthenticatorService', \true], '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator', 'getTokenAuthenticatorService', \true], '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator', 'getWebauthnAuthenticatorService', \true]], ['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator' => '?', '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator' => '?', '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator' => '?', '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator' => '?', '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => '?'])]); } } privates['security.listener.user_provider'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] ?? $container->load('getUserProviderService')); } } privates['.console.command.yaml_lint.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('lint:yaml', [], 'Lint a YAML file and outputs encountered errors', \false, #[\Closure(name: 'console.command.yaml_lint', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\YamlLintCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand => $container->privates['console.command.yaml_lint'] ?? $container->load('getConsole_Command_YamlLintService')); } } privates['secrets.vault'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault(\dirname(__DIR__, 4) . '/test-dir/config/secrets/' . $container->getEnv('string:default:kernel.environment:APP_RUNTIME_ENV'), \_ContaoManager\Symfony\Component\String\LazyString::fromCallable($container->getEnv(...), 'base64:default::SYMFONY_DECRYPTION_SECRET')); } } privates['console.command.config_dump_reference'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand(); $instance->setName('config:dump-reference'); $instance->setDescription('Dump the default configuration for an extension'); return $instance; } } privates['console.command.cache_warmup'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand($container->services['cache_warmer'] ?? $container->load('getCacheWarmerService')); $instance->setName('cache:warmup'); $instance->setDescription('Warm up an empty cache'); return $instance; } } privates['security.access.role_hierarchy_voter'] = new \_ContaoManager\Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter(new \_ContaoManager\Symfony\Component\Security\Core\Role\RoleHierarchy($container->parameters['security.role_hierarchy.roles'])); } } privates['argument_resolver.request_attribute'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver(); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Contao\BackupCreateTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['.Contao\\ManagerApi\\Command\\ProcessRunnerCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('background-task:run', [], 'Execute a background task', \false, #[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\ProcessRunnerCommand => $container->services['_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand'] ?? $container->load('getProcessRunnerCommandService')); } } privates['console.command.cache_pool_delete'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand($container->services['cache.global_clearer'] ?? $container->load('getCache_GlobalClearerService'), ['cache.app', 'cache.system', 'cache.validator', 'cache.serializer', 'cache.annotations', 'cache.property_info', 'cache.property_access', 'cache.security_expression_language', 'cache.security_is_granted_attribute_expression_language']); $instance->setName('cache:pool:delete'); $instance->setDescription('Delete an item from a cache pool'); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\CloudController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager'] ?? $container->load('getTaskManagerService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Packages\SetupTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver'] ?? $container->load('getCloudResolverService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig'] ?? $container->load('getUploadsConfigService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['.console.command.secrets_set.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:set', [], 'Set a secret in the vault', \false, #[\Closure(name: 'console.command.secrets_set', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsSetCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand => $container->privates['console.command.secrets_set'] ?? $container->load('getConsole_Command_SecretsSetService')); } } services['Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\TemplateController(NULL); } } privates['console.command.cache_pool_invalidate_tags'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolInvalidateTagsCommand(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['cache.app' => ['privates', 'cache.app.taggable', 'getCache_App_TaggableService', \true]], ['cache.app' => '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter'])); $instance->setName('cache:pool:invalidate-tags'); $instance->setDescription('Invalidate cache tags for all or a specific pool'); return $instance; } } privates['.console.command.event_dispatcher_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:event-dispatcher', [], 'Display configured listeners for an application', \false, #[\Closure(name: 'console.command.event_dispatcher_debug', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\EventDispatcherDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand => $container->privates['console.command.event_dispatcher_debug'] ?? $container->load('getConsole_Command_EventDispatcherDebugService')); } } privates['.console.command.cache_pool_list.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:list', [], 'List available cache pools', \false, #[\Closure(name: 'console.command.cache_pool_list', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolListCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand => $container->privates['console.command.cache_pool_list'] ?? $container->load('getConsole_Command_CachePoolListService')); } } privates['console.command.event_dispatcher_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand($container->privates['.service_locator.BvkMlPl'] ?? $container->load('get_ServiceLocator_BvkMlPlService')); $instance->setName('debug:event-dispatcher'); $instance->setDescription('Display configured listeners for an application'); return $instance; } } privates['argument_resolver.service'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver(new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::update' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::write' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController::__invoke' => ['privates', '.service_locator.y.Xs7Mw', 'get_ServiceLocator_Y_Xs7MwService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController::__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController::__invoke' => ['privates', '.service_locator.EZsc.DO', 'get_ServiceLocator_EZsc_DOService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController:update' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController:write' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController:__invoke' => ['privates', '.service_locator.y.Xs7Mw', 'get_ServiceLocator_Y_Xs7MwService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => ['privates', '.service_locator.y.Xs7Mw', 'get_ServiceLocator_Y_Xs7MwService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController:__invoke' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => ['privates', '.service_locator.aH5O6Sd', 'get_ServiceLocator_AH5O6SdService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController:__invoke' => ['privates', '.service_locator.EZsc.DO', 'get_ServiceLocator_EZsc_DOService', \true], '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => ['privates', '.service_locator.EZsc.DO', 'get_ServiceLocator_EZsc_DOService', \true]], ['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController::__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController::__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController::update' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController::write' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController::__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController::__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController::__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController:__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController:__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController:__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController:update' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController:__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController:write' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController:__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController:__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController:__invoke' => '?', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => '?'])); } } privates['.console.command.cache_pool_invalidate_tags.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:invalidate-tags', [], 'Invalidate cache tags for all or a specific pool', \false, #[\Closure(name: 'console.command.cache_pool_invalidate_tags', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolInvalidateTagsCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolInvalidateTagsCommand => $container->privates['console.command.cache_pool_invalidate_tags'] ?? $container->load('getConsole_Command_CachePoolInvalidateTagsService')); } } privates['.console.command.cache_warmup.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:warmup', [], 'Warm up an empty cache', \false, #[\Closure(name: 'console.command.cache_warmup', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheWarmupCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand => $container->privates['console.command.cache_warmup'] ?? $container->load('getConsole_Command_CacheWarmupService')); } } services['cache.system_clearer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer(['cache.system' => $container->services['cache.system'] ?? $container->load('getCache_SystemService'), 'cache.serializer' => $container->privates['cache.serializer'] ?? self::getCache_SerializerService($container), 'cache.property_info' => $container->privates['cache.property_info'] ?? self::getCache_PropertyInfoService($container), 'cache.property_access' => $container->privates['cache.property_access'] ?? self::getCache_PropertyAccessService($container), 'cache.security_is_granted_attribute_expression_language' => $container->services['cache.security_is_granted_attribute_expression_language'] ?? $container->load('getCache_SecurityIsGrantedAttributeExpressionLanguageService')]); } } privates['.service_locator.BvkMlPl'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['event_dispatcher' => ['services', 'event_dispatcher', 'getEventDispatcherService', \false], 'security.event_dispatcher.api' => ['privates', 'security.event_dispatcher.api', 'getSecurity_EventDispatcher_ApiService', \true]], ['event_dispatcher' => '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher', 'security.event_dispatcher.api' => '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher']); } } privates['monolog.logger.tasks'] = $instance = new \_ContaoManager\Monolog\Logger('tasks'); $instance->pushHandler($container->privates['monolog.handler.main'] ?? self::getMonolog_Handler_MainService($container)); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\AdminUserController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand($container->privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory'] ?? $container->load('getIntegrityCheckFactoryService')); $instance->setName('integrity-check'); $instance->setDescription('Performs integrity check for the Contao Manager'); return $instance; } } privates['.console.command.assets_install.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('assets:install', [], 'Install bundle\'s web assets under a public directory', \false, #[\Closure(name: 'console.command.assets_install', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AssetsInstallCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand => $container->privates['console.command.assets_install'] ?? $container->load('getConsole_Command_AssetsInstallService')); } } privates['security.firewall.event_dispatcher_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\ServiceLocator(['api' => #[\Closure(name: 'security.event_dispatcher.api', class: '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher')] fn() => $container->privates['security.event_dispatcher.api'] ?? $container->load('getSecurity_EventDispatcher_ApiService')]); } } privates['console.command.serializer_debug'] = $instance = new \_ContaoManager\Symfony\Component\Serializer\Command\DebugCommand($container->privates['serializer.mapping.cache_class_metadata_factory'] ?? self::getSerializer_Mapping_CacheClassMetadataFactoryService($container)); $instance->setName('debug:serializer'); $instance->setDescription('Display serialization information for classes'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\PhpExtensionsCheck($container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } privates['argument_resolver.default'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver(); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Config\AuthController(new \_ContaoManager\Contao\ManagerApi\Config\AuthConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem())); } } privates['argument_resolver.datetime'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver(new \_ContaoManager\Symfony\Component\Clock\Clock()); } } privates['argument_resolver.uid'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver(); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\InstallToolLockController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['.Contao\\ManagerApi\\Command\\UpdateCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('self-update', [], 'Updates Contao Manager to the latest version', \false, #[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\UpdateCommand => $container->services['_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand'] ?? $container->load('getUpdateCommandService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Config\ComposerController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig'] ?? $container->load('getComposerConfigService')); } } privates['argument_resolver.session'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver(); } } services['cache_warmer'] = new \_ContaoManager\Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate(new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['config_builder.warmer'] ?? $container->load('getConfigBuilder_WarmerService')); (yield 1 => $container->privates['router.cache_warmer'] ?? $container->load('getRouter_CacheWarmerService')); (yield 2 => $container->privates['serializer.mapping.cache_warmer'] ?? $container->load('getSerializer_Mapping_CacheWarmerService')); }, 3), \false, $container->targetDir . '' . '/Contao_ManagerApi_ApiKernelProdContainerDeprecations.log'); } } privates['router.request_context'] ?? self::getRouter_RequestContextService($container); return $container->services['Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Controller\RedirectController($container->services['router'] ?? self::getRouterService($container), $a->getHttpPort(), $a->getHttpsPort()); } } privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\UploadsConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Contao\DatabaseMigrationController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['kernel'] ?? $container->get('kernel', 1)); } } privates['console.command.yaml_lint'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand(); $instance->setName('lint:yaml'); $instance->setDescription('Lint a YAML file and outputs encountered errors'); return $instance; } } privates['config_builder.warmer'] = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\CacheWarmer\ConfigBuilderCacheWarmer($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager'] ?? self::getJwtManagerService($container), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['kernel'] ?? $container->get('kernel', 1)); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Composer\ClearCacheTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\RootPackageController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService')); } } privates['cache.app.taggable'] = new \_ContaoManager\Symfony\Component\Cache\Adapter\TagAwareAdapter($container->services['cache.app'] ?? $container->load('getCache_AppService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] = new \_ContaoManager\Contao\ManagerApi\Process\ContaoConsole($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\ManagerConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['security.user_value_resolver'] = new \_ContaoManager\Symfony\Component\Security\Http\Controller\UserValueResolver($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage()); } } privates['.console.command.debug_autowiring.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:autowiring', [], 'List classes/interfaces you can use for autowiring', \false, #[\Closure(name: 'console.command.debug_autowiring', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\DebugAutowiringCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand => $container->privates['console.command.debug_autowiring'] ?? $container->load('getConsole_Command_DebugAutowiringService')); } } privates['security.command.debug_firewall'] = $instance = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand($container->parameters['security.firewalls'], $container->privates['.service_locator.tpD_zef'] ?? self::get_ServiceLocator_TpDZefService($container), $container->privates['.service_locator.BvkMlPl'] ?? $container->load('get_ServiceLocator_BvkMlPlService'), ['api' => [$container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator'] ?? $container->load('getLoginAuthenticatorService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator'] ?? $container->load('getWebauthnAuthenticatorService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator'] ?? $container->load('getPasswordlessAuthenticatorService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator'] ?? $container->load('getJwtAuthenticatorService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator'] ?? $container->load('getTokenAuthenticatorService')]], \false); $instance->setName('debug:firewall'); $instance->setDescription('Display information about your security firewall(s)'); return $instance; } } privates['security.listener.check_authenticator_credentials'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\CheckCredentialsListener($container->privates['security.password_hasher_factory'] ?? self::getSecurity_PasswordHasherFactoryService($container)); } } privates['.console.command.cache_pool_clear.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:pool:clear', [], 'Clear cache pools', \false, #[\Closure(name: 'console.command.cache_pool_clear', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolClearCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand => $container->privates['console.command.cache_pool_clear'] ?? $container->load('getConsole_Command_CachePoolClearService')); } } privates['console.command.cache_clear'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand(new \_ContaoManager\Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer(new RewindableGenerator(fn() => new \EmptyIterator(), 0)), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); $instance->setName('cache:clear'); $instance->setDescription('Clear the cache'); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\PhpinfoController(); } } privates['console.command.cache_pool_list'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand(['cache.app', 'cache.system', 'cache.validator', 'cache.serializer', 'cache.annotations', 'cache.property_info', 'cache.property_access', 'cache.security_expression_language', 'cache.security_is_granted_attribute_expression_language']); $instance->setName('cache:pool:list'); $instance->setDescription('List available cache pools'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator'] ?? $container->load('getWebauthnAuthenticatorService'); if (isset($container->privates['security.authenticator.manager.api'])) { return $container->privates['security.authenticator.manager.api']; } return $container->privates['security.authenticator.manager.api'] = new \_ContaoManager\Symfony\Component\Security\Http\Authentication\AuthenticatorManager([$container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator'] ?? $container->load('getLoginAuthenticatorService'), $a, $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator'] ?? $container->load('getPasswordlessAuthenticatorService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator'] ?? $container->load('getJwtAuthenticatorService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator'] ?? $container->load('getTokenAuthenticatorService')], $container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.event_dispatcher.api'] ?? $container->load('getSecurity_EventDispatcher_ApiService'), 'api', $container->privates['monolog.logger.security'] ?? $container->load('getMonolog_Logger_SecurityService'), \true, \true, []); } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\AllowUrlFopenCheck($container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Contao\RebuildCacheTask($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['security.authenticator.manager.api'] ?? $container->load('getSecurity_Authenticator_Manager_ApiService'); if (isset($container->privates['security.firewall.authenticator.api'])) { return $container->privates['security.firewall.authenticator.api']; } return $container->privates['security.firewall.authenticator.api'] = new \_ContaoManager\Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener($a); } } privates['.console.command.secrets_generate_key.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:generate-keys', [], 'Generate new encryption keys', \false, #[\Closure(name: 'console.command.secrets_generate_key', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsGenerateKeysCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand => $container->privates['console.command.secrets_generate_key'] ?? $container->load('getConsole_Command_SecretsGenerateKeyService')); } } privates['.console.command.router_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:router', [], 'Display current routes for an application', \false, #[\Closure(name: 'console.command.router_debug', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand => $container->privates['console.command.router_debug'] ?? $container->load('getConsole_Command_RouterDebugService')); } } privates['console.command.cache_pool_clear'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand($container->services['cache.global_clearer'] ?? $container->load('getCache_GlobalClearerService'), ['cache.app', 'cache.system', 'cache.validator', 'cache.serializer', 'cache.annotations', 'cache.property_info', 'cache.property_access', 'cache.security_expression_language', 'cache.security_is_granted_attribute_expression_language']); $instance->setName('cache:pool:clear'); $instance->setDescription('Clear cache pools'); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController'] = new \_ContaoManager\Contao\ManagerApi\Controller\LogController($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['container.env_var_processor'] = new \_ContaoManager\Symfony\Component\DependencyInjection\EnvVarProcessor($container, new RewindableGenerator(function () use($container) { (yield 0 => $container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService')); }, 1)); } } privates['security.listener.api.user_provider'] = new \_ContaoManager\Symfony\Component\Security\Http\EventListener\UserProviderListener($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] ?? $container->load('getUserProviderService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Packages\InstallTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver'] ?? $container->load('getCloudResolverService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } services['container.env_var_processors_locator'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['base64' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'bool' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'const' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'csv' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'default' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'defined' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'enum' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'file' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'float' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'int' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'json' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'key' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'not' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'query_string' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'require' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'resolve' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'shuffle' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'string' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'trim' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true], 'url' => ['privates', 'container.env_var_processor', 'getContainer_EnvVarProcessorService', \true]], ['base64' => '?', 'bool' => '?', 'const' => '?', 'csv' => '?', 'default' => '?', 'defined' => '?', 'enum' => '?', 'file' => '?', 'float' => '?', 'int' => '?', 'json' => '?', 'key' => '?', 'not' => '?', 'query_string' => '?', 'require' => '?', 'resolve' => '?', 'shuffle' => '?', 'string' => '?', 'trim' => '?', 'url' => '?']); } } privates['_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener'] = new \_ContaoManager\Contao\ManagerApi\EventListener\ExceptionListener($container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService'), \false); } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\SymlinkCheck($container->services['kernel'] ?? $container->get('kernel', 1), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\System\\Request'] = new \_ContaoManager\Contao\ManagerApi\System\Request($container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck'] = new \_ContaoManager\Contao\ManagerApi\IntegrityCheck\SessionCheck($container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\MissingPackagesController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService')); } } privates['console.command.secrets_generate_key'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local')); $instance->setName('secrets:generate-keys'); $instance->setDescription('Generate new encryption keys'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Packages\UpdateTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver'] ?? $container->load('getCloudResolverService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig'] ?? $container->load('getUploadsConfigService'), $container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService'), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem(), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['.console.command.secrets_list.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('secrets:list', [], 'List all secrets', \false, #[\Closure(name: 'console.command.secrets_list', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsListCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand => $container->privates['console.command.secrets_list'] ?? $container->load('getConsole_Command_SecretsListService')); } } privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig'] = new \_ContaoManager\Contao\ManagerApi\Config\ComposerConfig($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['filesystem'] ??= new \_ContaoManager\Symfony\Component\Filesystem\Filesystem()); } } privates['console.command.secrets_encrypt_from_local'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local')); $instance->setName('secrets:encrypt-from-local'); $instance->setDescription('Encrypt all local secrets to the vault'); return $instance; } } privates['security.access_listener'] = new \_ContaoManager\Symfony\Component\Security\Http\Firewall\AccessListener($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage(), $container->privates['security.access.decision_manager'] ?? self::getSecurity_Access_DecisionManagerService($container), $container->privates['security.access_map'] ?? $container->load('getSecurity_AccessMapService'), \false); } } privates['console.command.cache_pool_prune'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand(new RewindableGenerator(function () use($container) { (yield 'cache.app' => $container->services['cache.app'] ?? $container->load('getCache_AppService')); }, 1)); $instance->setName('cache:pool:prune'); $instance->setDescription('Prune cache pools'); return $instance; } } privates['.security.command.user_password_hash.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('security:hash-password', [], 'Hash a user password', \false, #[\Closure(name: 'security.command.user_password_hash', class: '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Command\\UserPasswordHashCommand')] fn(): \_ContaoManager\Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand => $container->privates['security.command.user_password_hash'] ?? $container->load('getSecurity_Command_UserPasswordHashService')); } } privates['security.route_loader.logout'] = new \_ContaoManager\Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader([], 'security.logout_uris'); } } privates['.console.command.config_debug.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('debug:config', [], 'Dump the current configuration for an extension', \false, #[\Closure(name: 'console.command.config_debug', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDebugCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand => $container->privates['console.command.config_debug'] ?? $container->load('getConsole_Command_ConfigDebugService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Server\DatabaseController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi'] ?? $container->load('getContaoApiService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole'] ?? $container->load('getContaoConsoleService')); } } privates['console.command.secrets_decrypt_to_local'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand($container->privates['secrets.vault'] ?? $container->load('getSecrets_VaultService'), $container->privates['secrets.local_vault'] ??= new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault(\dirname(__DIR__, 4) . '/test-dir/.env.prod.local')); $instance->setName('secrets:decrypt-to-local'); $instance->setDescription('Decrypt all secrets and stores them in the local vault'); return $instance; } } services['_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController'] = new \_ContaoManager\Contao\ManagerApi\Controller\Packages\LocalPackagesController($container->privates['_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment'] ?? $container->load('getEnvironmentService')); } } services['_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand'] = $instance = new \_ContaoManager\Contao\ManagerApi\Command\AboutCommand($container->services['kernel'] ?? $container->get('kernel', 1), $container->privates['_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo'] ?? $container->load('getServerInfoService')); $instance->setName('about'); $instance->setDescription('Displays information about Contao Manager and the current server'); return $instance; } } privates['.Contao\\ManagerApi\\Command\\TaskAbortCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('task:abort', [], 'Aborts the current task and returns the status information.', \false, #[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\TaskAbortCommand => $container->services['_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand'] ?? $container->load('getTaskAbortCommandService')); } } privates['security.security_token_value_resolver'] = new \_ContaoManager\Symfony\Component\Security\Http\Controller\SecurityTokenValueResolver($container->services['security.token_storage'] ??= new \_ContaoManager\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage()); } } privates['_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator'] = new \_ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator($container->privates['_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider'] ?? $container->load('getUserProviderService'), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig'] ?? self::getUserConfigService($container)); } } privates['console.command.debug_autowiring'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand(NULL, $container->privates['debug.file_link_formatter'] ??= new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter(NULL)); $instance->setName('debug:autowiring'); $instance->setDescription('List classes/interfaces you can use for autowiring'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo'] = new \_ContaoManager\Contao\ManagerApi\System\ServerInfo(new \_ContaoManager\Contao\ManagerApi\Process\PhpExecutableFinder($container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService')), $container->privates['_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig'] ?? $container->load('getManagerConfigService')); } } privates['console.command.router_match'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand($container->services['router'] ?? self::getRouterService($container), new RewindableGenerator(fn() => new \EmptyIterator(), 0)); $instance->setName('router:match'); $instance->setDescription('Help debug routes by simulating a path info match'); return $instance; } } privates['.Contao\\ManagerApi\\Command\\IntegrityCheckCommand.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('integrity-check', [], 'Performs integrity check for the Contao Manager', \false, #[\Closure(name: '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand')] fn(): \_ContaoManager\Contao\ManagerApi\Command\IntegrityCheckCommand => $container->services['_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand'] ?? $container->load('getIntegrityCheckCommandService')); } } privates['.service_locator.aH5O6Sd'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['serverInfo' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo', 'getServerInfoService', \true]], ['serverInfo' => '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo']); } } services['request_stack'] ??= new \_ContaoManager\Symfony\Component\HttpFoundation\RequestStack(); return $container->services['error_controller'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ErrorController($container->services['http_kernel'] ?? self::getHttpKernelService($container), 'error_controller', new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer($container->privates['serializer'] ?? self::getSerializerService($container), \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer::getPreferredFormat($a), new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer(\_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::isDebug($a, \false), 'UTF-8', $container->privates['debug.file_link_formatter'] ??= new \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter(NULL), \dirname(__DIR__, 4) . '/test-dir', \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::getAndCleanOutputBuffer($a), $container->privates['monolog.logger'] ?? $container->load('getMonolog_LoggerService')), \_ContaoManager\Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer::isDebug($a, \false))); } } privates['.service_locator.EZsc.DO'] = new \_ContaoManager\Symfony\Component\DependencyInjection\Argument\ServiceLocator($container->getService ??= $container->getService(...), ['updater' => ['privates', '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate', 'getSelfUpdateService', \true]], ['updater' => '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate']); } } privates['.console.command.cache_clear.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('cache:clear', [], 'Clear the cache', \false, #[\Closure(name: 'console.command.cache_clear', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheClearCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand => $container->privates['console.command.cache_clear'] ?? $container->load('getConsole_Command_CacheClearService')); } } privates['argument_resolver.request'] = new \_ContaoManager\Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver(); } } [parent::class, 'serializer', parent::class], "\x00" . parent::class . "\x00" . 'translator' => [parent::class, 'translator', parent::class], "\x00" . parent::class . "\x00" . 'validator' => [parent::class, 'validator', parent::class], 'serializer' => [parent::class, 'serializer', parent::class], 'translator' => [parent::class, 'translator', parent::class], 'validator' => [parent::class, 'validator', parent::class]]; } \class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\Hydrator::class); \class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); \class_exists(\_ContaoManager\Symfony\Component\VarExporter\Internal\LazyObjectState::class); if (!\class_exists('_ContaoManager\\RequestPayloadValueResolverGhost8d82153', \false)) { \class_alias(__NAMESPACE__ . '\\RequestPayloadValueResolverGhost8d82153', '_ContaoManager\\RequestPayloadValueResolverGhost8d82153', \false); } privates['console.command.about'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\AboutCommand(); $instance->setName('about'); $instance->setDescription('Display information about the current project'); return $instance; } } privates['_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask'] = $instance = new \_ContaoManager\Contao\ManagerApi\Task\Composer\DumpAutoloadTask($container->privates['_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory'] ?? $container->load('getConsoleProcessFactoryService'), $container->services['_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator'] ?? $container->load('getTranslatorService')); $instance->setLogger($container->privates['monolog.logger.tasks'] ?? $container->load('getMonolog_Logger_TasksService')); return $instance; } } privates['.console.command.container_lint.lazy'] = new \_ContaoManager\Symfony\Component\Console\Command\LazyCommand('lint:container', [], 'Ensure that arguments injected into services match type declarations', \false, #[\Closure(name: 'console.command.container_lint', class: '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerLintCommand')] fn(): \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand => $container->privates['console.command.container_lint'] ?? $container->load('getConsole_Command_ContainerLintService')); } } privates['console.command.config_debug'] = $instance = new \_ContaoManager\Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand(); $instance->setName('debug:config'); $instance->setDescription('Dump the current configuration for an extension'); return $instance; } } 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController', 1 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AbstractConfigController', 2 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController', 3 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController', 4 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController', 5 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController', 6 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController', 7 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController', 8 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController', 9 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController', 10 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController', 11 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController', 12 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController', 13 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController', 14 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController', 15 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController', 16 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController', 17 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController', 18 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController', 19 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController', 20 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController', 21 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController', 22 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController', 23 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController', 24 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController', 25 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController', 26 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController', 27 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController', 28 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController', 29 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController', 30 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController', 31 => '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController', 32 => 'JsonSchema\\Entity\\JsonPointer', 34 => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver', 35 => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController', 36 => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController', 37 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver', 38 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface', 39 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver', 40 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver', 41 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver', 42 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver', 43 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver', 44 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver', 45 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver', 46 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver', 47 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver', 48 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver', 49 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver', 50 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver', 51 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver', 52 => 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface', 53 => 'Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver', 54 => 'Symfony\\Component\\HttpKernel\\Controller\\ControllerReference', 55 => 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver', 56 => 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface', 57 => 'Symfony\\Component\\HttpKernel\\Controller\\ErrorController', 58 => 'Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver', 59 => 'Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver', 60 => 'Symfony\\Component\\HttpKernel\\Controller\\ValueResolverInterface', 61 => 'Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver', 62 => 'Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver', );services: _defaults: autoconfigure: true autowire: true public: false bind: $debug: '%kernel.debug%' kernel: synthetic: true public: true tags: - routing.route_loader _ContaoManager\Contao\ManagerApi\: resource: '../../*' exclude: '../../{Command,Controller,Resources,Tests}' _ContaoManager\Contao\ManagerApi\Command\: resource: '../../Command' public: true _ContaoManager\Contao\ManagerApi\Controller\: resource: '../../Controller' public: true tags: ['controller.service_arguments'] ############################## # Additional configuration # ############################## _ContaoManager\Contao\ManagerApi\ApiKernel: '@kernel' _ContaoManager\Contao\ManagerApi\I18n\Translator: public: true locale_listener: class: _ContaoManager\Contao\ManagerApi\EventListener\LocaleListener _ContaoManager\Contao\ManagerApi\Task\TaskManager: arguments: - !tagged app.task contao_manager.webauthn.serializer_factory: class: _ContaoManager\Webauthn\Denormalizer\WebauthnSerializerFactory arguments: - !service { class: _ContaoManager\Webauthn\AttestationStatement\AttestationStatementSupportManager } contao_manager.webauthn.serializer: class: _ContaoManager\Symfony\Component\Serializer\SerializerInterface factory: ['@contao_manager.webauthn.serializer_factory', 'create'] contao_manager.webauthn.ceremony_step_manager_factory: class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory contao_manager.webauthn.creation_ceremony: class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManager factory: ['@contao_manager.webauthn.ceremony_step_manager_factory', 'creationCeremony'] contao_manager.webauthn.request_ceremony: class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManager factory: ['@contao_manager.webauthn.ceremony_step_manager_factory', 'requestCeremony'] contao_manager.webauthn.authenticator_attestation_response_validator: class: _ContaoManager\Webauthn\AuthenticatorAttestationResponseValidator arguments: $ceremonyStepManager: '@contao_manager.webauthn.creation_ceremony' calls: - setLogger: ['@logger'] contao_manager.webauthn.authenticator_assertion_response_validator: class: _ContaoManager\Webauthn\AuthenticatorAssertionResponseValidator arguments: $ceremonyStepManager: '@contao_manager.webauthn.request_ceremony' calls: - setLogger: ['@logger'] imports: - { resource: config.yaml } monolog: handlers: main: type: rotating_file path: "%kernel.logs_dir%/api.log" level: INFO channels: ['!event', '!security', '!request'] max_files: 10 services: contao_manager.webauthn.ceremony_step_manager_factory: class: _ContaoManager\Webauthn\CeremonyStep\CeremonyStepManagerFactory calls: - setSecuredRelyingPartyId: [ [ 'localhost' ] ] imports: - { resource: config.yaml } monolog: handlers: main: type: fingers_crossed action_level: error handler: file file: type: error_log imports: - { resource: services.yaml } # The secret is only required to sign fragment URLs which is not used framework: secret: '' default_locale: en router: resource: kernel::loadRoutes type: service security: password_hashers: _ContaoManager\Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' providers: contao_manager_user_provider: id: _ContaoManager\Contao\ManagerApi\Security\UserProvider firewalls: api: stateless: true provider: contao_manager_user_provider custom_authenticators: - _ContaoManager\Contao\ManagerApi\Security\LoginAuthenticator - _ContaoManager\Contao\ManagerApi\Security\WebauthnAuthenticator - _ContaoManager\Contao\ManagerApi\Security\PasswordlessAuthenticator - _ContaoManager\Contao\ManagerApi\Security\JwtAuthenticator - _ContaoManager\Contao\ManagerApi\Security\TokenAuthenticator role_hierarchy: ROLE_ADMIN: ROLE_INSTALL ROLE_INSTALL: ROLE_UPDATE ROLE_UPDATE: ROLE_READ ROLE_READ: ROLE_USER access_control: - { path: ^/api/session(/options)?$, roles: PUBLIC_ACCESS } - { path: ^/api, roles: ROLE_USER } cs: integrity: allow_url_fopen: title: 'Služba PHP "allow_url_fopen" není na tomto serveru spuštěna.' process: title: 'Funkce PHP "proc_*" není k dispozici na tomto serveru.' detail: 'Funkce "proc_open" a "proc_close" jsou nezbytné pro spouštění příkazů na pozadí. Dotázejte se Vašeho poskytovatele, proč není daná k dispozici. Správce Contaa nebude moct bez toho fungovat správně.' intl: title: 'Rozšíření PHP Intl není na tomto serveru spuštěno.' detail: 'Contao 4 vyžaduje rozšíření PHP Intl pro mezinárodní záležitosti.' openssl: title: 'Rozšíření PHP OpenSSL není na tomto serveru spuštěno.' detail: 'Správce Contaa vyžaduje rozšíření OpenSSL, aby mohl stahovat soubory přes zabezpečené připojení (https).' dom: title: 'Rozšíření PHP DOM není na tomto serveru spuštěno.' detail: 'Contao 4 vyžaduje rozšíření PHP DOM pro zpracování dokumentů XML.' xmlreader: title: 'Rozšíření PHP XMLReader není na tomto serveru spuštěno.' detail: 'Contao 4 vyžaduje rozšíření PHP XMLReader pro zpracování dokumentů XML.' graphics_lib: title: 'Není dostupná žádná knihovna PHP na zpracování obrázků.' detail: 'Contao 4 vyžaduje pro zpracování obrázku jedno z následujících rozšíření: GD, Imagick nebo Gmagick.' symlink: title: 'Metoda pro vytvoření symlinků buď není dostupná nebo nefunguje správně.' session: title: 'Sezení PHP nelze zahájit.' memory_limit: title: 'Nedostatečné množství paměti pro PHP.' detail: 'Vaše nastavení PHP dovoluje (na příkazovém řádku) jen omezené akce kvůli omezení paměti {limit}. Ta není dostatečná pro chod Composeru a nešlo automaticky zvýšit paměť. Kontaktujte prosím Vaše poskytovatele služeb.' systempdir: title: 'Nelze zapisovat do dočasné složky systému.' detail: 'Nejspíš jde o problém s Vaším nastavením služeb. Ujistěte se, že open_basedir dovoluje přístup k dočasné složce nebo zda je sys_temp_dir správně nastavená.' zip: title: 'Rozšíření zip a příkazy unzip/7z chybějí.' boot: composer: invalid: 'Schéma ověření composer.json: {exception}' config: php_cli: not_found: 'Tato cesta neobsahuje platné binární PHP.' incompatible: 'Tato verze je verze PHP {cli}, ale Váš server je ve verzi {web}.' error: 'Chyba při validaci binární PHP.' cloud: platform: 'Platforma nemusí být nastavená v composer.json.' cache: 'Položky meziúložiště nemusí být nastavené v composer.json.' task: setup_packages: title: 'Instalování aplikací Contaa' install_packages: title: 'Nainstalovat věci závislé na Composerovi' update_packages: title: 'Aktualizují se balíčky' dump_autoload: title: 'Vyčistit Autoloadera Composeru' clear_cache: title: 'Vyprazdňování meziúložiště Composeru' rebuild_cache: title: 'Přetváří se meziúložiště Contaa.' self_update: title: 'Spustit samoaktualizaci Správce Contaa' backup_create: title: 'Vytváření uložení databáze' backup_restore: title: 'Obnovení uložené databáze' taskoperation: self-update: detail: 'Aktualizování {old} na {new}' success: 'Aktualizovat na {new}' install-uploads: summary: 'Instalují se nahrané soubory' console: 'Nainstalovaný artefakt pro {package} (verze {version}) [do balíčků/{name}]' remove-uploads: summary: 'Smazat nahrané soubory' composer-install: retry: 'Nový pokus {current}/{max}' nothing: 'Neexistuje nic k nainstalování či aktualizování' result: 'nainstalováno: {installs}, zaktualizováno: {updates}, smazáno: {removals}' dump-autoload: result: 'Vygenerované optiomalizované autoload soubory obsahují počet tříd: {count}' cloud: queued: 'Proces začne za {seconds} s. (současný {jobs} proces - počet uživatelů: {workers})' processing: 'Doba aktivity: {seconds} s' error: 'Vyřešení závislostí nevyšlo' finished: 'Dokončení: {seconds} s. Využití paměti: {memory} (vrchol: {peak}), doba: {time}.' upload: error: file: 'Tento soubor není platný nebo neobsahuje žádnou composer.json.' json: 'Soubor composer.json neobsahuje žádná platná data JSON,' schema: 'Ověření schématu composer.json selhalo,' partial: 'Nahrání souborů nebylo dokončeno.' error: writable: root: 'Správce Contaa nemůže zapisovat do kořenového adresáře na "{path}".' directory: 'Správce Contaa nemůže vytvořit adresář "{path}".' config-file: 'Správce Contaa nemůže zapisovat do konfiguračního souboru v "{path}".' detail: 'Vypadá to, že Váš webový server není správně nastavený. Pokud chcete nainstalovat Contao, nastavte prosím kořenový dokument na Vašem webovém serveru. Jinak se jistěte, že jsou přístupová práva nastavená správně. Pokud si nejste jistí, obraťte se na správce webových služeb.' br: integrity: allow_url_fopen: title: 'An arventennoù PHP "allow_url_fopen" n''eo ket gweredekaet war ar servijer.' process: title: '' detail: '' intl: title: 'N''eo ket hegerz an astenn PHP Intl.' detail: 'Contao 4 a c''houlenn an astenn PHP Intl evit ma vo etrebroadel.' openssl: title: 'N''eo ket hegerz an astenn PHP OpenSSL.' detail: 'Manager contao a c''houl an amzer openssl evit pellgargañ restroù dre ur gevreadenn dirinegañ (https).' dom: title: '' detail: '' xmlreader: title: '' detail: '' graphics_lib: title: '' detail: '' symlink: title: '' session: title: 'N''hall ket bezañ kroget an dalc''h PHP.' memory_limit: title: '' detail: '' systempdir: title: '' detail: '' boot: composer: invalid: '' config: php_cli: not_found: '' incompatible: '' cloud: platform: '' cache: '' task: setup_packages: title: '' install_packages: title: '' update_packages: title: 'Oc''h hizivaat ar pakadoù' dump_autoload: title: '' clear_cache: title: '' rebuild_cache: title: 'Oc''h adsevel krubuilh Contao' self_update: title: '' taskoperation: self-update: detail: '' success: '' install-uploads: summary: '' console: '' remove-uploads: summary: '' composer-install: retry: '' nothing: '' result: '' dump-autoload: result: '' cloud: queued: '' processing: '' error: '' finished: '' upload: error: file: '' json: '' schema: '' partial: '' error: writable: root: '' directory: '' config-file: '' detail: '' es: integrity: allow_url_fopen: title: 'La configuración de PHP "allow_url_fopen" no está habilitada en el servidor.' process: title: 'Las funciones PHP "proc_ *" no están disponibles en el servidor. ' detail: 'Las funciones "proc_open", "proc_close", "proc_get_status" y "proc_terminate" son necesarias para ejecutar tareas de línea de comandos en segundo plano. Consulte con su proveedor de alojamiento por qué este método no está disponible; el Contao Manager no se ejecutará correctamente sin él. ' intl: title: 'La extensión PHP Intl no está disponible.' detail: 'Contao 4 requiere la extensión PHP Intl para fines de internacionalización.' openssl: title: 'La extensión PHP OpenSSL no está disponible.' detail: 'El Contao Manager requiere la extensión OpenSSL para descargar archivos a través de una conexión cifrada (https).' dom: title: 'La extensión PHP DOM no está disponible. ' detail: 'Contao 4 requiere la extensión DOM de PHP para analizar documentos XML.' xmlreader: title: 'La extensión PHP XMLReader no está disponible.' detail: 'Contao 4 requiere la extensión XMLReader de PHP para analizar documentos XML.' graphics_lib: title: 'No hay biblioteca de procesamiento de imágenes PHP disponible.' detail: 'Contao 4 requiere la extensión GD, Imagick o Gmagick para procesar imágenes.' symlink: title: 'El método de enlace simbólico PHP no está disponible o no funciona correctamente.' session: title: 'La sesión de PHP no se pudo iniciar.' memory_limit: title: 'Límite insuficiente de memoria de PHP.' detail: 'Su configuración PHP solo permite {limit} memoria (en la línea de comando). Esto no es suficiente para ejecutar Composer y no fue posible aumentar este límite automáticamente. Por favor, póngase en contacto con su proveedor de hosting para obtener asistencia.' systempdir: title: 'No se puede escribir en el directorio temporal del sistema.' detail: 'Probablemente esto sea un problema con su configuración de alojamiento. Asegúrese de que open_basedir permita el acceso al directorio temporal o que el sys_temp_dir esté configurado correctamente.' zip: title: 'Faltan la extensión zip y los comandos unzip/7z.' boot: composer: invalid: 'validación del esquema composer.json: {exception}' config: php_cli: not_found: 'Esta ruta no contiene un binario PHP válido.' incompatible: 'Este binario es una versión de PHP {cli}, pero su servidor web es la versión {web}.' error: 'Error al validar el binario PHP.' cloud: platform: 'La plataforma no debe configurarse en composer.json.' cache: 'Las propiedades de caché no deben configurarse en composer.json.' task: setup_packages: title: 'Instalación de la aplicación Contao' install_packages: title: 'Instalando dependencias del Composer' update_packages: title: 'Actualizando paquetes' dump_autoload: title: 'Autocargador de clases de dumping Composer' clear_cache: title: 'Limpiar el caché del Composer' rebuild_cache: title: 'Reconstruyendo de caché de Contao' self_update: title: 'Autoactualización de Contao Manager ' backup_create: title: 'Creando una copia de seguridad de la base de datos' backup_restore: title: 'Restaurar la copia de seguridad de la base de datos' taskoperation: self-update: detail: 'Actualización de {old} a {new}' success: 'Actualizado a {new}' install-uploads: summary: 'Instalación de cargas' console: 'Artefacto instalado para {package} (versión {version}) [a paquetes / {name}]' remove-uploads: summary: 'Eliminando cargas' composer-install: retry: 'volviendo a intentar {current}/{max}' nothing: 'Nada que instalar o actualizar' result: '{installs} instalado, {updates} actualizado, {removals} eliminado' dump-autoload: result: 'Archivos de carga automática optimizados generados que contienen {count} clases' cloud: queued: 'En cola, comenzando en aprox. {seconds} segundos (actualmente {jobs} trabajos en {workers} trabajadores)' processing: 'Activo durante {seconds} segundos.' error: 'No se pudieron resolver las dependencias' finished: 'Completado en {seconds} segundos. Uso de memoria: {memory} (pico: {peak}), tiempo: {time}.' upload: error: file: 'El archivo no es válido o no contiene un composer.json.' json: 'El composer.json no contiene datos JSON válidos.' schema: 'La validación del esquema composer.json ha fallado.' partial: 'La carga del archivo no se completó.' error: writable: root: 'El Contao Manager no pudo escribir en el directorio raíz en "{path}". ' directory: 'Contao Manager no pudo crear el directorio "{path}".' config-file: 'Contao Manager no pudo escribir un archivo de configuración en "{file}".' detail: 'Parece que su servidor no está configurado correctamente. Si está a punto de instalar Contao, configure el DocumentRoot de su servidor web. De lo contrario, asegúrese de que los permisos de acceso a archivos sean correctos. Si no está seguro de cómo solucionar este problema, comuníquese con su proveedor de alojamiento para obtener asistencia.' pt: integrity: allow_url_fopen: title: 'A função PHP "allow_url_fopen" não está ativada no servidor. ' process: title: 'As funções "proc_*" do PHP não estão disponíveis no servidor.' detail: 'As funções "proc_open", "proc_close", "proc_get_status" e "proc_terminate" são necessárias para executar tarefas de linha de comando em segundo plano. Verifique com o seu fornecedor de alojamento porque é que este método não está disponível; o Gestor de Contacto não funcionará correctamente sem ele.' intl: title: 'A extensão PHP Intl não está disponível.' detail: 'O Contao 4 necessita da extensão PHP Intl para propósitos de internacionalização.' openssl: title: 'A extensão PHP OpenSSL não se encontra disponível.' detail: 'O Contao Manager necessita da extensão OpenSSL para receber ficheiros através de uma ligação encriptada (https).' dom: title: 'A extensão PHP DOM não se encontra disponivel.' detail: 'O contao 4 necessita da extensão PHP DOM para reconhecer documentos XML.' xmlreader: title: 'A extensão PHP XMLReader não está disponível.' detail: 'O contao 4 necessita da extensão PHP XMLReader para reconhecer documentos XML.' graphics_lib: title: 'Nenhuma biblioteca de processamento de imagens PHP está disponível. ' detail: 'O Contacto 4 requer ou a extensão GD, Imagick ou Gmagick para processar imagens.' symlink: title: 'O método PHP symlink não está disponível ou não funciona correctamente.' session: title: 'A sessão PHP falhou ao iniciar.' memory_limit: title: 'Memória limite PHP insuficiente.' detail: 'A configuração PHP atual apenas permite {limit} de memória (na linha de comandos). Estes recursos não são suficientes para executar o Composer e não é possível aumentar este limite automaticamente. Por favor contacte o seu fornecedor de conteúdo para assistência.' systempdir: title: 'Impossível escrever no directório de memória de sistema temporário.' detail: 'Isto é muito provavelmente um problema com a configuração do seu alojamento. Certifique-se de que o open_basedir permite o acesso ao directório temporário ou de que o sys_temp_dir está correctamente configurado.' zip: title: '' boot: composer: invalid: 'composer.json schema validation: {exception}' config: php_cli: not_found: 'Este caminho não contém um binário PHP válido. ' incompatible: 'Este binário é uma versão PHP {cli} mas o seu servidor web é versão {web}.' error: '' cloud: platform: '' cache: 'Propriedades de cache não podem estar configuradas em composer.json .' task: setup_packages: title: 'A instalar aplicação Contao' install_packages: title: 'A instalar dependências composer' update_packages: title: 'A atualizar pacotes' dump_autoload: title: 'Compressor de descarga classe Autoloader' clear_cache: title: 'A limpar Cache Composer' rebuild_cache: title: 'A reconstruir Cache Composer' self_update: title: 'Contao Manager Auto-atualização' backup_create: title: '' backup_restore: title: '' taskoperation: self-update: detail: 'A atualizar de {old} para {new}' success: 'Actualizado para {new}' install-uploads: summary: 'Instalação de uploads' console: 'Artifact instalado de {package} (versão {version}) [para packages/{name}]' remove-uploads: summary: 'Remoção de uploads' composer-install: retry: 'tentando de novo {current}/{max}' nothing: 'Nada para instalar ou actualizar' result: '{installs} instalado, {updates} actualizado, {removals} retirado' dump-autoload: result: 'Geração de ficheiros de carga automática optimizados contendo classes {count}.' cloud: queued: 'Em fila de espera, começando em aproximadamente. {seconds} secundos (actualmente {jobs} empregos em {workers} trabalhadores)' processing: 'Activo durante {seconds} segundos.' error: 'Falha na resolução de dependências' finished: 'Concluído em {seconds} segundos. Utilização de memória: {memory} (pico: {peak}), hora: {time}.' upload: error: file: 'O ficheiro é inválido ou não contém um composer.json .' json: 'O composer.json não contém dados JSON válidos .' schema: 'O composer.json não passou a validação de schemas.' partial: 'O upload de ficheiros não completou com sucesso.' error: writable: root: 'O Gestor de Contacto não pôde escrever para o directório raiz em "{path}".' directory: 'O Contao Manager não pôde criar o directório "{path}".' config-file: 'O Contao Manager não pôde escrever um ficheiro de configuração para "{file}".' detail: 'Parece que o seu servidor não está configurado correctamente. Se está prestes a instalar o Contao, por favor configure o DocumentRoot do seu servidor web. Caso contrário, certifique-se de que as permissões de acesso ao ficheiro estão correctas. Se não tiver a certeza de como corrigir isto, contacte o seu fornecedor de alojamento para obter apoio.' de: integrity: allow_url_fopen: title: 'Die PHP-Einstellung "allow_url_fopen" ist auf dem Server deaktiviert.' process: title: 'Die PHP "proc_*" Funktionen ist auf dem Server nicht verfügbar.' detail: 'Die Funktionen "proc_open", "proc_close", "proc_get_status" und "proc_terminate" sind notwendig, um Kommandozeilentasks im Hintergrund auszuführen. Bitte frage bei deinem Hosting-Anbieter nach, warum die Funktionen nicht verfügbar sind; der Contao Manager läuft nicht ohne sie.' intl: title: 'Die PHP Intl-Erweiterung ist nicht verfügbar.' detail: 'Contao 4 benötigt die PHP Intl-Erweiterung für die Internationalisierung der Anwendung.' openssl: title: 'Die PHP OpenSSL-Erweiterung ist nicht verfügbar.' detail: 'Der Contao Manager benötigt die OpenSSL-Erweiterung, um Dateien über eine verschlüsselte Verbindung (https) herunterzuladen.' dom: title: 'Die PHP DOM-Erweiterung ist nicht verfügbar.' detail: 'Contao 4 benötigt die PHP DOM-Erweiterung, um XML-Dokumente zu parsen.' xmlreader: title: 'Die PHP XMLReader-Erweiterung ist nicht verfügbar.' detail: 'Contao 4 benötigt die PHP XMLReader-Erweiterung, um XML-Dokumente zu parsen.' graphics_lib: title: 'Keine PHP Bild-Bibliothek verfügbar.' detail: 'Contao 4 benötigt entweder die GD-, Imagick- oder Gmagick-Erweiterung, um Bilder zu verarbeiten.' symlink: title: 'Die PHP Symlink-Methode ist nicht verfügbar oder funktioniert nicht korrekt.' session: title: 'Die PHP-Session konnte nicht gestartet werden.' memory_limit: title: 'Ungenügendes PHP Memory-Limit.' detail: 'Deine PHP-Konfiguration erlaubt nur {limit} RAM (auf der Kommandozeile). Das ist nicht genug, um Composer auszuführen, und das Limit konnte auch nicht automatisch erhöht werden. Bitte kontaktiere deinen Hosting-Anbieter.' systempdir: title: 'Konnte nicht in den temporären Systemordner schreiben.' detail: 'Dies ist höchstwahrscheinlich ein Problem mit deiner Serverkonfiguration. Stelle sicher, dass entweder open_basedir den Zugriff auf den temporären Ordner erlaubt oder dass sys_temp_dir korrekt gesetzt ist.' zip: title: 'Die PHP ZIP-Erweiterung und die unzip/7z-Commands sind beide nicht verfügbar.' boot: composer: invalid: 'composer.json Schema-Validierung: {exception}' config: php_cli: not_found: 'Der Pfad enthält kein gültiges PHP-Binary.' incompatible: 'Dieses Binary beinhaltet PHP {cli}, der Webprozess verwendet jedoch PHP {web}.' error: 'Fehler beim Validieren des PHP-Binary.' cloud: platform: 'Die Plattform darf in der composer.json nicht konfiguriert sein.' cache: 'Cache-Einstellungen dürfen in der composer.json nicht konfiguriert sein.' task: setup_packages: title: 'Contao wird installiert' install_packages: title: 'Installieren von Composer-Abhängigkeiten' update_packages: title: 'Pakete werden aktualisiert' dump_autoload: title: 'Schreibe Composer-Autoloader' clear_cache: title: 'Leeren des Composer-Caches' rebuild_cache: title: 'Neuerstellung des Contao-Caches' self_update: title: 'Aktualisiere Contao Manager' backup_create: title: 'Erstelle Datenbank-Backup' backup_restore: title: 'Datenbank-Backup wird wiederhergestellt' taskoperation: self-update: detail: 'Aktualisiere von {old} nach {new}' success: 'Aktualisiert auf {new}' install-uploads: summary: 'Installiere hochgeladene Pakete' console: 'Artefakt für {package} (Version {version}) [nach packages/{name}] installiert' remove-uploads: summary: 'Entferne hochgeladene Dateien' composer-install: retry: 'Versuch {current}/{max}' nothing: 'Keine Aktualisierungen' result: '{installs} installiert, {updates} aktualisiert, {removals} entfernt' dump-autoload: result: 'Autoload-Dateien für {count} Klassen generiert' cloud: queued: 'Berechnung startet in ca. {seconds} Sekunden (aktuell {jobs} Aufgaben auf {workers} Servern)' processing: 'Aktiv seit {seconds} Sekunden.' error: 'Abhängigkeits-Auflösung fehlgeschlagen' finished: 'Erfolgreich nach {seconds} Sekunden. RAM-Verbrauch: {memory} (Spitze: {peak}), Dauer: {time}.' upload: error: file: 'Die Datei ist ungültig oder enthält keine composer.json.' json: 'Die composer.json enthält keine validen JSON-Daten.' schema: 'Die composer.json Schema-Validierung ist fehlgeschlagen.' partial: 'Der Upload wurde nicht abgeschlossen.' error: writable: root: 'Der Contao Manager kann das Wurzelverzeichnis unter "{path}" nicht beschreiben.' directory: 'Das Verzeichnis "{path}" konnte nicht angelegt werden.' config-file: 'Die Konfigurations-Datei unter "{file}" konnte nicht geschrieben werden.' detail: 'Es scheint als wäre dein Webserver nicht korrekt konfiguriert. Falls du gerade Contao installierst, stelle sicher, dass der DocumentRoot richtig konfiguriert ist. Andernfalls stelle sicher, dass die Dateiberechtigungen korrekt sind. Falls du dies nicht selber reparieren kannst, frage am besten bei deinem Hosting-Anbieter.' it: integrity: allow_url_fopen: title: 'L''impostazione PHP "allow_url_fopen" non è abilitata sul server.' process: title: 'Le funzioni PHP "proc_*" non sono disponibili sul server.' detail: 'Le funzioni "proc_open", "proc_close", "proc_get_status" e "proc_terminate" sono necessarie per eseguire compiti da linea di comando in background. Verifica con il tuo fornitore di hosting perché questo metodo non è disponibile; il Contao Manager non funzionerà correttamente senza di esso.' intl: title: 'L''estensione PHP Intl non è disponibile.' detail: 'Contao 4 richiede l''estensione PHP Intl per l''internazionalizzazione.' openssl: title: 'L''estensione PHP OpenSSL non è disponibile.' detail: 'Il Contao Manager richiede l''estensione OpenSSL per scaricare i file su una connessione criptata (https).' dom: title: 'L''estensione PHP DOM non è disponibile. ' detail: 'Contao 4 richiede l''estensione PHP DOM per analizzare i documenti XML. ' xmlreader: title: 'L''estensione PHP XMLReader non è disponibile.' detail: 'Contao 4 richiede l''estensione PHP XMLReader per analizzare i documenti XML. ' graphics_lib: title: 'Non è disponibile una libreria di elaborazione delle immagini PHP.' detail: 'Contao 4 richiede l''estensione GD, Imagick o Gmagick per elaborare le immagini.' symlink: title: 'Il metodo PHP symlink non è disponibile o non funziona correttamente.' session: title: 'Non è stato possibile avviare la sessione PHP.' memory_limit: title: 'Limite della memoria PHP non sufficiente.' detail: 'La configurazione PHP consente solo la memoria {limit} (sulla riga di comando). Questo non è sufficiente per eseguire Composer e non è stato possibile aumentare automaticamente questo limite. Si prega di contattare il proprio fornitore di webhosting per il supporto.' systempdir: title: 'Impossibile scrivere sulla cartella temporanea di sistema.' detail: 'Questo è molto probabilmente un problema con la vostra configurazione di hosting. Assicurarsi che open_basedir permetta l''accesso alla directory temporanea o che sys_temp_dir sia configurato correttamente.' zip: title: '' boot: composer: invalid: 'Convalida dello schema composer.json: {exception}' config: php_cli: not_found: 'Questo percorso non contiene un PHP valido.' incompatible: 'Il PHP è una versione {cli} ma il tuo server web è una versione {web}.' error: 'Errore durante la convalida del PHP binary.' cloud: platform: 'La piattaforma non deve essere configurata in composer.json.' cache: 'Le proprietà della cache non devono essere configurate in composer.json.' task: setup_packages: title: 'Installazione dell''applicazione Contao' install_packages: title: 'Installazione delle dipendenze del composer' update_packages: title: 'Aggiornamento pacchetti' dump_autoload: title: 'Dumping Composer Class Autoloader' clear_cache: title: 'Cancellazione della cache del compositore' rebuild_cache: title: 'Ricostruzione di Contao Cache' self_update: title: 'Auto-aggiornamento del Contao Manager' backup_create: title: 'Creazione del backup del database' backup_restore: title: 'Ripristino del backup del database' taskoperation: self-update: detail: 'Aggiornamento da {old} a {new}' success: 'Aggiornato a {nuovo}' install-uploads: summary: 'Installazione uploads' console: 'Installate modifiche per {package} (versione {version}) [su pacchetti / {name}]' remove-uploads: summary: 'Rimuovi uploads' composer-install: retry: 'riprova {current}/{max}' nothing: 'Niente da installare o aggiornare' result: '{installs} installato, {updates} aggiornato, {removals} rimosso' dump-autoload: result: 'Generati file di caricamento automatico ottimizzati contenenti {count} classi' cloud: queued: 'In coda, a partire da circa {seconds} secondi (attualmente {jobs} jobs {workers} attivi)' processing: 'Attivo per {secondi} secondi.' error: 'Verifica delle dipendenze non riuscita' finished: 'Completatio in {seconds} secondi. Utilizzo della memoria: {memory} (peak: {peak}), tempo: {time}.' upload: error: file: 'Il file non è valido o non contiene un composer.json.' json: 'Composer.json non contiene dati JSON validi.' schema: 'La convalida dello schema composer.json non è riuscita.' partial: 'Il caricamento del file non è stato completato.' error: writable: root: 'Il Contao Manager non poteva scrivere nella directory principale in "{path}".' directory: 'Contao Manager non è stato in grado di creare la directory "{path}".' config-file: 'Contao Manager non ha potuto scrivere un file di configurazione "{file}".' detail: 'Sembra che il tuo server non sia configurato correttamente. Se stai per installare Contao, configura la document root del tuo server web. In caso contrario, assicurarsi che le autorizzazioni di accesso al file siano corrette. Se non sei sicuro di come risolvere questo problema, contatta il tuo provider di hosting per supporto.' pl: integrity: allow_url_fopen: title: 'Ustawienie PHP "allow_url_fopen" nie jest włączone na serwerze.' process: title: 'Funkcje PHP "proc_*" są niedostępne na serwerze.' detail: 'Funkcje "proc_open", "proc_close", "proc_get_status" i "proc_terminate" są konieczne do wykonywania zadań w linii komend w tle. Skonsultuj z administratorem serwera, dlaczego te funkcje są niedostępne; Contao Manager nie będzie działał bez nich prawidłowo.' intl: title: 'Rozszerzenie PHP Intl jest niedostępne.' detail: 'Contao 4 wymaga rozszerzenia PHP Intl w celach umiędzynarodowienia.' openssl: title: 'Rozszerzenie PHP OpenSSL jest niedostępne.' detail: 'Contao Manager wymaga rozszerzenia OpenSSL w celu pobierania plików przez szyfrowane połączenie (https).' dom: title: 'Rozszerzenie PHP DOM jest niedostępne.' detail: 'Contao 4 wymaga rozszerzenia PHP DOM do czytania dokumentów XML.' xmlreader: title: 'Rozszerzenie PHP XMLReader jest niedostępne.' detail: 'Contao 4 wymaga rozszerzenia PHP XMLReader do czytania dokumentów XML.' graphics_lib: title: 'Nie ma dostępnej biblioteki PHP do przetwarzania obrazków.' detail: 'Contao 4 wymaga rozszerzenia GD, Imagick lub Gmgick do przetwarzania obrazków.' symlink: title: 'Metoda PHP symlink jest niedostępna lub nie działa prawidłowo.' session: title: 'Sesja PHP nie mogła zostać uruchomiona.' memory_limit: title: 'Niewystarczający limit pamięci.' detail: 'Twoja konfiguracja PHP pozwala tylko na {limit} pamięci (w linii komend). To nie wystarczy na uruchomienie Composera i automatycznie podniesienie limitu nie było możliwe. Skontaktuj się z hostingodawcą.' systempdir: title: 'Nie udało się zapisać do tymczasowego katalogu systemowego.' detail: 'To jest prawdopodobnie problem z konfiguracją hostingu. Upewnij się, że open_basedir pozwala na dostęp do tymczasowego katalogu lub, że sys_temp_dir jest poprawnie skonfigurowane.' zip: title: '' boot: composer: invalid: 'walidacja composer.json: {exception}' config: php_cli: not_found: 'Ta ścieżka nie zawiera prawidłowego PHP binary.' incompatible: 'Ta wersja PHP binary to {cli}, ale wersja na serwerze to {web}.' error: 'Błąd podczas sprawdzania poprawności pliku wykonywalnego PHP.' cloud: platform: 'Platforma nie może być skonfigurowana w composer.json.' cache: 'Właściwości cache nie mogą być skonfigurowane w composer.json.' task: setup_packages: title: 'Instalowanie Aplikacji Contao' install_packages: title: 'Instalowanie Pakietów Composera' update_packages: title: 'Aktualizowanie pakietów' dump_autoload: title: 'Generowanie Klas Autoloader Composer''a' clear_cache: title: 'Czyszczenie Cache Composera' rebuild_cache: title: 'Przebudowywanie Contao cache' self_update: title: 'Auto-Aktualizacja Contao Manager' backup_create: title: 'Tworzenie kopii zapasowej bazy danych' backup_restore: title: 'Przywracanie kopii zapasowej bazy danych' taskoperation: self-update: detail: 'Aktualizowanie z {old} do {new}' success: 'Aktualizuj do {new}' install-uploads: summary: 'Instalowanie załadowanych plików' console: 'Zainstalowano artifact dla {package} (wersja {version}) [w packages/{name}]' remove-uploads: summary: 'Usuwanie załadowanych plików' composer-install: retry: 'ponawianie {current}/{max}' nothing: 'Nic od instalacji lub aktualizacji' result: '{installs} zainstalowane, {updates} zaktualizowane, {removals} usunięte' dump-autoload: result: 'Wygenerowano zoptymalizowane pliki autoload zawierające {count} klas' cloud: queued: 'Dodane do kolejki, startuje za około {seconds} sekund (aktualnie {jobs} zadań w {workers} kolejkach)' processing: 'Aktywne od {seconds} sekund.' error: 'Nie udało się rozwiązać zależności' finished: 'Ukończone w {seconds} sekund. Użycie pamięci: {memory} (szczyt: {peak}), czas:{time}.' upload: error: file: 'Plik jest nieprawidłowy lub nie zawiera composer.json.' json: 'Plik composer.json nie zawiera poprawnych danych JSON.' schema: 'Walidacja struktury composer.json nie powiodła się.' partial: 'Wgrywanie pliku nie zostało zakończone.' error: writable: root: 'Contao Manager nie mógł wykonać zapisu w głównym katalogu w "{path}".' directory: 'Contao Manager nie mógł stworzyć katalogu "{path}".' config-file: 'Contao Manager nie mógł zapisać pliku konfiguracyjnego w "{file}".' detail: 'Wygląda na to, że twój serwer nie jest poprawnie skonfigurowany. Jeśli zamierzasz teraz instalować Contao, skonfiguruj katalog główny serwera www - document root. Sprawdź również, czy uprawnienia do zapisu plików są prawidłowe. Jeśli nie wiesz jak to naprawić, skontaktuj się z administratorem serwera, aby uzyskać wsparcie.' fa: integrity: allow_url_fopen: title: 'تنظیم PHP "allow_url_fopen" در سرور فعال نیست.' process: title: '' detail: '' intl: title: 'افزونه PHP Intl موجود نیست.' detail: '' openssl: title: 'افزونه‌ی PHP OpenSSL موجود نیست.' detail: '' dom: title: '' detail: '' xmlreader: title: '' detail: '' graphics_lib: title: '' detail: '' symlink: title: '' session: title: '' memory_limit: title: 'محدویت حافظه‌ی PHP ناکافی' detail: '' systempdir: title: 'قادر به نوشتن دایرکتوری سیستم موقت نیست.' detail: '' boot: composer: invalid: '' config: php_cli: not_found: 'این مسیر شما یک باینری PHP معتبر نیست.' incompatible: 'این باینری PHP نسخه‌ی {cli} است اما وب سرورتان نسخه‌ی {web} است.' cloud: platform: '' cache: '' task: setup_packages: title: '' install_packages: title: '' update_packages: title: 'بروزرسانی بسته‌ها' dump_autoload: title: '' clear_cache: title: '' rebuild_cache: title: '' self_update: title: '' taskoperation: self-update: detail: '' success: '' install-uploads: summary: '' console: '' remove-uploads: summary: '' composer-install: retry: '' nothing: '' result: '' dump-autoload: result: '' cloud: queued: '' processing: '' error: '' finished: '' upload: error: file: '' json: '' schema: '' partial: '' error: writable: root: '' directory: '' config-file: '' detail: '' sv: integrity: allow_url_fopen: title: 'PHP-inställningen "allow_url_fopen" är inte aktiverad på servern.' process: title: 'PHP "proc_*"-funktionerna är inte tillgängliga på servern.' detail: 'Funktionerna "proc_open", "proc_close", "proc_get_status" och "proc_terminate" är nödvändiga för att köra kommandoradsuppgifter i bakgrunden. Kontrollera med din värdleverantör varför den här metoden inte är tillgänglig; Contao Manager kommer inte att fungera korrekt utan den.' intl: title: 'PHP Intl-tillägget är inte tillgängligt.' detail: 'Contao 4 kräver PHP Intl-tillägget för internationaliseringsändamål.' openssl: title: 'PHP OpenSSL-tillägget är inte tillgängligt.' detail: 'Contao Manager kräver OpenSSL-tillägget för att ladda ner filer över en krypterad anslutning (https).' dom: title: 'PHP DOM-tillägget är inte tillgängligt.' detail: 'Contao 4 kräver PHP DOM-tillägget för att tolka XML-dokument.' xmlreader: title: 'PHP XMLReader-tillägget är inte tillgängligt.' detail: 'Contao 4 kräver PHP XMLReader-tillägget för att tolka XML-dokument.' graphics_lib: title: 'Inget PHP-bildbehandlingsbibliotek är tillgängligt.' detail: 'Contao 4 kräver antingen tillägget GD, Imagick eller Gmagick för att bearbeta bilder.' symlink: title: 'PHP symlink-metoden är inte tillgänglig eller fungerar inte korrekt.' session: title: 'PHP-sessionen kunde inte startas.' memory_limit: title: 'Otillräcklig gräns för PHP-minne.' detail: 'Din PHP-konfiguration tillåter endast {limit}-minne (på kommandoraden). Detta räcker inte för att köra Composer och det var inte möjligt att automatiskt öka denna gräns. Kontakta din värdleverantör för support.' systempdir: title: 'Det går inte att skriva till den tillfälliga systemkatalogen.' detail: 'Detta är troligen ett problem med din värdkonfiguration. Se till att antingen open_basedir tillåter åtkomst till den temporära katalogen eller att sys_temp_dir är korrekt konfigurerad.' zip: title: 'Både zip-tillägget och kommandona unzip/7z saknas.' boot: composer: invalid: 'composer.json schemavalidering: {exception}' config: php_cli: not_found: 'Den här sökvägen innehåller inte en giltig PHP-binär.' incompatible: 'Den här binära filen är en PHP-version {cli} men din webbserver är version {web}.' error: 'Fel vid validering av PHP-binären.' cloud: platform: 'Plattform får inte konfigureras i composer.json.' cache: 'Cacheegenskaper får inte konfigureras i composer.json.' task: setup_packages: title: 'Installerar Contao-applikationen' install_packages: title: 'Installera Composer Dependens' update_packages: title: 'Uppdaterar paket' dump_autoload: title: 'Dumping Composer Class Autoloader' clear_cache: title: 'Rensa Composer Cache' rebuild_cache: title: 'Bygger om Contao Cache' self_update: title: 'Självuppdatering för Contao Manager' backup_create: title: 'Skapar säkerhetskopiering av databas' backup_restore: title: 'Återställer säkerhetskopiering av databas' taskoperation: self-update: detail: 'Uppdaterar från {old} till {new}' success: 'Uppdaterad till {new}' install-uploads: summary: 'Installerar uppladdningar' console: 'Installerad artefakt för {package} (version {version}) [till package/{name}]' remove-uploads: summary: 'Tar bort uppladdningar' composer-install: retry: 'försöker igen {current}/{max}' nothing: 'Inget att installera eller uppdatera' result: '{installs} installerat, {updates} uppdaterat, {removals} borttaget' dump-autoload: result: 'Genererade optimerade autoload-filer som innehåller {count} klasser' cloud: queued: 'Kö, med start om ca. {seconds} sekunder (för närvarande {jobs} jobb på {workers} arbetare)' processing: 'Aktiv i {seconds} sekunder.' error: 'Det gick inte att lösa beroenden' finished: 'Klart på {seconds} sekunder. Minnesanvändning: {memory} (peak: {peak}), tid: {time}.' upload: error: file: 'Filen är ogiltig eller innehåller inte en composer.json.' json: 'Composer.json innehåller inte giltig JSON-data.' schema: 'Composer.json-schemavalideringen misslyckades.' partial: 'Filuppladdningen slutfördes inte.' error: writable: root: 'Contao Manager kunde inte skriva till rotkatalogen på "{path}".' directory: 'Contao Manager kunde inte skapa katalogen "{path}".' config-file: 'Contao Manager kunde inte skriva en konfigurationsfil till "{file}".' detail: 'Det verkar som om din server inte är korrekt konfigurerad. Om du är på väg att installera Contao, vänligen konfigurera DocumentRoot för din webbserver. Se annars till att filåtkomstbehörigheterna är korrekta. Om du är osäker på hur du åtgärdar detta, kontakta din värdleverantör för support.' en: integrity: allow_url_fopen: title: 'The PHP setting "allow_url_fopen" is not enabled on the server.' process: title: 'The PHP "proc_*" functions are not available on the server.' detail: 'The "proc_open", "proc_close", "proc_get_status" and "proc_terminate" functions are necessary to run command line tasks in the background. Check with your hosting provider why this method is not available; the Contao Manager will not run correctly without it.' intl: title: 'The PHP Intl extension is not available.' detail: 'Contao 4 requires the PHP Intl extension for internationalization purposes.' openssl: title: 'The PHP OpenSSL extension is not available.' detail: 'The Contao Manager requires the OpenSSL extension to download files over an encrypted connection (https).' dom: title: 'The PHP DOM extension is not available.' detail: 'Contao 4 requires the PHP DOM extension to parse XML documents.' xmlreader: title: 'The PHP XMLReader extension is not available.' detail: 'Contao 4 requires the PHP XMLReader extension to parse XML documents.' graphics_lib: title: 'No PHP image processing library is available.' detail: 'Contao 4 requires either the GD, Imagick or Gmagick extension to process images.' symlink: title: 'The PHP symlink method is unavailable or does not work correctly.' session: title: 'The PHP session could not be started.' memory_limit: title: 'Insufficient PHP memory limit.' detail: 'Your PHP configuration only allows for {limit} memory (on the command line). This is not enough to run Composer and it was not possible to automatically increase this limit. Please contact your hosting provider for support.' systempdir: title: 'Unable to write to the temporary system directory.' detail: 'This is most likely a problem with your hosting configuration. Make sure that either open_basedir does allow access to the temporary directory or that the sys_temp_dir is correctly configured.' zip: title: 'The zip extension and unzip/7z commands are both missing.' boot: composer: invalid: 'composer.json schema validation: {exception}' config: php_cli: not_found: 'This path does not contain a valid PHP binary.' incompatible: 'This binary is a PHP version {cli} but your web server is version {web}.' error: 'Error validating the PHP binary.' cloud: platform: 'Platform must not be configured in composer.json.' cache: 'Cache properties must not be configured in composer.json.' task: setup_packages: title: 'Installing Contao Application' install_packages: title: 'Installing Composer Dependencies' update_packages: title: 'Updating Packages' dump_autoload: title: 'Dumping Composer Class Autoloader' clear_cache: title: 'Clearing Composer Cache' rebuild_cache: title: 'Rebuilding Contao Cache' self_update: title: 'Contao Manager Self-Update' backup_create: title: 'Creating database backup' backup_restore: title: 'Restoring database backup' taskoperation: self-update: detail: 'Updating from {old} to {new}' success: 'Updated to {new}' install-uploads: summary: 'Installing uploads' console: 'Installed artifact for {package} (version {version}) [to packages/{name}]' remove-uploads: summary: 'Removing uploads' composer-install: retry: 'retrying {current}/{max}' nothing: 'Nothing to install or update' result: '{installs} installed, {updates} updated, {removals} removed' dump-autoload: result: 'Generated optimized autoload files containing {count} classes' cloud: queued: 'Queued, starting in approx. {seconds} seconds (currently {jobs} jobs on {workers} workers)' processing: 'Active for {seconds} seconds.' error: 'Failed resolving dependencies' finished: 'Completed in {seconds} seconds. Memory usage: {memory} (peak: {peak}), time: {time}.' upload: error: file: 'The file is invalid or does not contain a composer.json.' json: 'The composer.json does not contain valid JSON data.' schema: 'The composer.json schema validation failed.' partial: 'The file upload was not completed.' error: writable: root: 'The Contao Manager could not write to the root directory at "{path}".' directory: 'The Contao Manager could not create the directory "{path}".' config-file: 'The Contao Manager could not write a config file to "{file}".' detail: 'It looks like your server is not configured correctly. If you are about to install Contao, please setup the DocumentRoot of your web server. Otherwise make sure the file access permissions are correct. If you are unsure how to fix this, contact your hosting provider for support.' ja: integrity: allow_url_fopen: title: 'サーバーのPHPの設定で"allow_url_fopen"が有効ではありません。' process: title: 'PHPの"proc_"関数が有効ではありません。' detail: 'バックグラウンドでコマンド行のタスクを実行するために"proc_open"、"proc_close"、"proc_get_status"、"proc_terminate"といった関数が必要です。これらのメソッドが何故利用できないかをホスティングサービスの提供者に確認してください、これらなしではContao Managerは正しく動作しません。' intl: title: 'PHPのIntl拡張を利用できません。' detail: 'Contao 4は国際化の目的のためにPHPのIntl拡張を必要とします。' openssl: title: 'PHPのOpenSSL拡張を利用できません。' detail: 'Contao Managerは暗号化した接続(https)でファイルをダウンロードするためにOpenSSL拡張が必要です。' dom: title: 'PHPのDOM拡張を利用できません。' detail: 'Contao 4はXMLドキュメントの解析のためにPHPのDOM拡張を必要とします。' xmlreader: title: 'PHPのXMLReader拡張を利用できません。' detail: 'Contao 4はXMLドキュメントの解析のためにPHPのXMLReader拡張を必要とします。' graphics_lib: title: 'PHPの画像処理のライブラリが何も利用できません。' detail: 'Contao 4は画像を処理するためにGD、IMagick、Gmagickの拡張のいずれかを必要とします。' symlink: title: 'PHPのsymlinkメソッドを利用できないか、正しく動作しません。' session: title: 'PHPのセッションを開始できませんでした。' memory_limit: title: 'PHPのメモリの制限が不足しています。' detail: 'PHPの設定は(コマンド行では){limit}のメモリだけを許可しています。こではComposerを動作させるのに十分ではなく、制限を自動的に増やすこともできませんでした。ホスティングの提供者に連絡してサポートを求めてください。' systempdir: title: 'システムの一時ディレクトリに書き込みできませんでした。' detail: 'ホスティングの設定に問題の可能性がもっとも高いです。open_basedirが一時ディクトリへのアクセスを許可しているか、sys_temp_dirが正しく設定されているか確認してください。' zip: title: 'zip拡張とunzip/7zコマンドの両方がありません。' boot: composer: invalid: 'composer.jsonスキームの検証: {exception}' config: php_cli: not_found: 'このパスに有効なPHPの実行ファイルがありません。' incompatible: 'この実行ファイルはPHPのバージョンは{cli}ですが、ウェブサーバーでのバージョンは{web}です。' error: 'PHPの実行ファイルの有効性確認にエラーがあります。' cloud: platform: 'プラットフォームはcomposer.jsonに構成してはなりません。' cache: 'キャッシュの属性をcomposer.jsonに構成してはなりません。' task: setup_packages: title: 'Contaoアプリケーションをインストール中' install_packages: title: 'Composerの依存関係をインストール中' update_packages: title: 'パッケージを更新' dump_autoload: title: 'Composerのクラスのオートローダーを書き出し中' clear_cache: title: 'Composerのキャッシュを消去中' rebuild_cache: title: 'Contaoのキャッシュを再作成' self_update: title: 'Contao Managerの自己更新' backup_create: title: 'データベースのバックアップを作成中' backup_restore: title: 'データベースのバックアップを復元中' taskoperation: self-update: detail: '{old}から{new}に更新中' success: '{new}に更新完了' install-uploads: summary: 'アップロードしたファイルをインストール中' console: '{package} (バージョン {version})のインストール過程[packages/{name}に存在]' remove-uploads: summary: 'アップロードしたファイルを削除中' composer-install: retry: '再試行中 {current}/{max}' nothing: 'インストールやアップデートはなし' result: '{installs}個をインストール、{updates}個をアップデート、{removals}個を削除' dump-autoload: result: '{count}個のクラスを含む最適化した自動読み込みのファイルを生成' cloud: queued: 'キューに追加し約{seconds}秒で開始予定 (現在{workers}個のワーカーに{jobs}個のジョブ)' processing: '{seconds}秒動作中' error: '依存関係の解決に失敗' finished: '{seconds}秒で完了。メモリの使用: {memory} (最大: {peak})、時間: {time}。' upload: error: file: 'ファイルが無効、またはcomposer.jsonを含んでいません。' json: 'composer.jsonが正しいJSONのデータを含んでいません。' schema: 'composer.jsonスキーマの検証に失敗しました。' partial: 'アップロードしたファイルは完全ではありませんでした。' error: writable: root: 'Contao Managerは"{path}"のルートディレクトリに書き込みできませんでした。' directory: 'Contao Managerは"{path}"のディレクトリを作成できませんでした。' config-file: 'Contao Managerは構成ファイルを"{file}"に書き込めませんでした。' detail: 'サーバーを正しく構成できていない様です。Contaoをインストールしようとしている場合は、WebサーバーのDocumentRootを設定してください。そうでない場合はファイルのアクセス権限が正しいことを確認してください。これを修正する方法がわからない場合は、ホスティング提供者に連絡してサポートを求めてください。' ru: integrity: allow_url_fopen: title: 'Настройка PHP "allow_url_fopen" отключена на сервере.' process: title: 'Функции PHP "proc_*" недоступны на сервере.' detail: 'Функции "proc_open", "proc_close", "proc_get_status" и "proc_terminate" необходимы для выполнения задач командной строки в фоновом режиме. Узнайте у вашего хостинг-провайдера, почему этот метод недоступен, Contao Manager не будет корректно работать без него.' intl: title: 'Расширение PHP Intl недоступно.' detail: 'Contao 4 необходимо расширение PHP Intl в целях интернационализации.' openssl: title: 'Расширение PHP OpenSSL недоступно.' detail: 'Contao Manager необходимо расширение OpenSSL для передачи файлов по зашифрованному соединению (https).' dom: title: 'Расширение PHP DOM недоступно.' detail: 'Contao 4 необходимо расширение PHP DOM для анализа XML-документов.' xmlreader: title: 'Расширение PHP XMLReader недоступно.' detail: 'Contao 4 необходимо расширение PHP XMLReader для анализа XML-документов.' graphics_lib: title: 'Библиотека обработки изображений PHP не доступна.' detail: 'Для обработки изображений Contao 4 требует расширения GD, Imagick или Gmagick.' symlink: title: 'Метод PHP symlink недоступен или работает неправильно.' session: title: 'Не удалось запустить сеанс PHP.' memory_limit: title: 'Недостаточный предел памяти PHP.' detail: 'Конфигурация PHP позволяет использовать только {limit} памяти (в командной строке). Этого недостаточно для запуска Composer и автоматическое увеличение этого предела невозможно. Для получения поддержки обратитесь к вашему хостинг-провайдеру.' systempdir: title: 'Не удается записать во временный системный каталог.' detail: 'Вероятно, это проблема с настройкой вашего хостинга. Убедитесь, что open_basedir разрешает доступ к временному каталогу или sys_temp_dir настроен правильно.' zip: title: 'Расширение zip и команды unzip/7z отсутствуют.' boot: composer: invalid: 'composer.json проверка схемы: {exception}' config: php_cli: not_found: 'Путь не содержит верный бинарный файл PHP.' incompatible: 'Двоичный файл PHP версии {cli}, а веб-сервер версии {web}.' error: 'Ошибка проверки двоичного файла PHP.' cloud: platform: 'Платформа не должна быть настроена в composer.json.' cache: 'Свойства кеша не должны быть настроены в composer.json.' task: setup_packages: title: 'Установка приложения Contao' install_packages: title: 'Установка зависимостей Composer' update_packages: title: 'Обновление пакетов' dump_autoload: title: 'Дампинг автозагрузчика класса Composer' clear_cache: title: 'Очистка кеша Composer' rebuild_cache: title: 'Перестроение кеша Contao' self_update: title: 'Автоматическое обновление Contao Manager' backup_create: title: 'Создание резервной копии базы данных' backup_restore: title: 'Восстановление резервной копии базы данных' taskoperation: self-update: detail: 'Обновление с {old} до {new}' success: 'Обновлено до {new}' install-uploads: summary: 'Установка загрузок' console: 'Установлен артефакт для {package} (версии {version}) [к пакетам/{name}]' remove-uploads: summary: 'Удаление загрузок' composer-install: retry: 'повторная попытка {current}/{max}' nothing: 'Нечего устанавливать или обновлять' result: '{installs} установлено, {updates} обновлено, {removals} удалено' dump-autoload: result: 'Созданы оптимизированные файлы автозагрузки, содержащие классы {count}' cloud: queued: 'В очереди, начиная приблизительно с {seconds} сек. (сейчас {jobs} задач в {workers} воркерах (workers))' processing: 'Активен в течение {seconds} сек.' error: 'Ошибка разрешения зависимостей' finished: 'Завершено за {seconds} сек. Использование памяти: {memory} (пик: {peak}), время: {time}.' upload: error: file: 'Ошибка файла или отсутствует composer.json.' json: 'Файл composer.json не содержит допустимых данных JSON.' schema: 'Ошибка проверки схемы composer.json.' partial: 'Загрузка файла не была завершена.' error: writable: root: 'Contao Manager не смог записать в корневой каталог "{path}".' directory: 'Contao Manager не смог создать каталог "{path}".' config-file: 'Contao Manager не смог записать файл конфигурации "{file}".' detail: 'Вероятно, сервер настроен неправильно. Если вы собираетесь установить Contao, установите корневой каталог документов веб-сервера. В противном случае убедитесь, что права доступа к файлам указаны правильно. Если вы не знаете, как это исправить, обратитесь за помощью к своему хостинг-провайдеру.' sr: integrity: allow_url_fopen: title: 'Опција PHP "allow_url_fopen" није омогућена на серверу.' process: title: 'Функције PHP "proc_*" нису доступне на серверу.' detail: 'Функције "proc_open", "proc_close", "proc_get_status" and "proc_terminate"  су неопходне за извршавање задатака командне линије у позадини. Проверите са својим провајдером хостинга зашто нису доступне; Contao Manager без њих неће радити исправно.' intl: title: 'Екстензија PHP Intl није доступна.' detail: 'Contao 4 захтева Intl екстензију ради потреба интернационализације.' openssl: title: 'Екстензија PHP OpenSSL није доступна.' detail: 'Contao Менаџер захтева OpenSSL екстензију ради преузимања фајлова преко заштићене конекције (https). ' dom: title: 'Екстензија PHP DOM није доступна.' detail: 'Contao 4 треба екстензију PHP DOM да би могао да обрађује XML документе.' xmlreader: title: 'Екстензија PHP XMLReader није доступна.' detail: 'Contao 4 треба екстензију PHP XMLReader да би могао да обрађује XML документе.' graphics_lib: title: 'Није доступна нити једна PHP библиотека за обраду слика.' detail: 'Contao 4 треба GD, Imagick или Gmagick да би могао да обрађује слике.' symlink: title: 'Метода PHP symlink није доступна или не ради исправно.' session: title: 'PHP сесија није покренута.' memory_limit: title: 'Недовољан лимит меморије за PHP.' detail: 'Ваша конфигурација PHP дозвољава употребу {limit} меморије (у командној линији). То није довољно да би Композер радио, а није успело ни аутоматско повећање лимита. Контактирајте вашег провајдера ради подршке.' systempdir: title: 'Неуспешан упис у привремени системски директоријум.' detail: 'Ово је вероватно узроковано конфигурацијом хостинга. Проверите да ли open_basedir дозвољава приступ привременом директоријуму, и да ли је sys_temp_dir исправно конфигурисан.' zip: title: '' boot: composer: invalid: 'composer.json schema validation: {exception}' config: php_cli: not_found: 'Ова путања не садржи валидан PHP binary.' incompatible: 'Овај binary је намењен верзији PHP {cli} док је на вашем веб серверу верзија {web}.' error: 'Грешка приликом валидације PHP binary.' cloud: platform: 'Платформа не сме бити конфигурисана у composer.json.' cache: 'Подешавања Cache-а не смеју бити конфигурисана у composer.json.' task: setup_packages: title: 'Инсталирање Contao апликације' install_packages: title: 'Инсталирање Композер зависности' update_packages: title: 'Ажурирање Пакета' dump_autoload: title: 'Пражњење Composer Class Autoloader-а' clear_cache: title: 'Пражњење Композер Cache-а' rebuild_cache: title: 'Поновно креирање кеша' self_update: title: 'Contao Manager аутоматско ажурирање' backup_create: title: 'Креирање резервне копије базе података' backup_restore: title: 'Обнављање копије базе података' taskoperation: self-update: detail: 'Надоградња са {old} на {new}' success: 'Ажурирано на {new}' install-uploads: summary: 'Инсталирање преузетих фајлова' console: 'Инсталисани артифакти за {package} (верзија {version}) [to packages/{name}]' remove-uploads: summary: 'Уклањање преузетих фајлова' composer-install: retry: 'покушај {current}/{max}' nothing: 'Нема ништа за инсталацију или преузимање' result: '{installs} инсталирано, {updates} ажурирано, {removals} уклоњено' dump-autoload: result: 'Generated optimized autoload files containing {count} classes' cloud: queued: 'Убачено у редослед, почиње за око {seconds} секунди (тренутно {jobs} задатака у {workers} послова)' processing: 'Активно {seconds} секунди.' error: 'Неуспешно разрешавање зависности' finished: 'Завршено за {seconds} секунди. Употреба меморије: {memory} (peak: {peak}), time: {time}.' upload: error: file: 'Фајл је неисправан или не садржи composer.json.' json: 'Composer.json не садржи исправне JSON податке.' schema: 'Валидација composer.json schema није успела.' partial: 'Преузимање фајла није завршено.' error: writable: root: 'Contao Manager не може да пише у root directory на путањи "{path}".' directory: 'Contao Manager не може да креира директоријум "{path}".' config-file: 'Contao Manager не може да пише у конфигурациони фајл "{file}".' detail: 'Чини се да Ваш сервер није исправно конфигурисан. Ако планирате да инсталирате Contao, подесите DocumentRoot на Вашем мрежном серверу. У супротном будите сигурни да су дозволе за приступ фајловима исправне. Ако нисте сигурни како то да урадите, контактирајте Вашег хостинг провајдера.' fr: integrity: allow_url_fopen: title: 'Le paramètre PHP "allow_url_fopen" n''est pas activé sur le serveur.' process: title: '' detail: '' intl: title: 'L''extension PHP Intl n''est pas disponible.' detail: 'Contao 4 nécessite l''extension PHP Intl à des fins d''internationalisation.' openssl: title: 'L''extension PHP OpenSSL n''est pas disponible.' detail: 'Contao Manager requiert l''extension OpenSSL pour télécharger des fichiers via une connexion cryptée (https).' dom: title: 'L''extension PHP DOM n''est pas disponible.' detail: 'Contao 4 nécessite l''extension PHP DOM pour analyser les documents XML.' xmlreader: title: 'L''extension PHP XMLReader n''est pas disponible.' detail: 'Contao 4 nécessite l''extension PHP XMLReader pour analyser les documents XML.' graphics_lib: title: 'No PHP image processing library is available.' detail: 'Contao 4 requires either the GD, Imagick or Gmagick extension to process images.' symlink: title: 'La méthode PHP symlink n''est pas disponible ou ne fonctionne pas correctement.' session: title: 'La session PHP n''a pas pu être démarrée.' memory_limit: title: 'Limite de mémoire PHP insuffisante.' detail: 'Votre configuration PHP permet uniquement {limit} de mémoire (en ligne de commande). Ce n''est pas suffisant pour exécuter Composer et il n''a pas été possible d''augmenter automatiquement cette limite. Veuillez contacter votre hébergeur web pour obtenir de l''aide.' systempdir: title: 'Impossible d''écrire sur le répertoire temporaire du système.' detail: 'C''est probablement un problème avec votre configuration d''hébergement. Assurez-vous que open_basedir permet d''accéder au répertoire temporaire ou que sys_temp_dir est correctement configuré.' zip: title: '' boot: composer: invalid: 'composer.json schema validation: {exception}' config: php_cli: not_found: 'Ce chemin ne contient pas de binaire PHP valide.' incompatible: 'Ce binaire est une version PHP {cli} mais votre serveur web est en version {web}.' error: '' cloud: platform: 'Platform ne doit pas être configurée dans composer.json.' cache: 'Les propriétés du cache ne doivent pas être configurées dans composer.json.' task: setup_packages: title: 'Installation de l''application Contao' install_packages: title: 'Installation des dépendances de Composer' update_packages: title: 'Mise à jour des packages' dump_autoload: title: 'Vidage de l''autoloader de Composer' clear_cache: title: 'Effacer le cache de Composer' rebuild_cache: title: 'Reconstruction du cache de Contao' self_update: title: '' backup_create: title: '' backup_restore: title: '' taskoperation: self-update: detail: 'Mise à jour de {old} vers {new}' success: '' install-uploads: summary: 'Installation des uploads' console: 'Artifact installé pour {package} (version {version}) [to packages/{name}]' remove-uploads: summary: 'Suppression des uploads' composer-install: retry: 'réessayer {current}/{max}' nothing: 'Rien à installer ou à mettre à jour' result: '{installs} installés, {updates} mis à jour, {removals} supprimés' dump-autoload: result: 'Fichiers d''autoload optimisés générés contenant {count} classes' cloud: queued: 'En attente, débute dans environ {seconds} secondes (actuellement {jobs} jobs sur {workers} workers)' processing: 'En cours depuis {seconds} secondes.' error: 'La résolution des dépendances a echoué.' finished: 'Terminé en {seconds} secondes. Usage mémoire: {memory} (Pic: {peak}), Temps: {time}.' upload: error: file: 'Le fichier n''est pas valide ou ne contient pas de fichier composer.json.' json: 'Le fichier composer.json ne contient pas de données JSON valides.' schema: 'Le schéma du fichier composer.json n''est pas valide.' partial: 'L''upload du fichier a échoué' error: writable: root: 'Le Contao Manager n''a pas pu écrire dans le répertoire racine "{path}".' directory: 'Le Contao Manager n''a pas pu créer le répertoire "{path}".' config-file: 'The Contao Manager n''a pas pu créer un fichier de configuration dans "{file}".' detail: 'Il semble que votre serveur n''est pas configuré correctement. Si vous êtes sur le point d''installer Contao, veuillez configurer la racine du site sur votre serveur Web. Sinon, assurez-vous que les autorisations d''accès aux fichiers sont correctes. Si vous ne savez pas comment résoudre ce problème, contactez votre fournisseur d''hébergement pour obtenir de l''aide' lv: integrity: allow_url_fopen: title: 'PHP iestatījums "allow_url_fopen" serverī nav iespējots.' process: title: 'Serverī nav pieejamas PHP "proc_*" funkcijas.' detail: 'Funkcijas "proc_open", "proc_close", "proc_get_status" un "proc_terminate" ir nepieciešamas, lai fona režīmā palaistu komandrindas uzdevumus. Noskaidrojiet pie sava hostinga pakalpojumu sniedzēja, kāpēc šī metode nav pieejama; bez tās Contao Manager nedarbosies pareizi.' intl: title: 'PHP Intl paplašinājums nav pieejams.' detail: 'Contao 4 ir nepieciešams PHP Intl paplašinājums internacionalizācijas vajadzībām.' openssl: title: 'PHP OpenSSL paplašinājums nav pieejams.' detail: 'Contao Manager ir nepieciešams OpenSSL paplašinājums, lai failus lejupielādētu šifrētā savienojumā (https).' dom: title: 'PHP DOM paplašinājums nav pieejams.' detail: 'Contao 4 ir nepieciešams PHP DOM paplašinājums, lai analizētu XML dokumentus.' xmlreader: title: 'PHP XMLReader paplašinājums nav pieejams.' detail: 'Contao 4 ir nepieciešams PHP XMLReader paplašinājums, lai analizētu XML dokumentus.' graphics_lib: title: 'Nav pieejama neviena PHP attēlu apstrādes bibliotēka.' detail: 'Lai apstrādātu attēlus, Contao 4 nepieciešams paplašinājums GD, Imagick vai Gmagick.' symlink: title: 'PHP simbolu metode nav pieejama vai nedarbojas pareizi.' session: title: 'Nevarēja uzsākt PHP sesiju.' memory_limit: title: 'Nepietiekams PHP atmiņas ierobežojums.' detail: 'Jūsu PHP konfigurācija atļauj tikai {limit} atmiņu (komandrindā). Ar to nepietiek, lai palaistu Composer, un nebija iespējams automātiski palielināt šo limitu. Lūdzu, sazinieties ar savu hostinga pakalpojumu sniedzēju, lai saņemtu atbalstu.' systempdir: title: 'Nevar rakstīt sistēmas pagaidu direktorijā.' detail: 'Visticamāk, tā ir problēma ar jūsu hostinga konfigurāciju. Pārliecinieties, vai open_basedir ļauj piekļūt pagaidu direktorijai, vai arī sys_temp_dir ir pareizi konfigurēta.' zip: title: '' boot: composer: invalid: 'composer.json shēmas validācija: {exception}' config: php_cli: not_found: 'Šis ceļš nesatur derīgu PHP bināru.' incompatible: 'Šis binārs ir PHP versija {cli}, bet jūsu tīmekļa serveris ir versija {web}.' error: '' cloud: platform: 'Platforma nedrīkst būt konfigurēta composer.json.' cache: 'Kešatmiņas rekvizīti nedrīkst būt konfigurēti composer.json.' task: setup_packages: title: 'Instalē Contao lietotni' install_packages: title: 'Composer atkarību instalēšana' update_packages: title: 'Atjaunina pakotnes' dump_autoload: title: '' clear_cache: title: 'Iztīra Composer kešatmiņu' rebuild_cache: title: 'Pārbūvē Contao kešatmiņu' self_update: title: 'Contao Manager pašatjaunināšana' backup_create: title: '' backup_restore: title: '' taskoperation: self-update: detail: 'Atjaunina no {old} uz {new}' success: 'Atjaunināts uz {new}' install-uploads: summary: 'Augšupielādes instalēšana' console: 'Instalēts artefakts {package} (versija {version}) [uz packages/{name}]' remove-uploads: summary: 'Augšupielādes noņemšana' composer-install: retry: 'atkārtots mēģinājums {current}/{max}' nothing: 'Nekas nav jāinstalē vai jāatjaunina' result: '{installs} instalēts, {updates} atjaunināts, {removals} noņemts' dump-autoload: result: 'Izveidoti optimizēti autoload faili, kas satur {count} klases' cloud: queued: 'Ierindots, sāks aptuveni pēc {seconds} sekundēm (pašlaik {jobs} darbi uz {workers} darbiniekiem).' processing: 'Aktīvs {seconds} sekundes.' error: 'Neizdevās atrisināt atkarības' finished: 'Pabeigts {seconds} sekundēs. Atmiņas izmantošana: {memory} (maksimums: {peak}), laiks: {time}.' upload: error: file: 'Datne ir nederīga vai nesatur composer.json.' json: 'Composer.json nesatur derīgus JSON datus.' schema: 'Composer.json shēmas validācija neizdevās.' partial: 'Failu augšupielāde netika pabeigta.' error: writable: root: 'Contao Manager nevarēja rakstīt uz saknes direktoriju adresē "{path}".' directory: 'Contao Manager nevarēja izveidot direktoriju "{path}".' config-file: 'Contao Manager nevarēja uzrakstīt konfigurācijas failu uz "{file}".' detail: 'Izskatās, ka jūsu serveris nav pareizi konfigurēts. Ja gatavojaties instalēt Contao, lūdzu, iestatiet sava tīmekļa servera DocumentRoot. Pretējā gadījumā pārliecinieties, ka failu piekļuves atļaujas ir pareizas. Ja neesat pārliecināts, kā to novērst, sazinieties ar savu hostinga pakalpojumu sniedzēju, lai saņemtu atbalstu.' tr: integrity: allow_url_fopen: title: 'Sunucuda "allow_url_fopen" PHP ayarı etkinleştirilmemiş.' process: title: 'Sunucuda "proc_*" işlevleri kullanılamıyor.' detail: '"proc_open", "proc_close", "proc_get_status" ve "proc_terminate" işlevleri arka planda komut satırı işlemlerini yapmak için gereklidir. Barındırma hizmeti sağlayıcınıza bu yöntemlerin neden kullanılamadığını sorun. Bunlar olmadan Contao Manager düzgün şekilde çalışmaz.' intl: title: 'PHP Intl eklentisi kullanılamıyor.' detail: 'Contao 4 uluslararası özelliklerinin çalışabilmesi için PHP Intl eklentisi gereklidir.' openssl: title: 'PHP OpenSSL eklentisi kullanılamıyor.' detail: 'Contao Manager, şifrelenmiş bir bağlantı (https) üzerinden dosyaları indirebilmek için OpenSSL eklentisine gerek duyar.' dom: title: 'PHP DOM eklentisi kullanılamıyor.' detail: 'Contao 4, XML dosyalarını okuyabilmek için PHP XML Reader eklentisine gerek duyar.' xmlreader: title: 'PHP XML Reader eklentisi kullanılamıyor.' detail: 'Contao 4, XML dosyalarını okuyabilmek için PHP XMLReader eklentisine gerek duyar.' graphics_lib: title: 'Kullanılabilecek bir PHP görsel işleme kitaplığı bulunamadı.' detail: 'Contao 4, görselleri işlemek için GD, Imagick ya da Gmagick eklentisine gerek duyar.' symlink: title: 'PHP symlink yöntemi kullanılamıyor ya da düzgün şekilde çalışmıyor.' session: title: 'PHP oturumu başlatılamadı.' memory_limit: title: 'PHP bellek sınırı yetersiz.' detail: 'PHP yapılandırmanız yalnızca {limit} bellek kullanımına (komut satırında) izin veriyor. Bu değer, Composer çalıştırmak için yetersiz ve bu sınır otomatik olarak artırılamadı. Destek almak için barındırma hizmeti sağlayıcınızla görüşün.' systempdir: title: 'Geçici sistem klasörüne yazılamadı.' detail: 'Bu sorun büyük olasılıkla barındırma hizmeti yapılandırmanızla ilgilidir. open_basedir tarafından geçici klasöre erişme izin verildiğinden ya da sys_temp_dir parametresinin doğru yapılandırıldığından emin olun.' zip: title: 'zip eklentisi ile unzip/7z komutlarının ikisi de eksik.' boot: composer: invalid: 'composer.json şema doğrulaması: {exception}' config: php_cli: not_found: 'Bu yolda geçerli bir PHP binary dosyası bulunamadı.' incompatible: 'Bu binary dosyası bir PHP {cli} sürümü. Ancak site sunucunuzun sürümü {web}.' error: 'PHP binary dosyası doğrulanırken sorun çıktı.' cloud: platform: 'Platform, composer.json içinden yapılandırılmamalıdır.' cache: 'Ön bellek özellikleri composer.json içinde yapılandırılmamalıdır.' task: setup_packages: title: 'Contao uygulaması kuruluyor' install_packages: title: 'Composer bağımlılıkları kuruluyor' update_packages: title: 'Paketler güncelleniyor' dump_autoload: title: 'Composer sınıf otomatik yükleyicisi indiriliyor' clear_cache: title: 'Composer ön belleği temizleniyor' rebuild_cache: title: 'Contao ön belleği yeniden oluşturuluyor' self_update: title: 'Contao Manager kendi kendine güncelleme' backup_create: title: 'Veri tabanı yedeği oluşturuluyor' backup_restore: title: 'Veri tabanı yedeği geri yükleniyor' taskoperation: self-update: detail: '{old} sürümünden {new} sürümüne güncelleniyor' success: '{new} sürümüne güncellendi' install-uploads: summary: 'Yüklemeler kuruluyor' console: '{package} ({version} sürümü) için [to packages/{name}] artifaktı kuruldu' remove-uploads: summary: 'Yüklemeler kaldırılıyor' composer-install: retry: 'yeniden deneniyor {current}/{max}' nothing: 'Kurulacak ya da güncellenecek bir şey yok' result: '{installs} kuruldu, {updates} güncellendi, {removals} kaldırıldı' dump-autoload: result: '{count} sınıf içeren iyileştirilmiş otomatik yükleme dosyası üretildi' cloud: queued: 'Kuyrukta, yaklaşık {seconds} saniye içinde başlayacak (şu anda {workers} işlem üzerinde {jobs} görev yapılıyor)' processing: '{seconds} saniyedir işleniyor.' error: 'Bağımlılıklar çözümlenemedi' finished: '{seconds} saniyede tamamlandı. Bellek kullanımı: {memory} (en fazla: {peak}), süre: {time}.' upload: error: file: 'Dosya geçersiz ya da composer.json dosyasını içermiyor.' json: 'composer.json dosyasında geçerli bir JSON verisi bulunamadı.' schema: 'composer.json şeması doğrulanamadı.' partial: 'Dosya yüklemesi tamamlanamadı.' error: writable: root: 'Contao Manager "{path}" yolundaki kök klasöre yazamadı.' directory: 'Contao Manager "{path}" klasörünü oluşturamadı.' config-file: 'Contao Manager "{file}" dosyasına yapılandırmayı yazamadı.' detail: 'Sunucunuz doğru yapılandırılmamış gibi görünüyor. Contao kuracaksanız, lütfen site sunucunuzun kök belge klasörüne kurun. Yoksa dosya erişim izinlerinin doğru olduğundan emin olun. Bu sorunu nasıl düzelteceğinizden emin değilseniz, destek almak için barındırma hizmeti sağlayıcınızla görüşün.' nl: integrity: allow_url_fopen: title: 'De PHP instelling "allow_url_fopen" is niet ingeschakeld op de server.' process: title: 'De PHP "proc_*" functies zijn niet beschikbaar op de server.' detail: 'De functies "proc_open", "proc_close", "proc_get_status" en "proc_terminate" zijn nodig om opdrachtregeltaken op de achtergrond uit te voeren. Neem contact op met uw hostingprovider waarom deze methode niet beschikbaar is; De Contao Manager wordt niet correct uitgevoerd zonder deze methode.' intl: title: 'De PHP Intl extensie is niet beschikbaar.' detail: 'Contao 4 vereist de Intl extension voor internationalisering.' openssl: title: 'De PHP OpenSSL extensie is niet beschikbaar.' detail: 'Contao Manager vereist de OpenSSL extensie om bestanden over versleutelde verbindingen (https) te downloaden.' dom: title: 'De PHP DOM extensie is niet beschikbaar.' detail: 'Contao 4 vereist de PHP DOM extensie om XML-documenten te parsen.' xmlreader: title: 'De PHP XML Reader extensie is niet beschikbaar.' detail: 'Contao 4 vereist de PHP XMLReader extensie om XML-documenten te parsen.' graphics_lib: title: 'Er is geen bibliotheek voor PHP-beeldverwerking beschikbaar.' detail: 'Contao 4 vereist ofwel de GD, Imagick of Gmagick-extensie om afbeeldingen te verwerken.' symlink: title: 'PHP-symlink methode is niet beschikbaar of werkt niet correct.' session: title: 'PHP-sessie kan niet worden gestart.' memory_limit: title: 'Limiet PHP-geheugen onvoldoende.' detail: 'Uw PHP-configuratie staat alleen {limit} geheugen toe (op de opdrachtregel). Dit is niet genoeg om Composer uit te voeren, het was niet mogelijk om deze limiet automatisch te verhogen. Neem contact op met uw hostingprovider voor ondersteuning.' systempdir: title: 'Tijdelijke systeem directory niet beschrijfbaar.' detail: 'Er is waarschijnlijk een probleem met uw hostingconfiguratie. Zorg ervoor dat open_basedir toegang geeft tot de tijdelijke directory, of dat sys_temp_dir correct is geconfigureerd.' zip: title: '' boot: composer: invalid: 'composer.json schema validatie: {exception}' config: php_cli: not_found: 'Dit pad bevat geen geldige PHP binary.' incompatible: 'Dit binary is een PHP versie {cli} maar uw webserver is versie {web}.' error: 'Fout bij het valideren van het PHP-binaire bestand.' cloud: platform: 'Platform mag niet geconfigureerd zijn in composer.json.' cache: 'Cache instellingen mogen niet geconfigureerd zijn in composer.json.' task: setup_packages: title: 'Contao-applicatie installeren' install_packages: title: 'Composer Afhankelijkheden Installeren' update_packages: title: 'Pakketten bijwerken' dump_autoload: title: 'Dumping Composer Class Autoloader' clear_cache: title: 'Composer Cache Wissen' rebuild_cache: title: 'Contao Cache opnieuw opbouwen' self_update: title: 'Contao Manager Zelf-update' backup_create: title: 'Databaseback-up maken' backup_restore: title: 'Databaseback-up herstellen' taskoperation: self-update: detail: 'Bijwerken van {old} naar {new}' success: 'Update naar {new}' install-uploads: summary: 'Uploads installeren' console: 'Artefact geïnstalleerd voor {package} (version {version}) [to packages/{name}]' remove-uploads: summary: 'Uploads verwijderen' composer-install: retry: '{current} / {max} opnieuw proberen' nothing: 'Niets om te installeren of bij te werken' result: '{installs} geïnstalleerd, {updates} bijgewerkt, {removals} verwijderd' dump-autoload: result: 'Gegenereerde geoptimaliseerde autoload-bestanden met {count} classes' cloud: queued: 'In de wachtrij, beginnend over ca. {seconds} seconden (momenteel {jobs} banen voor {workers} workers)' processing: 'Actief gedurende {seconds} seconden.' error: 'Het oplossen van afhankelijkheden is mislukt' finished: 'Voltooid in {seconds} seconden. Geheugengebruik: {memory} (piek: {peak}), tijd: {time}.' upload: error: file: 'Het bestand is ongeldig of bevat geen composer.json.' json: 'De composer.json bevat geen geldige JSON-gegevens.' schema: 'De validatie van het componer.json-schema is mislukt.' partial: 'Het uploaden van het bestand is niet voltooid.' error: writable: root: 'Contao Manager kon niet schrijven naar de hoofdmap op "{path}".' directory: 'Contao Manager kon de directory "{path}" niet aanmaken.' config-file: 'Contao Manager kon geen configuratiebestand naar "{file}" schrijven.' detail: 'Het lijkt erop dat uw server niet correct is geconfigureerd. Als u op het punt staat Contao te installeren, stel dan de DocumentRoot van uw webserver in. Zorg er anders voor dat de toegangsrechten voor bestanden correct zijn. Als u niet zeker weet hoe dit op te lossen neem dan contact op met uw hostingprovider voor ondersteuning.' zh: integrity: allow_url_fopen: title: '服务器未启用PHP设置"allow_url_fopen"' process: title: '' detail: '' intl: title: 'PHP扩展Intl不可用' detail: 'Contao 4 系统需要使用PHP Intl扩展来进行国际化' openssl: title: 'PHP扩展OpenSSL不可用' detail: 'Contao Manager需要使用OpenSSL扩展来通过加密链接(https)下载文件。' dom: title: 'PHP DOM扩展不可用。' detail: 'Contao 4 需要 PHP DOM 扩展来解析XML文档。' xmlreader: title: 'The PHP XMLReader 扩展不可用。' detail: '' graphics_lib: title: '没有有效的PHP图片处理库,' detail: 'Contao 4 需要 GD, Imagick 或 Gmagick 扩展来处理图片。' symlink: title: 'PHP符号链接方法不可用或无法正常工作。' session: title: 'PHP session无法启动。' memory_limit: title: 'PHP内存限制不足' detail: '当前PHP配置仅允许 {limit} 内存 (在命令行中)。该内存设置无法满足运行Composer,该设置无法自动调整增加限制。请联系主机提供商提供相关支持。' systempdir: title: '系统临时目录无法写入' detail: '很有可能是主机的配置问题。请确保open_basedir允许访问临时目录,或者sys_temp_dir已正确配置。' zip: title: '' boot: composer: invalid: 'composer.json schema验证: {exception}' config: php_cli: not_found: '该路径没有包含有效的PHP二进制文件' incompatible: 'PHP二进制文件版本 {cli} 但是当前服务器版本为 {web}' error: '' cloud: platform: '不得在composer.json中配置平台。' cache: '不得在composer.json中配置缓存属性。' task: setup_packages: title: '安装Contao应用' install_packages: title: '正在安装Composer依赖' update_packages: title: '包更新中' dump_autoload: title: '' clear_cache: title: '正在清理Composer缓存' rebuild_cache: title: 'Contao 缓存重建中' self_update: title: '' backup_create: title: '' backup_restore: title: '' taskoperation: self-update: detail: '从 {old} 更新到 {new}' success: '' install-uploads: summary: '' console: '已安装的artifact类型 for {package} (版本 {version}) [to packages/{name}]' remove-uploads: summary: '' composer-install: retry: '' nothing: '' result: '' dump-autoload: result: '' cloud: queued: '' processing: '' error: '' finished: '' upload: error: file: '文件无效或者没有包含composer.json。' json: 'composer.json没有包含有效的JSON数据。' schema: 'composer.json schema验证失败。' partial: '上传文件未完成。' error: writable: root: '' directory: '' config-file: '' detail: '' getDefinition()->addOption(new InputOption('disable-events', null, InputOption::VALUE_NONE, 'Disables the event dispatcher.')); } /** * Gets the Kernel associated with this Console. */ public function getKernel() : ApiKernel { return $this->kernel; } public function doRun(InputInterface $input, OutputInterface $output) : int { $this->registerCommands(); if ('self-update' !== $this->getCommandName($input) && !$input->hasParameterOption(['--disable-events'], \true)) { $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher')); } return (int) parent::doRun($input, $output); } protected function getDefaultCommands() : array { $commands = parent::getDefaultCommands(); $commands[] = (new Command('composer'))->setDescription('Run Composer within Contao Manager'); return $commands; } private function registerCommands() : void { if ($this->commandsRegistered) { return; } $this->commandsRegistered = \true; $this->kernel->boot(); $container = $this->kernel->getContainer(); $this->add($container->get(ProcessRunnerCommand::class)->setName('run')); $this->add($container->get(AboutCommand::class)); $this->add($container->get(IntegrityCheckCommand::class)); $this->add($container->get(TaskAbortCommand::class)); $this->add($container->get(TaskDeleteCommand::class)); $this->add($container->get(TaskUpdateCommand::class)); $this->add($container->get(UpdateCommand::class)); if ((!\Phar::running(\false) || $this->kernel->isDebug()) && $container->has('console.command_loader')) { $this->setCommandLoader($container->get('console.command_loader')); } } } CloudJob::STATUS_QUEUED, 'queuePosition' => $queuePosition, 'stats' => ['averageProcessingTimeInMs' => $avgTime * 1000, 'numberOfJobsInQueue' => $queuePosition, 'numberOfWorkers' => $workers]]); $this->assertSame($expected, $job->getWaitingTime()); } public static function waitingTime() : iterable { (yield [12, 30, 6, 60]); (yield [10, 10, 5, 20]); (yield [3, 25, 8, 9]); } } assertSame(1, $result); $this->assertSame($line, $matches[0]); $this->assertSame($datetime, $matches['datetime'], 'DateTime does not match'); $this->assertSame($channel, $matches['channel'], 'Channel does not match'); $this->assertSame($level, $matches['level'], 'Level does not match'); $this->assertSame($message, $matches['message'], 'Message does not match'); $this->assertSame($context, $matches['context'], 'Context does not match'); $this->assertSame($extra, $matches['extra'], 'Extra does not match'); } public static function logMessages() : iterable { (yield ['[2024-08-20T00:41:04.411801+02:00] request.INFO: Matched route "tl_page.32". {"route":"tl_page.32","route_parameters":{"_controller":"Contao\\FrontendIndex::renderPage","_scope":"frontend","_locale":"de","_format":"html","_canonical_route":"tl_page.32","pageModel":{"Contao\\PageModel":[]},"_route":"tl_page.32","_route_object":{"Contao\\CoreBundle\\Routing\\Page\\PageRoute":[]}}} []', '2024-08-20T00:41:04.411801+02:00', 'request', 'INFO', 'Matched route "tl_page.32".', '{"route":"tl_page.32","route_parameters":{"_controller":"Contao\\FrontendIndex::renderPage","_scope":"frontend","_locale":"de","_format":"html","_canonical_route":"tl_page.32","pageModel":{"Contao\\PageModel":[]},"_route":"tl_page.32","_route_object":{"Contao\\CoreBundle\\Routing\\Page\\PageRoute":[]}}}', '[]']); (yield ['[2024-08-20T00:00:05.476105+02:00] app.ERROR: Github\\Exception\\RuntimeException: Bad credentials in vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php:137 Stack trace: #0 vendor/php-http/httplug/src/Promise/HttpFulfilledPromise.php(31): Github\\HttpClient\\Plugin\\GithubExceptionThrower->Github\\HttpClient\\Plugin\\{closure}(Object(Nyholm\\Psr7\\Response)) #1 vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php(28): Http\\Client\\Promise\\HttpFulfilledPromise->then(Object(Closure)) #2 vendor/php-http/client-common/src/PluginChain.php(44): Github\\HttpClient\\Plugin\\GithubExceptionThrower->handleRequest(Object(Nyholm\\Psr7\\Request), Object(Closure), Object(Http\\Client\\Common\\PluginChain)) #3 vendor/php-http/client-common/src/PluginChain.php(59): Http\\Client\\Common\\PluginChain->Http\\Client\\Common\\{closure}(Object(Nyholm\\Psr7\\Request)) #4 vendor/php-http/client-common/src/PluginClient.php(87): Http\\Client\\Common\\PluginChain->__invoke(Object(Nyholm\\Psr7\\Request)) #5 vendor/php-http/client-common/src/HttpMethodsClient.php(148): Http\\Client\\Common\\PluginClient->sendRequest(Object(Nyholm\\Psr7\\Request)) #6 vendor/php-http/client-common/src/HttpMethodsClient.php(107): Http\\Client\\Common\\HttpMethodsClient->sendRequest(Object(Nyholm\\Psr7\\Request)) #7 vendor/php-http/client-common/src/HttpMethodsClient.php(55): Http\\Client\\Common\\HttpMethodsClient->send(\'GET\', \'...\', Array, NULL) #8 vendor/knplabs/github-api/lib/Github/Api/AbstractApi.php(92): Http\\Client\\Common\\HttpMethodsClient->get(\'...\', Array) #9 vendor/knplabs/github-api/lib/Github/Api/AcceptHeaderTrait.php(19): Github\\Api\\AbstractApi->get(\'...\', Array, Array) #10 vendor/knplabs/github-api/lib/Github/Api/Repo.php(150): Github\\Api\\Repo->get(\'...\') #11 src/Cron/GithubUpdater.php(34): Github\\Api\\Repo->show(\'foo\', \'core\') #12 src/Cron/GithubUpdater.php(24): App\\Cron\\GithubUpdater->addRepositoryData(Array) #13 vendor/contao/core-bundle/src/Cron/CronJob.php(44): App\\Cron\\GithubUpdater->__invoke(\'cli\') #14 vendor/contao/core-bundle/src/Cron/Cron.php(197): Contao\\CoreBundle\\Cron\\CronJob->__invoke(\'cli\') #15 vendor/contao/core-bundle/src/Cron/Cron.php(182): Contao\\CoreBundle\\Cron\\Cron->executeCrons(Array, \'cli\', Object(Closure)) #16 vendor/contao/core-bundle/src/Cron/Cron.php(97): Contao\\CoreBundle\\Cron\\Cron->doRun(Array, \'cli\', false) #17 vendor/contao/core-bundle/src/Command/CronCommand.php(53): Contao\\CoreBundle\\Cron\\Cron->run(\'cli\', false) #18 vendor/symfony/console/Command/Command.php(326): Contao\\CoreBundle\\Command\\CronCommand->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #19 vendor/symfony/console/Application.php(1096): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #20 vendor/symfony/framework-bundle/Console/Application.php(126): Symfony\\Component\\Console\\Application->doRunCommand(Object(Contao\\CoreBundle\\Command\\CronCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #21 vendor/symfony/console/Application.php(324): Symfony\\Bundle\\FrameworkBundle\\Console\\Application->doRunCommand(Object(Contao\\CoreBundle\\Command\\CronCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #22 vendor/symfony/framework-bundle/Console/Application.php(80): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #23 vendor/symfony/console/Application.php(175): Symfony\\Bundle\\FrameworkBundle\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #24 vendor/contao/manager-bundle/bin/contao-console(40): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput)) #25 vendor/bin/contao-console(119): include(\'...\') #26 {main} [] []', '2024-08-20T00:00:05.476105+02:00', 'app', 'ERROR', 'Github\\Exception\\RuntimeException: Bad credentials in vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php:137 Stack trace: #0 vendor/php-http/httplug/src/Promise/HttpFulfilledPromise.php(31): Github\\HttpClient\\Plugin\\GithubExceptionThrower->Github\\HttpClient\\Plugin\\{closure}(Object(Nyholm\\Psr7\\Response)) #1 vendor/knplabs/github-api/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php(28): Http\\Client\\Promise\\HttpFulfilledPromise->then(Object(Closure)) #2 vendor/php-http/client-common/src/PluginChain.php(44): Github\\HttpClient\\Plugin\\GithubExceptionThrower->handleRequest(Object(Nyholm\\Psr7\\Request), Object(Closure), Object(Http\\Client\\Common\\PluginChain)) #3 vendor/php-http/client-common/src/PluginChain.php(59): Http\\Client\\Common\\PluginChain->Http\\Client\\Common\\{closure}(Object(Nyholm\\Psr7\\Request)) #4 vendor/php-http/client-common/src/PluginClient.php(87): Http\\Client\\Common\\PluginChain->__invoke(Object(Nyholm\\Psr7\\Request)) #5 vendor/php-http/client-common/src/HttpMethodsClient.php(148): Http\\Client\\Common\\PluginClient->sendRequest(Object(Nyholm\\Psr7\\Request)) #6 vendor/php-http/client-common/src/HttpMethodsClient.php(107): Http\\Client\\Common\\HttpMethodsClient->sendRequest(Object(Nyholm\\Psr7\\Request)) #7 vendor/php-http/client-common/src/HttpMethodsClient.php(55): Http\\Client\\Common\\HttpMethodsClient->send(\'GET\', \'...\', Array, NULL) #8 vendor/knplabs/github-api/lib/Github/Api/AbstractApi.php(92): Http\\Client\\Common\\HttpMethodsClient->get(\'...\', Array) #9 vendor/knplabs/github-api/lib/Github/Api/AcceptHeaderTrait.php(19): Github\\Api\\AbstractApi->get(\'...\', Array, Array) #10 vendor/knplabs/github-api/lib/Github/Api/Repo.php(150): Github\\Api\\Repo->get(\'...\') #11 src/Cron/GithubUpdater.php(34): Github\\Api\\Repo->show(\'foo\', \'core\') #12 src/Cron/GithubUpdater.php(24): App\\Cron\\GithubUpdater->addRepositoryData(Array) #13 vendor/contao/core-bundle/src/Cron/CronJob.php(44): App\\Cron\\GithubUpdater->__invoke(\'cli\') #14 vendor/contao/core-bundle/src/Cron/Cron.php(197): Contao\\CoreBundle\\Cron\\CronJob->__invoke(\'cli\') #15 vendor/contao/core-bundle/src/Cron/Cron.php(182): Contao\\CoreBundle\\Cron\\Cron->executeCrons(Array, \'cli\', Object(Closure)) #16 vendor/contao/core-bundle/src/Cron/Cron.php(97): Contao\\CoreBundle\\Cron\\Cron->doRun(Array, \'cli\', false) #17 vendor/contao/core-bundle/src/Command/CronCommand.php(53): Contao\\CoreBundle\\Cron\\Cron->run(\'cli\', false) #18 vendor/symfony/console/Command/Command.php(326): Contao\\CoreBundle\\Command\\CronCommand->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #19 vendor/symfony/console/Application.php(1096): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #20 vendor/symfony/framework-bundle/Console/Application.php(126): Symfony\\Component\\Console\\Application->doRunCommand(Object(Contao\\CoreBundle\\Command\\CronCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #21 vendor/symfony/console/Application.php(324): Symfony\\Bundle\\FrameworkBundle\\Console\\Application->doRunCommand(Object(Contao\\CoreBundle\\Command\\CronCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #22 vendor/symfony/framework-bundle/Console/Application.php(80): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #23 vendor/symfony/console/Application.php(175): Symfony\\Bundle\\FrameworkBundle\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput)) #24 vendor/contao/manager-bundle/bin/contao-console(40): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput)) #25 vendor/bin/contao-console(119): include(\'...\') #26 {main}', '[]', '[]']); (yield ['[2024-08-20T06:22:09.276738+02:00] php.WARNING: Warning: Undefined array key "MSC" {"exception":"[object] (ErrorException(code: 0): Warning: Undefined array key \\"MSC\\" at vendor/contao/newsletter-bundle/contao/modules/ModuleSubscribe.php:95)"} {"request_uri":"https://www.example.org/","request_method":"GET"}', '2024-08-20T06:22:09.276738+02:00', 'php', 'WARNING', 'Warning: Undefined array key "MSC"', '{"exception":"[object] (ErrorException(code: 0): Warning: Undefined array key \\"MSC\\" at vendor/contao/newsletter-bundle/contao/modules/ModuleSubscribe.php:95)"}', '{"request_uri":"https://www.example.org/","request_method":"GET"}']); (yield 'Insert tag in log message' => ['[2024-08-20T00:41:04.809596+02:00] contao.error.ERROR: Unknown insert tag {{foo::bar}} on page https://www.example.org/ [] {"request_uri":"https://www.example.org/","request_method":"GET","contao":{"Contao\\CoreBundle\\Monolog\\ContaoContext":"{\\"func\\":\\"Contao\\\\InsertTags::executeReplace\\",\\"action\\":\\"ERROR\\",\\"username\\":\\"N\\/A\\",\\"browser\\":\\"Mozilla\\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\\/537.36 (KHTML, like Gecko) Chrome\\/120.0.0.0 Safari\\/537.36\\",\\"uri\\":\\"https:\\/\\/www.example.org\\/\\",\\"pageId\\":32}"}}', '2024-08-20T00:41:04.809596+02:00', 'contao.error', 'ERROR', 'Unknown insert tag {{foo::bar}} on page https://www.example.org/', '[]', '{"request_uri":"https://www.example.org/","request_method":"GET","contao":{"Contao\\CoreBundle\\Monolog\\ContaoContext":"{\\"func\\":\\"Contao\\\\InsertTags::executeReplace\\",\\"action\\":\\"ERROR\\",\\"username\\":\\"N\\/A\\",\\"browser\\":\\"Mozilla\\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\\/537.36 (KHTML, like Gecko) Chrome\\/120.0.0.0 Safari\\/537.36\\",\\"uri\\":\\"https:\\/\\/www.example.org\\/\\",\\"pageId\\":32}"}}']); } } attributes->get('file'), self::ALLOWED_FILES, \true)) { return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_FORBIDDEN)); } $file = $this->kernel->getProjectDir() . '/' . $request->attributes->get('file'); if ($request->isMethod('PUT')) { $this->filesystem->dumpFile($file, $request->getContent()); } elseif (!$this->filesystem->exists($file)) { return new Response('', Response::HTTP_NO_CONTENT); } return new Response(\file_get_contents($file)); } } security->isGranted('ROLE_ADMIN')) { $username = $this->security->getUser()?->getUserIdentifier(); $user = $this->config->getUser($username); return $this->getUserResponse([$user]); } return $this->getUserResponse($this->config->getUsers()); } /** * Adds a new user to the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users', methods: ['POST'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_ADMIN')] public function createUser(Request $request) : Response { $user = $this->createUserFromRequest($request); if ($this->config->hasUser($user->getUserIdentifier())) { throw new BadRequestHttpException(\sprintf('User "%s" already exists.', $user->getUserIdentifier())); } $this->config->addUser($user); return $this->getUserResponse($user, Response::HTTP_CREATED, \true); } /** * Returns user data from the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}', name: 'user_get', methods: ['GET'])] public function retrieveUser(string $username) : Response { $this->denyAccessUnlessUserOrAdmin($username); $user = $this->config->getUser($username); if (null === $user) { throw new NotFoundHttpException(\sprintf('User "%s" was not found.', $username)); } return $this->getUserResponse($user); } /** * Replaces user data in the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}', methods: ['PUT'])] public function replaceUser(string $username, Request $request) : Response { $this->denyAccessUnlessUserOrAdmin($username); $user = $this->createUserFromRequest($request); if (!$this->config->hasUser($user->getUserIdentifier())) { throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $user->getUserIdentifier())); } $this->config->replaceUser($user); return $this->getUserResponse($user, Response::HTTP_OK, \true); } /** * Deletes a user from the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}', methods: ['DELETE'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_ADMIN')] public function deleteUser(string $username) : Response { $user = $this->config->getUser($username); if (null === $user) { throw new NotFoundHttpException(\sprintf('User "%s" was not found.', $username)); } $this->config->deleteUser($username); return $this->getUserResponse($user); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/password', methods: ['PUT'])] public function setPassword(string $username, Request $request) : Response { $this->denyAccessUnlessUser($username); $user = $this->config->getUser($username); if (null === $user) { throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username)); } if ($user->getPasskey()) { throw new ServiceUnavailableHttpException('Cannot change password of a user with a Passkey.'); } $currentPassword = $request->request->get('current_password'); $newPassword = $request->request->get('new_password'); if (!$currentPassword || !$newPassword) { throw new BadRequestHttpException('Invalid payload.'); } $isPasswordValid = $this->passwordHasherFactory->getPasswordHasher($user)->verify($user->getPassword(), $currentPassword); if (!$isPasswordValid) { throw new UnprocessableEntityHttpException('Current password is not valid.'); } $this->config->updateUser($username, ['password' => $newPassword]); return new JsonResponse(); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/totp', methods: ['GET'])] public function getTOTP(string $username) : Response { $this->denyAccessUnlessUser($username); $user = $this->config->getUser($username); if (null === $user) { throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username)); } if ($user->getPasskey()) { throw new ServiceUnavailableHttpException('Cannot configure TOTP of a user with a Passkey.'); } if (null !== $user->getTotpSecret()) { throw new BadRequestException('TOTP already configured.'); } $totp = TOTP::generate(); $totp->setLabel($username); return new JsonResponse(['provisioning_uri' => $totp->getProvisioningUri()]); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/totp', methods: ['PUT'])] public function setupTotp(string $username, Request $request) : Response { $this->denyAccessUnlessUser($username); $user = $this->config->getUser($username); if (null === $user) { throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username)); } if ($user->getPasskey()) { throw new ServiceUnavailableHttpException('Cannot configure TOTP of a user with a Passkey.'); } if (null !== $user->getTotpSecret()) { throw new AccessDeniedException('TOTP already configured.'); } try { $totp = Factory::loadFromProvisioningUri($request->request->get('provisioning_uri')); } catch (\Exception) { throw new BadRequestHttpException('Invalid provisioning_uri'); } if (!$totp instanceof TOTP) { throw new BadRequestHttpException('Invalid provisioning_uri'); } if (!$totp->verify($request->request->get('totp'))) { throw new UnprocessableEntityHttpException('Invalid TOTP'); } $this->config->updateUser($username, ['totp_secret' => $totp->getSecret()]); return new JsonResponse(null, Response::HTTP_CREATED); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/totp', methods: ['DELETE'])] public function deleteTotp(string $username, Request $request) : Response { $this->denyAccessUnlessUser($username); $user = $this->config->getUser($username); if (null === $user) { throw new NotFoundHttpException(\sprintf('User "%s" does not exist.', $username)); } if ($user->getPasskey()) { throw new ServiceUnavailableHttpException('Cannot configure TOTP of a user with a Passkey.'); } if (null === $user->getTotpSecret()) { throw new NotFoundHttpException('TOTP not configured.'); } try { $totp = TOTP::createFromSecret($user->getTotpSecret()); } catch (\Exception) { throw new \RuntimeException('TOTP error.'); } if (!$totp->verify($request->request->getString('totp'))) { throw new UnprocessableEntityHttpException('Invalid TOTP'); } $this->config->updateUser($username, ['totp_secret' => null]); return new JsonResponse(); } /** * Returns a list of tokens of a user in the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/tokens', methods: ['GET'])] public function listTokens(string $username) : Response { $this->denyAccessUnlessUserOrAdmin($username); $tokens = \array_filter($this->config->getTokens(), static fn($token): bool => $token['username'] === $username); return new JsonResponse($tokens); } /** * Adds a new token for a user to the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/tokens', methods: ['POST'])] public function createToken(string $username, Request $request) : Response { $this->denyAccessUnlessUserOrAdmin($username); if (!$this->config->hasUser($username)) { throw new BadRequestHttpException(\sprintf('User "%s" does not exists.', $username)); } $clientId = $request->request->get('client_id'); $scope = $request->request->get('scope'); $oneTimeToken = 'one-time' === $request->request->get('grant_type'); if (!$clientId || !$scope) { throw new BadRequestHttpException('Invalid payload for OAuth token.'); } $this->denyAccessUnlessGranted('ROLE_' . \strtoupper($scope)); $token = $this->config->createToken($username, $clientId, $scope, $oneTimeToken); if ($oneTimeToken) { $token['url'] = $request->getUriForPath('/#?token=' . $token['token']); } return new JsonResponse($token, Response::HTTP_CREATED); } /** * Returns token data of a user from the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/tokens/{id}', methods: ['GET'])] public function retrieveToken(string $username, string $id) : Response { $this->denyAccessUnlessUserOrAdmin($username); $payload = $this->config->getToken($id); if (null === $payload || $payload['username'] !== $username) { throw new NotFoundHttpException(\sprintf('Token with ID "%s" was not found.', $id)); } return new JsonResponse($payload); } /** * Deletes a token from the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/users/{username}/tokens/{id}', methods: ['DELETE'])] public function deleteToken(string $username, string $id) : Response { $this->denyAccessUnlessUserOrAdmin($username); $payload = $this->config->getToken($id); if (null === $payload || $payload['username'] !== $username) { throw new NotFoundHttpException(\sprintf('Token "%s" was not found.', $id)); } $this->config->deleteToken($id); return new JsonResponse($payload); } /** * Adds an invitation to the configuration file. */ #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/invitations', methods: ['POST'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_ADMIN')] public function inviteUser(Request $request) : Response { $token = $this->config->createInvitation($request->request->get('scope')); $token['url'] = $request->getUriForPath('/#?invitation=' . $token['token']); return new JsonResponse($token, Response::HTTP_CREATED); } /** * Creates a response for given user information. * * @param User|array $user */ private function getUserResponse(User|array $user, int $status = Response::HTTP_OK, bool $addLocation = \false) : Response { $response = new JsonResponse($this->convertToJson($user), $status); if ($addLocation && $user instanceof User) { $response->headers->set('Location', $this->urlGenerator->generate('user_get', ['username' => $user->getUserIdentifier()])); } return $response; } /** * Converts a user to JSON representation. * * @param array|User $user */ private function convertToJson(User|array $user) : array { if ($user instanceof User) { return ['username' => $user->getUserIdentifier(), 'scope' => $user->getScope()]; } foreach ($user as $k => $item) { $user[$k] = $this->convertToJson($item); } return $user; } /** * Creates and returns a new user from request data. * * @throws BadRequestHttpException */ private function createUserFromRequest(Request $request) : User { $username = $request->request->get('username', ''); $password = $request->request->get('password', ''); $scope = $request->request->get('scope'); if ('' === $username || \strlen($password) < 8) { throw new BadRequestHttpException('Username or password invalid.'); } if (!\in_array($scope, User::SCOPES, \true)) { throw new BadRequestHttpException('Only the following "scope" is required: ' . \implode(', ', User::SCOPES)); } return $this->config->createUser($username, $password, $scope); } private function denyAccessUnlessUser(string $username, string $message = 'Access Denied.') : void { if ($username !== $this->security->getUser()?->getUserIdentifier()) { throw new AccessDeniedException($message); } } private function denyAccessUnlessUserOrAdmin(string $username, string $message = 'Access Denied.') : void { if ($username !== $this->security->getUser()?->getUserIdentifier()) { $this->denyAccessUnlessGranted('ROLE_ADMIN', null, $message); } } private function denyAccessUnlessGranted(mixed $attribute, mixed $subject = null, string $message = 'Access Denied.') : void { if (!$this->security->isGranted($attribute, $subject)) { $exception = new AccessDeniedException($message); $exception->setAttributes([$attribute]); $exception->setSubject($subject); throw $exception; } } } \\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d+.*)\\] (?[\\w-]+(?:\\.[\\w-]+)?)\\.(?\\w+): (?.+)(?: (?(?:\\[.*?\\]|\\{.*?\\})))(?: (?(?:\\[.*\\]|\\{.*\\})))\\s{0,2}$/'; public function __construct(private readonly ApiKernel $kernel, private readonly Filesystem $filesystem) { } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/logs', methods: ['GET'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_READ')] public function listFiles() : Response { if (!$this->filesystem->exists($this->kernel->getProjectDir() . '/var/logs')) { return new JsonResponse([]); } /** @var Finder $finder */ $finder = Finder::create()->depth(0)->files()->ignoreDotFiles(\true)->name('*.log')->sortByName(\true)->in($this->kernel->getProjectDir() . '/var/logs'); $files = []; foreach ($finder as $file) { $files[] = ['name' => $this->getFilenameWithoutExtension($file), 'mtime' => \DateTime::createFromFormat('U', (string) $file->getMTime())->format(\DateTime::ATOM), 'size' => $file->getSize(), 'lines' => $this->countLines(new \SplFileObject((string) $file))]; } // Reverse files order to sort by date descending return new JsonResponse(\array_reverse($files)); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/logs/{filename}', methods: ['GET'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_READ')] public function retrieveFile(string $filename, Request $request) : Response { $file = $this->getFile($filename); if ('json' === $request->getPreferredFormat()) { return $this->parseJson($file, $request); } $response = new BinaryFileResponse($file); $response->headers->set('Content-Type', 'text/plain'); return $response; } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/logs/{filename}', methods: ['DELETE'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_ADMIN')] public function deleteFile(string $filename) : Response { $file = $this->getFile($filename); $this->filesystem->remove($file->getPathname()); return new Response('', Response::HTTP_NO_CONTENT); } /** * Gets absolute path for filename and checks for security and if file exists. */ private function getFile(string $filename) : \SplFileObject { if (\str_contains($filename, '/')) { throw new BadRequestHttpException(\sprintf('"%s" is not a valid file name.', $filename)); } $path = $this->kernel->getProjectDir() . '/var/logs/' . $filename . '.log'; if (!\is_file($path)) { throw new NotFoundHttpException(\sprintf('Log file "%s" does not exist.', $filename)); } return new \SplFileObject($path); } private function parseJson(\SplFileObject $file, Request $request) : JsonResponse { $file->setFlags(\SplFileObject::DROP_NEW_LINE); $content = []; $skipLastLine = \false; $total = $this->countLines($file, $skipLastLine); $limit = $request->query->getInt('limit', $total); $offset = $request->query->getInt('offset'); $channels = $request->query->has('channels') ? \explode(',', $request->query->get('channel')) : null; $levels = $request->query->has('levels') ? \explode(',', $request->query->get('levels')) : null; if ($offset) { $file->seek($offset); } while (!$file->eof() && $limit > 0) { if ($skipLastLine && $file->key() === $total) { break; } if (null !== ($line = $this->parseJsonLine($file->fgets(), $channels, $levels))) { $content[] = $line; } --$limit; } return new JsonResponse(['name' => $this->getFilenameWithoutExtension($file), 'mtime' => \DateTime::createFromFormat('U', (string) $file->getMTime())->format(\DateTime::ATOM), 'size' => $file->getSize(), 'lines' => $total, 'content' => $content]); } private function parseJsonLine(string $line, array|null $channels = null, array|null $levels = null) : array|string|null { if (!\preg_match(self::MONOLOG_PATTERN, $line, $matches)) { return $line; } if ($channels && !\in_array($matches['channel'], $channels, \true)) { return null; } if ($levels && !\in_array($matches['level'], $levels, \true)) { return null; } $matches['context'] = \json_decode(\trim($matches['context']), \true); $matches['extra'] = \json_decode(\trim($matches['extra']), \true); return \array_intersect_key($matches, \array_flip(['datetime', 'channel', 'level', 'message', 'context', 'extra'])); } private function countLines(\SplFileObject $file, bool &$skipLastLine = \false) : int { $skipLastLine = \false; $file->seek(\PHP_INT_MAX); $lines = $file->key() + 1; $file->seek($file->key()); if (empty($file->current())) { $skipLastLine = \true; --$lines; } $file->rewind(); return $lines; } /** * We use the file name without extension as REST object name, because some * hosters block *.log files for security reasons. * * @param SplFileInfo|\SplFileObject $file */ private function getFilenameWithoutExtension($file) : string { return \pathinfo($file->getFilename(), \PATHINFO_FILENAME); } } config instanceof AuthConfig || !$request->request->has('token')) { throw new BadRequestHttpException('GitHub token could not be stored.'); } $this->config->setGithubToken($request->request->get('token')); return new JsonResponse($this->config->get('github-oauth')); } } getMethod()) { 'PUT' => $this->config->replace($request->request->all()), 'PATCH' => $this->config->add($request->request->all()), default => new JsonResponse($this->config->all()), }; return new JsonResponse($this->config->all()); } } getMethod()) { 'GET' => $this->getTask(), 'PUT' => $this->putTask($request), 'PATCH' => $this->patchTask($request), 'DELETE' => $this->deleteTask(), default => new Response('', Response::HTTP_METHOD_NOT_ALLOWED), }; } private function getTask() : Response { return $this->getResponse($this->taskManager->updateTask()); } private function putTask(Request $request) : Response { if ($this->taskManager->hasTask()) { throw new BadRequestHttpException('A task is already active'); } $name = $request->request->get('name'); $config = $request->request->all('config'); if (empty($name) || !\is_array($config)) { throw new BadRequestHttpException('Invalid task data'); } return $this->getResponse($this->taskManager->createTask($name, $config)); } private function patchTask(Request $request) : Response { if (!$this->taskManager->hasTask()) { throw new BadRequestHttpException('No active task found.'); } if (TaskStatus::STATUS_ABORTING !== $request->request->get('status')) { throw new BadRequestHttpException('Unsupported task status'); } return $this->getResponse($this->taskManager->abortTask()); } private function deleteTask() : Response { if (!$this->taskManager->hasTask()) { return $this->getResponse(); } try { return $this->getResponse($this->taskManager->deleteTask()); } catch (\RuntimeException $e) { return new ApiProblemResponse((new ApiProblem($e->getMessage()))->setStatus(Response::HTTP_FORBIDDEN)); } } private function getResponse(TaskStatus|null $status = null) : Response { if (!$status instanceof TaskStatus) { return new Response('', Response::HTTP_NO_CONTENT); } return new JsonResponse($status); } } \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'platform' => $serverInfo->getPlatform(), 'problem' => $this->runIntegrityChecks()]); } /** * Checks system integrity and returns problem if found. */ private function runIntegrityChecks() : array|null { $problem = $this->integrity->runWebChecks(); if ($problem instanceof ApiProblem) { return $problem->asArray(); } return null; } } getPhpExecutable()) { return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE)); } try { $contaoVersion = $this->getContaoVersion(); } catch (\RuntimeException $e) { if ($request->isMethod('POST')) { return new Response('', Response::HTTP_BAD_REQUEST); } if ($e instanceof ProcessFailedException) { return $this->createResponse(['supported' => \false, 'error' => $e->getMessage()], Response::HTTP_BAD_GATEWAY); } if ($e instanceof ProcessOutputException) { return $this->createResponse(['supported' => \false, 'error' => $e->getProcess()->getErrorOutput() ?: $e->getProcess()->getOutput()], Response::HTTP_BAD_GATEWAY); } $contaoVersion = null; } if (null === $contaoVersion) { $files = $this->getProjectFiles(); if ($request->isMethod('POST')) { return $this->createDirectories($request->request->get('directory'), $request->request->getBoolean('usePublicDir')); } return $this->createResponse(['conflicts' => $files]); } return $this->createResponse(['version' => $contaoVersion, 'cli' => ['commands' => (object) $this->contaoConsole->getCommandList()], 'api' => ['version' => $this->contaoApi->getVersion(), 'features' => $this->contaoApi->getFeatures(), 'commands' => $this->contaoApi->getCommands()], 'config' => (object) $this->contaoConsole->getConfig(), 'supported' => \version_compare($contaoVersion, '4.0.0', '>=') || \str_starts_with($contaoVersion, 'dev-')]); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/server/contao', methods: ['POST'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_INSTALL')] public function update(Request $request, ServerInfo $serverInfo) : Response { return $this($request, $serverInfo); } private function createDirectories(string|null $directory, bool $usePublicDir) : Response { if (!ApiKernel::isPhar()) { return new Response('', Response::HTTP_SERVICE_UNAVAILABLE); } $currentRoot = $this->kernel->getProjectDir(); $targetRoot = $currentRoot; $publicDir = $currentRoot . '/' . ($usePublicDir ? 'public' : 'web'); if (null !== $directory) { if (\str_contains($directory, '..')) { return new Response('', Response::HTTP_BAD_REQUEST); } if ($this->filesystem->exists($currentRoot . '/' . $directory)) { return new ApiProblemResponse((new ApiProblem('Target directory exists'))->setStatus(Response::HTTP_FORBIDDEN)); } $targetRoot = $currentRoot . '/' . $directory; $publicDir = $targetRoot . '/' . ($usePublicDir ? 'public' : 'web'); $this->filesystem->mkdir($targetRoot); $this->filesystem->mirror($this->kernel->getConfigDir(), $targetRoot . '/contao-manager'); $this->filesystem->remove($this->kernel->getConfigDir()); } $this->filesystem->mkdir($publicDir); // Create response before moving Phar, otherwise the JsonResponse class // cannot be autoloaded $response = $this->createResponse(['project_dir' => $targetRoot, 'public_dir' => $usePublicDir ? 'public' : 'web', 'conflicts' => []], Response::HTTP_CREATED); $phar = \Phar::running(\false); $this->filesystem->rename($phar, $publicDir . '/' . \basename($phar)); if ($this->filesystem->exists(\dirname($phar) . '/.htaccess')) { $this->filesystem->rename(\dirname($phar) . '/.htaccess', $publicDir . '/.htaccess'); } if ([] === \array_diff(\scandir(\dirname($phar), \SCANDIR_SORT_NONE), ['.', '..'])) { $this->filesystem->remove(\dirname($phar)); } return $response; } /** * Gets a list of files in the project root directory, excluding what is allowed * to install Contao. */ private function getProjectFiles() : array { $content = \scandir($this->kernel->getProjectDir()); return \array_values(\array_diff($content, [ '.', '..', '.env', '.env.local', '.git', '.idea', '.ddev', '.well-known', 'cgi-bin', 'contao-manager', 'plesk-stat', 'public', 'web', '.bash_profile', '.bash_logout', '.bashrc', '.DS_Store', '.ftpquota', '.htaccess', 'user.ini', \basename(\dirname(\Phar::running())), // Allow parent directory of the PHAR file (public dir) \basename(\Phar::running()), ])); } /** * Tries to detect the Contao 4/3/2 version by analyzing the filesystem. */ private function getContaoVersion() : string|null { if ($this->filesystem->exists($this->processFactory->getContaoConsolePath())) { return $this->contaoConsole->getVersion(); } // Required for Contao 2.11 \define('_ContaoManager\\TL_ROOT', $this->kernel->getProjectDir()); $files = [$this->kernel->getProjectDir() . '/system/constants.php', $this->kernel->getProjectDir() . '/system/config/constants.php']; // Test if the Phar was placed in the Contao 2/3 root if ('' !== ($phar = \Phar::running(\false))) { $files[] = \dirname($phar) . '/system/constants.php'; $files[] = \dirname($phar) . '/system/config/constants.php'; } $this->logger->info('Searching for Contao 2/3', ['files' => $files]); foreach ($files as $file) { if ($this->filesystem->exists($file)) { try { @(include $file); } catch (\Throwable) { // do nothing on error or exception } if (\defined('_ContaoManager\\VERSION') && \defined('_ContaoManager\\BUILD')) { /** @noinspection PhpUndefinedConstantInspection */ return VERSION . '.' . BUILD; } break; } } return null; } private function createResponse(array $data, int $status = Response::HTTP_OK) : JsonResponse { return new JsonResponse(\array_merge(['version' => null, 'cli' => ['commands' => []], 'api' => ['version' => 0, 'features' => [], 'commands' => []], 'config' => new \stdClass(), 'supported' => \false, 'conflicts' => [], 'project_dir' => $this->kernel->getProjectDir(), 'public_dir' => \basename($this->kernel->getPublicDir()), 'directory_separator' => \DIRECTORY_SEPARATOR], $data), $status); } } getPhpExecutable()) { return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE)); } $commands = $this->contaoConsole->getCommandList(); $features = $this->contaoApi->getFeatures(); if (!isset($commands['contao:migrate']['options'], $features['contao/manager-bundle']['dot-env']) || !\in_array('format', $commands['contao:migrate']['options'], \true) || !\in_array('dry-run', $commands['contao:migrate']['options'], \true) || !\in_array('hash', $commands['contao:migrate']['options'], \true) || !\in_array('DATABASE_URL', $features['contao/manager-bundle']['dot-env'], \true)) { return new ApiProblemResponse((new ApiProblem('Contao console does not support the necessary contao:migrate command/arguments or CLI API features.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } if ($request->isMethod('POST')) { $url = $request->request->get('url'); if (empty($url) || !\preg_match('{' . self::URL_PATTERN . '}i', $url)) { return new ApiProblemResponse((new ApiProblem('Invalid URL'))->setStatus(Response::HTTP_BAD_REQUEST)); } $this->contaoApi->runCommand(['dot-env:set', 'DATABASE_URL', $url]); } else { $url = $this->contaoApi->runCommand(['dot-env:get', 'DATABASE_URL']); } return new JsonResponse(['url' => $url, 'pattern' => self::URL_PATTERN, 'status' => $this->contaoConsole->checkDatabaseMigrations()]); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/server/database', methods: ['POST'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_INSTALL')] public function write(Request $request, ServerInfo $serverInfo) : Response { return $this($request, $serverInfo); } } getPhpExecutable()) { return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE)); } $commands = $this->contaoConsole->getCommandList(); if (!isset($commands['contao:user:list']['options'], $commands['contao:user:create']['options']) || !\in_array('format', $commands['contao:user:list']['options'], \true) || !\in_array('column', $commands['contao:user:list']['options'], \true)) { return new ApiProblemResponse((new ApiProblem('Contao console does not support the necessary contao:user:list and/or contao:user:create commands/options.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } if ($request->isMethod('POST')) { if ($this->hasAdminUser()) { return new ApiProblemResponse((new ApiProblem('An admin user already exists.'))->setStatus(Response::HTTP_METHOD_NOT_ALLOWED)); } try { $this->contaoConsole->createBackendUser(['username' => $request->request->get('username'), 'name' => $request->request->get('name'), 'email' => $request->request->get('email'), 'language' => $request->getPreferredLanguage()], $request->request->get('password')); return $this->getUserResponse(Response::HTTP_CREATED); } catch (ProcessFailedException $exception) { $problem = new ApiProblem('Unable to create back end account.'); $problem->setStatus(Response::HTTP_INTERNAL_SERVER_ERROR); $problem['debug'] = $exception->getProcess()->getOutput() . $exception->getProcess()->getErrorOutput(); return new ApiProblemResponse($problem); } } return $this->getUserResponse(); } private function getUserResponse(int $status = Response::HTTP_OK) : JsonResponse { return new JsonResponse(['hasUser' => $this->hasAdminUser(\true)], $status); } private function hasAdminUser(bool $throw = \false) : bool { $users = $this->contaoConsole->getUsers($throw); foreach ($users as $user) { if ($user['admin']) { return \true; } } return \false; } } $opcacheEnabled, 'reset_token' => \md5(\Phar::running(\false))]; return new JsonResponse($status); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/server/opcache', methods: ['DELETE'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_UPDATE')] public function deleteOpcache() : Response { if (!\function_exists('opcache_reset')) { return new JsonResponse(null, Response::HTTP_NOT_IMPLEMENTED); } \opcache_reset(); return $this->getOpcache(); } } (string) $this->serverInfo->getPhpExecutable(), 'cloud' => $this->getCloudConfig()]); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/server/config', methods: ['PUT'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_INSTALL')] public function setConfig(Request $request) : Response { $phpCli = $request->request->get('php_cli'); if (null !== ($error = $this->validatePhpCli($phpCli))) { $problem = (new ApiProblem('Bad Request'))->setStatus(400); $problem->setDetail($error); return new ApiProblemResponse($problem); } $this->config->set('php_cli', $phpCli); if ($request->request->getBoolean('cloud', \true)) { $this->config->remove('disable_cloud'); } else { $this->config->set('disable_cloud', \true); } return $this->getConfig(); } private function validatePhpCli(string $phpCli) : string|null { try { $info = $this->serverInfo->getPhpExecutableFinder()->getServerInfo($phpCli); } catch (RuntimeException $e) { return $this->translator->trans('config.php_cli.error') . "\n\n" . $e->getMessage(); } if (null === $info) { return $this->translator->trans('config.php_cli.not_found'); } $vWeb = \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION; $vCli = \vsprintf('%s.%s', \explode('.', (string) $info['version'])); if (\version_compare($vWeb, $vCli, '<>')) { return $this->translator->trans('config.php_cli.incompatible', ['cli' => $vCli, 'web' => $vWeb]); } return null; } private function getCloudConfig() : array { $issues = $this->checkCloudIssues(); return ['enabled' => !$this->config->get('disable_cloud', \false), 'issues' => $issues]; } private function checkCloudIssues() : array { $json = new JsonFile($this->environment->getJsonFile()); if (!$json->exists()) { return []; } try { $data = $json->read(); } catch (\RuntimeException $e) { return [$e->getMessage()]; } $issues = []; if (isset($data['config']['platform'])) { $issues[] = $this->translator->trans('config.cloud.platform'); } if (isset($data['config']['cache-dir']) || isset($data['config']['cache-files-dir']) || isset($data['config']['cache-repo-dir']) || isset($data['config']['cache-vcs-dir']) || isset($data['config']['cache-files-ttl']) || isset($data['config']['cache-files-maxsize'])) { $issues[] = $this->translator->trans('config.cloud.cache'); } return \array_unique($issues); } } getPhpExecutable()) { return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE)); } $result = ['json' => ['found' => \false, 'valid' => \false, 'error' => null], 'lock' => ['found' => \false, 'fresh' => \false], 'vendor' => ['found' => \false]]; if ($this->filesystem->exists($this->environment->getJsonFile())) { $result['json']['found'] = \true; $result['json']['valid'] = \true; $result['vendor']['found'] = \is_dir($this->environment->getVendorDir()); if ($this->validateSchema($result)) { // If schema is valid but does not contain contao/manager-bundle, mark as "not // found" so the install screen will conflict with the file. if (!$this->environment->hasPackage('contao/manager-bundle')) { $result['json']['found'] = \false; $result['json']['valid'] = \false; } else { $this->validateLockFile($result); } } } return new JsonResponse($result); } private function validateSchema(array &$result) : bool { try { $schemaFile = __DIR__ . '/../../../vendor/composer/composer/res/composer-schema.json'; // Prepend with file:// only when not using a special schema already (e.g. in the phar) if (!\str_contains($schemaFile, '://')) { $schemaFile = 'file://' . $schemaFile; } $schema = (object) ['$ref' => $schemaFile]; $schema->required = []; $value = \json_decode(\file_get_contents($this->environment->getJsonFile()), \false); $validator = new Validator(); $validator->validate($value, $schema, Constraint::CHECK_MODE_EXCEPTIONS); return \true; } catch (ValidationException $exception) { $result['json']['valid'] = \false; $result['json']['error'] = $this->translator->trans('boot.composer.invalid', ['exception' => $exception->getMessage()]); return \false; } } private function validateLockFile(array &$result) : void { try { $locker = $this->environment->getComposer()->getLocker(); if ($locker->isLocked()) { $result['lock']['found'] = \true; if ($locker->isFresh()) { $result['lock']['fresh'] = \true; } } } catch (ParsingException $e) { $result['json']['valid'] = \false; $result['json']['error'] = $this->translator->trans('boot.composer.invalid', ['exception' => $e->getMessage() . ' ' . $e->getDetails()['text']]); } catch (\Exception $e) { $result['json']['valid'] = \false; $result['json']['error'] = $this->translator->trans('boot.composer.invalid', ['exception' => $e->getMessage()]); } } } getPhpExecutable()) { return new ApiProblemResponse((new ApiProblem('Missing hosting configuration.', '/api/server/config'))->setStatus(Response::HTTP_SERVICE_UNAVAILABLE)); } return new JsonResponse($this->runIntegrityChecks($processFactory)); } private function runIntegrityChecks(ConsoleProcessFactory $processFactory) : array { $process = $processFactory->createManagerConsoleProcess(['integrity-check', '--format=json']); $process->run(); $output = $process->getOutput(); $result = \json_decode($output, \true); if (!\is_array($result)) { return ['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'problem' => ['title' => 'Received invalid JSON output from the command line', 'type' => 'https://php.net/json_decode', 'detail' => $output]]; } return $result; } } canUpdate()) { return new ApiProblemResponse((new ApiProblem('This version cannot be updated.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } try { $error = null; $supportsUpdate = $updater->supportsUpdate(); $latestVersion = $updater->getNewVersion(); } catch (\Throwable $throwable) { $error = $throwable->getMessage(); $supportsUpdate = \true; $latestVersion = $updater->getOldVersion(); } return new JsonResponse(['current_version' => $updater->getOldVersion(), 'latest_version' => $latestVersion, 'channel' => $updater->getChannel(), 'supported' => $supportsUpdate, 'error' => $error]); } } getMethod()) { case 'GET': return $this->getStatus(); case 'POST': if (LoginAuthenticator::isLocked($this->kernel->getConfigDir())) { return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_FORBIDDEN)); } // Login should have been handled by the firewall return new Response('Bad Request', Response::HTTP_BAD_REQUEST); case 'DELETE': return $this->handleLogout($request); } return new Response(null, Response::HTTP_METHOD_NOT_ALLOWED); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/session/options', methods: ['GET', 'POST'])] public function getWebauthnOptions(Request $request) : Response { $username = $request->isMethod('POST') ? $request->request->get('username') : null; return new JsonResponse($this->webauthn->getCredentialOptions($request->getHost(), $username), json: \true); } /** * Returns the login status of the user. */ private function getStatus() : Response { if ($this->security->isGranted('ROLE_USER')) { $token = $this->security->getToken(); if (null !== $token && TokenAuthenticator::class === $token->getAttribute('authenticator') && null !== ($payload = $this->config->getToken($token->getAttribute('token_id')))) { return new JsonResponse($payload); } $user = $this->config->getUser($token->getUserIdentifier()); $scope = User::scopeFromRoles($token?->getRoleNames()); $json = ['username' => $token?->getUserIdentifier(), 'scope' => $scope, 'limited' => $scope !== User::scopeFromRoles($user?->getRoles())]; if ($user?->getPasskey()) { $json['passkey'] = \true; } else { $json['totp_enabled'] = (bool) $user?->getTotpSecret(); } return new JsonResponse($json); } if (LoginAuthenticator::isLocked($this->kernel->getConfigDir())) { return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_FORBIDDEN)); } if (!$this->config->hasUsers()) { return new Response('', Response::HTTP_NO_CONTENT); } return new ApiProblemResponse((new ApiProblem())->setStatus(Response::HTTP_UNAUTHORIZED)); } /** * Logs the user out by removing cookies from the browser. */ private function handleLogout(Request $request) : Response { if (!$this->security->isGranted('ROLE_USER')) { return new ApiProblemResponse((new ApiProblem('User is not logged in'))->setStatus(Response::HTTP_UNAUTHORIZED)); } $response = new Response('', Response::HTTP_NO_CONTENT); $this->jwtManager->removeToken($request, $response); return $response; } } getComposer(); $this->localRepository = $composer->getRepositoryManager()->getLocalRepository(); $this->compositeRepository = new InstalledRepository([new RootPackageRepository($composer->getPackage()), $this->localRepository, new PlatformRepository([], $composer->getConfig()->get('platform') ?: [])]); } public function __invoke() : Response { $missing = []; foreach ($this->localRepository->getPackages() as $package) { if ($this->hasDependents([$package->getName()])) { continue; } $replaces = \array_keys($package->getReplaces()); if ([] !== $replaces && $this->hasDependents($replaces)) { continue; } $missing[] = $package->getName(); } if ([] === $missing) { return new Response('', Response::HTTP_NO_CONTENT); } return new JsonResponse($missing); } private function hasDependents(array $names) : bool { $dependents = $this->compositeRepository->getDependents($names, null, \false, \false); foreach ($dependents as $dependent) { /** @var Link $link */ [, $link] = $dependent; if ('requires' === $link->getDescription()) { return \true; } } return \false; } } validateUploadSupport(); $uploads = $this->config->all(); foreach ($uploads as $id => &$upload) { if (!$this->filesystem->exists($this->uploadPath($id))) { unset($uploads[$id]); $this->config->remove($id); continue; } $upload['filesize'] = \filesize($this->uploadPath($id)); if ($upload['error']) { $upload['error'] = $this->translator->trans('upload.error.' . $upload['error']); } elseif (!$upload['success']) { $upload['error'] = $this->translator->trans('upload.error.partial'); } } return new JsonResponse(\array_reverse($uploads)); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/packages/uploads', methods: ['POST'], defaults: ['form-data' => \true])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_INSTALL')] public function upload(Request $request) : JsonResponse { $this->validateUploadSupport(); // Must be a HTML5 upload if ($request->files->has('package')) { /** @var UploadedFile $file */ $file = $request->files->get('package'); $id = $this->createUpload($file->getClientOriginalName(), $file->getSize()); $file->move($this->environment->getUploadDir(), $id); return $this->finishUpload($id, $request->getPreferredLanguage()); } switch ($request->request->get('phase')) { case 'start': $id = $this->createUpload($request->request->get('name'), $request->request->getInt('size')); return new JsonResponse(['status' => 'success', 'data' => ['session_id' => $id, 'end_offset' => self::CHUNK_SIZE]], Response::HTTP_CREATED); case 'upload': $this->addChunk($request->request->get('session_id'), $request->request->getInt('start_offset'), $request->files->get('chunk')); return new JsonResponse(['status' => 'success']); case 'finish': $id = $request->request->get('session_id'); return $this->finishUpload($id, $request->getPreferredLanguage()); } throw new \RuntimeException(\sprintf('Invalid chunk phase "%s"', $request->request->get('phase'))); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/packages/uploads/{id}', methods: ['DELETE'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_INSTALL')] public function delete(string $id) : JsonResponse { $this->validateUploadSupport(); if (!$this->config->has($id)) { throw new NotFoundHttpException(\sprintf('Unknown file ID "%s"', $id)); } try { $this->filesystem->remove($this->uploadPath($id)); } catch (IOException) { // Ignore if file could not be deleted } $this->config->remove($id); return new JsonResponse(['status' => 'success']); } private function createUpload(string $name, int $size) : string { /** @noinspection PhpUnhandledExceptionInspection */ $id = \bin2hex(\random_bytes(8)); $this->filesystem->touch($this->uploadPath($id)); $this->config->set($id, ['id' => $id, 'name' => $name, 'size' => $size, 'success' => \false, 'error' => null, 'package' => null]); return $id; } private function addChunk(string $id, int $offset, UploadedFile $file) : void { if (!$this->config->has($id)) { throw new NotFoundHttpException(\sprintf('Unknown file ID "%s"', $id)); } $fp = \fopen($this->uploadPath($id), 'cb+'); \flock($fp, \LOCK_EX); \fseek($fp, $offset); \fwrite($fp, \file_get_contents($file->getPathname()), self::CHUNK_SIZE); \flock($fp, \LOCK_UN); \fclose($fp); } private function finishUpload(string $id, string|null $language = null) : JsonResponse { $uploadFile = $this->uploadPath($id); $config = $this->config->get($id); if (null === $config || !$this->filesystem->exists($uploadFile)) { throw new NotFoundHttpException(\sprintf('Unknown file ID "%s"', $id)); } $size = \filesize($uploadFile); if ($config['success'] || $config['error']) { throw new \RuntimeException('File has already be uploaded completely.'); } if ($size !== $config['size']) { throw new \RuntimeException(\sprintf('Incomplete upload ID "%s": %s instead of %s bytes', $id, $size, $config['size'])); } try { $json = Zip::getComposerJson($uploadFile); if (null === $json) { return $this->installError($id, 'file'); } } catch (\RuntimeException) { return $this->installError($id, 'file'); } try { $data = JsonFile::parseJson($json, $uploadFile . '#composer.json'); } catch (ParsingException $exception) { return $this->installError($id, 'json', $exception); } try { $schemaFile = __DIR__ . '/../../../vendor/composer/composer/res/composer-schema.json'; // Prepend with file:// only when not using a special schema already (e.g. in the phar) if (!\str_contains($schemaFile, '://')) { $schemaFile = 'file://' . $schemaFile; } $schema = (object) ['$ref' => $schemaFile]; $schema->required = ['name', 'version']; $value = \json_decode(\json_encode($data), \false); $validator = new Validator(); $validator->validate($value, $schema, \_ContaoManager\JsonSchema\Constraints\Constraint::CHECK_MODE_EXCEPTIONS); } catch (ValidationException $exception) { return $this->installError($id, 'schema', $exception); } [$vendor, $package] = \explode('/', (string) $data['name']); $config['success'] = \true; $config['hash'] = \sha1_file($uploadFile); $config['package'] = \array_merge($this->environment->mergeMetadata($data, $language), ['installation-source' => 'dist', 'dist' => ['shasum' => $config['hash'], 'type' => 'zip', 'url' => \sprintf('/contao-manager/packages/%s__%s__%s__%s.zip', $vendor, $package, (new VersionParser())->normalize($data['version']), \substr(\sha1_file($uploadFile), 0, 8))]]); $this->config->set($id, $config); return new JsonResponse(['status' => 'success', 'data' => $this->config->get($id)]); } private function uploadPath(string $id) : string { return $this->environment->getUploadDir() . '/' . $id; } private function installError(string $id, string $error, \Exception|null $e = null) : JsonResponse { $config = $this->config->get($id); $config['success'] = \false; $config['error'] = $error; if ($e instanceof \Exception) { $config['exception'] = $e->getMessage(); } $this->config->set($id, $config); return new JsonResponse($config); } private function validateUploadSupport() : void { if (!$this->filesystem->exists($this->environment->getJsonFile())) { return; } if (!\extension_loaded('zip')) { throw new ApiProblemException((new ApiProblem("The artifact repository requires PHP's zip extension"))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } $packages = $this->environment->getComposer()->getRepositoryManager()->getLocalRepository()->getPackages(); foreach ($packages as $package) { if ('contao/manager-plugin' === $package->getName()) { $require = new MultiConstraint([new Constraint('>=', '2.7'), new Constraint('=', 'dev-main')], \false); if ($require->matches(new Constraint('=', $package->getVersion()))) { return; } } } throw new ApiProblemException((new ApiProblem('Must install contao/manager-plugin 2.7 or later to support artifacts.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } } dump($this->environment->getComposer()->getPackage())); } } $this->environment->getComposerJson(), 'composerLock' => $this->environment->getComposerLock(), 'platform' => $this->environment->getPlatformPackages(), 'localPackages' => $this->environment->getLocalPackages()]); } #[\_ContaoManager\Symfony\Component\Routing\Attribute\Route(path: '/packages/cloud', methods: ['PUT'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_INSTALL')] public function writeAndInstall(Request $request) : Response { if ($this->taskManager->hasTask()) { throw new BadRequestHttpException('A task is already active'); } $lock = $request->request->all('composerLock'); if (null === $lock) { return new Response('composerLock is missing', Response::HTTP_BAD_REQUEST); } try { $lockFile = new JsonFile($this->filesystem->tempnam(\sys_get_temp_dir(), \md5(\Phar::running()))); $lockFile->write($lock); $lockContent = $lockFile->read(); // Validates the JSON } catch (\Throwable $throwable) { $this->logger->error('Invalid composerLock for /api/packages/cloud.', ['composerLock' => $lock]); return ApiProblemResponse::createFromException($throwable); } try { if ($request->request->has('composerJson') && [] !== ($json = $request->request->all('composerJson'))) { $jsonFile = new JsonFile($this->filesystem->tempnam(\sys_get_temp_dir(), \md5(\Phar::running()))); $jsonFile->write($json); $jsonFile->validateSchema(JsonFile::LAX_SCHEMA); $this->environment->getComposerJsonFile()->write($jsonFile->read()); } } catch (\Throwable $throwable) { $this->logger->error('Invalid composerJson for /api/packages/cloud.', ['composerJson' => $json, 'composerLock' => $lock]); return ApiProblemResponse::createFromException($throwable); } // Only write after composer.json was validated $this->environment->getComposerLockFile()->write($lockContent); return new JsonResponse($this->taskManager->createTask('composer/install', [])); } } '.+'])] #[\_ContaoManager\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_READ')] class LocalPackagesController { private readonly InstalledRepositoryInterface $localRepository; private readonly InstalledRepository $compositeRepository; public function __construct(private readonly Environment $environment) { $composer = $this->environment->getComposer(); $this->localRepository = $composer->getRepositoryManager()->getLocalRepository(); $this->compositeRepository = new InstalledRepository([new RootPackageRepository($composer->getPackage()), $this->localRepository, new PlatformRepository([], $composer->getConfig()->get('platform') ?: [])]); } public function __invoke(Request $request, string|null $name = null) : Response { if (null !== $name) { return $this->getOnePackage($name, $request->getPreferredLanguage()); } $dumper = new ArrayDumper(); $packages = []; foreach ($this->localRepository->getPackages() as $package) { $packages[$package->getName()] = $this->environment->mergeMetadata($dumper->dump($package), $request->getPreferredLanguage()); $packages[$package->getName()]['dependents'] = $this->getDependents($package); } return new JsonResponse($packages); } private function getOnePackage(string $name, string|null $language = null) : Response { [$package] = \array_values($this->localRepository->findPackages($name)); if (!$package instanceof PackageInterface) { throw new NotFoundHttpException('Package "' . $name . '" is not installed'); } $dumper = new ArrayDumper(); $data = $this->environment->mergeMetadata($dumper->dump($package), $language); $data['dependents'] = $this->getDependents($package); return new JsonResponse($data); } private function getDependents(PackageInterface $package) : array { $dependents = $this->parseDependents([$package->getName()]); if ([] === $dependents && [] !== ($replaces = \array_keys($package->getReplaces()))) { return $this->parseDependents($replaces, \true); } return $dependents; } private function parseDependents(array $packageNames, bool $withReplaces = \false) : array { $links = []; $dependents = $this->compositeRepository->getDependents($packageNames, null, \false, \false); foreach ($dependents as $dependent) { /** @var Link $link */ [, $link] = $dependent; if (!$withReplaces && 'replaces' === $link->getDescription()) { continue; } $constraint = $link->getConstraint(); $links[] = ['description' => $link->getDescription(), 'source' => $link->getSource(), 'target' => $link->getTarget(), 'constraint' => $constraint->getPrettyString()]; } return $links; } } request->has('constraint')) { return new Response('Missing constraint in POST data.', Response::HTTP_BAD_REQUEST); } try { $versionParser = new VersionParser(); $versionParser->parseConstraints($request->request->get('constraint')); } catch (\Exception $exception) { return new JsonResponse(['valid' => \false, 'error' => $exception->getMessage()]); } return new JsonResponse(['valid' => \true, 'error' => null]); } } lockFile = $kernel->getProjectDir() . '/var/install_lock'; } public function __invoke(Request $request) : Response { try { $contaoVersion = $this->console->getVersion(); } catch (\RuntimeException) { $contaoVersion = null; } if (null === $contaoVersion || (new MultiConstraint([new Constraint('<', '4.4.9'), new Constraint('>', '4.13.9999')], \false))->matches(new Constraint('=', $contaoVersion))) { return new ApiProblemResponse((new ApiProblem('Contao does not support locking the install tool.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } return match ($request->getMethod()) { 'GET' => $this->getLockStatus(), 'PUT' => $this->lockInstallTool(), 'DELETE' => $this->unlockInstallTool(), default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED), }; } private function getLockStatus() : Response { return new JsonResponse(['locked' => $this->isLocked()]); } private function lockInstallTool() : Response { $this->filesystem->dumpFile($this->lockFile, '3'); return $this->getLockStatus(); } private function unlockInstallTool() : Response { $this->filesystem->remove($this->lockFile); return $this->getLockStatus(); } private function isLocked() : bool { return $this->filesystem->exists($this->lockFile) && @\file_get_contents($this->lockFile) >= 3; } } console->getCommandList(); if (!isset($commands['contao:migrate']['options']) || !\in_array('hash', $commands['contao:migrate']['options'], \true) || !\in_array('format', $commands['contao:migrate']['options'], \true) || !\in_array('dry-run', $commands['contao:migrate']['options'], \true)) { return new ApiProblemResponse((new ApiProblem('Contao does not support database migrations.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } switch ($request->getMethod()) { case 'GET': return $this->getStatus(); case 'PUT': if (null !== $this->getBackgroundProcess()) { throw new BadRequestHttpException('A migration is already active'); } $process = $this->createProcess($request->request->get('hash'), $request->request->get('type'), $request->request->getBoolean('withDeletes')); $process->setMeta(['skip_warnings' => $request->request->getBoolean('skipWarnings')]); $process->start(); return new Response('', Response::HTTP_CREATED); case 'DELETE': if (null === ($process = $this->getBackgroundProcess())) { return new Response(); } $process->delete(); return new Response(); } return new Response(null, Response::HTTP_METHOD_NOT_ALLOWED); } private function getStatus() : Response { $process = $this->getBackgroundProcess(); if (null === $process) { return new Response('', Response::HTTP_NO_CONTENT); } $skipWarnings = (bool) ($process->getMeta()['skip_warnings'] ?? \false); $output = \trim($process->getOutput()); if ('' !== $output) { $lines = \explode("\n", $output); while ($line = \array_shift($lines)) { $data = \json_decode($line, \true); $type = $data['type'] ?? null; if ('warning' === $type && $skipWarnings) { continue; } if (\in_array($type, ['error', 'problem', 'warning'], \true)) { \array_unshift($lines, $line); return $this->handleProblems($lines, $process); } if ('migration-pending' === $type && !empty($data['names'])) { return $this->handleMigrations($data, $lines, $process); } if ('schema-pending' === $type && !empty($data['commands'])) { return $this->handleSchema($data, $lines, $process); } } } return new JsonResponse(['type' => $this->getProcessType($process), 'status' => $this->getProcessStatus($process), 'operations' => [], 'hash' => null]); } private function createProcess(string|null $hash, string|null $type, bool $withDeletes) : ProcessController { $args = ['contao:migrate', '--no-interaction', '--format=ndjson', null === $hash ? '--dry-run' : '--hash=' . $hash]; switch ($type) { case 'migrations-only': $args[] = '--migrations-only'; break; case 'schema-only': $args[] = '--schema-only'; break; } if ($withDeletes && 'migrations-only' !== $type && null !== $hash) { $args[] = '--with-deletes'; } return $this->processFactory->createContaoConsoleBackgroundProcess($args, 'database-migration'); } private function getBackgroundProcess() : ProcessController|null { try { return $this->processFactory->restoreBackgroundProcess('database-migration'); } catch (\Exception) { return null; } } private function handleProblems(array $lines, ProcessController $process) : Response { $responseType = 'warning'; $operations = []; foreach ($lines as $line) { $data = \json_decode((string) $line, \true); $type = $data['type'] ?? null; if (!\in_array($type, ['error', 'problem', 'warning'], \true)) { continue; } if ('warning' !== $type) { $responseType = 'problem'; } if ('error' === $type && isset($data['message'], $data['file'], $data['line'], $data['trace'])) { $operations[] = ['status' => 'error', 'name' => \sprintf('Exception in file %s on line %s', \str_replace($this->kernel->getProjectDir() . '/', '', $data['file']), $data['line']), 'message' => $data['message'], 'trace' => \str_replace($this->kernel->getProjectDir() . '/', '', $data['trace'])]; } else { $message = \explode("\n", $data['message'] ?? '', 2) + ['', '']; $operations[] = ['status' => 'error', 'name' => $message[0], 'message' => $message[1]]; } } return new JsonResponse(['type' => $responseType, 'status' => $this->getProcessStatus($process), 'operations' => $operations]); } private function handleMigrations(array $pending, array $lines, ProcessController $process) : Response { $operations = []; foreach ($pending['names'] as $name) { $operations[] = ['name' => $name, 'status' => 'pending', 'message' => '']; } $c = 0; foreach ($lines as $line) { $data = \json_decode((string) $line, \true); if ('migration-result' === ($data['type'] ?? '')) { $operations[$c]['message'] = $data['message']; $operations[$c]['status'] = $data['isSuccessful'] ? TaskStatus::STATUS_COMPLETE : TaskStatus::STATUS_ERROR; ++$c; } } return new JsonResponse(['type' => $this->getProcessType($process, 'migrations'), 'status' => $this->getProcessStatus($process), 'operations' => \array_values($operations), 'hash' => $pending['hash']]); } private function handleSchema(array $pending, array $lines, ProcessController $process) : Response { $operations = []; foreach ($pending['commands'] as $name) { $operations[$name] = ['name' => $name, 'status' => !$process->isRunning() && !$process->isSuccessful() ? TaskStatus::STATUS_ERROR : 'pending', 'message' => '']; } foreach ($lines as $line) { $data = \json_decode((string) $line, \true); $type = $data['type'] ?? ''; $name = $data['command'] ?? ''; if ('schema-execute' === $type) { $operations[$name]['status'] = TaskStatus::STATUS_ACTIVE; continue; } if ('schema-result' === $type) { $operations[$name]['status'] = $data['isSuccessful'] ? TaskStatus::STATUS_COMPLETE : TaskStatus::STATUS_ERROR; $operations[$name]['message'] = $data['message'] ?? ''; } } return new JsonResponse(['type' => $this->getProcessType($process, 'schema'), 'status' => $this->getProcessStatus($process), 'operations' => \array_values($operations), 'hash' => $pending['hash']]); } private function getProcessStatus(ProcessController $process) : string { if (!$process->isStarted()) { $process->start(); return TaskStatus::STATUS_ACTIVE; } if ($process->isRunning()) { return TaskStatus::STATUS_ACTIVE; } if ($process->isSuccessful()) { if (\str_contains($process->getCommandLine(), '--dry-run')) { return 'pending'; } return TaskStatus::STATUS_COMPLETE; } return TaskStatus::STATUS_ERROR; } private function getProcessType(ProcessController $process, string $default = '') : string { if (\str_contains($process->getCommandLine(), '--schema-only')) { return 'schema-only'; } if (\str_contains($process->getCommandLine(), '--migrations-only')) { return 'migrations-only'; } return $default; } } getMethod()) { 'GET' => $this->getAccessKey(), 'PUT' => $this->setAccessKey($request), 'DELETE' => $this->removeAccessKey(), default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED), }; } /** * @throws ParsingException */ private function getAccessKey() : Response { if (!$this->isSupported('get')) { return new ApiProblemResponse((new ApiProblem('Contao does not support the access-key API.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } return new JsonResponse(['access-key' => $this->api->runCommand($this->getAccessKeyArguments('get'))]); } /** * @throws ParsingException */ private function setAccessKey(Request $request) : Response { if (!$this->isSupported('set')) { return new Response(null, Response::HTTP_NOT_IMPLEMENTED); } if (!$request->request->has('user') || !$request->request->has('password')) { return new Response(null, Response::HTTP_BAD_REQUEST); } $user = $request->request->get('user'); $password = $request->request->get('password'); $accessKey = \password_hash($user . ':' . $password, \PASSWORD_DEFAULT); $this->api->runCommand(\array_merge($this->getAccessKeyArguments('set'), [$accessKey])); return new JsonResponse(['access-key' => $accessKey]); } /** * @throws ParsingException */ private function removeAccessKey() : Response { if (!$this->isSupported('remove')) { return new Response(null, Response::HTTP_NOT_IMPLEMENTED); } $this->api->runCommand($this->getAccessKeyArguments('remove')); return new JsonResponse(['access-key' => '']); } private function getAccessKeyArguments(string $action) : array { if (1 === $this->api->getVersion()) { return ['access-key:' . $action]; } return ['dot-env:' . $action, 'APP_DEV_ACCESSKEY']; } /** * Returns whether access key command is supported. */ private function isSupported(string $action) : bool { return 1 === $this->api->getVersion() || $this->api->hasCommand('dot-env:' . $action) && \in_array('APP_DEV_ACCESSKEY', $this->api->getFeatures()['contao/manager-bundle']['dot-env'], \true); } } console->getCommandList(); if (!\array_key_exists('contao:backup:list', $commands) || !\array_key_exists('contao:backup:create', $commands) || !\array_key_exists('contao:backup:restore', $commands)) { return new ApiProblemResponse((new ApiProblem('Contao does not support backups.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } $arguments = ['contao:backup:list', '--format=json', '--no-interaction']; $process = $this->processFactory->createContaoConsoleProcess($arguments); $process->run(); $data = \json_decode(\trim($process->getOutput()), \true); if (!\is_array($data)) { throw new ProcessOutputException('Invalid response for listing backups.', $process); } return new JsonResponse($data); } } console->getCommandList(); } catch (\RuntimeException) { $commands = []; } $hasLexik = \array_key_exists('lexik:maintenance:lock', $commands) && \array_key_exists('lexik:maintenance:unlock', $commands); if (!$hasLexik && !\array_key_exists('contao:maintenance-mode', $commands)) { return new ApiProblemResponse((new ApiProblem('Contao does not support maintenance mode.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } return match ($request->getMethod()) { 'GET' => $this->getStatus($hasLexik), 'PUT' => $this->enable($hasLexik), 'DELETE' => $this->disable($hasLexik), default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED), }; } private function getStatus(bool $lexik) : Response { if ($lexik) { return new JsonResponse(['enabled' => $this->filesystem->exists($this->kernel->getProjectDir() . '/var/maintenance_lock')]); } return new JsonResponse($this->runContaoCommand()); } private function enable(bool $lexik) : Response { if ($lexik) { return new JsonResponse(['enabled' => $this->runLexikCommand('lock')]); } return new JsonResponse($this->runContaoCommand('enable')); } private function disable(bool $lexik) : Response { if ($lexik) { return new JsonResponse(['enabled' => !$this->runLexikCommand('unlock')]); } return new JsonResponse($this->runContaoCommand('disable')); } private function runContaoCommand(string|null $state = null) : array { $arguments = ['contao:maintenance']; if (null !== $state) { $arguments[] = $state; } $arguments[] = '--format=json'; $arguments[] = '--no-interaction'; $process = $this->processFactory->createContaoConsoleProcess($arguments); $process->run(); $data = \json_decode(\trim($process->getOutput()), \true); if (!\is_array($data)) { return ['enabled' => \false]; } return $data; } private function runLexikCommand(string $command) : bool { $process = $this->processFactory->createContaoConsoleProcess(['lexik:maintenance:' . $command, '--no-interaction']); $process->run(); return $process->isSuccessful(); } } isSupported()) { return new ApiProblemResponse((new ApiProblem('Contao does not support the jwt-token API.'))->setStatus(Response::HTTP_NOT_IMPLEMENTED)); } return match ($request->getMethod()) { 'GET' => $this->getJwtPayload($request), 'PUT' => $this->setJwtToken($request), 'DELETE' => $this->removeJwtToken(), default => new Response(null, Response::HTTP_METHOD_NOT_ALLOWED), }; } /** * @throws ParsingException */ private function getJwtPayload(Request $request) : Response { if (!$request->cookies->has(self::COOKIE_NAME)) { return new Response('', Response::HTTP_NO_CONTENT); } $payload = $this->api->runJsonCommand(['jwt-cookie:parse', $request->cookies->get(self::COOKIE_NAME)]); return new JsonResponse($payload); } /** * @throws ParsingException */ private function setJwtToken(Request $request) : Response { $arguments = ['jwt-cookie:generate']; if ($request->request->getBoolean('debug')) { $arguments[] = '--debug'; } $cookie = Cookie::fromString($this->api->runCommand($arguments)); $response = new JsonResponse(['debug' => $request->request->getBoolean('debug')]); $response->headers->setCookie($cookie); return $response; } private function removeJwtToken() : Response { $response = new Response('', Response::HTTP_NO_CONTENT); $response->headers->clearCookie(self::COOKIE_NAME); return $response; } private function isSupported() : bool { $features = $this->api->getFeatures(); return isset($features['contao/manager-bundle']['jwt-cookie']) && \in_array('debug', $features['contao/manager-bundle']['jwt-cookie'], \true); } } filesystem = new Filesystem(); $debug = 'dev' === $environment; ErrorHandler::register(); \error_reporting($debug ? \E_ALL : \E_ERROR | \E_PARSE | \E_CORE_ERROR | \E_COMPILE_ERROR); \ini_set('display_errors', $debug ? '1' : '0'); \ini_set('error_log', $this->getLogDir() . \DIRECTORY_SEPARATOR . 'error-' . \date('Y-m-d') . '.log'); parent::__construct($environment, $debug); $this->configureComposerEnvironment(); } public function isWebDir() : bool { $publicDir = $this->getPublicDir(); return 'web' === \dirname($publicDir) && $publicDir !== $this->getProjectDir(); } public function getRootDir() : string { return __DIR__; } public function getProjectDir() : string { if (null === $this->projectDir) { $this->findProjectDir(); } return $this->projectDir; } public function getPublicDir() : string { $this->getProjectDir(); return $this->publicDir; } public function getCacheDir() : string { $cacheDir = $this->debug ? $this->getConfigDir() . '/appcache' : __DIR__ . '/Resources/cache'; $this->ensureDirectoryExists($cacheDir); return $cacheDir; } public function getLogDir() : string { $logDir = $this->getConfigDir() . '/logs'; $this->ensureDirectoryExists($logDir); return $logDir; } /** * Gets the directory where to place manager files like config and logs. */ public function getConfigDir() : string { if (null !== $this->configDir) { return $this->configDir; } $this->configDir = $this->getProjectDir() . \DIRECTORY_SEPARATOR . 'contao-manager'; if (!self::isPhar()) { return $this->configDir; } // Try to find a config directory in the parent from previous version if (!$this->filesystem->exists($this->configDir)) { $parentDir = \dirname($this->getProjectDir()) . \DIRECTORY_SEPARATOR . 'contao-manager'; if ($this->filesystem->exists($parentDir . '/manager.json')) { $this->filesystem->mirror($parentDir, $this->configDir); } $this->ensureDirectoryExists($this->configDir); } // Make sure the config directory contains a .htaccess file if (!$this->filesystem->exists($this->configDir . \DIRECTORY_SEPARATOR . '.htaccess')) { $this->filesystem->dumpFile($this->configDir . \DIRECTORY_SEPARATOR . '.htaccess', <<<'CODE' Order deny,allow Deny from all Require all denied CODE ); } return $this->configDir; } public function getTranslator() : Translator { if ($this->container) { return $this->container->get(Translator::class); } // The kernel has not been bootet successfully, manually create a translator $requestStack = new RequestStack(); $requestStack->push(Request::createFromGlobals()); return new Translator($requestStack); } public function registerBundles() : array { return [new FrameworkBundle(), new SecurityBundle(), new MonologBundle()]; } public function registerContainerConfiguration(LoaderInterface $loader) : void { $loader->load(__DIR__ . '/Resources/config/config_' . $this->environment . '.yaml'); } /** * Loads the routes using framework.router config. We must use a loader method not * e.g. a routes.yaml because of dynamic path to the Phar. */ public function loadRoutes(LoaderInterface $loader) : RouteCollection { $resolver = $loader->getResolver()->resolve(__DIR__ . '/Controller', 'attribute'); $routes = $resolver->load(__DIR__ . '/Controller', 'attribute'); $routes->addPrefix('api'); return $routes; } public static function isPhar() : bool { return '' !== \Phar::running(\false); } /** * Configures the Composer environment variables to match the current setup. */ private function configureComposerEnvironment() : void { $root = $this->getProjectDir(); \putenv('COMPOSER=' . $root . \DIRECTORY_SEPARATOR . 'composer.json'); \putenv('COMPOSER_HOME=' . $this->getConfigDir()); \putenv('COMPOSER_HTACCESS_PROTECT=0'); \chdir($root); } /** * Finds the Contao installation directory depending on the Phar file or * development mode. */ private function findProjectDir() : void { // @see https://getcomposer.org/doc/03-cli.md#composer if (\false !== ($composer = \getenv('COMPOSER'))) { // We don't know the public dir when running on command line, but it shouldn't matter $this->projectDir = \dirname($composer); $this->publicDir = $this->projectDir; return; } // Not a phar file, use test directory in local development if (!self::isPhar()) { $this->projectDir = \dirname(__DIR__) . \DIRECTORY_SEPARATOR . 'test-dir'; $this->publicDir = $this->projectDir . '/web'; $this->ensureDirectoryExists($this->publicDir); return; } // Use the current working directory in CLI mode if (('cli' === \PHP_SAPI || !isset($_SERVER['REQUEST_URI'])) && !empty($_SERVER['PWD'])) { // We don't know the public dir when running on command line, but it shouldn't matter $this->projectDir = $_SERVER['PWD']; $this->publicDir = $_SERVER['PWD']; return; } $current = \getcwd(); if (!$current) { $current = \dirname(\Phar::running(\false)); } // Always use current folder if it is not named "web" or "public" if ('web' !== \basename($current) && 'public' !== \basename($current)) { $this->projectDir = $current; $this->publicDir = $current; return; } $contaoFiles = ['/vendor/contao/manager-bundle/bin/contao-console', '/system/constants.php', '/system/config/constants.php']; if ($this->debug) { $contaoFiles[] = '/vendor/contao/contao/manager-bundle/bin/contao-console'; } // Use current folder if it looks like Contao foreach ($contaoFiles as $file) { if ($this->filesystem->exists($current . $file)) { $this->projectDir = $current; $this->publicDir = $current; return; } } // Throw exception if parent folder looks like Contao but is not writeable if (!\is_writable(\dirname($current))) { $files = [\dirname($current) . '/vendor/contao/manager-bundle/bin/contao-console', \dirname($current) . '/system/constants.php', \dirname($current) . '/system/config/constants.php']; if ($this->debug) { $files[] = \dirname($current) . '/vendor/contao/contao/manager-bundle/bin/contao-console'; } foreach ($files as $file) { if ($this->filesystem->exists($file)) { $translator = $this->getTranslator(); $problem = (new ApiProblem($translator->trans('error.writable.root', ['path' => \dirname($current)]), 'https://php.net/is_writable'))->setDetail($translator->trans('error.writable.detail')); throw new ApiProblemException($problem); } } } $this->publicDir = $current; $this->projectDir = \dirname($current); } private function ensureDirectoryExists(string $directory) : void { try { $this->filesystem->mkdir($directory); } catch (IOException $exception) { $translator = $this->getTranslator(); $problem = new ApiProblem($translator->trans('error.writable.directory', ['path' => $exception->getPath()])); $problem->setDetail($translator->trans('error.writable.detail')); throw new ApiProblemException($problem, $exception); } } } phpExecutableFinder; } /** * Gets PHP executable by detecting known server paths. */ public function getPhpExecutable() : string|null { $paths = []; if ($php_cli = $this->managerConfig->get('php_cli')) { $paths[] = $php_cli; } foreach (self::PHP_BINARIES as $path) { $paths[] = $this->getPhpVersionPath($path); } $found = $this->phpExecutableFinder->find($paths); if ($php_cli && $found !== $php_cli) { $this->managerConfig->set('php_cli', $found); } return $found; } /** * Gets environment variables for the PHP command line process. */ public function getPhpEnv() : array { return ['PHP_PATH' => $this->getPhpExecutable()]; } /** * Returns the background process forker classes for the current server. */ public function getProcessForkers() : array { if (self::PLATFORM_WINDOWS === $this->getPlatform()) { return [WindowsStartForker::class, InlineForker::class]; } return [DisownForker::class, NohupForker::class, InlineForker::class]; } /** * Returns the server platform (Windows or UNIX). */ public function getPlatform() : string { return '\\' === \DIRECTORY_SEPARATOR ? self::PLATFORM_WINDOWS : self::PLATFORM_UNIX; } /** * Gets versionised path to PHP binary. */ private function getPhpVersionPath(string $path) : string { return \str_replace(['{major}', '{minor}', '{release}', '{extra}'], [\PHP_MAJOR_VERSION, \PHP_MINOR_VERSION, \PHP_RELEASE_VERSION, \PHP_EXTRA_VERSION], $path); } } getContent($url, $statusCode, [], $catch, $timeout); } public function getStream(string $url, ?int &$statusCode = null, bool $catch = \false) { $context = $this->createStreamContext($url, 0); try { $stream = \fopen($url, 'r', \false, $context); $statusCode = $this->getLastStatusCode($http_response_header ?? null); } catch (\Throwable $throwable) { if ($catch) { return \false; } throw new RequestException($url, $this->getLastStatusCode($http_response_header ?? null), $throwable); } return $stream; } public function getJson(string $url, array $headers = [], ?int &$statusCode = null, bool $catch = \false) : string|null { $headers[] = 'Accept: application/json'; return $this->getContent($url, $statusCode, ['http' => ['header' => $headers]], $catch); } public function postJson(string $url, string $content, array $headers = [], ?int &$statusCode = null, bool $catch = \false) : string|null { $headers[] = 'Accept: application/json'; $headers[] = 'Content-Type: application/json'; $options = ['http' => ['method' => 'POST', 'header' => $headers, 'content' => $content]]; return $this->getContent($url, $statusCode, $options, $catch); } public function deleteJson(string $url, array $headers = [], ?int &$statusCode = null, bool $catch = \false) : string|null { $headers[] = 'Accept: application/json'; $options = ['http' => ['method' => 'DELETE', 'header' => $headers]]; return $this->getContent($url, $statusCode, $options, $catch); } private function getContent(string $url, ?int &$statusCode, array $options, bool $catch, int $timeout = self::DEFAULT_TIMEOUT) : string|null { $context = $this->createStreamContext($url, $timeout, $options); try { if (\false === ($content = \file_get_contents($url, \false, $context))) { throw new \RuntimeException(); } $statusCode = $this->getLastStatusCode($http_response_header ?? null); } catch (\Throwable $throwable) { if ($catch) { return null; } throw new RequestException($url, $this->getLastStatusCode($http_response_header ?? null), $throwable); } return $content; } private function createStreamContext(string $url, int $timeout = self::DEFAULT_TIMEOUT, array $options = []) { $tlsDefaults = $this->getTlsDefaults($options); $options = \array_replace_recursive($tlsDefaults, $options); if ($timeout > 0) { $options['http']['timeout'] ??= $timeout; } $options['http']['ignore_errors'] ??= \true; if (isset($options['http']['header']) && !\is_array($options['http']['header'])) { $options['http']['header'] = [$options['http']['header']]; } $options['http']['header'][] = \sprintf('User-Agent: Contao Manager/%s (%s; %s; %s%s)', ApiKernel::VERSION_KEY === ApiKernel::MANAGER_VERSION ? 'source' : ApiKernel::MANAGER_VERSION, \function_exists('php_uname') ? \php_uname('s') : 'Unknown', \function_exists('php_uname') ? \php_uname('r') : 'Unknown', 'PHP ' . \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION, Platform::getEnv('CI') ? '; CI' : ''); return StreamContextFactory::getContext($url, $options); } /** * @see \Composer\Util\RemoteFilesystem::getTlsDefaults() */ private function getTlsDefaults(array $options) : array { $ciphers = \implode(':', ['ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'DHE-RSA-AES128-GCM-SHA256', 'DHE-DSS-AES128-GCM-SHA256', 'kEDH+AESGCM', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-RSA-AES128-SHA', 'ECDHE-ECDSA-AES128-SHA', 'ECDHE-RSA-AES256-SHA384', 'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES256-SHA', 'ECDHE-ECDSA-AES256-SHA', 'DHE-RSA-AES128-SHA256', 'DHE-RSA-AES128-SHA', 'DHE-DSS-AES128-SHA256', 'DHE-RSA-AES256-SHA256', 'DHE-DSS-AES256-SHA', 'DHE-RSA-AES256-SHA', 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256', 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA', 'AES', 'CAMELLIA', 'DES-CBC3-SHA', '!aNULL', '!eNULL', '!EXPORT', '!DES', '!RC4', '!MD5', '!PSK', '!aECDH', '!EDH-DSS-DES-CBC3-SHA', '!EDH-RSA-DES-CBC3-SHA', '!KRB5-DES-CBC3-SHA']); /** * CN_match and SNI_server_name are only known once a URL is passed. They will be * set in the getOptionsForUrl() method which receives a URL. * * cafile or capath can be overridden by passing in those options to constructor. */ $defaults = ['ssl' => ['ciphers' => $ciphers, 'verify_peer' => \true, 'verify_depth' => 7, 'SNI_enabled' => \true]]; if (isset($options['ssl'])) { $defaults['ssl'] = \array_replace_recursive($defaults['ssl'], $options['ssl']); } /* * Attempt to find a local cafile or throw an exception if none pre-set * The user may go download one if this occurs. */ if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) { $result = CaBundle::getSystemCaRootBundlePath($this->logger); if (\is_dir($result)) { $defaults['ssl']['capath'] = $result; } else { $defaults['ssl']['cafile'] = $result; } } /* * Disable TLS compression to prevent CRIME attacks where supported. */ $defaults['ssl']['disable_compression'] = \true; return $defaults; } private function getLastStatusCode(array|null $http_response_header) : int { if (!\is_array($http_response_header)) { return 500; } // Reverse the headers so we find the last HTTP status code if the request // was redirected See // http://php.net/manual/en/reserved.variables.httpresponseheader.php#122362 $http_response_header = \array_reverse($http_response_header); foreach ($http_response_header as $header) { if (\preg_match('{^HTTP/.+ (\\d{3}) }i', (string) $header, $matches)) { return (int) $matches[1]; } } return 500; } } checkForUpdate(); $requires = $this->managerConfig->get('latest_requires', []); $repository = new PlatformRepository(); foreach ($requires as $name => $constraint) { if (null === $repository->findPackage($name, $constraint)) { return \false; } } return \true; } /** * Returns whether this is a development build. */ public function isDev() : bool { // @phpstan-ignore-next-line return ApiKernel::VERSION_KEY === ApiKernel::MANAGER_VERSION || 'prod' !== $this->kernel->getEnvironment() || $this->kernel->isDebug(); } /** * Gets the release channel for the current version. */ public function getChannel() : string { return $this->isDev() ? 'dev' : 'stable'; } /** * Returns whether there is an update available. */ public function hasUpdate() : bool { return $this->getOldVersion() !== $this->getNewVersion(); } /** * Returns version of currently installed Phar. */ public function getOldVersion() : string { return ApiKernel::MANAGER_VERSION; } /** * Returns version of remotely available Phar. */ public function getNewVersion() : string|null { $this->checkForUpdate(); return $this->managerConfig->has('latest_version') ? (string) $this->managerConfig->get('latest_version') : null; } /** * Returns the requirements for the remotely available Phar. */ public function getNewRequires() : array { $this->checkForUpdate(); return $this->managerConfig->get('latest_requires', []); } /** * Updates the current Phar to the latest version available. * * @throws \Throwable */ public function update() : bool { if (!$this->hasUpdate() || !$this->canUpdate() || !$this->supportsUpdate()) { return \false; } $remote = $this->getRemoteInfo(); $phar = \Phar::running(\false); [$filename, $extension] = $this->splitFilename($phar); $backupFile = $this->kernel->getConfigDir() . '/' . $filename . '-old' . $extension; $tempFile = \dirname($phar) . '/' . $filename . '.temp'; $this->backup($phar, $backupFile); try { $this->download($tempFile); $this->validate($tempFile, $remote['sha1']); $this->install($tempFile, $phar); } catch (\Throwable $throwable) { $this->filesystem->remove($tempFile); throw $throwable; } // Check the update server after update. This might be necessary if an updated // version contains a new update URL, which will be the case one the PHP version // is no longer supported. $this->managerConfig->remove('last_update'); return \true; } /** * Loads latest information from the update server if the local cache has expired. */ private function checkForUpdate() : void { if ($this->checkedForUpdates) { return; } $lastUpdate = $this->managerConfig->get('last_update'); $latestVersion = $this->managerConfig->get('latest_version'); if (null !== $latestVersion && null !== $lastUpdate && \false !== ($lastUpdate = \strtotime((string) $lastUpdate)) && !$this->isDev() && $lastUpdate <= \time() && $lastUpdate > \strtotime('-1 hour')) { return; } $remote = $this->getRemoteInfo(); $this->checkedForUpdates = \true; $this->managerConfig->set('last_update', (new \DateTime())->format('c')); $this->managerConfig->set('latest_version', $remote['version']); $this->managerConfig->set('latest_requires', $remote['requires'] ?? []); } /** * Gets remote information about available updates. */ private function getRemoteInfo() : array { if (null === $this->remote) { $url = \sprintf(self::VERSION_URL, $this->getChannel()); $content = \trim((string) $this->request->get($url, $statusCode, \false, 0)); $data = \json_decode($content, \true); if (!isset($data['version'], $data['sha1']) || !\preg_match('@^\\d+\\.\\d+\\.\\d+(-[a-z0-9\\-]+)?$@', (string) $data['version']) || !\preg_match('%^[a-z0-9]{40}%', (string) $data['sha1'])) { throw new \RuntimeException('Version request returned incorrectly formatted response.'); } $this->remote = $data; } return $this->remote; } /** * Creates a backup of the current Phar to the given target. */ private function backup(string $current, string $target) : void { $this->filesystem->copy($current, $target, \true); } /** * Downloads the latest remote version to the given target. */ private function download(string $target) : void { $url = \sprintf(self::DOWNLOAD_URL, $this->getChannel()); $result = $this->request->getStream($url); if (null === $result) { throw new \RuntimeException(\sprintf('Request to URL failed: %s', $url)); } $this->filesystem->dumpFile($target, $result); } /** * Validates temporary file if it matches the given SHA1 hash. */ private function validate(string $tempFile, string $sha1) : void { $tmpVersion = \sha1_file($tempFile); if ($tmpVersion !== $sha1) { throw new \RuntimeException(\sprintf('Download file appears to be corrupted or outdated. The file received does not have the expected SHA-1 hash: %s.', $sha1)); } } /** * Installs the temporary Phar to the target location. */ private function install(string $tempFile, string $phar) : void { if (\defined('PHP_WINDOWS_VERSION_BUILD')) { $this->filesystem->copy($tempFile, $phar, \true); $this->filesystem->remove($tempFile); return; } $this->filesystem->rename($tempFile, $phar, \true); } /** * Gets filename and extension from current Phar file. */ private function splitFilename(string $phar) : array { $extension = '.phar.php'; $filename = \basename($phar, $extension); if ($filename === $phar) { $extension = '.phar'; $filename = \basename($phar, $extension); } return [$filename, $extension]; } } */ private readonly array $operations ) { } public function getTitle() : string { return $this->title; } public function getConsole() : string { $console = new ConsoleOutput(); foreach ($this->operations as $operation) { $console->add((string) $operation->getConsole()); } return (string) $console; } /** * @return array */ public function getOperations() : array { return $this->operations; } public function isCancellable() : bool { return $this->cancellable; } public function setCancellable(bool $stoppable) : self { $this->cancellable = $stoppable; return $this; } public function canAutoClose() : bool { return $this->autoClose; } public function setAutoClose(bool $autoClose) : self { $this->autoClose = $autoClose; return $this; } public function hasAudit() : bool { return $this->audit; } public function setAudit(bool $audit) : self { $this->audit = $audit; return $this; } public function getStatus() : string { foreach ($this->operations as $operation) { if ($this->abort) { if ($operation->isRunning()) { return self::STATUS_ABORTING; } continue; } if ($operation->hasError()) { return self::STATUS_ERROR; } if (!$operation->isStarted() || $operation->isRunning()) { return self::STATUS_ACTIVE; } } if ($this->abort) { return self::STATUS_STOPPED; } return self::STATUS_COMPLETE; } public function setAborted() : self { $this->abort = \true; return $this; } public function isActive() : bool { return self::STATUS_ACTIVE === $this->getStatus(); } public function isComplete() : bool { return self::STATUS_COMPLETE === $this->getStatus(); } public function isStopped() : bool { return self::STATUS_STOPPED === $this->getStatus(); } public function hasError() : bool { return self::STATUS_ERROR === $this->getStatus(); } public function jsonSerialize() : array { $operations = []; $sponsor = null; $isNext = \true; $hasError = \false; foreach ($this->operations as $operation) { $operations[] = ['summary' => $operation->getSummary(), 'details' => $operation->getDetails(), 'console' => (string) $operation->getConsole(), 'status' => $hasError ? self::STATUS_STOPPED : $this->getOperationStatus($operation, $isNext)]; if ($operation instanceof SponsoredOperationInterface) { $sponsor = $operation->getSponsor(); } $isNext = $operation->isSuccessful(); $hasError = $hasError || $operation->hasError(); } return ['id' => $this->id, 'title' => $this->title, 'console' => $this->getConsole(), 'cancellable' => $this->cancellable, 'autoclose' => $this->autoClose, 'audit' => $this->audit, 'status' => $this->getStatus(), 'operations' => $operations, 'sponsor' => $sponsor]; } private function getOperationStatus(TaskOperationInterface $operation, bool $isNext = \false) : string { return match (\true) { $operation->isRunning() => self::STATUS_ACTIVE, $operation->isSuccessful() => self::STATUS_COMPLETE, $operation->hasError() => self::STATUS_ERROR, $isNext || $operation->isStarted() => self::STATUS_ACTIVE, default => 'pending', }; } } setAutoClose(\true); } protected function getTitle() : string { return $this->translator->trans('task.dump_autoload.title'); } protected function buildOperations(TaskConfig $config) : array { return [new DumpAutoloadOperation($this->processFactory, $this->translator)]; } } setAutoClose(\true); } protected function getTitle() : string { return $this->translator->trans('task.clear_cache.title'); } protected function buildOperations(TaskConfig $config) : array { return [new ClearCacheOperation($this->processFactory)]; } } translator->trans('task.self_update.title'); } /** * @return array */ protected function buildOperations(TaskConfig $config) : array { return [new SelfUpdateOperation($this->updater, $config, $this->translator)]; } } buildOperations($config); foreach ($operations as $operation) { if (null !== $this->logger && $operation instanceof LoggerAwareInterface) { $operation->setLogger($this->logger); } } return new TaskStatus($config->getId(), $this->getTitle(), $operations); } public function update(TaskConfig $config) : TaskStatus { if ($config->isCancelled()) { return $this->abort($config); } $status = $this->create($config); foreach ($status->getOperations() as $operation) { if (!$operation->isStarted() || $operation->isRunning()) { if (null !== $this->logger) { $this->logger->info('Current operation: ' . $operation::class); } $operation->run(); if (null !== $this->logger && $operation->hasError()) { $this->logger->info('Failed operation: ' . $operation::class); } return $status; } if ($operation->isSuccessful()) { if (null !== $this->logger) { $this->logger->info('Completed operation: ' . $operation::class); } continue; } return $status; } return $status; } public function abort(TaskConfig $config) : TaskStatus { $config->setCancelled(); $status = $this->create($config)->setAborted(); foreach ($status->getOperations() as $operation) { $operation->abort(); if ($operation->isRunning()) { if (null !== $this->logger) { $this->logger->info('Task operation is active, aborting', ['class' => $operation::class]); } break; } } return $status; } public function delete(TaskConfig $config) : bool { $status = $this->create($config); $operations = $status->getOperations(); foreach ($operations as $operation) { if ($operation->isRunning()) { if (null !== $this->logger) { $this->logger->info('Cannot delete active operation', ['class' => $operation::class]); } return \false; } } foreach ($operations as $operation) { if (null !== $this->logger) { $this->logger->info('Deleting operation', ['class' => $operation::class]); } $operation->delete(); } $config->delete(); return \true; } protected abstract function getTitle() : string; /** * @return array */ protected abstract function buildOperations(TaskConfig $config) : array; } translator->trans('task.setup_packages.title'); } protected function buildOperations(TaskConfig $config) : array { $upload = null; if ($uploadId = $config->getOption('upload')) { $upload = $config->getState('upload'); if (!$upload) { $upload = $this->uploads->get($uploadId); $config->setState('upload', $upload); } $operations = [new InstallUploadsOperation([$upload], $config, $this->environment, $this->translator, $this->filesystem), new CreateProjectOperation($config, $this->processFactory, $this->kernel, $this->environment, $upload['package']['name'], null, \true)]; } elseif ($package = $config->getOption('package')) { $operations = [new CreateProjectOperation($config, $this->processFactory, $this->kernel, $this->environment, $package, $config->getOption('version'))]; } else { $operations = [new CreateContaoOperation($config, $this->environment, $this->kernel, $this->filesystem)]; } if ($config->getOption('no-update')) { return $operations; } if ($this->environment->useCloudResolver()) { $operations[] = new CloudOperation($this->cloudResolver, new CloudChanges(), $config, $this->environment, $this->translator, $this->filesystem); } $operations[] = new InstallOperation($this->processFactory, $config, $this->environment, $this->translator, \false, !$config->isCancelled()); if ($upload) { $operations[] = new RemoveUploadsOperation([$upload], $this->uploads, $config, $this->environment, $this->translator, $this->filesystem); } return $operations; } } isComplete() && $config->getOption('dry_run', \false)) { $this->restoreState($config); } return $status; } protected function getTitle() : string { return $this->translator->trans('task.update_packages.title'); } protected function buildOperations(TaskConfig $config) : array { $changes = $this->getComposerDefinition($config); $supportsMaintenance = \array_key_exists('contao:maintenance-mode', $this->contaoConsole->getCommandList()); $operations = []; if (($required = $changes->getRequiredPackages()) && [] !== $required) { $operations[] = new RequireOperation($this->processFactory, $required); } if (($removed = $changes->getRemovedPackages()) && [] !== $removed) { $operations[] = new RemoveOperation($this->processFactory, $removed); } if ($this->environment->useCloudResolver()) { $operations[] = new CloudOperation($this->cloudResolver, $changes, $config, $this->environment, $this->translator, $this->filesystem); } else { $operations[] = new UpdateOperation($this->processFactory, $this->environment, $changes->getUpdates(), $changes->getDryRun()); } if ($supportsMaintenance) { $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'enable'); } $operations[] = new InstallOperation($this->processFactory, $config, $this->environment, $this->translator, $changes->getDryRun(), !$config->isCancelled()); if ($supportsMaintenance) { $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'disable'); } if ($config->getOption('uploads', \false) && \count($this->uploads)) { $uploads = \array_filter($this->uploads->all(), static fn($upload): bool => $upload['success'] && isset($upload['package']['name']) && ([] === $changes->getUpdates() || \in_array($upload['package']['name'], $changes->getUpdates(), \true))); \array_unshift($operations, new InstallUploadsOperation($uploads, $config, $this->environment, $this->translator, $this->filesystem)); if (!$config->getOption('dry_run', \false)) { $operations[] = new RemoveUploadsOperation($uploads, $this->uploads, $config, $this->environment, $this->translator, $this->filesystem); } } return $operations; } protected function getComposerDefinition(TaskConfig $config) : CloudChanges { $updates = $config->getOption('update', []); $definition = new CloudChanges(); $definition->setUpdates($updates); $definition->setDryRun($config->getOption('dry_run', \false)); foreach ($config->getOption('require', []) as $name => $version) { $definition->requirePackage($name, $version); } foreach ($config->getOption('remove', []) as $name) { $definition->removePackage($name); } $this->addContaoConflictsRequirement($definition); $this->handleContaoRequirement($definition); // Update all packages if none are set if (empty($updates)) { $definition->setUpdates([]); } return $definition; } private function addContaoConflictsRequirement(CloudChanges $definition) : void { $rootRequires = $this->environment->getComposer()->getPackage()->getRequires(); if (isset($rootRequires['contao/conflicts']) && '*@dev' === $rootRequires['contao/conflicts']->getPrettyConstraint()) { if ([] !== $definition->getUpdates()) { $definition->addUpdate('contao/conflicts'); } return; } $definition->requirePackage('contao/conflicts', '*@dev'); } private function handleContaoRequirement(CloudChanges $definition) : void { foreach ($definition->getRequiredPackages() as $require) { $require = \explode('=', (string) $require, 2); $packageName = $require[0]; $version = $require[1] ?? null; // Automatically require core-bundle and installation-bundle if the // manager-bundle is not stable otherwise the dependency would not be resolved // because we don't set minimum-stability if ('contao/manager-bundle' === $packageName && null !== $version) { $rootRequires = $this->environment->getComposer()->getPackage()->getRequires(); $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($version); $isContao5 = $constraint->matches(new Constraint('>=', '5@dev')); // Patch composer.json to make sure we have a valid public-dir and install scripts if ($isContao5) { try { $jsonFile = $this->environment->getComposerJsonFile(); $json = $jsonFile->read(); if (!isset($json['extra']['public-dir'])) { $json['extra']['public-dir'] = \basename($this->kernel->getPublicDir()); } foreach (['post-install-cmd', 'post-update-cmd'] as $group) { if (isset($json['scripts'][$group]) && \is_array($json['scripts'][$group])) { foreach ($json['scripts'][$group] as $k => $script) { if ('Contao\\ManagerBundle\\Composer\\ScriptHandler::initializeApplication' === $script) { $json['scripts'][$group][$k] = '@php vendor/bin/contao-setup'; break; } } } elseif (isset($json['scripts'][$group]) && 'Contao\\ManagerBundle\\Composer\\ScriptHandler::initializeApplication' === $json['scripts'][$group]) { $json['scripts'][$group] = '@php vendor/bin/contao-setup'; } } $jsonFile->write($json); } catch (\Exception) { // Ignore } } if ('stable' !== VersionParser::parseStability($version)) { $definition->requirePackage('contao/core-bundle', $version); if (!$isContao5) { $definition->requirePackage('contao/installation-bundle', $version); } elseif (isset($rootRequires['contao/installation-bundle'])) { $definition->removePackage('contao/installation-bundle'); } } else { if (isset($rootRequires['contao/core-bundle'])) { $definition->removePackage('contao/core-bundle'); } if (isset($rootRequires['contao/installation-bundle'])) { $definition->removePackage('contao/installation-bundle'); } } return; } } // Automatically update the core-bundle and installation-bundle when updating Contao // (but only if they are actually installed, like not on the initial installation) foreach ($definition->getUpdates() as $packageName) { if ('contao/manager-bundle' === $packageName) { $localRepository = $this->environment->getComposer()->getRepositoryManager()->getLocalRepository(); if (!empty($localRepository->findPackages('contao/core-bundle'))) { $definition->addUpdate('contao/core-bundle'); } if (!empty($localRepository->findPackages('contao/installation-bundle'))) { $definition->addUpdate('contao/installation-bundle'); } } } } } translator->trans('task.install_packages.title'); } protected function buildOperations(TaskConfig $config) : array { $operations = []; $dryRun = (bool) $config->getOption('dry_run', \false); $supportsMaintenance = $config->getState('supports-maintenance'); if (null === $supportsMaintenance) { $supportsMaintenance = \array_key_exists('contao:maintenance-mode', $this->contaoConsole->getCommandList()); $config->setState('supports-maintenance', $supportsMaintenance); } if ($config->getOption('remove-vendor', \false)) { $operations[] = new RemoveVendorOperation($config, $this->environment, $this->filesystem); } if ($this->environment->useCloudResolver() && (!$this->filesystem->exists($this->environment->getLockFile()) || $config->getOption('cloud-job'))) { $changes = new CloudChanges(); $changes->setDryRun($dryRun); if ($config->getOption('cloud-job') && !$config->getState('cloud-job')) { $config->setState('cloud-job', $config->getOption('cloud-job')); } $operations[] = new CloudOperation($this->cloudResolver, $changes, $config, $this->environment, $this->translator, $this->filesystem); } if ($supportsMaintenance) { $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'enable'); } $operations[] = new InstallOperation($this->processFactory, $config, $this->environment, $this->translator, $dryRun, !$config->isCancelled()); if ($supportsMaintenance) { $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'disable'); } return $operations; } } setAudit(!$config->getOption('dry_run', \false))->setCancellable(\true); } public function update(TaskConfig $config) : TaskStatus { $this->createBackup($config); $status = parent::update($config); if ($status->hasError() || $status->isStopped()) { $this->restoreState($config); } return $status; } public function abort(TaskConfig $config) : TaskStatus { $status = parent::abort($config); if ($status->hasError() || $status->isStopped()) { $this->restoreState($config); } return $status; } /** * Creates a backup of the composer.json and composer.lock file and stores the * currently installed artifacts. */ protected function createBackup(TaskConfig $config) : void { if ($config->getState('backup-created', \false)) { return; } if (!$this->filesystem->exists($this->environment->getJsonFile())) { if (null !== $this->logger) { $this->logger->info('Cannot create composer file backup, source JSON does not exist', ['file' => $this->environment->getJsonFile()]); } return; } if (null !== $this->logger) { $this->logger->info('Creating backup of composer files'); } foreach ($this->getBackupPaths() as $source => $target) { if ($this->filesystem->exists($source)) { $this->filesystem->copy($source, $target, \true); if (null !== $this->logger) { $this->logger->info(\sprintf('Copied "%s" to "%s"', $source, $target)); } } elseif (null !== $this->logger) { $this->logger->info(\sprintf('File "%s" does not exist', $source)); } } $config->setState('backup-artifacts', $this->environment->getArtifacts()); $config->setState('backup-created', \true); } /** * Restores the backup files if a backup was created within this task. */ protected function restoreState(TaskConfig $config) : void { if ($config->getState('backup-created', \false) && !$config->getState('backup-restored', \false)) { if (null !== $this->logger) { $this->logger->info('Restoring backup of composer files'); } foreach (\array_flip($this->getBackupPaths()) as $source => $target) { if ($this->filesystem->exists($source)) { $this->filesystem->copy($source, $target, \true); $this->filesystem->remove($source); if (null !== $this->logger) { $this->logger->info(\sprintf('Copied "%s" to "%s"', $source, $target)); } } elseif (null !== $this->logger) { $this->logger->info(\sprintf('File "%s" does not exist', $source)); } } if (null !== ($previous = $config->getState('backup-artifacts'))) { foreach (\array_diff($this->environment->getArtifacts(), $previous) as $delete) { $this->filesystem->remove($this->environment->getArtifactDir() . '/' . $delete); } } $config->setState('backup-restored', \true); } } /** * Gets source and backup paths for composer.json and composer.lock. */ private function getBackupPaths() : array { return [$this->environment->getJsonFile() => \sprintf('%s/%s~', $this->environment->getBackupDir(), \basename($this->environment->getJsonFile())), $this->environment->getLockFile() => \sprintf('%s/%s~', $this->environment->getBackupDir(), \basename($this->environment->getLockFile()))]; } } setAutoClose(\true); } protected function getTitle() : string { return $this->translator->trans('task.backup_create.title'); } protected function buildOperations(TaskConfig $config) : array { return [new BackupCreateOperation($this->processFactory)]; } } translator->trans('task.backup_restore.title'); } protected function buildOperations(TaskConfig $config) : array { $file = $config->getOption('file'); $backup = $config->getOption('backup', \false); if (!$file) { throw new BadRequestException(); } $operations = [new BackupRestoreOperation($this->processFactory, $file)]; if ($backup) { \array_unshift($operations, new BackupCreateOperation($this->processFactory)); } return $operations; } } setAutoClose(\true); } protected function getTitle() : string { return $this->translator->trans('task.rebuild_cache.title'); } protected function buildOperations(TaskConfig $config) : array { $supportsMaintenance = $config->getState('supports-maintenance'); $environment = $config->getOption('environment', 'prod'); if (null === $supportsMaintenance) { $supportsMaintenance = \array_key_exists('contao:maintenance-mode', $this->contaoConsole->getCommandList()); $config->setState('supports-maintenance', $supportsMaintenance); } $operations = [new RemoveCacheOperation($environment, $this->kernel, $config, $this->filesystem), new CacheClearOperation($this->processFactory, $environment)]; if (\false !== $config->getOption('warmup', \true)) { $operations[] = new CacheWarmupOperation($this->processFactory, $environment); } else { // Remove cache directory again (contao/contao-manager#655) $operations[] = new RemoveCacheOperation($environment, $this->kernel, $config, $this->filesystem, 'remove-cache-again'); } if ($supportsMaintenance && 'dev' !== $environment) { \array_unshift($operations, new MaintenanceModeOperation($config, $this->processFactory, 'enable')); $operations[] = new MaintenanceModeOperation($config, $this->processFactory, 'disable'); } return $operations; } } 'tasks'])] class TaskManager implements LoggerAwareInterface { use LoggerAwareTrait; private string $configFile; private string $logFile; /** * @var array */ private array $tasks = []; /** * @param iterable $tasks */ public function __construct(iterable $tasks, private readonly ApiKernel $kernel, private readonly ConsoleProcessFactory $processFactory, private readonly AuthorizationCheckerInterface $authorizationChecker, private readonly Filesystem $filesystem) { $this->configFile = $this->kernel->getConfigDir() . \DIRECTORY_SEPARATOR . 'task.json'; $this->logFile = $this->kernel->getLogDir() . '/task-output.log'; foreach ($tasks as $task) { $this->tasks[$task->getName()] = $task; } } public function supportsTask(string $name) : bool { return isset($this->tasks[$name]); } public function hasTask() : bool { return $this->filesystem->exists($this->configFile); } public function createTask(string $name, array $options) : TaskStatus { if ($this->hasTask()) { throw new \RuntimeException('A task already exists.'); } $config = new TaskConfig($this->configFile, $this->filesystem, $this->kernel->getTranslator(), $name, $options); $config->save(); $task = $this->loadTask($config); $status = $task->create($config); foreach ($status->getOperations() as $operation) { foreach ((new \ReflectionClass($operation))->getAttributes(IsGranted::class) as $attribute) { /** @var IsGranted $isGranted */ $isGranted = $attribute->newInstance(); if (!$this->authorizationChecker->isGranted($isGranted->attribute, $isGranted->subject)) { $task->delete($config); if ($isGranted->statusCode) { throw new HttpException($isGranted->statusCode, $isGranted->message ?? '', null, [], $isGranted->exceptionCode ?? 0); } throw new AccessDeniedHttpException($isGranted->message ?? '', null, $isGranted->exceptionCode ?? 0); } } } if (null !== $this->logger) { $this->logger->info('Created new task', ['name' => $name, 'options' => $options, 'class' => $task::class]); } $this->processFactory->createManagerConsoleBackgroundProcess(['task:update', '--poll']); return $status; } public function updateTask() : TaskStatus|null { $config = $this->getTaskConfig(); if (null === $config) { return null; } $task = $this->loadTask($config); if (null !== $this->logger) { $this->logger->info('Updating task status', ['name' => $task->getName(), 'class' => $task::class]); } $status = $task->update($config); if (null !== $this->logger && $status->isComplete()) { $this->logger->info('Task has been completed', ['name' => $task->getName(), 'class' => $task::class]); } return $status; } public function abortTask() : TaskStatus|null { $config = $this->getTaskConfig(); if (null === $config) { return null; } $task = $this->loadTask($config); if (null !== $this->logger) { $this->logger->info('Aborting task', ['name' => $task->getName(), 'class' => $task::class]); } return $task->abort($config); } public function deleteTask() : TaskStatus|null { $config = $this->getTaskConfig(); if (null === $config) { return null; } $task = $this->loadTask($config); if (null !== $this->logger) { $this->logger->info('Deleting task', ['name' => $task->getName(), 'class' => $task::class]); } $status = $task->create($config); if ($status->isActive() || !$task->delete($config)) { throw new \RuntimeException('Active task cannot be deleted'); } $this->saveConsoleOutput($status->getConsole()); return $status; } private function loadTask(TaskConfig $config) : TaskInterface { $name = $config->getName(); if (!isset($this->tasks[$name])) { throw new \InvalidArgumentException(\sprintf('Unable to get task "%s".', $name)); } $task = $this->tasks[$name]; if (!$task instanceof TaskInterface) { throw new \RuntimeException(\sprintf('"%s" is not an instance of "%s"', $task::class, TaskInterface::class)); } return $task; } private function getTaskConfig() : TaskConfig|null { if ($this->filesystem->exists($this->configFile)) { try { return new TaskConfig($this->configFile, $this->filesystem, $this->kernel->getTranslator()); } catch (\Exception) { $this->filesystem->remove($this->configFile); } } return null; } private function saveConsoleOutput(string $output) : void { $rotate = new Rotate($this->logFile); $rotate->keep(50); $rotate->run(); $this->filesystem->dumpFile($this->logFile, $output); } } 'tasks'])] interface TaskInterface { /** * Gets the task name. */ public function getName() : string; /** * Creates a task. */ public function create(TaskConfig $config) : TaskStatus; /** * Updates the task. */ public function update(TaskConfig $config) : TaskStatus; /** * Cancels a task. */ public function abort(TaskConfig $config) : TaskStatus; /** * Deletes a task. */ public function delete(TaskConfig $config) : bool; } initialize(); if (null === $name && null === $options) { return; } $this->data = ['id' => Uuid::uuid4()->toString(), 'name' => $name, 'options' => $options, 'state' => [], 'cancelled' => \false]; } public function getId() : string { $this->initialize(); return $this->data['id'] ?? '--unknown--'; } public function getName() : string { $this->initialize(); return $this->data['name'] ?? '--unknown--'; } public function getOptions() : array { $this->initialize(); return $this->data['options'] ?? []; } public function getOption(string $name, array|bool|float|int|string|null $default = null) : array|bool|float|int|string|null { $this->initialize(); return \array_key_exists($name, $this->data['options']) ? $this->data['options'][$name] : $default; } public function getState(string $name, array|bool|float|int|string|null $default = null) : array|bool|float|int|string|null { $this->initialize(); return \array_key_exists($name, $this->data['state']) ? $this->data['state'][$name] : $default; } public function setState(string $name, array|bool|float|int|string|null $value) : void { $this->initialize(); $this->data['state'][$name] = $value; $this->save(); } public function clearState(string $name) : void { $this->initialize(); unset($this->data['state'][$name]); } public function isCancelled() : bool { $this->initialize(); return (bool) $this->data['cancelled']; } /** * Mark task as cancelled. */ public function setCancelled() : void { $this->initialize(); $this->data['cancelled'] = \true; $this->save(); } } addOption('format', null, InputOption::VALUE_REQUIRED, 'Use "text" or "json" to output the check results accordingly.', 'text'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $problem = $this->integrity->runCliCheck(); $format = $input->getOption('format'); if ('json' === $format) { return $this->writeJson($output, $problem); } if ('text' !== $format) { throw new \InvalidArgumentException(\sprintf('Unknown output format "%s"', $format)); } if (null !== $problem) { $output->writeln('Running PHP ' . \PHP_VERSION); $output->writeln($problem->getTitle()); if ('' !== ($detail = $problem->getDetail())) { $output->writeln(''); $output->writeln($detail); } return Command::FAILURE; } $output->writeln('Running PHP ' . \PHP_VERSION . ', all checks successful.'); return Command::SUCCESS; } private function writeJson(OutputInterface $output, ApiProblem|null $problem = null) : int { $output->write(\json_encode(['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'problem' => $problem?->asArray()], \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT)); return null === $problem ? Command::SUCCESS : Command::FAILURE; } } updater->supportsUpdate()) { throw new \RuntimeException('Your server does not meet the requirements of the next Contao Manager version.'); } if (!$this->updater->canUpdate()) { throw new \RuntimeException('This build of Contao Manager cannot be automatically updated.'); } return $this->update($output); } protected function configure() : void { } private function update(OutputInterface $output) : int { $result = $this->updater->update(); if (\false === $result) { $output->writeln('Already up-to-date.'); } else { $output->writeln(\sprintf('Updated from version %s to version %s.', $this->updater->getOldVersion(), $this->updater->getNewVersion())); } return Command::SUCCESS; } } taskManager->hasTask()) { $output->writeln('No task is currently active.'); return Command::FAILURE; } $this->taskManager->abortTask(); return parent::execute($input, $output); } } addOption('poll', null, InputOption::VALUE_NONE, 'Poll for updates until the task is completed.')->addOption('interval', null, InputOption::VALUE_REQUIRED, 'Poll interval in seconds.', 1); } protected function execute(InputInterface $input, OutputInterface $output) : int { if (!$this->taskManager->hasTask()) { $output->writeln('No task is currently active.'); return Command::FAILURE; } $status = $this->taskManager->updateTask(); if (null === $status) { return Command::FAILURE; } if (!$output instanceof ConsoleOutput) { return Command::FAILURE; } $style = new SymfonyStyle($input, $output); $style->title($status->getTitle()); $sections = []; $progresses = []; $operations = $status->getOperations(); foreach ($operations as $i => $operation) { $section = $output->section(); $section->writeln(($operation->isRunning() ? ' > ' : ' - ') . $operation->getSummary()); $section->writeln(''); $sections[$i] = $section; } $this->updateOperations($status->getOperations(), $sections, $progresses); if ($input->getOption('poll')) { while ($status->isActive()) { \sleep((int) $input->getOption('interval')); $newStatus = $this->taskManager->updateTask(); if (null === $newStatus) { return Command::FAILURE; } if ($this->updateOperations($newStatus->getOperations(), $sections, $progresses)) { break; } } } match ($status->getStatus()) { TaskStatus::STATUS_COMPLETE => $style->success('Operations completed successfully'), TaskStatus::STATUS_ERROR => $style->error('Task terminated unexpectedly'), TaskStatus::STATUS_STOPPED => $style->warning('Task has been stopped'), default => Command::SUCCESS, }; return Command::SUCCESS; } /** * @param array $operations * @param array $sections * @param array $progresses */ private function updateOperations(array $operations, array $sections, array &$progresses) : bool { foreach ($operations as $i => $operation) { $section = $sections[$i]; $progress = $progresses[$i] ?? null; $this->updateOperation($operation, $section, $progress); if ($progress) { $progresses[$i] = $progress; } if (!$operation->isStarted() || $operation->isRunning()) { return \false; } } return \true; } private function updateOperation(TaskOperationInterface $operation, ConsoleSectionOutput $section, ProgressIndicator|null &$progress) : void { if (!$operation->isStarted()) { return; } $section->clear(); if ($operation->isRunning()) { if (null === $progress) { $progress = new ProgressIndicator($section); $progress->start($operation->getSummary()); } $progress->advance(); $section->writeln(' ' . $operation->getDetails()); $section->writeln(''); return; } if (null !== $progress) { $progress->finish($operation->getSummary()); $section->clear(); $progress = null; } $icon = ''; if ($operation->isSuccessful()) { $icon = \sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "✔"); } elseif ($operation->hasError()) { $icon = \sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "✘"); } $section->writeln(' ' . $icon . ' ' . $operation->getSummary()); $section->writeln(' ' . $operation->getDetails()); $section->writeln(''); } } addArgument('path', InputArgument::REQUIRED, 'Absolute path to the task config file.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { \set_time_limit(0); \ignore_user_abort(\true); $process = new ProcessRunner($input->getArgument('path')); try { $process->run(); } catch (\Exception $exception) { $process->addOutput((string) $exception); $process->stop(); return Command::FAILURE; } return Command::SUCCESS; } } collectData(); $this->outputTable($input, $output, $data); return Command::SUCCESS; } private function outputTable(InputInterface $input, OutputInterface $output, array $data) : void { $io = new SymfonyStyle($input, $output); $osVersion = $data['server']['os_version'] ? ' (' . $data['server']['os_version'] . ')' : ''; $rows = [['Contao Manager'], new TableSeparator(), ['Version', $data['app']['version']], ['Environment', $data['app']['env']], ['Debug', $data['app']['debug'] ? 'true' : 'false'], ['Cache directory', $data['app']['cache_dir']], ['Contao directory', $data['app']['project_dir']], ['Data directory', $data['app']['config_dir']], new TableSeparator(), ['PHP'], new TableSeparator(), ['Version', $data['php']['version']], ['Architecture', $data['php']['arch'] . ' bits'], ['Server API', $data['php']['sapi']], ['Intl locale', $data['php']['locale']], ['Timezone', $data['php']['timezone']], ['Binary Path', $data['php']['binary'] ?: '-- NOT FOUND --'], new TableSeparator(), ['Server'], new TableSeparator(), ['Operating System', $data['server']['os_name'] . $osVersion]]; if (!empty($data['server']['arch'])) { $rows[] = ['Architecture', $data['server']['arch']]; } $io->table([], $rows); } private function collectData() : array { $version = $this->getManagerVersion(); $data = ['app' => ['version' => $version, 'env' => $this->kernel->getEnvironment(), 'debug' => $this->kernel->isDebug(), 'cache_dir' => $this->kernel->getCacheDir(), 'log_dir' => $this->kernel->getLogDir(), 'project_dir' => $this->kernel->getProjectDir(), 'config_dir' => $this->kernel->getConfigDir()], 'php' => ['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'arch' => \PHP_INT_SIZE * 8, 'sapi' => \PHP_SAPI, 'locale' => \class_exists('Locale', \false) && \Locale::getDefault() ? \Locale::getDefault() : '', 'timezone' => \date_default_timezone_get(), 'binary' => $this->serverInfo->getPhpExecutable()], 'server' => ['os_name' => \php_uname('s'), 'os_version' => \php_uname('r'), 'arch' => \php_uname('m')]]; if ($data['server']['os_name'] === $data['server']['os_version']) { $data['server']['os_version'] = ''; $data['server']['arch'] = ''; } return $data; } private function getManagerVersion() : string { $version = ApiKernel::MANAGER_VERSION; if (ApiKernel::VERSION_KEY === $version) { $git = new Process(['git', 'describe', '--tags', '--always']); try { $git->mustRun(); $version = \trim($git->getOutput()); } catch (ProcessFailedException) { return 'n/a'; } } return $version; } } taskManager->hasTask()) { $output->writeln('No task is currently active.'); return Command::FAILURE; } $status = $this->taskManager->deleteTask(); if (null === $status || $status->isActive()) { $output->writeln('Task could not be deleted.'); return Command::FAILURE; } return Command::SUCCESS; } } requestStack->getCurrentRequest())) { $locale = $request->getLocale(); if (5 === \strlen($locale)) { \array_unshift($locales, \substr($locale, 0, 2)); } \array_unshift($locales, $locale); } return $this->replaceParameters($this->findLabel($id, $locales), $params); } /** * Searches for label by ID in the given locales. */ private function findLabel(string $id, array $locales) : string { foreach ($locales as $locale) { $this->load($locale); if (isset($this->labels[$locale][$id]) && ('' !== $this->labels[$locale][$id] || 'en' === $locale)) { return $this->labels[$locale][$id]; } } return $id; } /** * Replaces parameters in label. */ private function replaceParameters(string $label, array $params) : string { if ([] === $params) { return $label; } $replace = []; foreach ($params as $k => $v) { $replace['{' . $k . '}'] = $v; } return \strtr($label, $replace); } /** * Loads labels from file for given locale if it exists. */ private function load(string $locale) : void { if (isset($this->labels[$locale])) { return; } $file = __DIR__ . '/../Resources/i18n/' . $locale . '.yml'; if (!\is_file($file)) { return; } $data = Yaml::parse(\file_get_contents($file)); if (empty($data[$locale]) || !\is_array($data[$locale])) { return; } $this->store($locale, $data[$locale]); } /** * Adds new labels to the label store by flattening array keys. */ private function store(string $locale, array $data, string $prefix = '') : void { foreach ($data as $k => $v) { if (\is_array($v)) { $this->store($locale, $v, $prefix . $k . '.'); } else { $this->labels[$locale][$prefix . $k] = $v; } } } } problem->getStatus(), $this->problem->getTitle(), $previous, $headers, $code); } /** * Gets the API problem. */ public function getApiProblem() : ApiProblem { return $this->problem; } } getExitCode(), $previous); $this->process = $process; } /** * Gets the process object. */ public function getProcess() : Process { return $this->process; } } user; } public function setUser(UserInterface $user) : void { $this->user = $user; } } filename), $code, $previous); $this->jsonError = \json_last_error(); $this->jsonErrorMsg = \json_last_error_msg(); } /** * Gets name of the JSON file. */ public function getFilename() : string { return $this->filename; } /** * Gets the invalid file content. */ public function getContent() : string { return $this->content; } /** * Gets the json_last_error. */ public function getJsonError() : int { return $this->jsonError; } /** * Gets the json_last_error_msg. */ public function getJsonErrorMessage() : string { return $this->jsonErrorMsg; } } url); if (null !== $this->statusCode) { $message .= 'with status code ' . $this->statusCode; } if (null !== $previous) { $message .= ' (' . $previous->getMessage() . ')'; } parent::__construct($message, $previous?->getCode() ?? 0, $previous); } public function getUrl() : string { return $this->url; } public function getStatusCode() : int { return $this->statusCode; } } trans('allow_url_fopen.title'), 'https://php.net/allow_url_fopen'); } } hasGraphicsLib()) { return null; } return (new ApiProblem($this->trans('graphics_lib.title'), 'https://php.net/gd'))->setDetail($this->trans('graphics_lib.detail')); } private function hasGraphicsLib() : bool { if (\function_exists('gd_info') && \version_compare(\constant('GD_VERSION'), '2.0.1', '>')) { return \true; } if (\class_exists('Imagick')) { return \true; } if (\class_exists('Gmagick')) { return \true; } return \false; } } find('unzip') || $finder->find('7z', null, ['C:\\Program Files\\7-Zip']) || !Platform::isWindows() && $finder->find('7zz')) { return null; } return new ApiProblem($this->trans('zip.title'), 'https://getcomposer.org/doc/articles/troubleshooting.md#zip-archives-are-not-unpacked-correctly-'); } } canWriteFileInDirectory($tempdir) || !$this->canWriteFileInDirectory($subdir, \true)) { return (new ApiProblem($this->trans('systempdir.title'), 'https://php.net/open_basedir'))->setDetail($this->trans('systempdir.detail')); } return null; } private function canWriteFileInDirectory(string $path, bool $createDirectory = \false) : bool { if ($createDirectory) { @\rmdir($path); @\mkdir($path); } $file = $path . '/' . \md5(__FILE__); $result = \touch($file) && \is_writable($file); @\unlink($file); if ($createDirectory) { @\rmdir($path); } return $result; } } trans('process.title'), 'https://php.net/proc_open'))->setDetail($this->trans('process.detail')); } } canCreateSymlinks())) { return null; } return (new ApiProblem($this->trans('symlink.title'), 'https://php.net/symlink'))->setDetail($error); } private function canCreateSymlinks() : string|null { if (!\function_exists('symlink')) { return ''; } try { $filesystem = new Filesystem(); $tempname = \tempnam(\sys_get_temp_dir(), ''); $filesystem->remove($tempname); $filesystem->symlink($this->kernel->getProjectDir(), $tempname); $filesystem->remove($tempname); } catch (\Exception $exception) { return $exception->getMessage(); } return null; } } '1', 'use_cookies' => '0']; if (\session_start($options)) { return null; } } catch (\Exception $exception) { $detail = $exception->getMessage(); } return (new ApiProblem($this->trans('session.title'), 'https://php.net/session_start'))->setDetail($detail); } } hasEnoughMemory()) { return null; } return (new ApiProblem($this->trans('memory_limit.title'), 'https://php.net/memory_limit'))->setDetail($this->trans('memory_limit.detail', ['limit' => \trim(\ini_get('memory_limit'))])); } private function hasEnoughMemory() : bool { $memoryLimit = \trim((string) \ini_get('memory_limit')); if ('-1' === $memoryLimit) { return \true; } /** @noinspection SubStrUsedAsArrayAccessInspection */ $unit = \strtolower(\substr($memoryLimit, -1, 1)); $memoryLimit = (int) $memoryLimit; switch ($unit) { case 'g': $memoryLimit *= 1024; // no break case 'm': $memoryLimit *= 1024; // no break (cumulative multiplier) case 'k': $memoryLimit *= 1024; } return $memoryLimit >= 1024 * 1024 * 256; } } checkExtension($extension))) { return $problem; } } return null; } private function checkExtension(string $extension) : ApiProblem|null { if (\extension_loaded($extension)) { return null; } return (new ApiProblem($this->trans($extension . '.title'), 'https://php.net/' . $extension))->setDetail($this->trans($extension . '.detail')); } } translator->trans('integrity.' . $id, $params); } } runChecks(self::$webChecks); } public function runCliCheck() : ApiProblem|null { return $this->runChecks(self::$cliChecks); } public static function getSubscribedServices() : array { return \array_unique(\array_merge(self::$cliChecks, self::$webChecks)); } private function runChecks(array $classes) : ApiProblem|null { foreach ($classes as $class) { /** @var IntegrityCheckInterface $check */ $check = $this->container->get($class); if (($problem = $check->run()) instanceof ApiProblem) { return $problem; } } return null; } } getApiInfo()['version']; } /** * Returns list of available API commands. */ public function getCommands() : array { return $this->getApiInfo()['commands']; } /** * Returns whether the given API command is available. */ public function hasCommand(string $name) : bool { return \in_array($name, $this->getApiInfo()['commands'], \true); } /** * Returns list of available API features. */ public function getFeatures() : array { return $this->getApiInfo()['features']; } public function runCommand(array|string $arguments) : string { $process = $this->processFactory->createContaoApiProcess((array) $arguments); $process->mustRun(); return $process->getOutput(); } /** * @throws ParsingException * @throws ProcessFailedException */ public function runJsonCommand(array|string $arguments) : array|null { $process = $this->processFactory->createContaoApiProcess((array) $arguments); $process->mustRun(); return $this->parseJson($process->getOutput()); } /** * Checks whether the Contao API binary exists. */ private function hasBinary() : bool { return $this->filesystem->exists($this->processFactory->getContaoApiPath()); } /** * Returns version, commands and features of the Contao API. */ private function getApiInfo() : array { if (null !== $this->apiInfo) { return $this->apiInfo; } $default = ['version' => 0, 'commands' => [], 'features' => []]; if (!$this->hasBinary()) { return $this->apiInfo = $default; } try { $process = $this->processFactory->createContaoApiProcess(['version']); $process->mustRun(); } catch (ExceptionInterface) { return $default; } $version = \trim($process->getOutput()); if (\preg_match('/^\\d+$/', $version)) { $default['version'] = (int) $version; return $this->apiInfo = $default; } try { return $this->apiInfo = $this->parseJson($version); } catch (ParsingException $exception) { $default['error'] = $exception->getMessage(); return $this->apiInfo = $default; } } /** * @throws ParsingException */ private function parseJson(string $output) : array|null { $data = \json_decode($output, \true); if (null === $data && \JSON_ERROR_NONE !== \json_last_error()) { $parser = new JsonParser(); $result = $parser->lint($output); if (null !== $result) { throw $result; } } return $data; } } */ private array $forkers = []; /** * @throws \InvalidArgumentException If the working directory does not exist */ public function __construct(array $config, string $workDir) { if (!isset($config['status'])) { $config['status'] = Process::STATUS_READY; } $this->config = $config; parent::__construct($this->config['id'], $workDir); } public function addForker(ForkerInterface $forker) : void { $this->forkers[] = $forker; } /** * Gets the task ID. */ public function getId() : string { return (string) $this->config['id']; } /** * Stores meta information about the process. */ public function setMeta(array $meta) : void { $this->config['meta'] = $meta; $this->saveConfig(\true); } /** * Gets meta information of the process. */ public function getMeta() : array|null { return $this->config['meta'] ?? null; } public function start() : void { if (Process::STATUS_STARTED === $this->config['status']) { return; } $forker = $this->getForker(); $this->saveConfig(\true); $this->config['status'] = Process::STATUS_STARTED; $forker->run($this->setFile); } public function getPid() : int|null { $this->updateStatus(); return isset($this->config['pid']) ? (int) $this->config['pid'] : null; } public function getExitCode() : int|null { $this->updateStatus(); return isset($this->config['exitcode']) ? (int) $this->config['exitcode'] : null; } public function getExitCodeText() : string { if (null === ($exitcode = $this->getExitCode())) { return ''; } return Process::$exitCodes[$exitcode] ?? 'Unknown error'; } public function isSuccessful() : bool { return 0 === $this->getExitCode(); } public function hasBeenSignaled() : bool { return isset($this->config['signaled']) && $this->config['signaled']; } public function getTermSignal() : int|null { return isset($this->config['termsig']) ? (int) $this->config['termsig'] : null; } public function hasBeenStopped() : bool { return isset($this->config['stopped']) && $this->config['stopped']; } public function getStopSignal() : int|null { return isset($this->config['stopsig']) ? (int) $this->config['stopsig'] : null; } public function isRunning() : bool { return Process::STATUS_STARTED === $this->getStatus(); } public function isStarted() : bool { return Process::STATUS_READY !== $this->getStatus(); } public function isTerminated() : bool { return Process::STATUS_TERMINATED === $this->getStatus(); } public function isTimedOut() : bool { return Process::STATUS_TERMINATED === $this->getStatus() && $this->config['timedout'] > 0; } public function getStatus() : string { $this->updateStatus(); return $this->config['status']; } public function stop() : void { $this->config['stop'] = \true; $this->saveConfig(); } public function delete() : void { if ($this->isRunning()) { throw new \LogicException('Cannot delete a running process.'); } $this->close(); } public function getCommandLine() : string { if (!\is_array($this->config['commandline'])) { return (string) $this->config['commandline']; } return \implode(' ', $this->config['commandline']); } public function setCommandLine(array $commandline) : void { $this->config['commandline'] = $commandline; $this->saveConfig(); } public function setWorkingDirectory(string $cwd) : void { $this->config['cwd'] = $cwd; $this->saveConfig(); } public function getOutput() : string { if (!\is_file($this->outputFile)) { return ''; } return \file_get_contents($this->outputFile); } public function setTimeout(int $timeout) : void { $this->config['timeout'] = $timeout; $this->saveConfig(); } public function setIdleTimeout(int $timeout) : void { $this->config['idleTimeout'] = $timeout; $this->saveConfig(); } public function getForker() : ForkerInterface { $class = $this->config['forker'] ?? null; foreach ($this->forkers as $forker) { if (null === $class ? $forker->isSupported() : $forker instanceof $class) { $this->config['forker'] = $forker::class; return $forker; } } throw new \RuntimeException('No forker found for your current platform.'); } public static function create(string $workDir, array $commandline, string|null $cwd = null, string|null $id = null) : self { return new self(['id' => $id ?: \md5(\uniqid('', \true)), 'commandline' => $commandline, 'cwd' => $cwd ?: \getcwd()], $workDir); } public static function restore(string $workDir, string $id) : self { $config = static::readConfig($workDir . '/' . $id . '.set.json'); if (\is_file($getFile = $workDir . '/' . $id . '.get.json')) { $config = \array_merge($config, static::readConfig($getFile)); } return new self($config, $workDir); } private function saveConfig(bool $always = \false) : void { if ($always || Process::STATUS_STARTED === $this->config['status']) { static::writeConfig($this->setFile, $this->config); } } private function updateStatus() : void { if (Process::STATUS_STARTED !== $this->config['status']) { return; } if (\is_file($this->getFile)) { $this->config = \array_merge($this->config, static::readConfig($this->getFile)); } } private function close() : void { $fs = new Filesystem(); $fs->remove($this->setFile); $fs->remove($this->getFile); $fs->remove($this->inputFile); $fs->remove($this->outputFile); } } command = $command; return $this; } public function getCommand() : array { return $this->command; } public function setTimeout(int $timeout) : ForkerInterface { $this->timeout = $timeout; return $this; } public function getTimeout() : int { return $this->timeout; } protected function startCommand(string $commandline) : Process { if (null !== $this->logger) { $this->logger->info('Starting "{commandline}" with {forker_class}', ['commandline' => $commandline, 'forker_class' => static::class]); } $process = Process::fromShellCommandline($commandline); $process->setTimeout(null); $process->setIdleTimeout(null); $process->start(null, $this->env ?: []); \usleep($this->timeout); if (null !== $this->logger && !$process->isStarted()) { $this->logger->error('Process did not start correctly', ['commandline' => $commandline, 'forker_class' => static::class, 'exit_code' => $process->getExitCode(), 'exit_text' => $process->getExitCodeText(), 'stopped' => $process->hasBeenStopped(), 'signaled' => $process->hasBeenSignaled(), 'stopsignal' => $process->getStopSignal(), 'termsignal' => $process->getTermSignal()]); } return $process; } /** * Escapes a string to be used as a shell argument. * * @see Process::escapeArgument() */ protected function escapeArgument(string|null $argument) : string { if ('' === $argument || null === $argument) { return '""'; } if ('\\' !== \DIRECTORY_SEPARATOR) { return "'" . \str_replace("'", "'\\''", $argument) . "'"; } if (\str_contains($argument, "\x00")) { $argument = \str_replace("\x00", '?', $argument); } if (!\preg_match('/[\\/()%!^"<>&|\\s]/', $argument)) { return $argument; } $argument = \preg_replace('/(\\\\+)$/', '$1$1', $argument); return '"' . \str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument) . '"'; } } /dev/null 2>&1 command)), $this->escapeArgument($configFile)); $this->startCommand($commandline); } public function isSupported() : bool { try { Process::fromShellCommandline("exec echo '' & disown")->mustRun(null, $this->env); } catch (ProcessFailedException) { return \false; } return \true; } } /dev/null &1 &', \implode(' ', \array_map([$this, 'escapeArgument'], $this->command)), $this->escapeArgument($configFile)); $this->startCommand($commandline); } public function isSupported() : bool { try { Process::fromShellCommandline('exec nohup ls')->mustRun(null, $this->env); } catch (ProcessFailedException) { return \false; } return \true; } } &1 >nul command)), $this->escapeArgument($configFile)); $this->startCommand($commandline); } public function isSupported() : bool { if ('\\' !== \DIRECTORY_SEPARATOR) { return \false; } try { Process::fromShellCommandline('start /b dir')->mustRun(null, $this->env); } catch (ProcessFailedException) { return \false; } return \true; } } command; $binary = \array_shift($arguments); $commandline = \sprintf('%s %s %s', \escapeshellcmd($binary), \implode(' ', \array_map([$this, 'escapeArgument'], $arguments)), $this->escapeArgument($configFile)); $process = $this->startCommand($commandline); $process->wait(); } public function isSupported() : bool { return \true; } } normalizeOutput(parent::getOutput()); } public function getErrorOutput() : string { return $this->normalizeOutput(parent::getErrorOutput()); } /** * Normalize encoding and try to fix PHP error level issues. */ private function normalizeOutput(string $output) : string { $output = $this->convertEncoding($output); return \implode("\n", \array_filter(\preg_split('/\\r\\n|\\r|\\n/', $output), static fn(string $line): bool => !\str_starts_with($line, 'PHP Warning:') && !\str_starts_with($line, 'Warning:') && !\str_starts_with($line, 'Deprecated:') && !\str_starts_with($line, 'Runtime Notice:') && !\str_starts_with($line, 'Failed loading '))); } private function convertEncoding(string $data) : string { if (\false !== @\json_encode($data)) { return $data; } if (\function_exists('mb_convert_encoding')) { $encoding = null; if (\function_exists('mb_detect_encoding')) { $encoding = \mb_detect_encoding($data, \mb_detect_order(), \true) ?: null; } return \mb_convert_encoding($data, 'UTF-8', $encoding); } if (\function_exists('utf8_encode')) { return \utf8_encode($data); } return $data; } } process = new Utf8Process($commandline, $cwd); $this->loadConfig($config); } public function __destruct() { $this->stop(0); } public function run(int $interval = 1) : int { $this->start(); return $this->wait($interval); } public function start() : void { if ($this->process->isStarted()) { return; } $handler = function ($signo = 15) { $this->signalHandler($signo); return null; }; \register_shutdown_function($handler); if (\function_exists('pcntl_signal')) { \pcntl_signal(\SIGHUP, $handler); \pcntl_signal(\SIGINT, $handler); \pcntl_signal(\SIGQUIT, $handler); \pcntl_signal(\SIGTERM, $handler); } if (\is_file($this->inputFile)) { $this->stdin = \fopen($this->inputFile, 'r'); $this->process->setInput($this->stdin); } $this->process->start(function ($type, $data) : void { $this->addOutput($data); }); $this->saveConfig(); } public function wait(int $interval) : int { do { \usleep($interval * 1000000); try { $this->process->checkTimeout(); $running = $this->process->isRunning(); } catch (ProcessTimedOutException $e) { $this->timeout = $e; $running = \false; } $config = $this->loadConfig(); if ($running && isset($config['stop']) && $config['stop']) { return $this->stop(); } $this->saveConfig(); } while ($running); $this->close(); return $this->process->getExitCode(); } public function stop(int $timeout = 10) : int { if (!$this->process->isRunning()) { return $this->process->getExitCode(); } $exitCode = $this->process->stop($timeout); $this->saveConfig(); $this->close(); return $exitCode; } public function addOutput(string $line) : void { if (!\is_resource($this->stdout)) { $this->stdout = \fopen($this->outputFile, 'w'); } \fwrite($this->stdout, $line); } private function close() : void { if (\is_resource($this->stdin)) { \fclose($this->stdin); } if (\is_resource($this->stdout)) { \fclose($this->stdout); } } private function signalHandler(int $signo) : void { $this->stop(15 === $signo ? 0 : 10); } private function loadConfig(array|null $config = null) : array { if (null === $config) { $config = static::readConfig($this->setFile); } $props = ['timeout' => 'setTimeout', 'idleTimeout' => 'setIdleTimeout']; foreach ($props as $key => $setter) { if (isset($config[$key])) { $this->process->{$setter}($config[$key]); } } return $config; } private function saveConfig() : void { $status = $this->process->getStatus(); $config = ['cwd' => $this->process->getWorkingDirectory(), 'timeout' => $this->process->getTimeout(), 'idleTimeout' => $this->process->getIdleTimeout(), 'pid' => $this->process->getPid(), 'status' => $status]; if (Process::STATUS_TERMINATED === $status) { $config['exitcode'] = $this->process->getExitCode(); $config['signaled'] = $this->process->hasBeenSignaled(); $config['termsig'] = $this->process->getTermSignal(); $config['stopped'] = $this->process->hasBeenStopped(); $config['stopsig'] = $this->process->getStopSignal(); $config['timedout'] = $this->timeoutCode(); } static::writeConfig($this->getFile, $config); } /** * Returns the timeout type. */ private function timeoutCode() : int { if ($this->timeout instanceof ProcessTimedOutException) { if ($this->timeout->isGeneralTimeout()) { return ProcessTimedOutException::TYPE_GENERAL; } if ($this->timeout->isIdleTimeout()) { return ProcessTimedOutException::TYPE_IDLE; } } return 0; } } setFile = $dir . '/' . $id . '.set.json'; $this->getFile = $dir . '/' . $id . '.get.json'; $this->inputFile = $dir . '/' . $id . '.in.log'; $this->outputFile = $dir . '/' . $id . '.out.log'; } /** * @throws InvalidJsonException */ protected static function readConfig(string $filename) : array { // Make sure new process files are found (see // https://github.com/contao/contao-manager/issues/438) \clearstatcache(); $content = @\file_get_contents($filename); if (\false === $content) { throw new \InvalidArgumentException(\sprintf('Config file "%s" is not readable or does not exist.', $filename)); } $config = \json_decode($content, \true); if (!\is_array($config)) { throw new InvalidJsonException($filename, $content); } return $config; } /** * @throws \RuntimeException */ protected static function writeConfig(string $filename, array $config) : void { try { (new Filesystem())->dumpFile($filename, \json_encode($config)); } catch (IOException $ioException) { throw new \RuntimeException(\sprintf('Unable to write config file to %s. ' . $ioException->getMessage(), $filename), 0, $ioException); } } } version) { return $this->version; } $this->getCommandList(\true); // @phpstan-ignore notIdentical.alwaysFalse if (null !== $this->version) { return $this->version; } $process = $this->processFactory->createContaoConsoleProcess(['contao:version']); $process->run(); $version = \trim($process->getOutput()); try { // Run parser to check whether a valid version was returned $parser = new VersionParser(); $parser->normalize($version); } catch (\UnexpectedValueException) { throw new ProcessOutputException('Console output is not a valid version string.', $process); } return $this->version = $version; } public function getCommandList(bool $throw = \false) : array { if (null !== $this->commands) { return $this->commands; } $process = $this->processFactory->createContaoConsoleProcess(['list', '--format=json']); $process->run(); // If the console does not work, we don't have any command support. if (!$process->isSuccessful() || !\is_array($data = \json_decode(\trim($process->getOutput()), \true))) { if ($throw) { throw new ProcessOutputException('Unable to retrieve console commands.', $process); } return $this->commands = []; } if ('Contao Managed Edition' === ($data['application']['name'] ?? '') && isset($data['application']['version'])) { try { // Run parser to check whether a valid version was returned $parser = new VersionParser(); $parser->normalize($data['application']['version']); $this->version = $data['application']['version']; } catch (\UnexpectedValueException) { // ignore version from command list } } return $this->commands = $this->normalizeCommands($data['commands'] ?? []); } public function getConfig() : array|null { if (null !== $this->config) { return $this->config; } $commands = $this->getCommandList(); if (!isset($commands['debug:config']['options']) || !\in_array('format', $commands['debug:config']['options'], \true)) { return $this->config = []; } $process = $this->processFactory->createContaoConsoleProcess(['debug:config', 'contao', '--format=json', '--resolve-env']); $process->run(); // If the console does not work, we don't have any command support. if (!$process->isSuccessful() || !\is_array($data = \json_decode(\trim($process->getOutput()), \true))) { return $this->config = []; } return $this->config = $data['contao'] ?? []; } public function checkDatabaseMigrations() : array|null { $commands = $this->getCommandList(); if (!isset($commands['contao:migrate']['options']) || !\in_array('format', $commands['contao:migrate']['options'], \true) || !\in_array('dry-run', $commands['contao:migrate']['options'], \true)) { return null; } $arguments = ['contao:migrate', '--format=ndjson', '--dry-run', '--no-interaction']; if (\in_array('no-backup', $commands['contao:migrate']['options'], \true)) { $arguments[] = '--no-backup'; } $process = $this->processFactory->createContaoConsoleProcess($arguments); $process->run(); $output = \trim($process->getOutput()); // Process could exit with error but still output JSON if (!$process->isSuccessful() && !\str_starts_with($output, '{')) { return ['type' => 'error', 'total' => 1, 'message' => $process->getOutput() . $process->getErrorOutput(), 'warnings' => 0]; } $warnings = 0; if ('' !== $output) { $lines = \explode("\n", $output); while ($line = \array_shift($lines)) { $data = \json_decode($line, \true); $type = $data['type'] ?? null; if ('warning' === $type) { ++$warnings; continue; } if ('error' === $type || 'problem' === $type) { return ['type' => $type, 'total' => 1, 'message' => $data['message'] ?? '', 'warnings' => $warnings]; } if ('migration-pending' === $type && !empty($data['names'])) { return ['type' => 'migration', 'total' => \count($data['names']), 'warnings' => $warnings]; } if ('schema-pending' === $type && !empty($data['commands'])) { return ['type' => 'schema', 'total' => \count($data['commands']), 'warnings' => $warnings]; } } } return ['type' => 'empty', 'total' => 0, 'warnings' => $warnings]; } public function getUsers(bool $throw = \false) : array|null { $commands = $this->getCommandList(); if (!isset($commands['contao:user:list']['options']) || !\in_array('format', $commands['contao:user:list']['options'], \true) || !\in_array('column', $commands['contao:user:list']['options'], \true)) { return null; } $arguments = ['contao:user:list', '--format=json', '--column=username', '--column=name', '--column=admin', '--column=dateAdded', '--column=lastLogin', '--no-interaction']; $process = $this->processFactory->createContaoConsoleProcess($arguments); $process->run(); if (!$process->isSuccessful()) { if ($throw) { throw new ProcessFailedException($process); } return null; } $data = \json_decode($process->getOutput(), \true); if (!\is_array($data)) { if ($throw) { throw new ProcessOutputException('Unable to list Contao users', $process); } return null; } return $data; } /** * @throws \RuntimeException * @throws ProcessFailedException */ public function createBackendUser(array $user, string $password, bool $admin = \true) : void { $commands = $this->getCommandList(); if (!isset($commands['contao:user:create']['options']) || $admin && !\in_array('admin', $commands['contao:user:create']['options'], \true) || [] !== \array_diff(\array_keys($user), $commands['contao:user:create']['options'])) { throw new \RuntimeException('Unsupported argument to the contao:user:create command.'); } $arguments = ['contao:user:create']; foreach ($user as $k => $v) { $arguments[] = '--' . $k . '=' . $v; } if ($admin) { $arguments[] = '--admin'; } if (Platform::isWindows()) { $arguments[] = '--password=' . $password; } $process = $this->processFactory->createContaoConsoleProcess($arguments); if (!Platform::isWindows()) { $process->setInput($password . \PHP_EOL . $password . \PHP_EOL); // Password and confirmation } $process->mustRun(); } private function normalizeCommands(array $commands) : array { $data = []; foreach ($commands as $command) { $data[$command['name']] = ['arguments' => \array_keys($command['definition']['arguments'] ?? []), 'options' => \array_keys($command['definition']['options'] ?? [])]; } return $data; } } findBestBinary($paths); } if ($bin = \constant('PHP_BINARY')) { if (\false !== ($suffix = \strrchr(\basename($bin), '-'))) { $php = \substr($bin, 0, -\strlen($suffix)); $paths[] = $php . '-cli'; $paths[] = $php; } $paths[] = $bin . '-cli'; $paths[] = $bin; $this->includePath($paths, \dirname($bin)); } if (\defined('PHP_BINDIR') && '' !== \PHP_BINDIR) { $this->includePath($paths, \PHP_BINDIR); } if ($php = \getenv('PHP_PATH')) { $paths[] = $php; } if ($php = \getenv('PHP_PEAR_PHP_BIN')) { $paths[] = $php; } $paths[] = '/usr/bin/php'; $paths = \array_merge($paths, $this->findExecutables()); $paths = \array_unique($paths); \ksort($paths); return $this->findBestBinary($paths); } public function getServerInfo(string $cli) : array|null { $phar = \Phar::running(\false); $arguments = [$cli, '-q']; $arguments[] = $phar ?: \dirname(__DIR__) . '/console'; $arguments[] = 'test'; try { $process = new Process($arguments); $process->mustRun(null, \array_map(static fn(): bool => \false, $_ENV)); $output = @\json_decode(\trim($process->getOutput()), \true); if (null === $output) { throw new RuntimeException('Unexpected output from "' . \implode(' ', $arguments) . '": ' . $process->getOutput()); } return $output; } catch (RuntimeException $exception) { // Do not log every attempt to find a PHP binary (exit code 127 = Command not found) if (127 === $process->getExitCode()) { return null; } $this->logger->error($exception->getMessage(), ['exception' => $exception]); throw $exception; } } /** * Finds PHP executables within open_basedir or PATH environment variable. */ private function findExecutables() : array { $results = []; if (\ini_get('open_basedir')) { $searchPath = \explode(\PATH_SEPARATOR, \ini_get('open_basedir')); $dirs = []; foreach ($searchPath as $path) { // Silencing against https://bugs.php.net/69240 if (@\is_dir($path)) { $dirs[] = $path; } elseif (@\is_executable($path) && \in_array(\basename($path), $this->names, \true)) { $results[] = $path; } } } else { $dirs = []; if ($path = \getenv('PATH') ?: \getenv('Path')) { $dirs = \explode(\PATH_SEPARATOR, $path); } if ('\\' === \DIRECTORY_SEPARATOR) { $dirs[] = 'C:\\xampp\\php\\'; } } $suffixes = ['']; if ('\\' === \DIRECTORY_SEPARATOR) { $pathExt = \getenv('PATHEXT'); $suffixes = \array_merge($suffixes, $pathExt ? \explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']); } foreach ($this->names as $name) { foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { if (@\is_file($file = $dir . \DIRECTORY_SEPARATOR . $name . $suffix) && ('\\' === \DIRECTORY_SEPARATOR || \is_executable($file))) { $results[] = $file; } } } } return $results; } private function findBestBinary(array $paths) : string|null { $fallbackPath = null; $fallbackSapi = null; if ($openBasedir = \ini_get('open_basedir')) { $openBasedir = \explode(\PATH_SEPARATOR, $openBasedir); } foreach ($paths as $path) { // we only test for is_executable if no open_basedir restrictions are set or the // target is within allowed paths. If the path is not within open_basedir we can // still execute the binary on the command line and check the version. if ((!$openBasedir || $this->isAllowed($path, $openBasedir)) && !\is_executable($path)) { continue; } try { $info = $this->getServerInfo($path); } catch (RuntimeException) { continue; } if (!\is_array($info)) { continue; } if ('cli' === $info['sapi'] && \version_compare(\PHP_VERSION, $info['version'], 'eq')) { return $path; } $vWeb = \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION; $vCli = \vsprintf('%s.%s', \explode('.', (string) $info['version'])); // Ignore binary if minor version does not match if (!\version_compare($vWeb, $vCli, 'eq')) { continue; } // Allow fallback to another patch version of the same PHP major/minor and prefer // a CLI SAPI over e.g. a CGI SAPI. if (null === $fallbackPath || 'cli' !== $fallbackSapi && 'cli' === $info['sapi']) { $fallbackPath = $path; $fallbackSapi = $info['sapi']; } } return $fallbackPath; } /** * Tests if the given path is within any of the given directories. */ private function isAllowed(string $path, array $dirs) : bool { foreach ($dirs as $dir) { if (\str_starts_with($path, (string) $dir)) { return \true; } } return \false; } /** * Adds the all binaries for given path to paths array. */ private function includePath(array &$paths, string $path) : void { foreach ($this->names as $name) { $paths[] = $path . \DIRECTORY_SEPARATOR . $name; } } } 'tasks'])] class ConsoleProcessFactory implements LoggerAwareInterface { use LoggerAwareTrait; public function __construct(private readonly ApiKernel $kernel, private readonly ServerInfo $serverInfo, private readonly Filesystem $filesystem) { } /** * Gets the path to manager console or Phar file. */ public function getManagerConsolePath() : string { if ('' !== ($phar = \Phar::running(\false))) { return $phar; } return $this->kernel->getRootDir() . '/console'; } /** * Gets the path to the Contao console. */ public function getContaoConsolePath() : string { $contaoPath = $this->kernel->getProjectDir() . '/vendor/contao/contao/manager-bundle/bin/contao-console'; if ($this->kernel->isDebug() && $this->filesystem->exists($contaoPath)) { return $contaoPath; } return $this->kernel->getProjectDir() . '/vendor/contao/manager-bundle/bin/contao-console'; } /** * Gets the path to the Contao API. */ public function getContaoApiPath() : string { $contaoPath = $this->kernel->getProjectDir() . '/vendor/contao/contao/manager-bundle/bin/contao-api'; if ($this->kernel->isDebug() && $this->filesystem->exists($contaoPath)) { return $contaoPath; } return $this->kernel->getProjectDir() . '/vendor/contao/manager-bundle/bin/contao-api'; } /** * Creates a foreground process for the Manager console. */ public function createManagerConsoleProcess(array $arguments) : Process { \array_unshift($arguments, $this->getManagerConsolePath()); return $this->createForegroundProcess($arguments); } /** * Creates a background process for the Manager console. */ public function createManagerConsoleBackgroundProcess(array $arguments, string|null $id = null) : ProcessController { \array_unshift($arguments, $this->getManagerConsolePath()); return $this->createBackgroundProcess($arguments, $id); } /** * Creates a foreground process for the Contao console. */ public function createContaoConsoleProcess(array $arguments) : Process { \array_unshift($arguments, $this->getContaoConsolePath()); return $this->createForegroundProcess($arguments); } /** * Creates a background process for the Contao console. */ public function createContaoConsoleBackgroundProcess(array $arguments, string|null $id = null) : ProcessController { \array_unshift($arguments, $this->getContaoConsolePath()); return $this->createBackgroundProcess($arguments, $id); } /** * Creates a foreground process for the Contao API. */ public function createContaoApiProcess(array $arguments) : Process { \array_unshift($arguments, $this->getContaoApiPath()); return $this->createForegroundProcess($arguments); } /** * Restores the ProcessController for given task ID. * * @throws ApiProblemException */ public function restoreBackgroundProcess(string $id) : ProcessController { try { $process = ProcessController::restore($this->kernel->getConfigDir(), $id); } catch (InvalidJsonException $exception) { $problem = (new ApiProblem($exception->getMessage()))->setDetail($exception->getJsonErrorMessage() . "\n\n" . $exception->getContent()); throw new ApiProblemException($problem, $exception); } $this->addForkers($process); return $process; } /** * Creates a foreground process. */ private function createForegroundProcess(array $arguments) : Process { return (new Utf8Process($this->addPhpRuntime($arguments), $this->kernel->getProjectDir(), $this->serverInfo->getPhpEnv()))->setTimeout(0); } /** * Creates a background process controller. */ private function createBackgroundProcess(array $arguments, string|null $id = null) : ProcessController { $process = ProcessController::create($this->kernel->getConfigDir(), $this->addPhpRuntime($arguments), $this->kernel->getProjectDir(), $id); $process->setTimeout(0); $this->addForkers($process); return $process; } /** * Adds forker instances to the process controller. */ private function addForkers(ProcessController $process) : void { $backgroundCommand = $this->addPhpRuntime([$this->getManagerConsolePath(), '--no-interaction', 'run']); foreach ($this->serverInfo->getProcessForkers() as $class) { /** @var ForkerInterface $forker */ $forker = new $class($backgroundCommand, $this->serverInfo->getPhpEnv(), $this->logger); $forker->setTimeout(5000); $process->addForker($forker); } } /** * Adds PHP runtime to console arguments. */ private function addPhpRuntime(array $arguments) : array { if (null === ($phpCli = $this->serverInfo->getPhpExecutable())) { return $arguments; } $defaultArgs = [$phpCli, '-q']; if ($this->filesystem->exists($this->kernel->getConfigDir() . '/php.ini')) { $defaultArgs[] = '-c'; $defaultArgs[] = $this->kernel->getConfigDir() . '/php.ini'; } $defaultArgs[] = '-dmax_execution_time=0'; $defaultArgs[] = '-dmemory_limit=-1'; $defaultArgs[] = '-ddisplay_errors=0'; $defaultArgs[] = '-ddisplay_startup_errors=0'; $defaultArgs[] = '-derror_reporting=0'; $defaultArgs[] = '-dallow_url_fopen=1'; $defaultArgs[] = '-ddisable_functions='; $defaultArgs[] = '-ddate.timezone=' . @\date_default_timezone_get(); return \array_merge($defaultArgs, $arguments); } } check(); unset($xdebug); if (\function_exists('ini_set')) { @\ini_set('display_errors', 1); @\ini_set('zlib.output_compression', 0); // Set user defined memory limit if ($memoryLimit = \getenv('COMPOSER_MEMORY_LIMIT')) { @\ini_set('memory_limit', $memoryLimit); } else { $memoryInBytes = static function ($value) { $unit = \strtolower(\substr($value, -1, 1)); $value = (int) $value; switch ($unit) { /** @noinspection PhpMissingBreakStatementInspection */ case 'g': $value *= 1024; // no break (cumulative multiplier) /** @noinspection PhpMissingBreakStatementInspection */ case 'm': $value *= 1024; // no break (cumulative multiplier) case 'k': $value *= 1024; } return $value; }; $memoryLimit = \trim(\ini_get('memory_limit')); // Increase memory_limit if it is lower than 1.5GB if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) { @\ini_set('memory_limit', '1536M'); } unset($memoryInBytes); } unset($memoryLimit); } // Workaround PHP bug on Windows where env vars containing Unicode chars are mangled in $_SERVER // see https://github.com/php/php-src/issues/7896 if (\PHP_VERSION_ID >= 70113 && (\PHP_VERSION_ID < 80016 || \PHP_VERSION_ID >= 80100 && \PHP_VERSION_ID < 80103) && Platform::isWindows()) { foreach ($_SERVER as $serverVar => $serverVal) { if (($serverVal = \getenv($serverVar)) !== \false) { $_SERVER[$serverVar] = $serverVal; } } } Platform::putEnv('COMPOSER_BINARY', \realpath($_SERVER['argv'][0])); // Always create kernel to initialize the application $kernel = new ApiKernel('prod' === 'prod' ? 'prod' : 'dev'); $input = new ArgvInput(); switch ($input->getFirstArgument()) { // This "test" command is only for the dev version, if the Phar is compiled this is done in the stub.php case 'test': die(\json_encode(['version' => \PHP_VERSION, 'version_id' => \PHP_VERSION_ID, 'sapi' => \PHP_SAPI])); case 'composer': $application = new ComposerApplication(); $argv = $_SERVER['argv']; \array_shift($argv); $input = new ArgvInput($argv); break; default: $application = new ApiApplication($kernel); } $application->run($input); getRequest(); if ($locale = $request->getPreferredLanguage()) { $request->setLocale($locale); } } } getRequest()->getAcceptableContentTypes(), \true)) { return; } Response::closeOutputBuffers(0, \false); $exception = $this->convertException($event->getThrowable()); $this->logException($exception); $response = ApiProblemResponse::createFromException($exception, $this->debug); $event->setResponse($response); } /** * Logs the exception if a logger is available. */ private function logException(\Throwable $exception) : void { $message = \sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $exception::class, $exception->getMessage(), $exception->getFile(), $exception->getLine()); if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { $this->logger->critical($message, ['exception' => $exception]); } else { $this->logger->error($message, ['exception' => $exception]); } } /** * Tries to convert known exceptions to a HttpException. */ private function convertException(\Throwable $exception) : \Throwable { return match (\true) { $exception instanceof AccessDeniedException, $exception instanceof AuthenticationException => new AccessDeniedHttpException($exception->getMessage(), $exception), default => $exception, }; } } isMainRequest() || $this->jwtManager->hasResponseToken($event->getResponse())) { return; } $token = $this->tokenStorage->getToken(); if (null !== $token && $token->hasAttribute('authenticator') && JwtAuthenticator::class === $token->getAttribute('authenticator') && $this->authorizationChecker->isGranted('ROLE_USER')) { $this->jwtManager->addToken($event->getRequest(), $event->getResponse(), $token); } else { $this->jwtManager->removeToken($event->getRequest(), $event->getResponse()); } } } getPassport(); if (!$passport->hasBadge(TotpBadge::class)) { return; } /** @var TotpBadge $badge */ $badge = $passport->getBadge(TotpBadge::class); $user = $passport->getUser(); if ($badge->isResolved() || !$user instanceof User) { return; } $badge->verify($user); } } getRequest(); $content = $request->getContent(); if ('' === $content && $request->attributes->get('form-data')) { return; } $data = []; if ('' !== $content) { if ('json' !== $request->getContentTypeFormat()) { throw new UnsupportedMediaTypeHttpException('Only JSON requests are supported.'); } $data = \json_decode($content, \true); if (!\is_array($data)) { throw new BadRequestHttpException('Invalid JSON data received.'); } } $request->request->replace($data); } } setTimeout(function() { window.location.reload(true) }, 5000)'; } die("Contao Manager was downgraded to the latest version supported by your PHP version.\n{$reload}"); } } /** * @see Composer\Util\StreamContextFactory */ class StreamContextFactory { /** * Creates a context supporting HTTP proxies * * @param string $url URL the context is to be used for * @param array $defaultOptions Options to merge with the default * @param array $defaultParams Parameters to specify on the context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled * @return resource Default context */ public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array()) { $options = array('http' => array( // specify defaults again to try and work better with curlwrappers enabled 'follow_location' => 1, 'max_redirects' => 20, )); // Handle HTTP_PROXY/http_proxy on CLI only for security reasons if ((\PHP_SAPI === 'cli' || \PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) { $proxy = \parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']); } // Prefer CGI_HTTP_PROXY if available if (!empty($_SERVER['CGI_HTTP_PROXY'])) { $proxy = \parse_url($_SERVER['CGI_HTTP_PROXY']); } // Override with HTTPS proxy if present and URL is https if (\preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) { $proxy = \parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']); } // Remove proxy if URL matches no_proxy directive if ((!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy'])) && \parse_url($url, \PHP_URL_HOST)) { $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']); if ($pattern->test($url)) { unset($proxy); } } if (!empty($proxy)) { $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : ''; $proxyURL .= isset($proxy['host']) ? $proxy['host'] : ''; if (isset($proxy['port'])) { $proxyURL .= ":" . $proxy['port']; } elseif ('http://' === \substr($proxyURL, 0, 7)) { $proxyURL .= ":80"; } elseif ('https://' === \substr($proxyURL, 0, 8)) { $proxyURL .= ":443"; } // http(s):// is not supported in proxy $proxyURL = \str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); if (0 === \strpos($proxyURL, 'ssl:') && !\extension_loaded('openssl')) { throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); } $options['http']['proxy'] = $proxyURL; // enabled request_fulluri unless it is explicitly disabled switch (\parse_url($url, \PHP_URL_SCHEME)) { case 'http': // default request_fulluri to true $reqFullUriEnv = \getenv('HTTP_PROXY_REQUEST_FULLURI'); if ($reqFullUriEnv === \false || $reqFullUriEnv === '' || \strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) { $options['http']['request_fulluri'] = \true; } break; case 'https': // default request_fulluri to true $reqFullUriEnv = \getenv('HTTPS_PROXY_REQUEST_FULLURI'); if ($reqFullUriEnv === \false || $reqFullUriEnv === '' || \strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv) { $options['http']['request_fulluri'] = \true; } break; } // add SNI opts for https URLs if ('https' === \parse_url($url, \PHP_URL_SCHEME)) { $options['ssl']['SNI_enabled'] = \true; if (\PHP_VERSION_ID < 50600) { $options['ssl']['SNI_server_name'] = \parse_url($url, \PHP_URL_HOST); } } // handle proxy auth if present if (isset($proxy['user'])) { $auth = \rawurldecode($proxy['user']); if (isset($proxy['pass'])) { $auth .= ':' . \rawurldecode($proxy['pass']); } $auth = \base64_encode($auth); // Preserve headers if already set in default options if (isset($defaultOptions['http']['header'])) { if (\is_string($defaultOptions['http']['header'])) { $defaultOptions['http']['header'] = array($defaultOptions['http']['header']); } $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}"; } else { $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}"); } } } $options = \array_replace_recursive($options, $defaultOptions); if (isset($options['http']['header'])) { $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']); } if (\defined('_ContaoManager\\HHVM_VERSION')) { $phpVersion = 'HHVM ' . \_ContaoManager\HHVM_VERSION; } else { $phpVersion = 'PHP ' . \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION; } if (!isset($options['http']['header']) || \false === \stripos(\implode('', $options['http']['header']), 'user-agent')) { $options['http']['header'][] = \sprintf('User-Agent: Contao Manager/@package_version@ (%s; %s; %s%s)', \function_exists('php_uname') ? \php_uname('s') : 'Unknown', \function_exists('php_uname') ? \php_uname('r') : 'Unknown', $phpVersion, \getenv('CI') ? '; CI' : ''); } return \stream_context_create($options, $defaultParams); } /** * A bug in PHP prevents the headers from correctly being sent when a content-type header is present and * NOT at the end of the array * * This method fixes the array by moving the content-type header to the end * * @link https://bugs.php.net/bug.php?id=61548 * @param string|array $header * @return array */ private static function fixHttpHeaderField($header) { if (!\is_array($header)) { $header = \explode("\r\n", $header); } \uasort($header, function ($el) { return \stripos($el, 'content-type') === 0 ? 1 : -1; }); return $header; } } /** * @see Composer\Util\NoProxyPattern */ class NoProxyPattern { /** * @var string[] */ protected $rules = array(); /** * @param string $pattern no_proxy pattern */ public function __construct($pattern) { $this->rules = \preg_split("/[\\s,]+/", $pattern); } /** * Test a URL against the stored pattern. * * @param string $url * * @return bool true if the URL matches one of the rules. */ public function test($url) { $host = \parse_url($url, \PHP_URL_HOST); $port = \parse_url($url, \PHP_URL_PORT); if (empty($port)) { switch (\parse_url($url, \PHP_URL_SCHEME)) { case 'http': $port = 80; break; case 'https': $port = 443; break; } } foreach ($this->rules as $rule) { if ($rule === '*') { return \true; } list($ruleHost) = \explode(':', $rule); list($base) = \explode('/', $ruleHost); if (\filter_var($base, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { // ip or cidr match if (!isset($ip)) { $ip = \gethostbyname($host); } if (\strpos($ruleHost, '/') === \false) { $match = $ip === $ruleHost; } else { // gethostbyname() failed to resolve $host to an ip, so we assume // it must be proxied to let the proxy's DNS resolve it if ($ip === $host) { $match = \false; } else { // match resolved IP against the rule $match = self::inCIDRBlock($ruleHost, $ip); } } } else { // match end of domain $haystack = '.' . \trim($host, '.') . '.'; $needle = '.' . \trim($ruleHost, '.') . '.'; $match = \stripos(\strrev($haystack), \strrev($needle)) === 0; } // final port check if ($match && \strpos($rule, ':') !== \false) { list(, $rulePort) = \explode(':', $rule); if (!empty($rulePort) && $port != $rulePort) { $match = \false; } } if ($match) { return \true; } } return \false; } /** * Check an IP address against a CIDR * * http://framework.zend.com/svn/framework/extras/incubator/library/ZendX/Whois/Adapter/Cidr.php * * @param string $cidr IPv4 block in CIDR notation * @param string $ip IPv4 address * * @return bool */ private static function inCIDRBlock($cidr, $ip) { // Get the base and the bits from the CIDR list($base, $bits) = \explode('/', $cidr); // Now split it up into it's classes list($a, $b, $c, $d) = \explode('.', $base); // Now do some bit shifting/switching to convert to ints $i = ($a << 24) + ($b << 16) + ($c << 8) + $d; $mask = $bits == 0 ? 0 : ~0 << 32 - $bits; // Here's our lowest int $low = $i & $mask; // Here's our highest int $high = $i | ~$mask & 0xffffffff; // Now split the ip we're checking against up into classes list($a, $b, $c, $d) = \explode('.', $ip); // Now convert the ip we're checking against to an int $check = ($a << 24) + ($b << 16) + ($c << 8) + $d; // If the ip is within the range, including highest/lowest values, // then it's within the CIDR range return $check >= $low && $check <= $high; } } if (\PHP_VERSION_ID < 80100) { ContaoManagerDowngrade::run(); } { "_readme": [ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "hash": "e5afe72073d9266712c8e1ddc1648513", "packages": [], "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=5.3" }, "platform-dev": [] } Copyright (c) 2015 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. PHAR Utils ========== PHAR file format utilities, for when PHP phars you up. Installation ------------ `composer require seld/phar-utils` API --- ### `Seld\PharUtils\Timestamps` - `__construct($pharFile)` > Load a phar file in memory. - `updateTimestamps($timestamp = null)` > Updates each file's unix timestamps in the PHAR so the PHAR signature > can be produced in a reproducible manner. - `save($path, $signatureAlgo = '')` > Saves the updated phar file with an updated signature. > Algo must be one of `Phar::MD5`, `Phar::SHA1`, `Phar::SHA256` > or `Phar::SHA512` ### `Seld\PharUtils\Linter` - `Linter::lint($pharFile)` > Lints all php files inside a given phar with the current PHP version. Requirements ------------ PHP 5.3 and above License ------- PHAR Utils is licensed under the MIT License - see the LICENSE file for details { "name": "seld\/phar-utils", "description": "PHAR file format utilities, for when PHP phars you up", "type": "library", "keywords": [ "phar" ], "license": "MIT", "require": { "php": ">=5.3" }, "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be" } ], "autoload": { "psr-4": { "_ContaoManager\\Seld\\PharUtils\\": "src\/" } }, "extra": { "branch-alias": { "dev-master": "1.x-dev" } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\PharUtils; class Linter { /** * Lints all php files inside a given phar with the current PHP version * * @param string $path Phar file path * @param list $excludedPaths Paths which should be skipped by the linter */ public static function lint($path, array $excludedPaths = array()) { $php = \defined('PHP_BINARY') ? \PHP_BINARY : 'php'; if ($isWindows = \defined('PHP_WINDOWS_VERSION_BUILD')) { $tmpFile = @\tempnam(\sys_get_temp_dir(), ''); if (!$tmpFile || !\is_writable($tmpFile)) { throw new \RuntimeException('Unable to create temp file'); } $php = self::escapeWindowsPath($php); $tmpFile = self::escapeWindowsPath($tmpFile); // PHP 8 encloses the command in double-quotes if (\PHP_VERSION_ID >= 80000) { $format = '%s -l %s'; } else { $format = '"%s -l %s"'; } $command = \sprintf($format, $php, $tmpFile); } else { $command = "'" . $php . "' -l"; } $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); // path to phar + phar:// + trailing slash $baseLen = \strlen(\realpath($path)) + 7 + 1; foreach (new \RecursiveIteratorIterator(new \Phar($path)) as $file) { if ($file->isDir()) { continue; } if (\substr($file, -4) === '.php') { $filename = (string) $file; if (\in_array(\substr($filename, $baseLen), $excludedPaths, \true)) { continue; } if ($isWindows) { \file_put_contents($tmpFile, \file_get_contents($filename)); } $process = \proc_open($command, $descriptorspec, $pipes); if (\is_resource($process)) { if (!$isWindows) { \fwrite($pipes[0], \file_get_contents($filename)); } \fclose($pipes[0]); $stdout = \stream_get_contents($pipes[1]); \fclose($pipes[1]); $stderr = \stream_get_contents($pipes[2]); \fclose($pipes[2]); $exitCode = \proc_close($process); if ($exitCode !== 0) { if ($isWindows) { $stderr = \str_replace($tmpFile, $filename, $stderr); } throw new \UnexpectedValueException('Failed linting ' . $file . ': ' . $stderr); } } else { throw new \RuntimeException('Could not start linter process'); } } } if ($isWindows) { @\unlink($tmpFile); } } /** * Escapes a Windows file path * * @param string $path * @return string The escaped path */ private static function escapeWindowsPath($path) { // Quote if path contains spaces or brackets if (\strpbrk($path, " ()") !== \false) { $path = '"' . $path . '"'; } return $path; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\PharUtils; class Timestamps { private $contents; /** * @param string $file path to the phar file to use */ public function __construct($file) { $this->contents = \file_get_contents($file); } /** * Updates each file's unix timestamps in the PHAR * * The PHAR signature can then be produced in a reproducible manner. * * @param int|\DateTimeInterface|string $timestamp Date string or DateTime or unix timestamp to use */ public function updateTimestamps($timestamp = null) { if ($timestamp instanceof \DateTime || $timestamp instanceof \DateTimeInterface) { $timestamp = $timestamp->getTimestamp(); } elseif (\is_string($timestamp)) { $timestamp = \strtotime($timestamp); } elseif (!\is_int($timestamp)) { $timestamp = \strtotime('1984-12-24T00:00:00Z'); } // detect manifest offset / end of stub if (!\preg_match('{__HALT_COMPILER\\(\\);(?: +\\?>)?\\r?\\n}', $this->contents, $match, \PREG_OFFSET_CAPTURE)) { throw new \RuntimeException('Could not detect the stub\'s end in the phar'); } // set starting position and skip past manifest length $pos = $match[0][1] + \strlen($match[0][0]); $stubEnd = $pos + $this->readUint($pos, 4); $pos += 4; $numFiles = $this->readUint($pos, 4); $pos += 4; // skip API version (YOLO) $pos += 2; // skip PHAR flags $pos += 4; $aliasLength = $this->readUint($pos, 4); $pos += 4 + $aliasLength; $metadataLength = $this->readUint($pos, 4); $pos += 4 + $metadataLength; while ($pos < $stubEnd) { $filenameLength = $this->readUint($pos, 4); $pos += 4 + $filenameLength; // skip filesize $pos += 4; // update timestamp to a fixed value $timeStampBytes = \pack('L', $timestamp); $this->contents[$pos + 0] = $timeStampBytes[0]; $this->contents[$pos + 1] = $timeStampBytes[1]; $this->contents[$pos + 2] = $timeStampBytes[2]; $this->contents[$pos + 3] = $timeStampBytes[3]; // skip timestamp, compressed file size, crc32 checksum and file flags $pos += 4 * 4; $metadataLength = $this->readUint($pos, 4); $pos += 4 + $metadataLength; $numFiles--; } if ($numFiles !== 0) { throw new \LogicException('All files were not processed, something must have gone wrong'); } } /** * Saves the updated phar file, optionally with an updated signature. * * @param string $path * @param int $signatureAlgo One of Phar::MD5, Phar::SHA1, Phar::SHA256 or Phar::SHA512 * @return bool */ public function save($path, $signatureAlgo) { $pos = $this->determineSignatureBegin(); $algos = array(\Phar::MD5 => 'md5', \Phar::SHA1 => 'sha1', \Phar::SHA256 => 'sha256', \Phar::SHA512 => 'sha512'); if (!isset($algos[$signatureAlgo])) { throw new \UnexpectedValueException('Invalid hash algorithm given: ' . $signatureAlgo . ' expected one of Phar::MD5, Phar::SHA1, Phar::SHA256 or Phar::SHA512'); } $algo = $algos[$signatureAlgo]; // re-sign phar // signature $signature = \hash($algo, \substr($this->contents, 0, $pos), \true) . \pack('L', $signatureAlgo) . 'GBMB'; $this->contents = \substr($this->contents, 0, $pos) . $signature; return \file_put_contents($path, $this->contents); } private function readUint($pos, $bytes) { $res = \unpack('V', \substr($this->contents, $pos, $bytes)); return $res[1]; } /** * Determine the beginning of the signature. * * @return int */ private function determineSignatureBegin() { // detect signature position if (!\preg_match('{__HALT_COMPILER\\(\\);(?: +\\?>)?\\r?\\n}', $this->contents, $match, \PREG_OFFSET_CAPTURE)) { throw new \RuntimeException('Could not detect the stub\'s end in the phar'); } // set starting position and skip past manifest length $pos = $match[0][1] + \strlen($match[0][0]); $manifestEnd = $pos + 4 + $this->readUint($pos, 4); $pos += 4; $numFiles = $this->readUint($pos, 4); $pos += 4; // skip API version (YOLO) $pos += 2; // skip PHAR flags $pos += 4; $aliasLength = $this->readUint($pos, 4); $pos += 4 + $aliasLength; $metadataLength = $this->readUint($pos, 4); $pos += 4 + $metadataLength; $compressedSizes = 0; while ($numFiles > 0 && $pos < $manifestEnd - 24) { $filenameLength = $this->readUint($pos, 4); $pos += 4 + $filenameLength; // skip filesize and timestamp $pos += 2 * 4; $compressedSizes += $this->readUint($pos, 4); // skip compressed file size, crc32 checksum and file flags $pos += 3 * 4; $metadataLength = $this->readUint($pos, 4); $pos += 4 + $metadataLength; $numFiles--; } if ($numFiles !== 0) { throw new \LogicException('All files were not processed, something must have gone wrong'); } return $manifestEnd + $compressedSizes; } } Copyright (c) 2011 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. #!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ function includeIfExists($file) { if (\file_exists($file)) { return include $file; } } if (!includeIfExists(__DIR__ . '/../vendor/autoload.php') && !includeIfExists(__DIR__ . '/../../../autoload.php')) { $msg = 'You must set up the project dependencies, run the following commands:' . \PHP_EOL . 'curl -sS https://getcomposer.org/installer | php' . \PHP_EOL . 'php composer.phar install' . \PHP_EOL; \fwrite(\STDERR, $msg); exit(1); } use _ContaoManager\Seld\JsonLint\JsonParser; $files = array(); $quiet = \false; if (isset($_SERVER['argc']) && $_SERVER['argc'] > 1) { for ($i = 1; $i < $_SERVER['argc']; $i++) { $arg = $_SERVER['argv'][$i]; if ($arg == '-q' || $arg == '--quiet') { $quiet = \true; } else { if ($arg == '-h' || $arg == '--help') { showUsage($_SERVER['argv'][0]); } else { $files[] = $arg; } } } } if (!empty($files)) { // file linting $exitCode = 0; foreach ($files as $file) { $result = lintFile($file, $quiet); if ($result === \false) { $exitCode = 1; } } exit($exitCode); } else { //stdin linting if ($contents = \file_get_contents('php://stdin')) { lint($contents, $quiet); } else { \fwrite(\STDERR, 'No file name or json input given' . \PHP_EOL); exit(1); } } // stdin lint function function lint($content, $quiet = \false) { $parser = new JsonParser(); if ($err = $parser->lint($content)) { \fwrite(\STDERR, $err->getMessage() . ' (stdin)' . \PHP_EOL); exit(1); } if (!$quiet) { echo 'Valid JSON (stdin)' . \PHP_EOL; exit(0); } } // file lint function function lintFile($file, $quiet = \false) { if (!\preg_match('{^https?://}i', $file)) { if (!\file_exists($file)) { \fwrite(\STDERR, 'File not found: ' . $file . \PHP_EOL); return \false; } if (!\is_readable($file)) { \fwrite(\STDERR, 'File not readable: ' . $file . \PHP_EOL); return \false; } } $content = \file_get_contents($file); $parser = new JsonParser(); if ($err = $parser->lint($content)) { \fwrite(\STDERR, $file . ': ' . $err->getMessage() . \PHP_EOL); return \false; } if (!$quiet) { echo 'Valid JSON (' . $file . ')' . \PHP_EOL; } return \true; } // usage text function function showUsage($programPath) { echo 'Usage: ' . $programPath . ' file [options]' . \PHP_EOL; echo \PHP_EOL; echo 'Options:' . \PHP_EOL; echo ' -q, --quiet Cause jsonlint to be quiet when no errors are found' . \PHP_EOL; echo ' -h, --help Show this message' . \PHP_EOL; exit(0); } You can find newer changelog entries in [GitHub releases](https://github.com/Seldaek/jsonlint/releases) ### 1.10.0 (2023-05-11) * Added ALLOW_COMMENTS flag to parse while allowing (and ignoring) inline `//` and multiline `/* */` comments in the JSON document (#81) ### 1.9.0 (2022-04-01) * Internal cleanups and type fixes ### 1.8.1 (2020-08-13) * Added type annotations ### 1.8.0 (2020-04-30) * Improved lexer performance * Added (tentative) support for PHP 8 * Fixed wording of error reporting for invalid strings when the error happened after the 20th character ### 1.7.2 (2019-10-24) * Fixed issue decoding some unicode escaped characters (for " and ') ### 1.7.1 (2018-01-24) * Fixed PHP 5.3 compatibility in bin/jsonlint ### 1.7.0 (2018-01-03) * Added ability to lint multiple files at once using the jsonlint binary ### 1.6.2 (2017-11-30) * No meaningful public changes ### 1.6.1 (2017-06-18) * Fixed parsing of `0` as invalid ### 1.6.0 (2017-03-06) * Added $flags arg to JsonParser::lint() to take the same flag as parse() did * Fixed backtracking performance issues on long strings with a lot of escaped characters ### 1.5.0 (2016-11-14) * Added support for PHP 7.1 (which converts `{"":""}` to an object property called `""` and not `"_empty_"` like 7.0 and below). ### 1.4.0 (2015-11-21) * Added a DuplicateKeyException allowing for more specific error detection and handling ### 1.3.1 (2015-01-04) * Fixed segfault when parsing large JSON strings ### 1.3.0 (2014-09-05) * Added parsing to an associative array via JsonParser::PARSE_TO_ASSOC * Fixed a warning when rendering parse errors on empty lines ### 1.2.0 (2014-07-20) * Added support for linting multiple files at once in bin/jsonlint * Added a -q/--quiet flag to suppress the output * Fixed error output being on STDOUT instead of STDERR * Fixed parameter parsing ### 1.1.2 (2013-11-04) * Fixed handling of Unicode BOMs to give a better failure hint ### 1.1.1 (2013-02-12) * Fixed handling of empty keys in objects in certain cases ### 1.1.0 (2012-12-13) * Added optional parsing of duplicate keys into key.2, key.3, etc via JsonParser::ALLOW_DUPLICATE_KEYS * Improved error reporting for common mistakes ### 1.0.1 (2012-04-03) * Added optional detection and error reporting for duplicate keys via JsonParser::DETECT_KEY_CONFLICTS * Added ability to pipe content through stdin into bin/jsonlint ### 1.0.0 (2012-03-12) * Initial release JSON Lint ========= [![Build Status](https://github.com/Seldaek/jsonlint/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/Seldaek/jsonlint/actions/workflows/continuous-integration.yml) Usage ----- ```php use Seld\JsonLint\JsonParser; $parser = new JsonParser(); // returns null if it's valid json, or a ParsingException object. $parser->lint($json); // Call getMessage() on the exception object to get // a well formatted error message error like this // Parse error on line 2: // ... "key": "value" "numbers": [1, 2, 3] // ----------------------^ // Expected one of: 'EOF', '}', ':', ',', ']' // Call getDetails() on the exception to get more info. // returns parsed json, like json_decode() does, but slower, throws // exceptions on failure. $parser->parse($json); ``` You can also pass additional flags to `JsonParser::lint/parse` that tweak the functionality: - `JsonParser::DETECT_KEY_CONFLICTS` throws an exception on duplicate keys. - `JsonParser::ALLOW_DUPLICATE_KEYS` collects duplicate keys. e.g. if you have two `foo` keys they will end up as `foo` and `foo.2`. - `JsonParser::PARSE_TO_ASSOC` parses to associative arrays instead of stdClass objects. - `JsonParser::ALLOW_COMMENTS` parses while allowing (and ignoring) inline `//` and multiline `/* */` comments in the JSON document. - `JsonParser::ALLOW_DUPLICATE_KEYS_TO_ARRAY` collects duplicate keys. e.g. if you have two `foo` keys the `foo` key will become an object (or array in assoc mode) with all `foo` values accessible as an array in `$result->foo->__duplicates__` (or `$result['foo']['__duplicates__']` in assoc mode). Example: ```php $parser = new JsonParser; try { $parser->parse(file_get_contents($jsonFile), JsonParser::DETECT_KEY_CONFLICTS); } catch (DuplicateKeyException $e) { $details = $e->getDetails(); echo 'Key '.$details['key'].' is a duplicate in '.$jsonFile.' at line '.$details['line']; } ``` > **Note:** This library is meant to parse JSON while providing good error messages on failure. There is no way it can be as fast as php native `json_decode()`. > > It is recommended to parse with `json_decode`, and when it fails parse again with seld/jsonlint to get a proper error message back to the user. See for example [how Composer uses this library](https://github.com/composer/composer/blob/56edd53046fd697d32b2fd2fbaf45af5d7951671/src/Composer/Json/JsonFile.php#L283-L318): Installation ------------ For a quick install with Composer use: ```bash composer require seld/jsonlint ``` JSON Lint can easily be used within another app if you have a [PSR-4](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md) autoloader, or it can be installed through [Composer](https://getcomposer.org/) for use as a CLI util. Once installed via Composer you can run the following command to lint a json file or URL: $ bin/jsonlint file.json Requirements ------------ - PHP 5.3+ - [optional] PHPUnit 3.5+ to execute the test suite (phpunit --version) Submitting bugs and feature requests ------------------------------------ Bugs and feature request are tracked on [GitHub](https://github.com/Seldaek/jsonlint/issues) Author ------ Jordi Boggiano - - License ------- JSON Lint is licensed under the MIT License - see the LICENSE file for details Acknowledgements ---------------- This library is a port of the JavaScript [jsonlint](https://github.com/zaach/jsonlint) library. { "name": "seld\/jsonlint", "description": "JSON Linter", "keywords": [ "json", "parser", "linter", "validator" ], "type": "library", "license": "MIT", "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "https:\/\/seld.be" } ], "require": { "php": "^5.3 || ^7.0 || ^8.0" }, "require-dev": { "phpunit\/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13", "phpstan\/phpstan": "^1.11" }, "autoload": { "psr-4": { "_ContaoManager\\Seld\\JsonLint\\": "src\/Seld\/JsonLint\/" } }, "bin": [ "bin\/jsonlint" ], "scripts": { "test": "vendor\/bin\/phpunit", "phpstan": "vendor\/bin\/phpstan analyse" } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\JsonLint; class DuplicateKeyException extends ParsingException { /** * @var array{key: string, line: int} */ protected $details; /** * @param string $message * @param string $key * @phpstan-param array{line: int} $details */ public function __construct($message, $key, array $details) { $details['key'] = $key; parent::__construct($message, $details); } /** * @return string */ public function getKey() { return $this->details['key']; } /** * @phpstan-return array{key: string, line: int} */ public function getDetails() { return $this->details; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\JsonLint; class ParsingException extends \Exception { /** * @var array{text?: string, token?: string|int, line?: int, loc?: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected?: string[]} */ protected $details; /** * @param string $message * @phpstan-param array{text?: string, token?: string|int, line?: int, loc?: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected?: string[]} $details */ public function __construct($message, $details = array()) { $this->details = $details; parent::__construct($message); } /** * @phpstan-return array{text?: string, token?: string|int, line?: int, loc?: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected?: string[]} */ public function getDetails() { return $this->details; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\JsonLint; /** * Lexer class * * Ported from https://github.com/zaach/jsonlint */ class Lexer { /** @internal */ const EOF = 1; /** @internal */ const T_INVALID = -1; const T_SKIP_WHITESPACE = 0; const T_ERROR = 2; /** @internal */ const T_BREAK_LINE = 3; /** @internal */ const T_COMMENT = 30; /** @internal */ const T_OPEN_COMMENT = 31; /** @internal */ const T_CLOSE_COMMENT = 32; /** * @phpstan-var array, string> * @const */ private $rules = array(0 => '/\\G\\s*\\n\\r?/', 1 => '/\\G\\s+/', 2 => '/\\G-?([0-9]|[1-9][0-9]+)(\\.[0-9]+)?([eE][+-]?[0-9]+)?\\b/', 3 => '{\\G"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\\0-\\x1f\\\\"]++)*+"}', 4 => '/\\G\\{/', 5 => '/\\G\\}/', 6 => '/\\G\\[/', 7 => '/\\G\\]/', 8 => '/\\G,/', 9 => '/\\G:/', 10 => '/\\Gtrue\\b/', 11 => '/\\Gfalse\\b/', 12 => '/\\Gnull\\b/', 13 => '/\\G$/', 14 => '/\\G\\/\\//', 15 => '/\\G\\/\\*/', 16 => '/\\G\\*\\//', 17 => '/\\G./'); /** @var string */ private $input; /** @var bool */ private $more; /** @var bool */ private $done; /** @var 0|positive-int */ private $offset; /** @var int */ private $flags; /** @var string */ public $match; /** @var 0|positive-int */ public $yylineno; /** @var 0|positive-int */ public $yyleng; /** @var string */ public $yytext; /** @var array{first_line: 0|positive-int, first_column: 0|positive-int, last_line: 0|positive-int, last_column: 0|positive-int} */ public $yylloc; /** * @param int $flags */ public function __construct($flags = 0) { $this->flags = $flags; } /** * @return 0|1|4|6|8|10|11|14|17|18|21|22|23|24|30|-1 */ public function lex() { while (\true) { $symbol = $this->next(); switch ($symbol) { case self::T_SKIP_WHITESPACE: case self::T_BREAK_LINE: break; case self::T_COMMENT: case self::T_OPEN_COMMENT: if (!($this->flags & JsonParser::ALLOW_COMMENTS)) { $this->parseError('Lexical error on line ' . ($this->yylineno + 1) . ". Comments are not allowed.\n" . $this->showPosition()); } $this->skipUntil($symbol === self::T_COMMENT ? self::T_BREAK_LINE : self::T_CLOSE_COMMENT); if ($this->done) { // last symbol '/\G$/' before EOF return 14; } break; case self::T_CLOSE_COMMENT: $this->parseError('Lexical error on line ' . ($this->yylineno + 1) . ". Unexpected token.\n" . $this->showPosition()); default: return $symbol; } } } /** * @param string $input * @return $this */ public function setInput($input) { $this->input = $input; $this->more = \false; $this->done = \false; $this->offset = 0; $this->yylineno = $this->yyleng = 0; $this->yytext = $this->match = ''; $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0); return $this; } /** * @return string */ public function showPosition() { if ($this->yylineno === 0 && $this->offset === 1 && $this->match !== '{') { return $this->match . '...' . "\n^"; } $pre = \str_replace("\n", '', $this->getPastInput()); $c = \str_repeat('-', \max(0, \strlen($pre) - 1)); // new Array(pre.length + 1).join("-"); return $pre . \str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^"; } /** * @return string */ public function getPastInput() { $pastLength = $this->offset - \strlen($this->match); return ($pastLength > 20 ? '...' : '') . \substr($this->input, \max(0, $pastLength - 20), \min(20, $pastLength)); } /** * @return string */ public function getUpcomingInput() { $next = $this->match; if (\strlen($next) < 20) { $next .= \substr($this->input, $this->offset, 20 - \strlen($next)); } return \substr($next, 0, 20) . (\strlen($next) > 20 ? '...' : ''); } /** * @return string */ public function getFullUpcomingInput() { $next = $this->match; if (\substr($next, 0, 1) === '"' && \substr_count($next, '"') === 1) { $len = \strlen($this->input); if ($len === $this->offset) { $strEnd = $len; } else { $strEnd = \min(\strpos($this->input, '"', $this->offset + 1) ?: $len, \strpos($this->input, "\n", $this->offset + 1) ?: $len); } $next .= \substr($this->input, $this->offset, $strEnd - $this->offset); } elseif (\strlen($next) < 20) { $next .= \substr($this->input, $this->offset, 20 - \strlen($next)); } return $next; } /** * @param string $str * @return never */ protected function parseError($str) { throw new ParsingException($str); } /** * @param int $token * @return void */ private function skipUntil($token) { $symbol = $this->next(); while ($symbol !== $token && \false === $this->done) { $symbol = $this->next(); } } /** * @return 0|1|3|4|6|8|10|11|14|17|18|21|22|23|24|30|31|32|-1 */ private function next() { if ($this->done) { return self::EOF; } if ($this->offset === \strlen($this->input)) { $this->done = \true; } $token = null; $match = null; $col = null; $lines = null; if (!$this->more) { $this->yytext = ''; $this->match = ''; } $rulesLen = \count($this->rules); for ($i = 0; $i < $rulesLen; $i++) { if (\preg_match($this->rules[$i], $this->input, $match, 0, $this->offset)) { $lines = \explode("\n", $match[0]); \array_shift($lines); $lineCount = \count($lines); $this->yylineno += $lineCount; $this->yylloc = array('first_line' => $this->yylloc['last_line'], 'last_line' => $this->yylineno + 1, 'first_column' => $this->yylloc['last_column'], 'last_column' => $lineCount > 0 ? \strlen($lines[$lineCount - 1]) : $this->yylloc['last_column'] + \strlen($match[0])); $this->yytext .= $match[0]; $this->match .= $match[0]; $this->yyleng = \strlen($this->yytext); $this->more = \false; $this->offset += \strlen($match[0]); return $this->performAction($i); } } if ($this->offset === \strlen($this->input)) { return self::EOF; } $this->parseError('Lexical error on line ' . ($this->yylineno + 1) . ". Unrecognized text.\n" . $this->showPosition()); } /** * @param int $rule * @return 0|3|4|6|8|10|11|14|17|18|21|22|23|24|30|31|32|-1 */ private function performAction($rule) { switch ($rule) { case 0: /* skip break line */ return self::T_BREAK_LINE; case 1: /* skip whitespace */ return self::T_SKIP_WHITESPACE; case 2: return 6; case 3: $this->yytext = \substr($this->yytext, 1, $this->yyleng - 2); return 4; case 4: return 17; case 5: return 18; case 6: return 23; case 7: return 24; case 8: return 22; case 9: return 21; case 10: return 10; case 11: return 11; case 12: return 8; case 13: return 14; case 14: return self::T_COMMENT; case 15: return self::T_OPEN_COMMENT; case 16: return self::T_CLOSE_COMMENT; case 17: return self::T_INVALID; default: throw new \LogicException('Unsupported rule ' . $rule); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\JsonLint; class Undefined { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\JsonLint; use stdClass; /** * Parser class * * Example: * * $parser = new JsonParser(); * // returns null if it's valid json, or an error object * $parser->lint($json); * // returns parsed json, like json_decode does, but slower, throws exceptions on failure. * $parser->parse($json); * * Ported from https://github.com/zaach/jsonlint */ class JsonParser { const DETECT_KEY_CONFLICTS = 1; const ALLOW_DUPLICATE_KEYS = 2; const PARSE_TO_ASSOC = 4; const ALLOW_COMMENTS = 8; const ALLOW_DUPLICATE_KEYS_TO_ARRAY = 16; /** @var Lexer */ private $lexer; /** * @var int * @phpstan-var int-mask-of */ private $flags; /** @var list */ private $stack; /** @var list|int|bool|float|string|null> */ private $vstack; // semantic value stack /** @var list */ private $lstack; // location stack /** * @phpstan-var array */ private $symbols = array('error' => 2, 'JSONString' => 3, 'STRING' => 4, 'JSONNumber' => 5, 'NUMBER' => 6, 'JSONNullLiteral' => 7, 'NULL' => 8, 'JSONBooleanLiteral' => 9, 'TRUE' => 10, 'FALSE' => 11, 'JSONText' => 12, 'JSONValue' => 13, 'EOF' => 14, 'JSONObject' => 15, 'JSONArray' => 16, '{' => 17, '}' => 18, 'JSONMemberList' => 19, 'JSONMember' => 20, ':' => 21, ',' => 22, '[' => 23, ']' => 24, 'JSONElementList' => 25, '$accept' => 0, '$end' => 1); /** * @phpstan-var array * @const */ private $terminals_ = array(2 => "error", 4 => "STRING", 6 => "NUMBER", 8 => "NULL", 10 => "TRUE", 11 => "FALSE", 14 => "EOF", 17 => "{", 18 => "}", 21 => ":", 22 => ",", 23 => "[", 24 => "]"); /** * @phpstan-var array, array{int, int}> * @const */ private $productions_ = array(1 => array(3, 1), 2 => array(5, 1), 3 => array(7, 1), 4 => array(9, 1), 5 => array(9, 1), 6 => array(12, 2), 7 => array(13, 1), 8 => array(13, 1), 9 => array(13, 1), 10 => array(13, 1), 11 => array(13, 1), 12 => array(13, 1), 13 => array(15, 2), 14 => array(15, 3), 15 => array(20, 3), 16 => array(19, 1), 17 => array(19, 3), 18 => array(16, 2), 19 => array(16, 3), 20 => array(25, 1), 21 => array(25, 3)); /** * @var array, array|int>> List of stateID=>symbolID=>actionIDs|actionID * @const */ private $table = array(0 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 12 => 1, 13 => 2, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15)), 1 => array(1 => array(3)), 2 => array(14 => array(1, 16)), 3 => array(14 => array(2, 7), 18 => array(2, 7), 22 => array(2, 7), 24 => array(2, 7)), 4 => array(14 => array(2, 8), 18 => array(2, 8), 22 => array(2, 8), 24 => array(2, 8)), 5 => array(14 => array(2, 9), 18 => array(2, 9), 22 => array(2, 9), 24 => array(2, 9)), 6 => array(14 => array(2, 10), 18 => array(2, 10), 22 => array(2, 10), 24 => array(2, 10)), 7 => array(14 => array(2, 11), 18 => array(2, 11), 22 => array(2, 11), 24 => array(2, 11)), 8 => array(14 => array(2, 12), 18 => array(2, 12), 22 => array(2, 12), 24 => array(2, 12)), 9 => array(14 => array(2, 3), 18 => array(2, 3), 22 => array(2, 3), 24 => array(2, 3)), 10 => array(14 => array(2, 4), 18 => array(2, 4), 22 => array(2, 4), 24 => array(2, 4)), 11 => array(14 => array(2, 5), 18 => array(2, 5), 22 => array(2, 5), 24 => array(2, 5)), 12 => array(14 => array(2, 1), 18 => array(2, 1), 21 => array(2, 1), 22 => array(2, 1), 24 => array(2, 1)), 13 => array(14 => array(2, 2), 18 => array(2, 2), 22 => array(2, 2), 24 => array(2, 2)), 14 => array(3 => 20, 4 => array(1, 12), 18 => array(1, 17), 19 => 18, 20 => 19), 15 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 13 => 23, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15), 24 => array(1, 21), 25 => 22), 16 => array(1 => array(2, 6)), 17 => array(14 => array(2, 13), 18 => array(2, 13), 22 => array(2, 13), 24 => array(2, 13)), 18 => array(18 => array(1, 24), 22 => array(1, 25)), 19 => array(18 => array(2, 16), 22 => array(2, 16)), 20 => array(21 => array(1, 26)), 21 => array(14 => array(2, 18), 18 => array(2, 18), 22 => array(2, 18), 24 => array(2, 18)), 22 => array(22 => array(1, 28), 24 => array(1, 27)), 23 => array(22 => array(2, 20), 24 => array(2, 20)), 24 => array(14 => array(2, 14), 18 => array(2, 14), 22 => array(2, 14), 24 => array(2, 14)), 25 => array(3 => 20, 4 => array(1, 12), 20 => 29), 26 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 13 => 30, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15)), 27 => array(14 => array(2, 19), 18 => array(2, 19), 22 => array(2, 19), 24 => array(2, 19)), 28 => array(3 => 5, 4 => array(1, 12), 5 => 6, 6 => array(1, 13), 7 => 3, 8 => array(1, 9), 9 => 4, 10 => array(1, 10), 11 => array(1, 11), 13 => 31, 15 => 7, 16 => 8, 17 => array(1, 14), 23 => array(1, 15)), 29 => array(18 => array(2, 17), 22 => array(2, 17)), 30 => array(18 => array(2, 15), 22 => array(2, 15)), 31 => array(22 => array(2, 21), 24 => array(2, 21))); /** * @var array{16: array{2, 6}} * @const */ private $defaultActions = array(16 => array(2, 6)); /** * @param string $input JSON string * @param int $flags Bitmask of parse/lint options (see constants of this class) * @return null|ParsingException null if no error is found, a ParsingException containing all details otherwise * * @phpstan-param int-mask-of $flags */ public function lint($input, $flags = 0) { try { $this->parse($input, $flags); } catch (ParsingException $e) { return $e; } return null; } /** * @param string $input JSON string * @param int $flags Bitmask of parse/lint options (see constants of this class) * @return mixed * @throws ParsingException * * @phpstan-param int-mask-of $flags */ public function parse($input, $flags = 0) { if ($flags & self::ALLOW_DUPLICATE_KEYS_TO_ARRAY && $flags & self::ALLOW_DUPLICATE_KEYS) { throw new \InvalidArgumentException('Only one of ALLOW_DUPLICATE_KEYS and ALLOW_DUPLICATE_KEYS_TO_ARRAY can be used, you passed in both.'); } $this->failOnBOM($input); $this->flags = $flags; $this->stack = array(0); $this->vstack = array(null); $this->lstack = array(); $yytext = ''; $yylineno = 0; $yyleng = 0; /** @var int<0,3> */ $recovering = 0; $this->lexer = new Lexer($flags); $this->lexer->setInput($input); $yyloc = $this->lexer->yylloc; $this->lstack[] = $yyloc; $symbol = null; $preErrorSymbol = null; $action = null; $a = null; $r = null; $p = null; $len = null; $newState = null; $expected = null; /** @var string|null */ $errStr = null; while (\true) { // retrieve state number from top of stack $state = $this->stack[\count($this->stack) - 1]; // use default actions if available if (isset($this->defaultActions[$state])) { $action = $this->defaultActions[$state]; } else { if ($symbol === null) { $symbol = $this->lexer->lex(); } // read action for current state and first input /** @var array|false */ $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : \false; } // handle parse error if (!$action || !$action[0]) { \assert(isset($symbol)); if (!$recovering) { // Report error $expected = array(); foreach ($this->table[$state] as $p => $ignore) { if (isset($this->terminals_[$p]) && $p > 2) { $expected[] = "'" . $this->terminals_[$p] . "'"; } } $message = null; if (\in_array("'STRING'", $expected) && \in_array(\substr($this->lexer->match, 0, 1), array('"', "'"))) { $message = "Invalid string"; if ("'" === \substr($this->lexer->match, 0, 1)) { $message .= ", it appears you used single quotes instead of double quotes"; } elseif (\preg_match('{".+?(\\\\[^"bfnrt/\\\\u](...)?)}', $this->lexer->getFullUpcomingInput(), $match)) { $message .= ", it appears you have an unescaped backslash at: " . $match[1]; } elseif (\preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getFullUpcomingInput())) { $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid"; } } $errStr = 'Parse error on line ' . ($yylineno + 1) . ":\n"; $errStr .= $this->lexer->showPosition() . "\n"; if ($message) { $errStr .= $message; } else { $errStr .= \count($expected) > 1 ? "Expected one of: " : "Expected: "; $errStr .= \implode(', ', $expected); } if (',' === \substr(\trim($this->lexer->getPastInput()), -1)) { $errStr .= " - It appears you have an extra trailing comma"; } $this->parseError($errStr, array('text' => $this->lexer->match, 'token' => isset($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol, 'line' => $this->lexer->yylineno, 'loc' => $yyloc, 'expected' => $expected)); } // just recovered from another error if ($recovering == 3) { if ($symbol === Lexer::EOF) { throw new ParsingException($errStr ?: 'Parsing halted.'); } // discard current lookahead and grab another $yyleng = $this->lexer->yyleng; $yytext = $this->lexer->yytext; $yylineno = $this->lexer->yylineno; $yyloc = $this->lexer->yylloc; $symbol = $this->lexer->lex(); } // try to recover from error while (\true) { // check for error recovery rule in this state if (\array_key_exists(Lexer::T_ERROR, $this->table[$state])) { break; } if ($state == 0) { throw new ParsingException($errStr ?: 'Parsing halted.'); } $this->popStack(1); $state = $this->stack[\count($this->stack) - 1]; } $preErrorSymbol = $symbol; // save the lookahead token $symbol = Lexer::T_ERROR; // insert generic error symbol as new lookahead $state = $this->stack[\count($this->stack) - 1]; /** @var array|false */ $action = isset($this->table[$state][Lexer::T_ERROR]) ? $this->table[$state][Lexer::T_ERROR] : \false; if ($action === \false) { throw new \LogicException('No table value found for ' . $state . ' => ' . Lexer::T_ERROR); } $recovering = 3; // allow 3 real symbols to be shifted before reporting a new error } // this shouldn't happen, unless resolve defaults are off if (\is_array($action[0]) && \count($action) > 1) { throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol); } switch ($action[0]) { case 1: // shift \assert(isset($symbol)); $this->stack[] = $symbol; $this->vstack[] = $this->lexer->yytext; $this->lstack[] = $this->lexer->yylloc; $this->stack[] = $action[1]; // push state $symbol = null; if (!$preErrorSymbol) { // normal execution/no error $yyleng = $this->lexer->yyleng; $yytext = $this->lexer->yytext; $yylineno = $this->lexer->yylineno; $yyloc = $this->lexer->yylloc; if ($recovering > 0) { $recovering--; } } else { // error just occurred, resume old lookahead from before error $symbol = $preErrorSymbol; $preErrorSymbol = null; } break; case 2: // reduce $len = $this->productions_[$action[1]][1]; // perform semantic action $currentToken = $this->vstack[\count($this->vstack) - $len]; // default to $$ = $1 // default location, uses first token for firsts, last for lasts $position = array( // _$ = store 'first_line' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_line'], 'last_line' => $this->lstack[\count($this->lstack) - 1]['last_line'], 'first_column' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_column'], 'last_column' => $this->lstack[\count($this->lstack) - 1]['last_column'], ); list($newToken, $actionResult) = $this->performAction($currentToken, $yytext, $yyleng, $yylineno, $action[1]); if (!$actionResult instanceof Undefined) { return $actionResult; } if ($len) { $this->popStack($len); } $this->stack[] = $this->productions_[$action[1]][0]; // push nonterminal (reduce) $this->vstack[] = $newToken; $this->lstack[] = $position; /** @var int */ $newState = $this->table[$this->stack[\count($this->stack) - 2]][$this->stack[\count($this->stack) - 1]]; $this->stack[] = $newState; break; case 3: // accept return \true; } } } /** * @param string $str * @param array{text: string, token: string|int, line: int, loc: array{first_line: int, first_column: int, last_line: int, last_column: int}, expected: string[]}|null $hash * @return never */ protected function parseError($str, $hash = null) { throw new ParsingException($str, $hash ?: array()); } /** * @param stdClass|array|int|bool|float|string|null $currentToken * @param string $yytext * @param int $yyleng * @param int $yylineno * @param int $yystate * @return array{stdClass|array|int|bool|float|string|null, stdClass|array|int|bool|float|string|null|Undefined} */ private function performAction($currentToken, $yytext, $yyleng, $yylineno, $yystate) { $token = $currentToken; $len = \count($this->vstack) - 1; switch ($yystate) { case 1: $yytext = \preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext); $token = $yytext; break; case 2: if (\strpos($yytext, 'e') !== \false || \strpos($yytext, 'E') !== \false) { $token = \floatval($yytext); } else { $token = \strpos($yytext, '.') === \false ? \intval($yytext) : \floatval($yytext); } break; case 3: $token = null; break; case 4: $token = \true; break; case 5: $token = \false; break; case 6: $token = $this->vstack[$len - 1]; return array($token, $token); case 13: if ($this->flags & self::PARSE_TO_ASSOC) { $token = array(); } else { $token = new stdClass(); } break; case 14: $token = $this->vstack[$len - 1]; break; case 15: $token = array($this->vstack[$len - 2], $this->vstack[$len]); break; case 16: \assert(\is_array($this->vstack[$len])); if (\PHP_VERSION_ID < 70100) { $property = $this->vstack[$len][0] === '' ? '_empty_' : $this->vstack[$len][0]; } else { $property = $this->vstack[$len][0]; } if ($this->flags & self::PARSE_TO_ASSOC) { $token = array(); $token[$property] = $this->vstack[$len][1]; } else { $token = new stdClass(); $token->{$property} = $this->vstack[$len][1]; } break; case 17: \assert(\is_array($this->vstack[$len])); if ($this->flags & self::PARSE_TO_ASSOC) { \assert(\is_array($this->vstack[$len - 2])); $token =& $this->vstack[$len - 2]; $key = $this->vstack[$len][0]; if ($this->flags & self::DETECT_KEY_CONFLICTS && isset($this->vstack[$len - 2][$key])) { $errStr = 'Parse error on line ' . ($yylineno + 1) . ":\n"; $errStr .= $this->lexer->showPosition() . "\n"; $errStr .= "Duplicate key: " . $this->vstack[$len][0]; throw new DuplicateKeyException($errStr, $this->vstack[$len][0], array('line' => $yylineno + 1)); } if ($this->flags & self::ALLOW_DUPLICATE_KEYS && isset($this->vstack[$len - 2][$key])) { $duplicateCount = 1; do { $duplicateKey = $key . '.' . $duplicateCount++; } while (isset($this->vstack[$len - 2][$duplicateKey])); $this->vstack[$len - 2][$duplicateKey] = $this->vstack[$len][1]; } elseif ($this->flags & self::ALLOW_DUPLICATE_KEYS_TO_ARRAY && isset($this->vstack[$len - 2][$key])) { if (!isset($this->vstack[$len - 2][$key]['__duplicates__']) || !\is_array($this->vstack[$len - 2][$key]['__duplicates__'])) { $this->vstack[$len - 2][$key] = array('__duplicates__' => array($this->vstack[$len - 2][$key])); } $this->vstack[$len - 2][$key]['__duplicates__'][] = $this->vstack[$len][1]; } else { $this->vstack[$len - 2][$key] = $this->vstack[$len][1]; } } else { \assert($this->vstack[$len - 2] instanceof stdClass); $token = $this->vstack[$len - 2]; if (\PHP_VERSION_ID < 70100) { $key = $this->vstack[$len][0] === '' ? '_empty_' : $this->vstack[$len][0]; } else { $key = $this->vstack[$len][0]; } if ($this->flags & self::DETECT_KEY_CONFLICTS && isset($this->vstack[$len - 2]->{$key})) { $errStr = 'Parse error on line ' . ($yylineno + 1) . ":\n"; $errStr .= $this->lexer->showPosition() . "\n"; $errStr .= "Duplicate key: " . $this->vstack[$len][0]; throw new DuplicateKeyException($errStr, $this->vstack[$len][0], array('line' => $yylineno + 1)); } if ($this->flags & self::ALLOW_DUPLICATE_KEYS && isset($this->vstack[$len - 2]->{$key})) { $duplicateCount = 1; do { $duplicateKey = $key . '.' . $duplicateCount++; } while (isset($this->vstack[$len - 2]->{$duplicateKey})); $this->vstack[$len - 2]->{$duplicateKey} = $this->vstack[$len][1]; } elseif ($this->flags & self::ALLOW_DUPLICATE_KEYS_TO_ARRAY && isset($this->vstack[$len - 2]->{$key})) { if (!isset($this->vstack[$len - 2]->{$key}->__duplicates__)) { $this->vstack[$len - 2]->{$key} = (object) array('__duplicates__' => array($this->vstack[$len - 2]->{$key})); } $this->vstack[$len - 2]->{$key}->__duplicates__[] = $this->vstack[$len][1]; } else { $this->vstack[$len - 2]->{$key} = $this->vstack[$len][1]; } } break; case 18: $token = array(); break; case 19: $token = $this->vstack[$len - 1]; break; case 20: $token = array($this->vstack[$len]); break; case 21: \assert(\is_array($this->vstack[$len - 2])); $this->vstack[$len - 2][] = $this->vstack[$len]; $token = $this->vstack[$len - 2]; break; } return array($token, new Undefined()); } /** * @param string $match * @return string */ private function stringInterpolation($match) { switch ($match[0]) { case '\\\\': return '\\'; case '\\"': return '"'; case '\\b': return \chr(8); case '\\f': return \chr(12); case '\\n': return "\n"; case '\\r': return "\r"; case '\\t': return "\t"; case '\\/': return "/"; default: return \html_entity_decode('&#x' . \ltrim(\substr($match[0], 2), '0') . ';', \ENT_QUOTES, 'UTF-8'); } } /** * @param int $n * @return void */ private function popStack($n) { $this->stack = \array_slice($this->stack, 0, -(2 * $n)); $this->vstack = \array_slice($this->vstack, 0, -$n); $this->lstack = \array_slice($this->lstack, 0, -$n); } /** * @param string $input * @return void */ private function failOnBOM($input) { // UTF-8 ByteOrderMark sequence $bom = ""; if (\substr($input, 0, 3) === $bom) { $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark"); } } } Copyright (c) 2015 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. { "name": "seld\/signal-handler", "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development", "keywords": [ "unix", "posix", "signal", "sigint", "sigterm" ], "type": "library", "license": "MIT", "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http:\/\/seld.be" } ], "require": { "php": ">=7.2.0" }, "require-dev": { "phpunit\/phpunit": "^7.5.20 || ^8.5.23", "psr\/log": "^1 || ^2 || ^3", "phpstan\/phpstan": "^1", "phpstan\/phpstan-phpunit": "^1", "phpstan\/phpstan-strict-rules": "^1.3", "phpstan\/phpstan-deprecation-rules": "^1.0" }, "autoload": { "psr-4": { "_ContaoManager\\Seld\\Signal\\": "src\/" } }, "autoload-dev": { "psr-4": { "_ContaoManager\\Seld\\Signal\\": "tests\/" } }, "scripts": { "phpstan": "@php phpstan analyse", "test": "@php phpunit" }, "extra": { "branch-alias": { "dev-main": "2.x-dev" } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _ContaoManager\Seld\Signal; use _ContaoManager\Psr\Log\LoggerInterface; use Closure; use WeakReference; /** * SignalHandler and factory */ final class SignalHandler { /** * The SIGHUP signal is sent to a process when its controlling terminal is closed. It was originally designed to * notify the process of a serial line drop (a hangup). In modern systems, this signal usually means that the * controlling pseudo or virtual terminal has been closed. Many daemons will reload their configuration files and * reopen their logfiles instead of exiting when receiving this signal. nohup is a command to make a command ignore * the signal. */ public const SIGHUP = 'SIGHUP'; /** * The SIGINT signal is sent to a process by its controlling terminal when a user wishes to interrupt the process. * This is typically initiated by pressing Ctrl-C, but on some systems, the "delete" character or "break" key can be * used. * * On Windows this is used to denote a PHP_WINDOWS_EVENT_CTRL_C */ public const SIGINT = 'SIGINT'; /** * The SIGQUIT signal is sent to a process by its controlling terminal when the user requests that the process quit * and perform a core dump. */ public const SIGQUIT = 'SIGQUIT'; /** * The SIGILL signal is sent to a process when it attempts to execute an illegal, malformed, unknown, or privileged * instruction. */ public const SIGILL = 'SIGILL'; /** * The SIGTRAP signal is sent to a process when an exception (or trap) occurs: a condition that a debugger has * requested to be informed of — for example, when a particular function is executed, or when a particular variable * changes value. */ public const SIGTRAP = 'SIGTRAP'; /** * The SIGABRT signal is sent to a process to tell it to abort, i.e. to terminate. The signal is usually initiated * by the process itself when it calls abort function of the C Standard Library, but it can be sent to the process * from outside like any other signal. */ public const SIGABRT = 'SIGABRT'; public const SIGIOT = 'SIGIOT'; /** * The SIGBUS signal is sent to a process when it causes a bus error. The conditions that lead to the signal being * sent are, for example, incorrect memory access alignment or non-existent physical address. */ public const SIGBUS = 'SIGBUS'; public const SIGFPE = 'SIGFPE'; /** * The SIGKILL signal is sent to a process to cause it to terminate immediately (kill). In contrast to SIGTERM and * SIGINT, this signal cannot be caught or ignored, and the receiving process cannot perform any clean-up upon * receiving this signal. */ public const SIGKILL = 'SIGKILL'; /** * The SIGUSR1 signal is sent to a process to indicate user-defined conditions. */ public const SIGUSR1 = 'SIGUSR1'; /** * The SIGUSR1 signa2 is sent to a process to indicate user-defined conditions. */ public const SIGUSR2 = 'SIGUSR2'; /** * The SIGSEGV signal is sent to a process when it makes an invalid virtual memory reference, or segmentation fault, * i.e. when it performs a segmentation violation. */ public const SIGSEGV = 'SIGSEGV'; /** * The SIGPIPE signal is sent to a process when it attempts to write to a pipe without a process connected to the * other end. */ public const SIGPIPE = 'SIGPIPE'; /** * The SIGALRM, SIGVTALRM and SIGPROF signal is sent to a process when the time limit specified in a call to a * preceding alarm setting function (such as setitimer) elapses. SIGALRM is sent when real or clock time elapses. * SIGVTALRM is sent when CPU time used by the process elapses. SIGPROF is sent when CPU time used by the process * and by the system on behalf of the process elapses. */ public const SIGALRM = 'SIGALRM'; /** * The SIGTERM signal is sent to a process to request its termination. Unlike the SIGKILL signal, it can be caught * and interpreted or ignored by the process. This allows the process to perform nice termination releasing * resources and saving state if appropriate. SIGINT is nearly identical to SIGTERM. */ public const SIGTERM = 'SIGTERM'; public const SIGSTKFLT = 'SIGSTKFLT'; public const SIGCLD = 'SIGCLD'; /** * The SIGCHLD signal is sent to a process when a child process terminates, is interrupted, or resumes after being * interrupted. One common usage of the signal is to instruct the operating system to clean up the resources used by * a child process after its termination without an explicit call to the wait system call. */ public const SIGCHLD = 'SIGCHLD'; /** * The SIGCONT signal instructs the operating system to continue (restart) a process previously paused by the * SIGSTOP or SIGTSTP signal. One important use of this signal is in job control in the Unix shell. */ public const SIGCONT = 'SIGCONT'; /** * The SIGSTOP signal instructs the operating system to stop a process for later resumption. */ public const SIGSTOP = 'SIGSTOP'; /** * The SIGTSTP signal is sent to a process by its controlling terminal to request it to stop (terminal stop). It is * commonly initiated by the user pressing Ctrl+Z. Unlike SIGSTOP, the process can register a signal handler for or * ignore the signal. */ public const SIGTSTP = 'SIGTSTP'; /** * The SIGTTIN signal is sent to a process when it attempts to read in from the tty while in the background. * Typically, this signal is received only by processes under job control; daemons do not have controlling */ public const SIGTTIN = 'SIGTTIN'; /** * The SIGTTOU signal is sent to a process when it attempts to write out from the tty while in the background. * Typically, this signal is received only by processes under job control; daemons do not have controlling */ public const SIGTTOU = 'SIGTTOU'; /** * The SIGURG signal is sent to a process when a socket has urgent or out-of-band data available to read. */ public const SIGURG = 'SIGURG'; /** * The SIGXCPU signal is sent to a process when it has used up the CPU for a duration that exceeds a certain * predetermined user-settable value. The arrival of a SIGXCPU signal provides the receiving process a chance to * quickly save any intermediate results and to exit gracefully, before it is terminated by the operating system * using the SIGKILL signal. */ public const SIGXCPU = 'SIGXCPU'; /** * The SIGXFSZ signal is sent to a process when it grows a file larger than the maximum allowed size */ public const SIGXFSZ = 'SIGXFSZ'; /** * The SIGVTALRM signal is sent to a process when the time limit specified in a call to a preceding alarm setting * function (such as setitimer) elapses. SIGVTALRM is sent when CPU time used by the process elapses. */ public const SIGVTALRM = 'SIGVTALRM'; /** * The SIGPROF signal is sent to a process when the time limit specified in a call to a preceding alarm setting * function (such as setitimer) elapses. SIGPROF is sent when CPU time used by the process and by the system on * behalf of the process elapses. */ public const SIGPROF = 'SIGPROF'; /** * The SIGWINCH signal is sent to a process when its controlling terminal changes its size (a window change). */ public const SIGWINCH = 'SIGWINCH'; /** * The SIGPOLL signal is sent when an event occurred on an explicitly watched file descriptor.Using it effectively * leads to making asynchronous I/O requests since the kernel will poll the descriptor in place of the caller. It * provides an alternative to active polling. */ public const SIGPOLL = 'SIGPOLL'; public const SIGIO = 'SIGIO'; /** * The SIGPWR signal is sent to a process when the system experiences a power failure. */ public const SIGPWR = 'SIGPWR'; /** * The SIGSYS signal is sent to a process when it passes a bad argument to a system call. In practice, this kind of * signal is rarely encountered since applications rely on libraries (e.g. libc) to make the call for them. */ public const SIGSYS = 'SIGSYS'; public const SIGBABY = 'SIGBABY'; /** * CTRL+Break support, available on Windows only for PHP_WINDOWS_EVENT_CTRL_BREAK */ public const SIGBREAK = 'SIGBREAK'; private const ALL_SIGNALS = [self::SIGHUP, self::SIGINT, self::SIGQUIT, self::SIGILL, self::SIGTRAP, self::SIGABRT, self::SIGIOT, self::SIGBUS, self::SIGFPE, self::SIGKILL, self::SIGUSR1, self::SIGUSR2, self::SIGSEGV, self::SIGPIPE, self::SIGALRM, self::SIGTERM, self::SIGSTKFLT, self::SIGCLD, self::SIGCHLD, self::SIGCONT, self::SIGSTOP, self::SIGTSTP, self::SIGTTIN, self::SIGTTOU, self::SIGURG, self::SIGXCPU, self::SIGXFSZ, self::SIGVTALRM, self::SIGPROF, self::SIGWINCH, self::SIGPOLL, self::SIGIO, self::SIGPWR, self::SIGSYS, self::SIGBABY, self::SIGBREAK]; /** * @var self::SIG*|null */ private $triggered = null; /** * @var list * @readonly */ private $signals; /** * @var LoggerInterface|(callable(self::SIG* $name, SignalHandler $self): void)|null * @readonly */ private $loggerOrCallback; /** * @var array> */ private static $handlers = []; /** @var Closure|null */ private static $windowsHandler = null; /** * @param array $signals * @param LoggerInterface|(callable(self::SIG* $name, SignalHandler $self): void)|null $loggerOrCallback */ private function __construct(array $signals, $loggerOrCallback) { if (!\is_callable($loggerOrCallback) && !$loggerOrCallback instanceof LoggerInterface && $loggerOrCallback !== null) { throw new \InvalidArgumentException('$loggerOrCallback must be a ' . LoggerInterface::class . ' instance, a callable, or null, ' . (\is_object($loggerOrCallback) ? \get_class($loggerOrCallback) : \gettype($loggerOrCallback)) . ' received.'); } $this->signals = $signals; $this->loggerOrCallback = $loggerOrCallback; } /** * @param self::SIG* $signalName */ private function trigger(string $signalName) : void { $this->triggered = $signalName; if ($this->loggerOrCallback instanceof LoggerInterface) { $this->loggerOrCallback->info('Received ' . $signalName); } elseif ($this->loggerOrCallback !== null) { ($this->loggerOrCallback)($signalName, $this); } } /** * Fetches the triggered state of the handler * * @phpstan-impure */ public function isTriggered() : bool { return $this->triggered !== null; } /** * Exits the process while communicating that the handled signal was what killed the process * * This is different from doing exit(SIGINT), and is also different to a successful exit(0). * * This should only be used when you received a signal and then handled it to gracefully shutdown and are now ready to shutdown. * * ``` * $signal = SignalHandler::create([SignalHandler::SIGINT], function (string $signal, SignalHandler $handler) { * // do cleanup here.. * * $handler->exitWithLastSignal(); * }); * * // or... * * $signal = SignalHandler::create([SignalHandler::SIGINT]); * * while ($doingThings) { * if ($signal->isTriggered()) { * $signal->exitWithLastSignal(); * } * * // do more things * } * ``` * * @see https://www.cons.org/cracauer/sigint.html * @return never */ public function exitWithLastSignal() : void { $signal = $this->triggered ?? 'SIGINT'; $signal = \defined($signal) ? \constant($signal) : 2; if (\function_exists('posix_kill') && \function_exists('posix_getpid')) { \pcntl_signal($signal, \SIG_DFL); \posix_kill(\posix_getpid(), $signal); } // just in case posix_kill above could not run // not strictly correct but it's the best we can do here exit(128 + $signal); } /** * Resets the state to let a handler accept a signal again */ public function reset() : void { $this->triggered = null; } public function __destruct() { $this->unregister(); } /** * @param (string|int)[] $signals array of signal names (more portable, see SignalHandler::SIG*) or constants - defaults to [SIGINT, SIGTERM] * @param LoggerInterface|callable $loggerOrCallback A PSR-3 Logger or a callback($signal, $signalName) * @return self A handler on which you can call isTriggered to know if the signal was received, and reset() to forget * * @phpstan-param list $signals * @phpstan-param LoggerInterface|(callable(self::SIG* $name, SignalHandler $self): void) $loggerOrCallback */ public static function create(?array $signals = null, $loggerOrCallback = null) : self { if ($signals === null) { $signals = [self::SIGINT, self::SIGTERM]; } $signals = \array_map(function ($signal) { if (\is_int($signal)) { return self::getSignalName($signal); } elseif (!\in_array($signal, self::ALL_SIGNALS, \true)) { throw new \InvalidArgumentException('$signals must be an array of SIG* constants or self::SIG* constants, got ' . \var_export($signal, \true)); } return $signal; }, (array) $signals); $handler = new self($signals, $loggerOrCallback); if (\PHP_VERSION_ID >= 80000) { \array_unshift(self::$handlers, WeakReference::create($handler)); } else { \array_unshift(self::$handlers, $handler); } if (\function_exists('sapi_windows_set_ctrl_handler') && \PHP_SAPI === 'cli' && (\in_array(self::SIGINT, $signals, \true) || \in_array(self::SIGBREAK, $signals, \true))) { if (null === self::$windowsHandler) { self::$windowsHandler = Closure::fromCallable([self::class, 'handleWindowsSignal']); \sapi_windows_set_ctrl_handler(self::$windowsHandler); } } if (\function_exists('pcntl_signal') && \function_exists('pcntl_async_signals')) { \pcntl_async_signals(\true); self::registerPcntlHandler($signals); } return $handler; } /** * Clears the signal handler * * On PHP 8+ this is not necessary and it will happen automatically on __destruct, but PHP 7 does not * support weak references and thus there you need to manually do this. * * If another handler was registered previously to this one, it becomes active again */ public function unregister() : void { $signals = $this->signals; $index = \false; foreach (self::$handlers as $key => $handler) { if ($handler instanceof WeakReference && $handler->get() === $this || $handler === $this) { $index = $key; break; } } if ($index === \false) { // guard against double-unregistration when __destruct happens return; } unset(self::$handlers[$index]); if (self::$windowsHandler !== null && (\in_array(self::SIGINT, $signals, \true) || \in_array(self::SIGBREAK, $signals, \true))) { if (self::getHandlerFor(self::SIGINT) === null && self::getHandlerFor(self::SIGBREAK) === null) { \sapi_windows_set_ctrl_handler(self::$windowsHandler, \false); self::$windowsHandler = null; } } if (\function_exists('pcntl_signal')) { foreach ($signals as $signal) { // skip missing signals, for example OSX does not have all signals if (!\defined($signal)) { continue; } // keep listening to signals where we have a handler registered if (self::getHandlerFor($signal) !== null) { continue; } \pcntl_signal(\constant($signal), \SIG_DFL); } } } /** * Clears all signal handlers * * On PHP 8+ this should not be necessary as it will happen automatically on __destruct, but PHP 7 does not * support weak references and thus there you need to manually do this. * * This can be done to reset the global state, but ideally you should always call ->unregister() in a try/finally block to ensure it happens. */ public static function unregisterAll() : void { if (self::$windowsHandler !== null) { \sapi_windows_set_ctrl_handler(self::$windowsHandler, \false); self::$windowsHandler = null; } foreach (self::$handlers as $key => $handler) { if ($handler instanceof WeakReference) { $handler = $handler->get(); if ($handler === null) { unset(self::$handlers[$key]); continue; } } $handler->unregister(); } } /** * @param list $signals */ private static function registerPcntlHandler(array $signals) : void { static $callable; if ($callable === null) { $callable = Closure::fromCallable([self::class, 'handlePcntlSignal']); } foreach ($signals as $signal) { // skip missing signals, for example OSX does not have all signals if (!\defined($signal)) { continue; } \pcntl_signal(\constant($signal), $callable); } } private static function handleWindowsSignal(int $event) : void { if (\PHP_WINDOWS_EVENT_CTRL_C === $event) { self::callHandlerFor(self::SIGINT); } elseif (\PHP_WINDOWS_EVENT_CTRL_BREAK === $event) { self::callHandlerFor(self::SIGBREAK); } } private static function handlePcntlSignal(int $signal) : void { self::callHandlerFor(self::getSignalName($signal)); } /** * Calls the first handler from the top of the stack that can handle a given signal * * @param self::SIG* $signal */ private static function callHandlerFor(string $signal) : void { $handler = self::getHandlerFor($signal); if ($handler !== null) { $handler->trigger($signal); } } /** * Returns the first handler from the top of the stack that can handle a given signal * * @param self::SIG* $signal * @return self|null */ private static function getHandlerFor(string $signal) : ?self { foreach (self::$handlers as $key => $handler) { if ($handler instanceof WeakReference) { $handler = $handler->get(); if ($handler === null) { unset(self::$handlers[$key]); continue; } } if (\in_array($signal, $handler->signals, \true)) { return $handler; } } return null; } /** * @return self::SIG* */ private static function getSignalName(int $signo) : string { static $signals = null; if ($signals === null) { $signals = []; foreach (self::ALL_SIGNALS as $value) { if (\defined($value)) { $signals[\constant($value)] = $value; } } } if (isset($signals[$signo])) { return $signals[$signo]; } throw new \InvalidArgumentException('Unknown signal #' . $signo); } } PHPDoc Parser for PHPStan This library `phpstan/phpdoc-parser` represents PHPDocs with an AST (Abstract Syntax Tree). It supports parsing and modifying PHPDocs. For the complete list of supported PHPDoc features check out PHPStan documentation. PHPStan is the main (but not the only) user of this library. * [PHPDoc Basics](https://phpstan.org/writing-php-code/phpdocs-basics) (list of PHPDoc tags) * [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) (list of PHPDoc types) * [phpdoc-parser API Reference](https://phpstan.github.io/phpdoc-parser/2.1.x/namespace-PHPStan.PhpDocParser.html) with all the AST node types etc. This parser also supports parsing [Doctrine Annotations](https://github.com/doctrine/annotations). The AST nodes live in the [PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace](https://phpstan.github.io/phpdoc-parser/2.1.x/namespace-PHPStan.PhpDocParser.Ast.PhpDoc.Doctrine.html). ## Installation ``` composer require phpstan/phpdoc-parser ``` ## Basic usage ```php tokenize('/** @param Lorem $a */')); $phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode $paramTags = $phpDocNode->getParamTagValues(); // ParamTagValueNode[] echo $paramTags[0]->parameterName; // '$a' echo $paramTags[0]->type; // IdentifierTypeNode - 'Lorem' ``` ### Format-preserving printer This component can be used to modify the AST and print it again as close as possible to the original. It's heavily inspired by format-preserving printer component in [nikic/PHP-Parser](https://github.com/nikic/PHP-Parser). ```php true, 'indexes' => true, 'comments' => true]); $lexer = new Lexer($config); $constExprParser = new ConstExprParser($config); $typeParser = new TypeParser($config, $constExprParser); $phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser); $tokens = new TokenIterator($lexer->tokenize('/** @param Lorem $a */')); $phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode $cloningTraverser = new NodeTraverser([new CloningVisitor()]); /** @var PhpDocNode $newPhpDocNode */ [$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]); // change something in $newPhpDocNode $newPhpDocNode->getParamTagValues()[0]->type = new IdentifierTypeNode('Ipsum'); // print changed PHPDoc $printer = new Printer(); $newPhpDoc = $printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens); echo $newPhpDoc; // '/** @param Ipsum $a */' ``` ## Code of Conduct This project adheres to a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code. ## Building Initially you need to run `composer install`, or `composer update` in case you aren't working in a folder which was built before. Afterwards you can either run the whole build including linting and coding standards using make or run only tests using make tests Upgrading from phpstan/phpdoc-parser 1.x to 2.0 ================================= ### PHP version requirements phpstan/phpdoc-parser now requires PHP 7.4 or newer to run. ### Changed constructors of parser classes Instead of different arrays and boolean values passed into class constructors during setup, parser classes now share a common ParserConfig object. Before: ```php use PHPStan\PhpDocParser\Lexer\Lexer; use PHPStan\PhpDocParser\Parser\ConstExprParser; use PHPStan\PhpDocParser\Parser\TypeParser; use PHPStan\PhpDocParser\Parser\PhpDocParser; $usedAttributes = ['lines' => true, 'indexes' => true]; $lexer = new Lexer(); $constExprParser = new ConstExprParser(true, true, $usedAttributes); $typeParser = new TypeParser($constExprParser, true, $usedAttributes); $phpDocParser = new PhpDocParser($typeParser, $constExprParser, true, true, $usedAttributes); ``` After: ```php use PHPStan\PhpDocParser\Lexer\Lexer; use PHPStan\PhpDocParser\ParserConfig; use PHPStan\PhpDocParser\Parser\ConstExprParser; use PHPStan\PhpDocParser\Parser\TypeParser; use PHPStan\PhpDocParser\Parser\PhpDocParser; $config = new ParserConfig(usedAttributes: ['lines' => true, 'indexes' => true]); $lexer = new Lexer($config); $constExprParser = new ConstExprParser($config); $typeParser = new TypeParser($config, $constExprParser); $phpDocParser = new PhpDocParser($config, $typeParser, $constExprParser); ``` The point of ParserConfig is that over the course of phpstan/phpdoc-parser 2.x development series it's most likely going to gain new optional parameters akin to PHPStan's [bleeding edge](https://phpstan.org/blog/what-is-bleeding-edge). These parameters will allow opting in to new behaviour which will become the default in 3.0. With ParserConfig object, it's now going to be impossible to configure parser classes inconsistently. Which [happened to users](https://github.com/phpstan/phpdoc-parser/issues/251#issuecomment-2333927959) when they were separate boolean values. ### Support for parsing Doctrine annotations This parser now supports parsing [Doctrine Annotations](https://github.com/doctrine/annotations). The AST nodes representing Doctrine Annotations live in the [PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace](https://phpstan.github.io/phpdoc-parser/2.0.x/namespace-PHPStan.PhpDocParser.Ast.PhpDoc.Doctrine.html). ### Whitespace before description is required phpdoc-parser 1.x sometimes silently consumed invalid part of a PHPDoc type as description: ```php /** @return \Closure(...int, string): string */ ``` This became `IdentifierTypeNode` of `\Closure` and with `(...int, string): string` as description. (Valid callable syntax is: `\Closure(int ...$u, string): string`.) Another example: ```php /** @return array{foo: int}} */ ``` The extra `}` also became description. Both of these examples are now InvalidTagValueNode. If these parts are supposed to be PHPDoc descriptions, you need to put whitespace between the type and the description text: ```php /** @return \Closure (...int, string): string */ /** @return array{foo: int} } */ ``` ### Type aliases with invalid types are preserved In phpdoc-parser 1.x, invalid type alias syntax was represented as [`InvalidTagValueNode`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.PhpDoc.InvalidTagValueNode.html), losing information about a type alias being present. ```php /** * @phpstan-type TypeAlias */ ``` This `@phpstan-type` is missing the actual type to alias. In phpdoc-parser 2.0 this is now represented as [`TypeAliasTagValueNode`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.PhpDoc.TypeAliasTagValueNode.html) (instead of `InvalidTagValueNode`) with [`InvalidTypeNode`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.Type.InvalidTypeNode.html) in place of the type. ### Removal of QuoteAwareConstExprStringNode The class [QuoteAwareConstExprStringNode](https://phpstan.github.io/phpdoc-parser/1.23.x/PHPStan.PhpDocParser.Ast.ConstExpr.QuoteAwareConstExprStringNode.html) has been removed. Instead, [ConstExprStringNode](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.ConstExpr.ConstExprStringNode.html) gained information about the kind of quotes being used. ### Removed 2nd parameter of `ConstExprParser::parse()` (`$trimStrings`) `ConstExprStringNode::$value` now contains unescaped values without surrounding `''` or `""` quotes. Use `ConstExprStringNode::__toString()` or [`Printer`](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Printer.Printer.html) to get the escaped value along with surrounding quotes. ### Text between tags always belongs to description Multi-line descriptions between tags were previously represented as separate [PhpDocTextNode](https://phpstan.github.io/phpdoc-parser/2.0.x/PHPStan.PhpDocParser.Ast.PhpDoc.PhpDocTextNode.html): ```php /** * @param Foo $foo 1st multi world description * some text in the middle * @param Bar $bar 2nd multi world description */ ``` The line with `some text in the middle` in phpdoc-parser 2.0 is now part of the description of the first `@param` tag. ### `ArrayShapeNode` construction changes `ArrayShapeNode` constructor made private, added public static methods `createSealed()` and `createUnsealed()`. ### Minor BC breaks * Constructor parameter `$isEquality` in `AssertTag*ValueNode` made required * Constructor parameter `$templateTypes` in `MethodTagValueNode` made required * Constructor parameter `$isReference` in `ParamTagValueNode` made required * Constructor parameter `$isReference` in `TypelessParamTagValueNode` made required * Constructor parameter `$templateTypes` in `CallableTypeNode` made required * Constructor parameters `$expectedTokenValue` and `$currentTokenLine` in `ParserException` made required * `ArrayShapeItemNode` and `ObjectShapeItemNode` are not standalone TypeNode, just Node { "name": "phpstan\/phpdoc-parser", "description": "PHPDoc parser with support for nullable, intersection and generic types", "license": "MIT", "require": { "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine\/annotations": "^2.0", "nikic\/php-parser": "^5.3.0", "php-parallel-lint\/php-parallel-lint": "^1.2", "phpstan\/extension-installer": "^1.0", "phpstan\/phpstan": "^2.0", "phpstan\/phpstan-phpunit": "^2.0", "phpstan\/phpstan-strict-rules": "^2.0", "phpunit\/phpunit": "^9.6", "symfony\/process": "^5.2" }, "config": { "platform": { "php": "7.4.6" }, "sort-packages": true, "allow-plugins": { "phpstan\/extension-installer": true } }, "autoload": { "psr-4": { "_ContaoManager\\PHPStan\\PhpDocParser\\": [ "src\/" ] } }, "autoload-dev": { "psr-4": { "_ContaoManager\\PHPStan\\PhpDocParser\\": [ "tests\/PHPStan" ] } }, "minimum-stability": "dev", "prefer-stable": true } '\'&\'', self::TOKEN_UNION => '\'|\'', self::TOKEN_INTERSECTION => '\'&\'', self::TOKEN_NULLABLE => '\'?\'', self::TOKEN_NEGATED => '\'!\'', self::TOKEN_OPEN_PARENTHESES => '\'(\'', self::TOKEN_CLOSE_PARENTHESES => '\')\'', self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'', self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'', self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'', self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'', self::TOKEN_OPEN_CURLY_BRACKET => '\'{\'', self::TOKEN_CLOSE_CURLY_BRACKET => '\'}\'', self::TOKEN_COMMA => '\',\'', self::TOKEN_COMMENT => '\'//\'', self::TOKEN_COLON => '\':\'', self::TOKEN_VARIADIC => '\'...\'', self::TOKEN_DOUBLE_COLON => '\'::\'', self::TOKEN_DOUBLE_ARROW => '\'=>\'', self::TOKEN_ARROW => '\'->\'', self::TOKEN_EQUAL => '\'=\'', self::TOKEN_OPEN_PHPDOC => '\'/**\'', self::TOKEN_CLOSE_PHPDOC => '\'*/\'', self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG', self::TOKEN_DOCTRINE_TAG => 'TOKEN_DOCTRINE_TAG', self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL', self::TOKEN_FLOAT => 'TOKEN_FLOAT', self::TOKEN_INTEGER => 'TOKEN_INTEGER', self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING', self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING', self::TOKEN_DOCTRINE_ANNOTATION_STRING => 'TOKEN_DOCTRINE_ANNOTATION_STRING', self::TOKEN_IDENTIFIER => 'type', self::TOKEN_THIS_VARIABLE => '\'$this\'', self::TOKEN_VARIABLE => 'variable', self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS', self::TOKEN_OTHER => 'TOKEN_OTHER', self::TOKEN_END => 'TOKEN_END', self::TOKEN_WILDCARD => '*']; public const VALUE_OFFSET = 0; public const TYPE_OFFSET = 1; public const LINE_OFFSET = 2; private ParserConfig $config; // @phpstan-ignore property.onlyWritten private ?string $regexp = null; public function __construct(ParserConfig $config) { $this->config = $config; } /** * @return list */ public function tokenize(string $s) : array { if ($this->regexp === null) { $this->regexp = $this->generateRegexp(); } preg_match_all($this->regexp, $s, $matches, PREG_SET_ORDER); $tokens = []; $line = 1; foreach ($matches as $match) { $type = (int) $match['MARK']; $tokens[] = [$match[0], $type, $line]; if ($type !== self::TOKEN_PHPDOC_EOL) { continue; } $line++; } $tokens[] = ['', self::TOKEN_END, $line]; return $tokens; } private function generateRegexp() : string { $patterns = [ self::TOKEN_HORIZONTAL_WS => '[\\x09\\x20]++', self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF-]*+)++', self::TOKEN_THIS_VARIABLE => '\\$this(?![0-9a-z_\\x80-\\xFF])', self::TOKEN_VARIABLE => '\\$[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF]*+', // '&' followed by TOKEN_VARIADIC, TOKEN_VARIABLE, TOKEN_EQUAL, TOKEN_EQUAL or TOKEN_CLOSE_PARENTHESES self::TOKEN_REFERENCE => '&(?=\\s*+(?:[.,=)]|(?:\\$(?!this(?![0-9a-z_\\x80-\\xFF])))))', self::TOKEN_UNION => '\\|', self::TOKEN_INTERSECTION => '&', self::TOKEN_NULLABLE => '\\?', self::TOKEN_NEGATED => '!', self::TOKEN_OPEN_PARENTHESES => '\\(', self::TOKEN_CLOSE_PARENTHESES => '\\)', self::TOKEN_OPEN_ANGLE_BRACKET => '<', self::TOKEN_CLOSE_ANGLE_BRACKET => '>', self::TOKEN_OPEN_SQUARE_BRACKET => '\\[', self::TOKEN_CLOSE_SQUARE_BRACKET => '\\]', self::TOKEN_OPEN_CURLY_BRACKET => '\\{', self::TOKEN_CLOSE_CURLY_BRACKET => '\\}', self::TOKEN_COMMA => ',', self::TOKEN_COMMENT => '\\/\\/[^\\r\\n]*(?=\\n|\\r|\\*/)', self::TOKEN_VARIADIC => '\\.\\.\\.', self::TOKEN_DOUBLE_COLON => '::', self::TOKEN_DOUBLE_ARROW => '=>', self::TOKEN_ARROW => '->', self::TOKEN_EQUAL => '=', self::TOKEN_COLON => ':', self::TOKEN_OPEN_PHPDOC => '/\\*\\*(?=\\s)\\x20?+', self::TOKEN_CLOSE_PHPDOC => '\\*/', self::TOKEN_PHPDOC_TAG => '@(?:[a-z][a-z0-9-\\\\]+:)?[a-z][a-z0-9-\\\\]*+', self::TOKEN_DOCTRINE_TAG => '@[a-z_\\\\][a-z0-9_\\:\\\\]*[a-z_][a-z0-9_]*', self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/)\\x20?+)?', self::TOKEN_FLOAT => '[+\\-]?(?:(?:[0-9]++(_[0-9]++)*\\.[0-9]*+(_[0-9]++)*(?:e[+\\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]*+(_[0-9]++)*\\.[0-9]++(_[0-9]++)*(?:e[+\\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]++(_[0-9]++)*e[+\\-]?[0-9]++(_[0-9]++)*))', self::TOKEN_INTEGER => '[+\\-]?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))', self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\\r\\n]|[^\'\\r\\n\\\\])*+\'', self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\\r\\n]|[^"\\r\\n\\\\])*+"', self::TOKEN_DOCTRINE_ANNOTATION_STRING => '"(?:""|[^"])*+"', self::TOKEN_WILDCARD => '\\*', // anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL self::TOKEN_OTHER => '(?:(?!\\*/)[^\\s])++', ]; foreach ($patterns as $type => &$pattern) { $pattern = '(?:' . $pattern . ')(*MARK:' . $type . ')'; } return '~' . implode('|', $patterns) . '~Asi'; } } type = $type; $this->old = $old; $this->new = $new; } } isEqual = $isEqual; } /** * Calculate diff (edit script) from $old to $new. * * @param T[] $old Original array * @param T[] $new New array * * @return DiffElem[] Diff (edit script) */ public function diff(array $old, array $new) : array { [$trace, $x, $y] = $this->calculateTrace($old, $new); return $this->extractDiff($trace, $x, $y, $old, $new); } /** * Calculate diff, including "replace" operations. * * If a sequence of remove operations is followed by the same number of add operations, these * will be coalesced into replace operations. * * @param T[] $old Original array * @param T[] $new New array * * @return DiffElem[] Diff (edit script), including replace operations */ public function diffWithReplacements(array $old, array $new) : array { return $this->coalesceReplacements($this->diff($old, $new)); } /** * @param T[] $old * @param T[] $new * @return array{array>, int, int} */ private function calculateTrace(array $old, array $new) : array { $n = count($old); $m = count($new); $max = $n + $m; $v = [1 => 0]; $trace = []; for ($d = 0; $d <= $max; $d++) { $trace[] = $v; for ($k = -$d; $k <= $d; $k += 2) { if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $x = $v[$k + 1]; } else { $x = $v[$k - 1] + 1; } $y = $x - $k; while ($x < $n && $y < $m && ($this->isEqual)($old[$x], $new[$y])) { $x++; $y++; } $v[$k] = $x; if ($x >= $n && $y >= $m) { return [$trace, $x, $y]; } } } throw new Exception('Should not happen'); } /** * @param array> $trace * @param T[] $old * @param T[] $new * @return DiffElem[] */ private function extractDiff(array $trace, int $x, int $y, array $old, array $new) : array { $result = []; for ($d = count($trace) - 1; $d >= 0; $d--) { $v = $trace[$d]; $k = $x - $y; if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $prevK = $k + 1; } else { $prevK = $k - 1; } $prevX = $v[$prevK]; $prevY = $prevX - $prevK; while ($x > $prevX && $y > $prevY) { $result[] = new DiffElem(DiffElem::TYPE_KEEP, $old[$x - 1], $new[$y - 1]); $x--; $y--; } if ($d === 0) { break; } while ($x > $prevX) { $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $old[$x - 1], null); $x--; } while ($y > $prevY) { $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $new[$y - 1]); $y--; } } return array_reverse($result); } /** * Coalesce equal-length sequences of remove+add into a replace operation. * * @param DiffElem[] $diff * @return DiffElem[] */ private function coalesceReplacements(array $diff) : array { $newDiff = []; $c = count($diff); for ($i = 0; $i < $c; $i++) { $diffType = $diff[$i]->type; if ($diffType !== DiffElem::TYPE_REMOVE) { $newDiff[] = $diff[$i]; continue; } $j = $i; while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) { $j++; } $k = $j; while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) { $k++; } if ($j - $i === $k - $j) { $len = $j - $i; for ($n = 0; $n < $len; $n++) { $newDiff[] = new DiffElem(DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new); } } else { for (; $i < $k; $i++) { $newDiff[] = $diff[$i]; } } $i = $k - 1; } return $newDiff; } } */ private Differ $differ; /** * Map From "{$class}->{$subNode}" to string that should be inserted * between elements of this list subnode * * @var array */ private array $listInsertionMap = [PhpDocNode::class . '->children' => "\n * ", UnionTypeNode::class . '->types' => '|', IntersectionTypeNode::class . '->types' => '&', ArrayShapeNode::class . '->items' => ', ', ObjectShapeNode::class . '->items' => ', ', CallableTypeNode::class . '->parameters' => ', ', CallableTypeNode::class . '->templateTypes' => ', ', GenericTypeNode::class . '->genericTypes' => ', ', ConstExprArrayNode::class . '->items' => ', ', MethodTagValueNode::class . '->parameters' => ', ', DoctrineArray::class . '->items' => ', ', DoctrineAnnotation::class . '->arguments' => ', ']; /** * [$find, $extraLeft, $extraRight] * * @var array */ private array $emptyListInsertionMap = [CallableTypeNode::class . '->parameters' => ['(', '', ''], ArrayShapeNode::class . '->items' => ['{', '', ''], ObjectShapeNode::class . '->items' => ['{', '', ''], DoctrineArray::class . '->items' => ['{', '', ''], DoctrineAnnotation::class . '->arguments' => ['(', '', '']]; /** @var array>> */ private array $parenthesesMap = [CallableTypeNode::class . '->returnType' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class], ArrayTypeNode::class . '->type' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class, ConstTypeNode::class, NullableTypeNode::class], OffsetAccessTypeNode::class . '->type' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class, NullableTypeNode::class]]; /** @var array>> */ private array $parenthesesListMap = [IntersectionTypeNode::class . '->types' => [IntersectionTypeNode::class, UnionTypeNode::class, NullableTypeNode::class], UnionTypeNode::class . '->types' => [IntersectionTypeNode::class, UnionTypeNode::class, NullableTypeNode::class]]; public function printFormatPreserving(PhpDocNode $node, PhpDocNode $originalNode, TokenIterator $originalTokens) : string { $this->differ = new Differ(static function ($a, $b) { if ($a instanceof Node && $b instanceof Node) { return $a === $b->getAttribute(Attribute::ORIGINAL_NODE); } return \false; }); $tokenIndex = 0; $result = $this->printArrayFormatPreserving($node->children, $originalNode->children, $originalTokens, $tokenIndex, PhpDocNode::class, 'children'); if ($result !== null) { return $result . $originalTokens->getContentBetween($tokenIndex, $originalTokens->getTokenCount()); } return $this->print($node); } public function print(Node $node) : string { if ($node instanceof PhpDocNode) { return "/**\n *" . implode("\n *", array_map(function (PhpDocChildNode $child) : string { $s = $this->print($child); return $s === '' ? '' : ' ' . $s; }, $node->children)) . "\n */"; } if ($node instanceof PhpDocTextNode) { return $node->text; } if ($node instanceof PhpDocTagNode) { if ($node->value instanceof DoctrineTagValueNode) { return $this->print($node->value); } return trim(sprintf('%s %s', $node->name, $this->print($node->value))); } if ($node instanceof PhpDocTagValueNode) { return $this->printTagValue($node); } if ($node instanceof TypeNode) { return $this->printType($node); } if ($node instanceof ConstExprNode) { return $this->printConstExpr($node); } if ($node instanceof MethodTagValueParameterNode) { $type = $node->type !== null ? $this->print($node->type) . ' ' : ''; $isReference = $node->isReference ? '&' : ''; $isVariadic = $node->isVariadic ? '...' : ''; $default = $node->defaultValue !== null ? ' = ' . $this->print($node->defaultValue) : ''; return "{$type}{$isReference}{$isVariadic}{$node->parameterName}{$default}"; } if ($node instanceof CallableTypeParameterNode) { $type = $this->print($node->type) . ' '; $isReference = $node->isReference ? '&' : ''; $isVariadic = $node->isVariadic ? '...' : ''; $isOptional = $node->isOptional ? '=' : ''; return trim("{$type}{$isReference}{$isVariadic}{$node->parameterName}") . $isOptional; } if ($node instanceof ArrayShapeUnsealedTypeNode) { if ($node->keyType !== null) { return sprintf('<%s, %s>', $this->printType($node->keyType), $this->printType($node->valueType)); } return sprintf('<%s>', $this->printType($node->valueType)); } if ($node instanceof DoctrineAnnotation) { return (string) $node; } if ($node instanceof DoctrineArgument) { return (string) $node; } if ($node instanceof DoctrineArray) { return (string) $node; } if ($node instanceof DoctrineArrayItem) { return (string) $node; } if ($node instanceof ArrayShapeItemNode) { if ($node->keyName !== null) { return sprintf('%s%s: %s', $this->print($node->keyName), $node->optional ? '?' : '', $this->printType($node->valueType)); } return $this->printType($node->valueType); } if ($node instanceof ObjectShapeItemNode) { if ($node->keyName !== null) { return sprintf('%s%s: %s', $this->print($node->keyName), $node->optional ? '?' : '', $this->printType($node->valueType)); } return $this->printType($node->valueType); } throw new LogicException(sprintf('Unknown node type %s', get_class($node))); } private function printTagValue(PhpDocTagValueNode $node) : string { // only nodes that contain another node are handled here // the rest falls back on (string) $node if ($node instanceof AssertTagMethodValueNode) { $isNegated = $node->isNegated ? '!' : ''; $isEquality = $node->isEquality ? '=' : ''; $type = $this->printType($node->type); return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->method}() {$node->description}"); } if ($node instanceof AssertTagPropertyValueNode) { $isNegated = $node->isNegated ? '!' : ''; $isEquality = $node->isEquality ? '=' : ''; $type = $this->printType($node->type); return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->property} {$node->description}"); } if ($node instanceof AssertTagValueNode) { $isNegated = $node->isNegated ? '!' : ''; $isEquality = $node->isEquality ? '=' : ''; $type = $this->printType($node->type); return trim("{$isNegated}{$isEquality}{$type} {$node->parameter} {$node->description}"); } if ($node instanceof ExtendsTagValueNode || $node instanceof ImplementsTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->description}"); } if ($node instanceof MethodTagValueNode) { $static = $node->isStatic ? 'static ' : ''; $returnType = $node->returnType !== null ? $this->printType($node->returnType) . ' ' : ''; $parameters = implode(', ', array_map(fn(MethodTagValueParameterNode $parameter): string => $this->print($parameter), $node->parameters)); $description = $node->description !== '' ? " {$node->description}" : ''; $templateTypes = count($node->templateTypes) > 0 ? '<' . implode(', ', array_map(fn(TemplateTagValueNode $templateTag): string => $this->print($templateTag), $node->templateTypes)) . '>' : ''; return "{$static}{$returnType}{$node->methodName}{$templateTypes}({$parameters}){$description}"; } if ($node instanceof MixinTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->description}"); } if ($node instanceof RequireExtendsTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->description}"); } if ($node instanceof RequireImplementsTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->description}"); } if ($node instanceof ParamOutTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->parameterName} {$node->description}"); } if ($node instanceof ParamTagValueNode) { $reference = $node->isReference ? '&' : ''; $variadic = $node->isVariadic ? '...' : ''; $type = $this->printType($node->type); return trim("{$type} {$reference}{$variadic}{$node->parameterName} {$node->description}"); } if ($node instanceof ParamImmediatelyInvokedCallableTagValueNode) { return trim("{$node->parameterName} {$node->description}"); } if ($node instanceof ParamLaterInvokedCallableTagValueNode) { return trim("{$node->parameterName} {$node->description}"); } if ($node instanceof ParamClosureThisTagValueNode) { return trim("{$node->type} {$node->parameterName} {$node->description}"); } if ($node instanceof PureUnlessCallableIsImpureTagValueNode) { return trim("{$node->parameterName} {$node->description}"); } if ($node instanceof PropertyTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->propertyName} {$node->description}"); } if ($node instanceof ReturnTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->description}"); } if ($node instanceof SelfOutTagValueNode) { $type = $this->printType($node->type); return trim($type . ' ' . $node->description); } if ($node instanceof TemplateTagValueNode) { $upperBound = $node->bound !== null ? ' of ' . $this->printType($node->bound) : ''; $lowerBound = $node->lowerBound !== null ? ' super ' . $this->printType($node->lowerBound) : ''; $default = $node->default !== null ? ' = ' . $this->printType($node->default) : ''; return trim("{$node->name}{$upperBound}{$lowerBound}{$default} {$node->description}"); } if ($node instanceof ThrowsTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->description}"); } if ($node instanceof TypeAliasImportTagValueNode) { return trim("{$node->importedAlias} from " . $this->printType($node->importedFrom) . ($node->importedAs !== null ? " as {$node->importedAs}" : '')); } if ($node instanceof TypeAliasTagValueNode) { $type = $this->printType($node->type); return trim("{$node->alias} {$type}"); } if ($node instanceof UsesTagValueNode) { $type = $this->printType($node->type); return trim("{$type} {$node->description}"); } if ($node instanceof VarTagValueNode) { $type = $this->printType($node->type); return trim("{$type} " . trim("{$node->variableName} {$node->description}")); } return (string) $node; } private function printType(TypeNode $node) : string { if ($node instanceof ArrayShapeNode) { $items = array_map(fn(ArrayShapeItemNode $item): string => $this->print($item), $node->items); if (!$node->sealed) { $items[] = '...' . ($node->unsealedType === null ? '' : $this->print($node->unsealedType)); } return $node->kind . '{' . implode(', ', $items) . '}'; } if ($node instanceof ArrayTypeNode) { return $this->printOffsetAccessType($node->type) . '[]'; } if ($node instanceof CallableTypeNode) { if ($node->returnType instanceof CallableTypeNode || $node->returnType instanceof UnionTypeNode || $node->returnType instanceof IntersectionTypeNode) { $returnType = $this->wrapInParentheses($node->returnType); } else { $returnType = $this->printType($node->returnType); } $template = $node->templateTypes !== [] ? '<' . implode(', ', array_map(fn(TemplateTagValueNode $templateNode): string => $this->print($templateNode), $node->templateTypes)) . '>' : ''; $parameters = implode(', ', array_map(fn(CallableTypeParameterNode $parameterNode): string => $this->print($parameterNode), $node->parameters)); return "{$node->identifier}{$template}({$parameters}): {$returnType}"; } if ($node instanceof ConditionalTypeForParameterNode) { return sprintf('(%s %s %s ? %s : %s)', $node->parameterName, $node->negated ? 'is not' : 'is', $this->printType($node->targetType), $this->printType($node->if), $this->printType($node->else)); } if ($node instanceof ConditionalTypeNode) { return sprintf('(%s %s %s ? %s : %s)', $this->printType($node->subjectType), $node->negated ? 'is not' : 'is', $this->printType($node->targetType), $this->printType($node->if), $this->printType($node->else)); } if ($node instanceof ConstTypeNode) { return $this->printConstExpr($node->constExpr); } if ($node instanceof GenericTypeNode) { $genericTypes = []; foreach ($node->genericTypes as $index => $type) { $variance = $node->variances[$index] ?? GenericTypeNode::VARIANCE_INVARIANT; if ($variance === GenericTypeNode::VARIANCE_INVARIANT) { $genericTypes[] = $this->printType($type); } elseif ($variance === GenericTypeNode::VARIANCE_BIVARIANT) { $genericTypes[] = '*'; } else { $genericTypes[] = sprintf('%s %s', $variance, $this->print($type)); } } return $node->type . '<' . implode(', ', $genericTypes) . '>'; } if ($node instanceof IdentifierTypeNode) { return $node->name; } if ($node instanceof IntersectionTypeNode || $node instanceof UnionTypeNode) { $items = []; foreach ($node->types as $type) { if ($type instanceof IntersectionTypeNode || $type instanceof UnionTypeNode || $type instanceof NullableTypeNode) { $items[] = $this->wrapInParentheses($type); continue; } $items[] = $this->printType($type); } return implode($node instanceof IntersectionTypeNode ? '&' : '|', $items); } if ($node instanceof InvalidTypeNode) { return (string) $node; } if ($node instanceof NullableTypeNode) { if ($node->type instanceof IntersectionTypeNode || $node->type instanceof UnionTypeNode) { return '?(' . $this->printType($node->type) . ')'; } return '?' . $this->printType($node->type); } if ($node instanceof ObjectShapeNode) { $items = array_map(fn(ObjectShapeItemNode $item): string => $this->print($item), $node->items); return 'object{' . implode(', ', $items) . '}'; } if ($node instanceof OffsetAccessTypeNode) { return $this->printOffsetAccessType($node->type) . '[' . $this->printType($node->offset) . ']'; } if ($node instanceof ThisTypeNode) { return (string) $node; } throw new LogicException(sprintf('Unknown node type %s', get_class($node))); } private function wrapInParentheses(TypeNode $node) : string { return '(' . $this->printType($node) . ')'; } private function printOffsetAccessType(TypeNode $type) : string { if ($type instanceof CallableTypeNode || $type instanceof UnionTypeNode || $type instanceof IntersectionTypeNode || $type instanceof NullableTypeNode) { return $this->wrapInParentheses($type); } return $this->printType($type); } private function printConstExpr(ConstExprNode $node) : string { // this is fine - ConstExprNode classes do not contain nodes that need smart printer logic return (string) $node; } /** * @param Node[] $nodes * @param Node[] $originalNodes */ private function printArrayFormatPreserving(array $nodes, array $originalNodes, TokenIterator $originalTokens, int &$tokenIndex, string $parentNodeClass, string $subNodeName) : ?string { $diff = $this->differ->diffWithReplacements($originalNodes, $nodes); $mapKey = $parentNodeClass . '->' . $subNodeName; $insertStr = $this->listInsertionMap[$mapKey] ?? null; $result = ''; $beforeFirstKeepOrReplace = \true; $delayedAdd = []; $insertNewline = \false; [$isMultiline, $beforeAsteriskIndent, $afterAsteriskIndent] = $this->isMultiline($tokenIndex, $originalNodes, $originalTokens); if ($insertStr === "\n * ") { $insertStr = sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } foreach ($diff as $i => $diffElem) { $diffType = $diffElem->type; $arrItem = $diffElem->new; $origArrayItem = $diffElem->old; if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) { $beforeFirstKeepOrReplace = \false; if (!$arrItem instanceof Node || !$origArrayItem instanceof Node) { return null; } /** @var int $itemStartPos */ $itemStartPos = $origArrayItem->getAttribute(Attribute::START_INDEX); /** @var int $itemEndPos */ $itemEndPos = $origArrayItem->getAttribute(Attribute::END_INDEX); if ($itemStartPos < 0 || $itemEndPos < 0 || $itemStartPos < $tokenIndex) { throw new LogicException(); } $comments = $arrItem->getAttribute(Attribute::COMMENTS) ?? []; $origComments = $origArrayItem->getAttribute(Attribute::COMMENTS) ?? []; $commentStartPos = count($origComments) > 0 ? $origComments[0]->startIndex : $itemStartPos; assert($commentStartPos >= 0); $result .= $originalTokens->getContentBetween($tokenIndex, $itemStartPos); if (count($delayedAdd) > 0) { foreach ($delayedAdd as $delayedAddNode) { $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) && in_array(get_class($delayedAddNode), $this->parenthesesListMap[$mapKey], \true); if ($parenthesesNeeded) { $result .= '('; } if ($insertNewline) { $delayedAddComments = $delayedAddNode->getAttribute(Attribute::COMMENTS) ?? []; if (count($delayedAddComments) > 0) { $result .= $this->printComments($delayedAddComments, $beforeAsteriskIndent, $afterAsteriskIndent); $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } } $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens); if ($parenthesesNeeded) { $result .= ')'; } if ($insertNewline) { $result .= $insertStr . sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } else { $result .= $insertStr; } } $delayedAdd = []; } $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) && in_array(get_class($arrItem), $this->parenthesesListMap[$mapKey], \true) && !in_array(get_class($origArrayItem), $this->parenthesesListMap[$mapKey], \true); $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($itemStartPos, $itemEndPos); if ($addParentheses) { $result .= '('; } if ($comments !== $origComments) { if (count($comments) > 0) { $result .= $this->printComments($comments, $beforeAsteriskIndent, $afterAsteriskIndent); $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } } $result .= $this->printNodeFormatPreserving($arrItem, $originalTokens); if ($addParentheses) { $result .= ')'; } $tokenIndex = $itemEndPos + 1; } elseif ($diffType === DiffElem::TYPE_ADD) { if ($insertStr === null) { return null; } if (!$arrItem instanceof Node) { return null; } if ($insertStr === ', ' && $isMultiline || count($arrItem->getAttribute(Attribute::COMMENTS) ?? []) > 0) { $insertStr = ','; $insertNewline = \true; } if ($beforeFirstKeepOrReplace) { // Will be inserted at the next "replace" or "keep" element $delayedAdd[] = $arrItem; continue; } /** @var int $itemEndPos */ $itemEndPos = $tokenIndex - 1; if ($insertNewline) { $comments = $arrItem->getAttribute(Attribute::COMMENTS) ?? []; $result .= $insertStr; if (count($comments) > 0) { $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); $result .= $this->printComments($comments, $beforeAsteriskIndent, $afterAsteriskIndent); } $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } else { $result .= $insertStr; } $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) && in_array(get_class($arrItem), $this->parenthesesListMap[$mapKey], \true); if ($parenthesesNeeded) { $result .= '('; } $result .= $this->printNodeFormatPreserving($arrItem, $originalTokens); if ($parenthesesNeeded) { $result .= ')'; } $tokenIndex = $itemEndPos + 1; } elseif ($diffType === DiffElem::TYPE_REMOVE) { if (!$origArrayItem instanceof Node) { return null; } /** @var int $itemStartPos */ $itemStartPos = $origArrayItem->getAttribute(Attribute::START_INDEX); /** @var int $itemEndPos */ $itemEndPos = $origArrayItem->getAttribute(Attribute::END_INDEX); if ($itemStartPos < 0 || $itemEndPos < 0) { throw new LogicException(); } if ($i === 0) { // If we're removing from the start, keep the tokens before the node and drop those after it, // instead of the other way around. $originalTokensArray = $originalTokens->getTokens(); for ($j = $tokenIndex; $j < $itemStartPos; $j++) { if ($originalTokensArray[$j][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) { break; } $result .= $originalTokensArray[$j][Lexer::VALUE_OFFSET]; } } $tokenIndex = $itemEndPos + 1; } } if (count($delayedAdd) > 0) { if (!isset($this->emptyListInsertionMap[$mapKey])) { return null; } [$findToken, $extraLeft, $extraRight] = $this->emptyListInsertionMap[$mapKey]; if ($findToken !== null) { $originalTokensArray = $originalTokens->getTokens(); for (; $tokenIndex < count($originalTokensArray); $tokenIndex++) { $result .= $originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET]; if ($originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET] !== $findToken) { continue; } $tokenIndex++; break; } } $first = \true; $result .= $extraLeft; foreach ($delayedAdd as $delayedAddNode) { if (!$first) { $result .= $insertStr; if ($insertNewline) { $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } } $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens); $first = \false; } $result .= $extraRight; } return $result; } /** * @param list $comments */ private function printComments(array $comments, string $beforeAsteriskIndent, string $afterAsteriskIndent) : string { $formattedComments = []; foreach ($comments as $comment) { $formattedComments[] = str_replace("\n", "\n" . $beforeAsteriskIndent . '*' . $afterAsteriskIndent, $comment->getReformattedText()); } return implode("\n{$beforeAsteriskIndent}*{$afterAsteriskIndent}", $formattedComments); } /** * @param array $nodes * @return array{bool, string, string} */ private function isMultiline(int $initialIndex, array $nodes, TokenIterator $originalTokens) : array { $isMultiline = count($nodes) > 1; $pos = $initialIndex; $allText = ''; /** @var Node|null $node */ foreach ($nodes as $node) { if (!$node instanceof Node) { continue; } $endPos = $node->getAttribute(Attribute::END_INDEX) + 1; $text = $originalTokens->getContentBetween($pos, $endPos); $allText .= $text; if (strpos($text, "\n") === \false) { // We require that a newline is present between *every* item. If the formatting // is inconsistent, with only some items having newlines, we don't consider it // as multiline $isMultiline = \false; } $pos = $endPos; } $c = preg_match_all('~\\n(?[\\x09\\x20]*)\\*(?\\x20*)~', $allText, $matches, PREG_SET_ORDER); if ($c === 0) { return [$isMultiline, ' ', ' ']; } $before = ''; $after = ''; foreach ($matches as $match) { if (strlen($match['before']) > strlen($before)) { $before = $match['before']; } if (strlen($match['after']) <= strlen($after)) { continue; } $after = $match['after']; } $before = strlen($before) === 0 ? ' ' : $before; $after = strlen($after) === 0 ? ' ' : $after; return [$isMultiline, $before, $after]; } private function printNodeFormatPreserving(Node $node, TokenIterator $originalTokens) : string { /** @var Node|null $originalNode */ $originalNode = $node->getAttribute(Attribute::ORIGINAL_NODE); if ($originalNode === null) { return $this->print($node); } $class = get_class($node); if ($class !== get_class($originalNode)) { throw new LogicException(); } $startPos = $originalNode->getAttribute(Attribute::START_INDEX); $endPos = $originalNode->getAttribute(Attribute::END_INDEX); if ($startPos < 0 || $endPos < 0) { throw new LogicException(); } $result = ''; $pos = $startPos; $subNodeNames = array_keys(get_object_vars($node)); foreach ($subNodeNames as $subNodeName) { $subNode = $node->{$subNodeName}; $origSubNode = $originalNode->{$subNodeName}; if (!$subNode instanceof Node && $subNode !== null || !$origSubNode instanceof Node && $origSubNode !== null) { if ($subNode === $origSubNode) { // Unchanged, can reuse old code continue; } if (is_array($subNode) && is_array($origSubNode)) { // Array subnode changed, we might be able to reconstruct it $listResult = $this->printArrayFormatPreserving($subNode, $origSubNode, $originalTokens, $pos, $class, $subNodeName); if ($listResult === null) { return $this->print($node); } $result .= $listResult; continue; } return $this->print($node); } if ($origSubNode === null) { if ($subNode === null) { // Both null, nothing to do continue; } return $this->print($node); } $subStartPos = $origSubNode->getAttribute(Attribute::START_INDEX); $subEndPos = $origSubNode->getAttribute(Attribute::END_INDEX); if ($subStartPos < 0 || $subEndPos < 0) { throw new LogicException(); } if ($subEndPos < $subStartPos) { return $this->print($node); } if ($subNode === null) { return $this->print($node); } $result .= $originalTokens->getContentBetween($pos, $subStartPos); $mapKey = get_class($node) . '->' . $subNodeName; $parenthesesNeeded = isset($this->parenthesesMap[$mapKey]) && in_array(get_class($subNode), $this->parenthesesMap[$mapKey], \true); if ($subNode->getAttribute(Attribute::ORIGINAL_NODE) !== null) { $parenthesesNeeded = $parenthesesNeeded && !in_array(get_class($subNode->getAttribute(Attribute::ORIGINAL_NODE)), $this->parenthesesMap[$mapKey], \true); } $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($subStartPos, $subEndPos); if ($addParentheses) { $result .= '('; } $result .= $this->printNodeFormatPreserving($subNode, $originalTokens); if ($addParentheses) { $result .= ')'; } $pos = $subEndPos + 1; } return $result . $originalTokens->getContentBetween($pos, $endPos + 1); } } currentTokenValue = $currentTokenValue; $this->currentTokenType = $currentTokenType; $this->currentOffset = $currentOffset; $this->expectedTokenType = $expectedTokenType; $this->expectedTokenValue = $expectedTokenValue; $this->currentTokenLine = $currentTokenLine; parent::__construct(sprintf('Unexpected token %s, expected %s%s at offset %d%s', $this->formatValue($currentTokenValue), Lexer::TOKEN_LABELS[$expectedTokenType], $expectedTokenValue !== null ? sprintf(' (%s)', $this->formatValue($expectedTokenValue)) : '', $currentOffset, $currentTokenLine === null ? '' : sprintf(' on line %d', $currentTokenLine))); } public function getCurrentTokenValue() : string { return $this->currentTokenValue; } public function getCurrentTokenType() : int { return $this->currentTokenType; } public function getCurrentOffset() : int { return $this->currentOffset; } public function getExpectedTokenType() : int { return $this->expectedTokenType; } public function getExpectedTokenValue() : ?string { return $this->expectedTokenValue; } public function getCurrentTokenLine() : ?int { return $this->currentTokenLine; } private function formatValue(string $value) : string { $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE); assert($json !== \false); return $json; } } config = $config; $this->typeParser = $typeParser; $this->constantExprParser = $constantExprParser; $this->doctrineConstantExprParser = $constantExprParser->toDoctrine(); } public function parse(TokenIterator $tokens) : Ast\PhpDoc\PhpDocNode { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC); $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); $children = []; if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { $lastChild = $this->parseChild($tokens); $children[] = $lastChild; while (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode && ($lastChild->value instanceof Doctrine\DoctrineTagValueNode || $lastChild->value instanceof Ast\PhpDoc\GenericTagValueNode)) { $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { break; } $lastChild = $this->parseChild($tokens); $children[] = $lastChild; continue; } if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL)) { break; } if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { break; } $lastChild = $this->parseChild($tokens); $children[] = $lastChild; } } try { $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC); } catch (ParserException $e) { $name = ''; $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if (count($children) > 0) { $lastChild = $children[count($children) - 1]; if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode) { $name = $lastChild->name; $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); } } $tag = new Ast\PhpDoc\PhpDocTagNode($name, $this->enrichWithAttributes($tokens, new Ast\PhpDoc\InvalidTagValueNode($e->getMessage(), $e), $startLine, $startIndex)); $tokens->forwardToTheEnd(); $comments = $tokens->flushComments(); if ($comments !== []) { throw new LogicException('Comments should already be flushed'); } return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode([$this->enrichWithAttributes($tokens, $tag, $startLine, $startIndex)]), 1, 0); } $comments = $tokens->flushComments(); if ($comments !== []) { throw new LogicException('Comments should already be flushed'); } return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode($children), 1, 0); } /** @phpstan-impure */ private function parseChild(TokenIterator $tokens) : Ast\PhpDoc\PhpDocChildNode { if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); return $this->enrichWithAttributes($tokens, $this->parseTag($tokens), $startLine, $startIndex); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_TAG)) { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $tag = $tokens->currentTokenValue(); $tokens->next(); $tagStartLine = $tokens->currentTokenLine(); $tagStartIndex = $tokens->currentTokenIndex(); return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocTagNode($tag, $this->enrichWithAttributes($tokens, $this->parseDoctrineTagValue($tokens, $tag), $tagStartLine, $tagStartIndex)), $startLine, $startIndex); } $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $text = $this->parseText($tokens); return $this->enrichWithAttributes($tokens, $text, $startLine, $startIndex); } /** * @template T of Ast\Node * @param T $tag * @return T */ private function enrichWithAttributes(TokenIterator $tokens, Ast\Node $tag, int $startLine, int $startIndex) : Ast\Node { if ($this->config->useLinesAttributes) { $tag->setAttribute(Ast\Attribute::START_LINE, $startLine); $tag->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); } if ($this->config->useIndexAttributes) { $tag->setAttribute(Ast\Attribute::START_INDEX, $startIndex); $tag->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); } return $tag; } private function parseText(TokenIterator $tokens) : Ast\PhpDoc\PhpDocTextNode { $text = ''; $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; $savepoint = \false; // if the next token is EOL, everything below is skipped and empty string is returned while (\true) { $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, ...$endTokens); $text .= $tmpText; // stop if we're not at EOL - meaning it's the end of PHPDoc if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC)) { break; } if (!$savepoint) { $tokens->pushSavePoint(); $savepoint = \true; } elseif ($tmpText !== '') { $tokens->dropSavePoint(); $tokens->pushSavePoint(); } $tokens->pushSavePoint(); $tokens->next(); // if we're at EOL, check what's next // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) { $tokens->rollback(); break; } // otherwise if the next is text, continue building the description string $tokens->dropSavePoint(); $text .= $tokens->getDetectedNewline() ?? "\n"; } if ($savepoint) { $tokens->rollback(); $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n"); } return new Ast\PhpDoc\PhpDocTextNode(trim($text, " \t")); } private function parseOptionalDescriptionAfterDoctrineTag(TokenIterator $tokens) : string { $text = ''; $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; $savepoint = \false; // if the next token is EOL, everything below is skipped and empty string is returned while (\true) { $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, Lexer::TOKEN_PHPDOC_EOL, ...$endTokens); $text .= $tmpText; // stop if we're not at EOL - meaning it's the end of PHPDoc if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC)) { if (!$tokens->isPrecededByHorizontalWhitespace()) { return trim($text . $this->parseText($tokens)->text, " \t"); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) { $tokens->pushSavePoint(); $child = $this->parseChild($tokens); if ($child instanceof Ast\PhpDoc\PhpDocTagNode) { if ($child->value instanceof Ast\PhpDoc\GenericTagValueNode || $child->value instanceof Doctrine\DoctrineTagValueNode) { $tokens->rollback(); break; } if ($child->value instanceof Ast\PhpDoc\InvalidTagValueNode) { $tokens->rollback(); $tokens->pushSavePoint(); $tokens->next(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { $tokens->rollback(); break; } $tokens->rollback(); return trim($text . $this->parseText($tokens)->text, " \t"); } } $tokens->rollback(); return trim($text . $this->parseText($tokens)->text, " \t"); } break; } if (!$savepoint) { $tokens->pushSavePoint(); $savepoint = \true; } elseif ($tmpText !== '') { $tokens->dropSavePoint(); $tokens->pushSavePoint(); } $tokens->pushSavePoint(); $tokens->next(); // if we're at EOL, check what's next // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) { $tokens->rollback(); break; } // otherwise if the next is text, continue building the description string $tokens->dropSavePoint(); $text .= $tokens->getDetectedNewline() ?? "\n"; } if ($savepoint) { $tokens->rollback(); $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n"); } return trim($text, " \t"); } public function parseTag(TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagNode { $tag = $tokens->currentTokenValue(); $tokens->next(); $value = $this->parseTagValue($tokens, $tag); return new Ast\PhpDoc\PhpDocTagNode($tag, $value); } public function parseTagValue(TokenIterator $tokens, string $tag) : Ast\PhpDoc\PhpDocTagValueNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); try { $tokens->pushSavePoint(); switch ($tag) { case '@param': case '@phpstan-param': case '@psalm-param': case '@phan-param': $tagValue = $this->parseParamTagValue($tokens); break; case '@param-immediately-invoked-callable': case '@phpstan-param-immediately-invoked-callable': $tagValue = $this->parseParamImmediatelyInvokedCallableTagValue($tokens); break; case '@param-later-invoked-callable': case '@phpstan-param-later-invoked-callable': $tagValue = $this->parseParamLaterInvokedCallableTagValue($tokens); break; case '@param-closure-this': case '@phpstan-param-closure-this': $tagValue = $this->parseParamClosureThisTagValue($tokens); break; case '@pure-unless-callable-is-impure': case '@phpstan-pure-unless-callable-is-impure': $tagValue = $this->parsePureUnlessCallableIsImpureTagValue($tokens); break; case '@var': case '@phpstan-var': case '@psalm-var': case '@phan-var': $tagValue = $this->parseVarTagValue($tokens); break; case '@return': case '@phpstan-return': case '@psalm-return': case '@phan-return': case '@phan-real-return': $tagValue = $this->parseReturnTagValue($tokens); break; case '@throws': case '@phpstan-throws': $tagValue = $this->parseThrowsTagValue($tokens); break; case '@mixin': case '@phan-mixin': $tagValue = $this->parseMixinTagValue($tokens); break; case '@psalm-require-extends': case '@phpstan-require-extends': $tagValue = $this->parseRequireExtendsTagValue($tokens); break; case '@psalm-require-implements': case '@phpstan-require-implements': $tagValue = $this->parseRequireImplementsTagValue($tokens); break; case '@deprecated': $tagValue = $this->parseDeprecatedTagValue($tokens); break; case '@property': case '@property-read': case '@property-write': case '@phpstan-property': case '@phpstan-property-read': case '@phpstan-property-write': case '@psalm-property': case '@psalm-property-read': case '@psalm-property-write': case '@phan-property': case '@phan-property-read': case '@phan-property-write': $tagValue = $this->parsePropertyTagValue($tokens); break; case '@method': case '@phpstan-method': case '@psalm-method': case '@phan-method': $tagValue = $this->parseMethodTagValue($tokens); break; case '@template': case '@phpstan-template': case '@psalm-template': case '@phan-template': case '@template-covariant': case '@phpstan-template-covariant': case '@psalm-template-covariant': case '@template-contravariant': case '@phpstan-template-contravariant': case '@psalm-template-contravariant': $tagValue = $this->typeParser->parseTemplateTagValue($tokens, fn($tokens) => $this->parseOptionalDescription($tokens, \true)); break; case '@extends': case '@phpstan-extends': case '@phan-extends': case '@phan-inherits': case '@template-extends': $tagValue = $this->parseExtendsTagValue('@extends', $tokens); break; case '@implements': case '@phpstan-implements': case '@template-implements': $tagValue = $this->parseExtendsTagValue('@implements', $tokens); break; case '@use': case '@phpstan-use': case '@template-use': $tagValue = $this->parseExtendsTagValue('@use', $tokens); break; case '@phpstan-type': case '@psalm-type': case '@phan-type': $tagValue = $this->parseTypeAliasTagValue($tokens); break; case '@phpstan-import-type': case '@psalm-import-type': $tagValue = $this->parseTypeAliasImportTagValue($tokens); break; case '@phpstan-assert': case '@phpstan-assert-if-true': case '@phpstan-assert-if-false': case '@psalm-assert': case '@psalm-assert-if-true': case '@psalm-assert-if-false': case '@phan-assert': case '@phan-assert-if-true': case '@phan-assert-if-false': $tagValue = $this->parseAssertTagValue($tokens); break; case '@phpstan-this-out': case '@phpstan-self-out': case '@psalm-this-out': case '@psalm-self-out': $tagValue = $this->parseSelfOutTagValue($tokens); break; case '@param-out': case '@phpstan-param-out': case '@psalm-param-out': $tagValue = $this->parseParamOutTagValue($tokens); break; default: if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { $tagValue = $this->parseDoctrineTagValue($tokens, $tag); } else { $tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescriptionAfterDoctrineTag($tokens)); } break; } $tokens->dropSavePoint(); } catch (ParserException $e) { $tokens->rollback(); $tagValue = new Ast\PhpDoc\InvalidTagValueNode($this->parseOptionalDescription($tokens, \false), $e); } return $this->enrichWithAttributes($tokens, $tagValue, $startLine, $startIndex); } private function parseDoctrineTagValue(TokenIterator $tokens, string $tag) : Ast\PhpDoc\PhpDocTagValueNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); return new Doctrine\DoctrineTagValueNode($this->enrichWithAttributes($tokens, new Doctrine\DoctrineAnnotation($tag, $this->parseDoctrineArguments($tokens, \false)), $startLine, $startIndex), $this->parseOptionalDescriptionAfterDoctrineTag($tokens)); } /** * @return list */ private function parseDoctrineArguments(TokenIterator $tokens, bool $deep) : array { if (!$tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { return []; } if (!$deep) { $tokens->addEndOfLineToSkippedTokens(); } $arguments = []; try { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); do { if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { break; } $arguments[] = $this->parseDoctrineArgument($tokens); } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); } finally { if (!$deep) { $tokens->removeEndOfLineFromSkippedTokens(); } } $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); return $arguments; } private function parseDoctrineArgument(TokenIterator $tokens) : Doctrine\DoctrineArgument { if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex); } $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); try { $tokens->pushSavePoint(); $currentValue = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); $key = $this->enrichWithAttributes($tokens, new IdentifierTypeNode($currentValue), $startLine, $startIndex); $tokens->consumeTokenType(Lexer::TOKEN_EQUAL); $value = $this->parseDoctrineArgumentValue($tokens); $tokens->dropSavePoint(); return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument($key, $value), $startLine, $startIndex); } catch (ParserException $e) { $tokens->rollback(); return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex); } } /** * @return DoctrineValueType */ private function parseDoctrineArgumentValue(TokenIterator $tokens) { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG)) { $name = $tokens->currentTokenValue(); $tokens->next(); return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineAnnotation($name, $this->parseDoctrineArguments($tokens, \true)), $startLine, $startIndex); } if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) { $items = []; do { if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { break; } $items[] = $this->parseDoctrineArrayItem($tokens); } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArray($items), $startLine, $startIndex); } $currentTokenValue = $tokens->currentTokenValue(); $tokens->pushSavePoint(); // because of ConstFetchNode if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { $identifier = $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode($currentTokenValue), $startLine, $startIndex); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { $tokens->dropSavePoint(); return $identifier; } $tokens->rollback(); // because of ConstFetchNode } else { $tokens->dropSavePoint(); // because of ConstFetchNode } $currentTokenValue = $tokens->currentTokenValue(); $currentTokenType = $tokens->currentTokenType(); $currentTokenOffset = $tokens->currentTokenOffset(); $currentTokenLine = $tokens->currentTokenLine(); try { $constExpr = $this->doctrineConstantExprParser->parse($tokens); if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) { throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine); } return $constExpr; } catch (LogicException $e) { throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine); } } private function parseDoctrineArrayItem(TokenIterator $tokens) : Doctrine\DoctrineArrayItem { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); try { $tokens->pushSavePoint(); $key = $this->parseDoctrineArrayKey($tokens); if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) { if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_COLON)) { $tokens->consumeTokenType(Lexer::TOKEN_EQUAL); // will throw exception } } $value = $this->parseDoctrineArgumentValue($tokens); $tokens->dropSavePoint(); return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArrayItem($key, $value), $startLine, $startIndex); } catch (ParserException $e) { $tokens->rollback(); return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArrayItem(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex); } } /** * @return ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|ConstFetchNode */ private function parseDoctrineArrayKey(TokenIterator $tokens) { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) { $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue())); $tokens->next(); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) { $key = $this->doctrineConstantExprParser->parseDoctrineString($tokens->currentTokenValue(), $tokens); $tokens->next(); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED); $tokens->next(); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { $value = $tokens->currentTokenValue(); $tokens->next(); $key = $this->doctrineConstantExprParser->parseDoctrineString($value, $tokens); } else { $currentTokenValue = $tokens->currentTokenValue(); $tokens->pushSavePoint(); // because of ConstFetchNode if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { $tokens->dropSavePoint(); throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine()); } if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { $tokens->dropSavePoint(); return $this->enrichWithAttributes($tokens, new IdentifierTypeNode($currentTokenValue), $startLine, $startIndex); } $tokens->rollback(); $constExpr = $this->doctrineConstantExprParser->parse($tokens); if (!$constExpr instanceof Ast\ConstExpr\ConstFetchNode) { throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine()); } return $constExpr; } return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex); } /** * @return Ast\PhpDoc\ParamTagValueNode|Ast\PhpDoc\TypelessParamTagValueNode */ private function parseParamTagValue(TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagValueNode { if ($tokens->isCurrentTokenType(Lexer::TOKEN_REFERENCE, Lexer::TOKEN_VARIADIC, Lexer::TOKEN_VARIABLE)) { $type = null; } else { $type = $this->typeParser->parse($tokens); } $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE); $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC); $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, \false); if ($type !== null) { return new Ast\PhpDoc\ParamTagValueNode($type, $isVariadic, $parameterName, $description, $isReference); } return new Ast\PhpDoc\TypelessParamTagValueNode($isVariadic, $parameterName, $description, $isReference); } private function parseParamImmediatelyInvokedCallableTagValue(TokenIterator $tokens) : Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode { $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode($parameterName, $description); } private function parseParamLaterInvokedCallableTagValue(TokenIterator $tokens) : Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode { $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode($parameterName, $description); } private function parseParamClosureThisTagValue(TokenIterator $tokens) : Ast\PhpDoc\ParamClosureThisTagValueNode { $type = $this->typeParser->parse($tokens); $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\ParamClosureThisTagValueNode($type, $parameterName, $description); } private function parsePureUnlessCallableIsImpureTagValue(TokenIterator $tokens) : Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode { $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode($parameterName, $description); } private function parseVarTagValue(TokenIterator $tokens) : Ast\PhpDoc\VarTagValueNode { $type = $this->typeParser->parse($tokens); $variableName = $this->parseOptionalVariableName($tokens); $description = $this->parseOptionalDescription($tokens, $variableName === ''); return new Ast\PhpDoc\VarTagValueNode($type, $variableName, $description); } private function parseReturnTagValue(TokenIterator $tokens) : Ast\PhpDoc\ReturnTagValueNode { $type = $this->typeParser->parse($tokens); $description = $this->parseOptionalDescription($tokens, \true); return new Ast\PhpDoc\ReturnTagValueNode($type, $description); } private function parseThrowsTagValue(TokenIterator $tokens) : Ast\PhpDoc\ThrowsTagValueNode { $type = $this->typeParser->parse($tokens); $description = $this->parseOptionalDescription($tokens, \true); return new Ast\PhpDoc\ThrowsTagValueNode($type, $description); } private function parseMixinTagValue(TokenIterator $tokens) : Ast\PhpDoc\MixinTagValueNode { $type = $this->typeParser->parse($tokens); $description = $this->parseOptionalDescription($tokens, \true); return new Ast\PhpDoc\MixinTagValueNode($type, $description); } private function parseRequireExtendsTagValue(TokenIterator $tokens) : Ast\PhpDoc\RequireExtendsTagValueNode { $type = $this->typeParser->parse($tokens); $description = $this->parseOptionalDescription($tokens, \true); return new Ast\PhpDoc\RequireExtendsTagValueNode($type, $description); } private function parseRequireImplementsTagValue(TokenIterator $tokens) : Ast\PhpDoc\RequireImplementsTagValueNode { $type = $this->typeParser->parse($tokens); $description = $this->parseOptionalDescription($tokens, \true); return new Ast\PhpDoc\RequireImplementsTagValueNode($type, $description); } private function parseDeprecatedTagValue(TokenIterator $tokens) : Ast\PhpDoc\DeprecatedTagValueNode { $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\DeprecatedTagValueNode($description); } private function parsePropertyTagValue(TokenIterator $tokens) : Ast\PhpDoc\PropertyTagValueNode { $type = $this->typeParser->parse($tokens); $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\PropertyTagValueNode($type, $parameterName, $description); } private function parseMethodTagValue(TokenIterator $tokens) : Ast\PhpDoc\MethodTagValueNode { $staticKeywordOrReturnTypeOrMethodName = $this->typeParser->parse($tokens); if ($staticKeywordOrReturnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode && $staticKeywordOrReturnTypeOrMethodName->name === 'static') { $isStatic = \true; $returnTypeOrMethodName = $this->typeParser->parse($tokens); } else { $isStatic = \false; $returnTypeOrMethodName = $staticKeywordOrReturnTypeOrMethodName; } if ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { $returnType = $returnTypeOrMethodName; $methodName = $tokens->currentTokenValue(); $tokens->next(); } elseif ($returnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode) { $returnType = $isStatic ? $staticKeywordOrReturnTypeOrMethodName : null; $methodName = $returnTypeOrMethodName->name; $isStatic = \false; } else { $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); // will throw exception exit; } $templateTypes = []; if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { do { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $templateTypes[] = $this->enrichWithAttributes($tokens, $this->typeParser->parseTemplateTagValue($tokens), $startLine, $startIndex); } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); } $parameters = []; $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { $parameters[] = $this->parseMethodTagValueParameter($tokens); while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $parameters[] = $this->parseMethodTagValueParameter($tokens); } } $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\MethodTagValueNode($isStatic, $returnType, $methodName, $parameters, $description, $templateTypes); } private function parseMethodTagValueParameter(TokenIterator $tokens) : Ast\PhpDoc\MethodTagValueParameterNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); switch ($tokens->currentTokenType()) { case Lexer::TOKEN_IDENTIFIER: case Lexer::TOKEN_OPEN_PARENTHESES: case Lexer::TOKEN_NULLABLE: $parameterType = $this->typeParser->parse($tokens); break; default: $parameterType = null; } $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE); $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC); $parameterName = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); if ($tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) { $defaultValue = $this->constantExprParser->parse($tokens); } else { $defaultValue = null; } return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue), $startLine, $startIndex); } private function parseExtendsTagValue(string $tagName, TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagValueNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $baseType = new IdentifierTypeNode($tokens->currentTokenValue()); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); $type = $this->typeParser->parseGeneric($tokens, $this->typeParser->enrichWithAttributes($tokens, $baseType, $startLine, $startIndex)); $description = $this->parseOptionalDescription($tokens, \true); switch ($tagName) { case '@extends': return new Ast\PhpDoc\ExtendsTagValueNode($type, $description); case '@implements': return new Ast\PhpDoc\ImplementsTagValueNode($type, $description); case '@use': return new Ast\PhpDoc\UsesTagValueNode($type, $description); } throw new ShouldNotHappenException(); } private function parseTypeAliasTagValue(TokenIterator $tokens) : Ast\PhpDoc\TypeAliasTagValueNode { $alias = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); // support phan-type/psalm-type syntax $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL); $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); try { $type = $this->typeParser->parse($tokens); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_PHPDOC_EOL, null, $tokens->currentTokenLine()); } } return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type); } catch (ParserException $e) { $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $this->enrichWithAttributes($tokens, new Ast\Type\InvalidTypeNode($e), $startLine, $startIndex)); } } private function parseTypeAliasImportTagValue(TokenIterator $tokens) : Ast\PhpDoc\TypeAliasImportTagValueNode { $importedAlias = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); $tokens->consumeTokenValue(Lexer::TOKEN_IDENTIFIER, 'from'); $identifierStartLine = $tokens->currentTokenLine(); $identifierStartIndex = $tokens->currentTokenIndex(); $importedFrom = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); $importedFromType = $this->enrichWithAttributes($tokens, new IdentifierTypeNode($importedFrom), $identifierStartLine, $identifierStartIndex); $importedAs = null; if ($tokens->tryConsumeTokenValue('as')) { $importedAs = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); } return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, $importedFromType, $importedAs); } /** * @return Ast\PhpDoc\AssertTagValueNode|Ast\PhpDoc\AssertTagPropertyValueNode|Ast\PhpDoc\AssertTagMethodValueNode */ private function parseAssertTagValue(TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagValueNode { $isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED); $isEquality = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL); $type = $this->typeParser->parse($tokens); $parameter = $this->parseAssertParameter($tokens); $description = $this->parseOptionalDescription($tokens, \false); if (array_key_exists('method', $parameter)) { return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description, $isEquality); } elseif (array_key_exists('property', $parameter)) { return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description, $isEquality); } return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description, $isEquality); } /** * @return array{parameter: string}|array{parameter: string, property: string}|array{parameter: string, method: string} */ private function parseAssertParameter(TokenIterator $tokens) : array { if ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) { $parameter = '$this'; $tokens->next(); } else { $parameter = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_ARROW)) { $tokens->consumeTokenType(Lexer::TOKEN_ARROW); $propertyOrMethod = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); return ['parameter' => $parameter, 'method' => $propertyOrMethod]; } return ['parameter' => $parameter, 'property' => $propertyOrMethod]; } return ['parameter' => $parameter]; } private function parseSelfOutTagValue(TokenIterator $tokens) : Ast\PhpDoc\SelfOutTagValueNode { $type = $this->typeParser->parse($tokens); $description = $this->parseOptionalDescription($tokens, \true); return new Ast\PhpDoc\SelfOutTagValueNode($type, $description); } private function parseParamOutTagValue(TokenIterator $tokens) : Ast\PhpDoc\ParamOutTagValueNode { $type = $this->typeParser->parse($tokens); $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, \false); return new Ast\PhpDoc\ParamOutTagValueNode($type, $parameterName, $description); } private function parseOptionalVariableName(TokenIterator $tokens) : string { if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) { $parameterName = $tokens->currentTokenValue(); $tokens->next(); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) { $parameterName = '$this'; $tokens->next(); } else { $parameterName = ''; } return $parameterName; } private function parseRequiredVariableName(TokenIterator $tokens) : string { $parameterName = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); return $parameterName; } /** * @param bool $limitStartToken true should be used when the description immediately follows a parsed type */ private function parseOptionalDescription(TokenIterator $tokens, bool $limitStartToken) : string { if ($limitStartToken) { foreach (self::DISALLOWED_DESCRIPTION_START_TOKENS as $disallowedStartToken) { if (!$tokens->isCurrentTokenType($disallowedStartToken)) { continue; } $tokens->consumeTokenType(Lexer::TOKEN_OTHER); // will throw exception } if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END) && !$tokens->isPrecededByHorizontalWhitespace()) { $tokens->consumeTokenType(Lexer::TOKEN_HORIZONTAL_WS); // will throw exception } } return $this->parseText($tokens)->text; } } config = $config; $this->parseDoctrineStrings = \false; } /** * @internal */ public function toDoctrine() : self { $self = new self($this->config); $self->parseDoctrineStrings = \true; return $self; } public function parse(TokenIterator $tokens) : Ast\ConstExpr\ConstExprNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) { $value = $tokens->currentTokenValue(); $tokens->next(); return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprFloatNode(str_replace('_', '', $value)), $startLine, $startIndex); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) { $value = $tokens->currentTokenValue(); $tokens->next(); return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $value)), $startLine, $startIndex); } if ($this->parseDoctrineStrings && $tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) { $value = $tokens->currentTokenValue(); $tokens->next(); return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\DoctrineConstExprStringNode(Ast\ConstExpr\DoctrineConstExprStringNode::unescape($value)), $startLine, $startIndex); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING, Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { if ($this->parseDoctrineStrings) { if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_DOUBLE_QUOTED_STRING, null, $tokens->currentTokenLine()); } $value = $tokens->currentTokenValue(); $tokens->next(); return $this->enrichWithAttributes($tokens, $this->parseDoctrineString($value, $tokens), $startLine, $startIndex); } $value = StringUnescaper::unescapeString($tokens->currentTokenValue()); $type = $tokens->currentTokenType(); $tokens->next(); return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprStringNode($value, $type === Lexer::TOKEN_SINGLE_QUOTED_STRING ? Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED : Ast\ConstExpr\ConstExprStringNode::DOUBLE_QUOTED), $startLine, $startIndex); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { $identifier = $tokens->currentTokenValue(); $tokens->next(); switch (strtolower($identifier)) { case 'true': return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprTrueNode(), $startLine, $startIndex); case 'false': return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprFalseNode(), $startLine, $startIndex); case 'null': return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprNullNode(), $startLine, $startIndex); case 'array': $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES, $startIndex); } if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) { $classConstantName = ''; $lastType = null; while (\true) { if ($lastType !== Lexer::TOKEN_IDENTIFIER && $tokens->currentTokenType() === Lexer::TOKEN_IDENTIFIER) { $classConstantName .= $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); $lastType = Lexer::TOKEN_IDENTIFIER; continue; } if ($lastType !== Lexer::TOKEN_WILDCARD && $tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) { $classConstantName .= '*'; $lastType = Lexer::TOKEN_WILDCARD; if ($tokens->getSkippedHorizontalWhiteSpaceIfAny() !== '') { break; } continue; } if ($lastType === null) { // trigger parse error if nothing valid was consumed $tokens->consumeTokenType(Lexer::TOKEN_WILDCARD); } break; } return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName), $startLine, $startIndex); } return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstFetchNode('', $identifier), $startLine, $startIndex); } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET, $startIndex); } throw new ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine()); } private function parseArray(TokenIterator $tokens, int $endToken, int $startIndex) : Ast\ConstExpr\ConstExprArrayNode { $items = []; $startLine = $tokens->currentTokenLine(); if (!$tokens->tryConsumeTokenType($endToken)) { do { $items[] = $this->parseArrayItem($tokens); } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA) && !$tokens->isCurrentTokenType($endToken)); $tokens->consumeTokenType($endToken); } return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprArrayNode($items), $startLine, $startIndex); } /** * This method is supposed to be called with TokenIterator after reading TOKEN_DOUBLE_QUOTED_STRING and shifting * to the next token. */ public function parseDoctrineString(string $text, TokenIterator $tokens) : Ast\ConstExpr\DoctrineConstExprStringNode { // Because of how Lexer works, a valid Doctrine string // can consist of a sequence of TOKEN_DOUBLE_QUOTED_STRING and TOKEN_DOCTRINE_ANNOTATION_STRING while ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING, Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) { $text .= $tokens->currentTokenValue(); $tokens->next(); } return new Ast\ConstExpr\DoctrineConstExprStringNode(Ast\ConstExpr\DoctrineConstExprStringNode::unescape($text)); } private function parseArrayItem(TokenIterator $tokens) : Ast\ConstExpr\ConstExprArrayItemNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $expr = $this->parse($tokens); if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_ARROW)) { $key = $expr; $value = $this->parse($tokens); } else { $key = null; $value = $expr; } return $this->enrichWithAttributes($tokens, new Ast\ConstExpr\ConstExprArrayItemNode($key, $value), $startLine, $startIndex); } /** * @template T of Ast\ConstExpr\ConstExprNode * @param T $node * @return T */ private function enrichWithAttributes(TokenIterator $tokens, Ast\ConstExpr\ConstExprNode $node, int $startLine, int $startIndex) : Ast\ConstExpr\ConstExprNode { if ($this->config->useLinesAttributes) { $node->setAttribute(Ast\Attribute::START_LINE, $startLine); $node->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); } if ($this->config->useIndexAttributes) { $node->setAttribute(Ast\Attribute::START_INDEX, $startIndex); $node->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); } return $node; } } '\\', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1b"]; public static function unescapeString(string $string) : string { $quote = $string[0]; if ($quote === '\'') { return str_replace(['\\\\', '\\\''], ['\\', '\''], substr($string, 1, -1)); } return self::parseEscapeSequences(substr($string, 1, -1), '"'); } /** * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130 */ private static function parseEscapeSequences(string $str, string $quote) : string { $str = str_replace('\\' . $quote, $quote, $str); return preg_replace_callback('~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\\{([0-9a-fA-F]+)\\})~', static function ($matches) { $str = $matches[1]; if (isset(self::REPLACEMENTS[$str])) { return self::REPLACEMENTS[$str]; } if ($str[0] === 'x' || $str[0] === 'X') { return chr((int) hexdec(substr($str, 1))); } if ($str[0] === 'u') { if (!isset($matches[2])) { throw new ShouldNotHappenException(); } return self::codePointToUtf8((int) hexdec($matches[2])); } return chr((int) octdec($str)); }, $str); } /** * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154 */ private static function codePointToUtf8(int $num) : string { if ($num <= 0x7f) { return chr($num); } if ($num <= 0x7ff) { return chr(($num >> 6) + 0xc0) . chr(($num & 0x3f) + 0x80); } if ($num <= 0xffff) { return chr(($num >> 12) + 0xe0) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80); } if ($num <= 0x1fffff) { return chr(($num >> 18) + 0xf0) . chr(($num >> 12 & 0x3f) + 0x80) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80); } // Invalid UTF-8 codepoint escape sequence: Codepoint too large return "�"; } } config = $config; $this->constExprParser = $constExprParser; } /** @phpstan-impure */ public function parse(TokenIterator $tokens) : Ast\Type\TypeNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) { $type = $this->parseNullable($tokens); } else { $type = $this->parseAtomic($tokens); $tokens->pushSavePoint(); $tokens->skipNewLineTokensAndConsumeComments(); try { $enrichedType = $this->enrichTypeOnUnionOrIntersection($tokens, $type); } catch (ParserException $parserException) { $enrichedType = null; } if ($enrichedType !== null) { $type = $enrichedType; $tokens->dropSavePoint(); } else { $tokens->rollback(); $type = $this->enrichTypeOnUnionOrIntersection($tokens, $type) ?? $type; } } return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } /** @phpstan-impure */ private function enrichTypeOnUnionOrIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type) : ?Ast\Type\TypeNode { if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) { return $this->parseUnion($tokens, $type); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) { return $this->parseIntersection($tokens, $type); } return null; } /** * @internal * @template T of Ast\Node * @param T $type * @return T */ public function enrichWithAttributes(TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex) : Ast\Node { if ($this->config->useLinesAttributes) { $type->setAttribute(Ast\Attribute::START_LINE, $startLine); $type->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); } $comments = $tokens->flushComments(); if ($this->config->useCommentsAttributes) { $type->setAttribute(Ast\Attribute::COMMENTS, $comments); } if ($this->config->useIndexAttributes) { $type->setAttribute(Ast\Attribute::START_INDEX, $startIndex); $type->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); } return $type; } /** @phpstan-impure */ private function subParse(TokenIterator $tokens) : Ast\Type\TypeNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) { $type = $this->parseNullable($tokens); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) { $type = $this->parseConditionalForParameter($tokens, $tokens->currentTokenValue()); } else { $type = $this->parseAtomic($tokens); if ($tokens->isCurrentTokenValue('is')) { $type = $this->parseConditional($tokens, $type); } else { $tokens->skipNewLineTokensAndConsumeComments(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) { $type = $this->subParseUnion($tokens, $type); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) { $type = $this->subParseIntersection($tokens, $type); } } } return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } /** @phpstan-impure */ private function parseAtomic(TokenIterator $tokens) : Ast\Type\TypeNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { $tokens->skipNewLineTokensAndConsumeComments(); $type = $this->subParse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); } return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } if ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) { $type = $this->enrichWithAttributes($tokens, new Ast\Type\ThisTypeNode(), $startLine, $startIndex); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); } return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } $currentTokenValue = $tokens->currentTokenValue(); $tokens->pushSavePoint(); // because of ConstFetchNode if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { $type = $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode($currentTokenValue), $startLine, $startIndex); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { $tokens->dropSavePoint(); // because of ConstFetchNode if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { $tokens->pushSavePoint(); $isHtml = $this->isHtml($tokens); $tokens->rollback(); if ($isHtml) { return $type; } $origType = $type; $type = $this->tryParseCallable($tokens, $type, \true); if ($type === $origType) { $type = $this->parseGeneric($tokens, $type); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); } } } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { $type = $this->tryParseCallable($tokens, $type, \false); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); } elseif (in_array($type->name, [Ast\Type\ArrayShapeNode::KIND_ARRAY, Ast\Type\ArrayShapeNode::KIND_LIST, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_ARRAY, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_LIST, 'object'], \true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) { if ($type->name === 'object') { $type = $this->parseObjectShape($tokens); } else { $type = $this->parseArrayShape($tokens, $type, $type->name); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex)); } } return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } else { $tokens->rollback(); // because of ConstFetchNode } } else { $tokens->dropSavePoint(); // because of ConstFetchNode } $currentTokenValue = $tokens->currentTokenValue(); $currentTokenType = $tokens->currentTokenType(); $currentTokenOffset = $tokens->currentTokenOffset(); $currentTokenLine = $tokens->currentTokenLine(); try { $constExpr = $this->constExprParser->parse($tokens); if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) { throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine); } $type = $this->enrichWithAttributes($tokens, new Ast\Type\ConstTypeNode($constExpr), $startLine, $startIndex); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); } return $type; } catch (LogicException $e) { throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine); } } /** @phpstan-impure */ private function parseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode { $types = [$type]; while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) { $types[] = $this->parseAtomic($tokens); $tokens->pushSavePoint(); $tokens->skipNewLineTokensAndConsumeComments(); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) { $tokens->rollback(); break; } $tokens->dropSavePoint(); } return new Ast\Type\UnionTypeNode($types); } /** @phpstan-impure */ private function subParseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode { $types = [$type]; while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) { $tokens->skipNewLineTokensAndConsumeComments(); $types[] = $this->parseAtomic($tokens); $tokens->skipNewLineTokensAndConsumeComments(); } return new Ast\Type\UnionTypeNode($types); } /** @phpstan-impure */ private function parseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode { $types = [$type]; while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) { $types[] = $this->parseAtomic($tokens); $tokens->pushSavePoint(); $tokens->skipNewLineTokensAndConsumeComments(); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) { $tokens->rollback(); break; } $tokens->dropSavePoint(); } return new Ast\Type\IntersectionTypeNode($types); } /** @phpstan-impure */ private function subParseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode { $types = [$type]; while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) { $tokens->skipNewLineTokensAndConsumeComments(); $types[] = $this->parseAtomic($tokens); $tokens->skipNewLineTokensAndConsumeComments(); } return new Ast\Type\IntersectionTypeNode($types); } /** @phpstan-impure */ private function parseConditional(TokenIterator $tokens, Ast\Type\TypeNode $subjectType) : Ast\Type\TypeNode { $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); $negated = \false; if ($tokens->isCurrentTokenValue('not')) { $negated = \true; $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); } $targetType = $this->parse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE); $tokens->skipNewLineTokensAndConsumeComments(); $ifType = $this->parse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_COLON); $tokens->skipNewLineTokensAndConsumeComments(); $elseType = $this->subParse($tokens); return new Ast\Type\ConditionalTypeNode($subjectType, $targetType, $ifType, $elseType, $negated); } /** @phpstan-impure */ private function parseConditionalForParameter(TokenIterator $tokens, string $parameterName) : Ast\Type\TypeNode { $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); $tokens->consumeTokenValue(Lexer::TOKEN_IDENTIFIER, 'is'); $negated = \false; if ($tokens->isCurrentTokenValue('not')) { $negated = \true; $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); } $targetType = $this->parse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE); $tokens->skipNewLineTokensAndConsumeComments(); $ifType = $this->parse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_COLON); $tokens->skipNewLineTokensAndConsumeComments(); $elseType = $this->subParse($tokens); return new Ast\Type\ConditionalTypeForParameterNode($parameterName, $targetType, $ifType, $elseType, $negated); } /** @phpstan-impure */ private function parseNullable(TokenIterator $tokens) : Ast\Type\TypeNode { $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE); $type = $this->parseAtomic($tokens); return new Ast\Type\NullableTypeNode($type); } /** @phpstan-impure */ public function isHtml(TokenIterator $tokens) : bool { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { return \false; } $htmlTagName = $tokens->currentTokenValue(); $tokens->next(); if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) { return \false; } $endTag = ''; $endTagSearchOffset = -strlen($endTag); while (!$tokens->isCurrentTokenType(Lexer::TOKEN_END)) { if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET) && strpos($tokens->currentTokenValue(), '/' . $htmlTagName . '>') !== \false || substr_compare($tokens->currentTokenValue(), $endTag, $endTagSearchOffset) === 0) { return \true; } $tokens->next(); } return \false; } /** @phpstan-impure */ public function parseGeneric(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $baseType) : Ast\Type\GenericTypeNode { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); $tokens->skipNewLineTokensAndConsumeComments(); $startLine = $baseType->getAttribute(Ast\Attribute::START_LINE); $startIndex = $baseType->getAttribute(Ast\Attribute::START_INDEX); $genericTypes = []; $variances = []; $isFirst = \true; while ($isFirst || $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $tokens->skipNewLineTokensAndConsumeComments(); // trailing comma case if (!$isFirst && $tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) { break; } $isFirst = \false; [$genericTypes[], $variances[]] = $this->parseGenericTypeArgument($tokens); $tokens->skipNewLineTokensAndConsumeComments(); } $type = new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances); if ($startLine !== null && $startIndex !== null) { $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); return $type; } /** * @phpstan-impure * @return array{Ast\Type\TypeNode, Ast\Type\GenericTypeNode::VARIANCE_*} */ public function parseGenericTypeArgument(TokenIterator $tokens) : array { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) { return [$this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode('mixed'), $startLine, $startIndex), Ast\Type\GenericTypeNode::VARIANCE_BIVARIANT]; } if ($tokens->tryConsumeTokenValue('contravariant')) { $variance = Ast\Type\GenericTypeNode::VARIANCE_CONTRAVARIANT; } elseif ($tokens->tryConsumeTokenValue('covariant')) { $variance = Ast\Type\GenericTypeNode::VARIANCE_COVARIANT; } else { $variance = Ast\Type\GenericTypeNode::VARIANCE_INVARIANT; } $type = $this->parse($tokens); return [$type, $variance]; } /** * @throws ParserException * @param ?callable(TokenIterator): string $parseDescription */ public function parseTemplateTagValue(TokenIterator $tokens, ?callable $parseDescription = null) : TemplateTagValueNode { $name = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); $upperBound = $lowerBound = null; if ($tokens->tryConsumeTokenValue('of') || $tokens->tryConsumeTokenValue('as')) { $upperBound = $this->parse($tokens); } if ($tokens->tryConsumeTokenValue('super')) { $lowerBound = $this->parse($tokens); } if ($tokens->tryConsumeTokenValue('=')) { $default = $this->parse($tokens); } else { $default = null; } if ($parseDescription !== null) { $description = $parseDescription($tokens); } else { $description = ''; } if ($name === '') { throw new LogicException('Template tag name cannot be empty.'); } return new Ast\PhpDoc\TemplateTagValueNode($name, $upperBound, $description, $default, $lowerBound); } /** @phpstan-impure */ private function parseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier, bool $hasTemplate) : Ast\Type\TypeNode { $templates = $hasTemplate ? $this->parseCallableTemplates($tokens) : []; $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); $tokens->skipNewLineTokensAndConsumeComments(); $parameters = []; if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { $parameters[] = $this->parseCallableParameter($tokens); $tokens->skipNewLineTokensAndConsumeComments(); while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $tokens->skipNewLineTokensAndConsumeComments(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { break; } $parameters[] = $this->parseCallableParameter($tokens); $tokens->skipNewLineTokensAndConsumeComments(); } } $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); $tokens->consumeTokenType(Lexer::TOKEN_COLON); $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $returnType = $this->enrichWithAttributes($tokens, $this->parseCallableReturnType($tokens), $startLine, $startIndex); return new Ast\Type\CallableTypeNode($identifier, $parameters, $returnType, $templates); } /** * @return Ast\PhpDoc\TemplateTagValueNode[] * * @phpstan-impure */ private function parseCallableTemplates(TokenIterator $tokens) : array { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); $templates = []; $isFirst = \true; while ($isFirst || $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $tokens->skipNewLineTokensAndConsumeComments(); // trailing comma case if (!$isFirst && $tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) { break; } $isFirst = \false; $templates[] = $this->parseCallableTemplateArgument($tokens); $tokens->skipNewLineTokensAndConsumeComments(); } $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); return $templates; } private function parseCallableTemplateArgument(TokenIterator $tokens) : Ast\PhpDoc\TemplateTagValueNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); return $this->enrichWithAttributes($tokens, $this->parseTemplateTagValue($tokens), $startLine, $startIndex); } /** @phpstan-impure */ private function parseCallableParameter(TokenIterator $tokens) : Ast\Type\CallableTypeParameterNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $type = $this->parse($tokens); $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE); $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC); if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) { $parameterName = $tokens->currentTokenValue(); $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); } else { $parameterName = ''; } $isOptional = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL); return $this->enrichWithAttributes($tokens, new Ast\Type\CallableTypeParameterNode($type, $isReference, $isVariadic, $parameterName, $isOptional), $startLine, $startIndex); } /** @phpstan-impure */ private function parseCallableReturnType(TokenIterator $tokens) : Ast\Type\TypeNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) { return $this->parseNullable($tokens); } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { $type = $this->subParse($tokens); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); } return $type; } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) { $type = new Ast\Type\ThisTypeNode(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex)); } return $type; } else { $currentTokenValue = $tokens->currentTokenValue(); $tokens->pushSavePoint(); // because of ConstFetchNode if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { $type = new Ast\Type\IdentifierTypeNode($currentTokenValue); if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { $type = $this->parseGeneric($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex)); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex)); } } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex)); } elseif (in_array($type->name, [Ast\Type\ArrayShapeNode::KIND_ARRAY, Ast\Type\ArrayShapeNode::KIND_LIST, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_ARRAY, Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_LIST, 'object'], \true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) { if ($type->name === 'object') { $type = $this->parseObjectShape($tokens); } else { $type = $this->parseArrayShape($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex), $type->name); } if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex)); } } return $type; } else { $tokens->rollback(); // because of ConstFetchNode } } else { $tokens->dropSavePoint(); // because of ConstFetchNode } } $currentTokenValue = $tokens->currentTokenValue(); $currentTokenType = $tokens->currentTokenType(); $currentTokenOffset = $tokens->currentTokenOffset(); $currentTokenLine = $tokens->currentTokenLine(); try { $constExpr = $this->constExprParser->parse($tokens); if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) { throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine); } $type = $this->enrichWithAttributes($tokens, new Ast\Type\ConstTypeNode($constExpr), $startLine, $startIndex); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); } return $type; } catch (LogicException $e) { throw new ParserException($currentTokenValue, $currentTokenType, $currentTokenOffset, Lexer::TOKEN_IDENTIFIER, null, $currentTokenLine); } } /** @phpstan-impure */ private function tryParseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier, bool $hasTemplate) : Ast\Type\TypeNode { try { $tokens->pushSavePoint(); $type = $this->parseCallable($tokens, $identifier, $hasTemplate); $tokens->dropSavePoint(); } catch (ParserException $e) { $tokens->rollback(); $type = $identifier; } return $type; } /** @phpstan-impure */ private function tryParseArrayOrOffsetAccess(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode { $startLine = $type->getAttribute(Ast\Attribute::START_LINE); $startIndex = $type->getAttribute(Ast\Attribute::START_INDEX); try { while ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { $tokens->pushSavePoint(); $canBeOffsetAccessType = !$tokens->isPrecededByHorizontalWhitespace(); $tokens->consumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET); if ($canBeOffsetAccessType && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET)) { $offset = $this->parse($tokens); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET); $tokens->dropSavePoint(); $type = new Ast\Type\OffsetAccessTypeNode($type, $offset); if ($startLine !== null && $startIndex !== null) { $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } } else { $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET); $tokens->dropSavePoint(); $type = new Ast\Type\ArrayTypeNode($type); if ($startLine !== null && $startIndex !== null) { $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); } } } } catch (ParserException $e) { $tokens->rollback(); } return $type; } /** * @phpstan-impure * @param Ast\Type\ArrayShapeNode::KIND_* $kind */ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type, string $kind) : Ast\Type\ArrayShapeNode { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET); $items = []; $sealed = \true; $unsealedType = null; $done = \false; do { $tokens->skipNewLineTokensAndConsumeComments(); if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { return Ast\Type\ArrayShapeNode::createSealed($items, $kind); } if ($tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC)) { $sealed = \false; $tokens->skipNewLineTokensAndConsumeComments(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { if ($kind === Ast\Type\ArrayShapeNode::KIND_ARRAY) { $unsealedType = $this->parseArrayShapeUnsealedType($tokens); } else { $unsealedType = $this->parseListShapeUnsealedType($tokens); } $tokens->skipNewLineTokensAndConsumeComments(); } $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA); break; } $items[] = $this->parseArrayShapeItem($tokens); $tokens->skipNewLineTokensAndConsumeComments(); if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $done = \true; } if ($tokens->currentTokenType() !== Lexer::TOKEN_COMMENT) { continue; } $tokens->next(); } while (!$done); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); if ($sealed) { return Ast\Type\ArrayShapeNode::createSealed($items, $kind); } return Ast\Type\ArrayShapeNode::createUnsealed($items, $unsealedType, $kind); } /** @phpstan-impure */ private function parseArrayShapeItem(TokenIterator $tokens) : Ast\Type\ArrayShapeItemNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); // parse any comments above the item $tokens->skipNewLineTokensAndConsumeComments(); try { $tokens->pushSavePoint(); $key = $this->parseArrayShapeKey($tokens); $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE); $tokens->consumeTokenType(Lexer::TOKEN_COLON); $value = $this->parse($tokens); $tokens->dropSavePoint(); return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeItemNode($key, $optional, $value), $startLine, $startIndex); } catch (ParserException $e) { $tokens->rollback(); $value = $this->parse($tokens); return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeItemNode(null, \false, $value), $startLine, $startIndex); } } /** * @phpstan-impure * @return Ast\ConstExpr\ConstExprIntegerNode|Ast\ConstExpr\ConstExprStringNode|Ast\Type\IdentifierTypeNode */ private function parseArrayShapeKey(TokenIterator $tokens) { $startIndex = $tokens->currentTokenIndex(); $startLine = $tokens->currentTokenLine(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) { $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue())); $tokens->next(); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED); $tokens->next(); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::DOUBLE_QUOTED); $tokens->next(); } else { $key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue()); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); } return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex); } /** * @phpstan-impure */ private function parseArrayShapeUnsealedType(TokenIterator $tokens) : Ast\Type\ArrayShapeUnsealedTypeNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); $tokens->skipNewLineTokensAndConsumeComments(); $valueType = $this->parse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); $keyType = null; if ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $tokens->skipNewLineTokensAndConsumeComments(); $keyType = $valueType; $valueType = $this->parse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); } $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeUnsealedTypeNode($valueType, $keyType), $startLine, $startIndex); } /** * @phpstan-impure */ private function parseListShapeUnsealedType(TokenIterator $tokens) : Ast\Type\ArrayShapeUnsealedTypeNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); $tokens->skipNewLineTokensAndConsumeComments(); $valueType = $this->parse($tokens); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); return $this->enrichWithAttributes($tokens, new Ast\Type\ArrayShapeUnsealedTypeNode($valueType, null), $startLine, $startIndex); } /** * @phpstan-impure */ private function parseObjectShape(TokenIterator $tokens) : Ast\Type\ObjectShapeNode { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET); $items = []; do { $tokens->skipNewLineTokensAndConsumeComments(); if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { return new Ast\Type\ObjectShapeNode($items); } $items[] = $this->parseObjectShapeItem($tokens); $tokens->skipNewLineTokensAndConsumeComments(); } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); $tokens->skipNewLineTokensAndConsumeComments(); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); return new Ast\Type\ObjectShapeNode($items); } /** @phpstan-impure */ private function parseObjectShapeItem(TokenIterator $tokens) : Ast\Type\ObjectShapeItemNode { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $tokens->skipNewLineTokensAndConsumeComments(); $key = $this->parseObjectShapeKey($tokens); $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE); $tokens->consumeTokenType(Lexer::TOKEN_COLON); $value = $this->parse($tokens); return $this->enrichWithAttributes($tokens, new Ast\Type\ObjectShapeItemNode($key, $optional, $value), $startLine, $startIndex); } /** * @phpstan-impure * @return Ast\ConstExpr\ConstExprStringNode|Ast\Type\IdentifierTypeNode */ private function parseObjectShapeKey(TokenIterator $tokens) { $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::SINGLE_QUOTED); $tokens->next(); } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { $key = new Ast\ConstExpr\ConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\ConstExprStringNode::DOUBLE_QUOTED); $tokens->next(); } else { $key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue()); $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); } return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex); } } */ private array $tokens; private int $index; /** @var list */ private array $comments = []; /** @var list}> */ private array $savePoints = []; /** @var list */ private array $skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS]; private ?string $newline = null; /** * @param list $tokens */ public function __construct(array $tokens, int $index = 0) { $this->tokens = $tokens; $this->index = $index; $this->skipIrrelevantTokens(); } /** * @return list */ public function getTokens() : array { return $this->tokens; } public function getContentBetween(int $startPos, int $endPos) : string { if ($startPos < 0 || $endPos > count($this->tokens)) { throw new LogicException(); } $content = ''; for ($i = $startPos; $i < $endPos; $i++) { $content .= $this->tokens[$i][Lexer::VALUE_OFFSET]; } return $content; } public function getTokenCount() : int { return count($this->tokens); } public function currentTokenValue() : string { return $this->tokens[$this->index][Lexer::VALUE_OFFSET]; } public function currentTokenType() : int { return $this->tokens[$this->index][Lexer::TYPE_OFFSET]; } public function currentTokenOffset() : int { $offset = 0; for ($i = 0; $i < $this->index; $i++) { $offset += strlen($this->tokens[$i][Lexer::VALUE_OFFSET]); } return $offset; } public function currentTokenLine() : int { return $this->tokens[$this->index][Lexer::LINE_OFFSET]; } public function currentTokenIndex() : int { return $this->index; } public function endIndexOfLastRelevantToken() : int { $endIndex = $this->currentTokenIndex(); $endIndex--; while (in_array($this->tokens[$endIndex][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, \true)) { if (!isset($this->tokens[$endIndex - 1])) { break; } $endIndex--; } return $endIndex; } public function isCurrentTokenValue(string $tokenValue) : bool { return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue; } public function isCurrentTokenType(int ...$tokenType) : bool { return in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, \true); } public function isPrecededByHorizontalWhitespace() : bool { return ($this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] ?? -1) === Lexer::TOKEN_HORIZONTAL_WS; } /** * @throws ParserException */ public function consumeTokenType(int $tokenType) : void { if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) { $this->throwError($tokenType); } if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) { if ($this->newline === null) { $this->detectNewline(); } } $this->next(); } /** * @throws ParserException */ public function consumeTokenValue(int $tokenType, string $tokenValue) : void { if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType || $this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) { $this->throwError($tokenType, $tokenValue); } $this->next(); } /** @phpstan-impure */ public function tryConsumeTokenValue(string $tokenValue) : bool { if ($this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) { return \false; } $this->next(); return \true; } /** * @return list */ public function flushComments() : array { $res = $this->comments; $this->comments = []; return $res; } /** @phpstan-impure */ public function tryConsumeTokenType(int $tokenType) : bool { if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) { return \false; } if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) { if ($this->newline === null) { $this->detectNewline(); } } $this->next(); return \true; } /** * @deprecated Use skipNewLineTokensAndConsumeComments instead (when parsing a type) */ public function skipNewLineTokens() : void { if (!$this->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { return; } do { $foundNewLine = $this->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); } while ($foundNewLine === \true); } public function skipNewLineTokensAndConsumeComments() : void { if ($this->currentTokenType() === Lexer::TOKEN_COMMENT) { $this->comments[] = new Comment($this->currentTokenValue(), $this->currentTokenLine(), $this->currentTokenIndex()); $this->next(); } if (!$this->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { return; } do { $foundNewLine = $this->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); if ($this->currentTokenType() !== Lexer::TOKEN_COMMENT) { continue; } $this->comments[] = new Comment($this->currentTokenValue(), $this->currentTokenLine(), $this->currentTokenIndex()); $this->next(); } while ($foundNewLine === \true); } private function detectNewline() : void { $value = $this->currentTokenValue(); if (substr($value, 0, 2) === "\r\n") { $this->newline = "\r\n"; } elseif (substr($value, 0, 1) === "\n") { $this->newline = "\n"; } } public function getSkippedHorizontalWhiteSpaceIfAny() : string { if ($this->index > 0 && $this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { return $this->tokens[$this->index - 1][Lexer::VALUE_OFFSET]; } return ''; } /** @phpstan-impure */ public function joinUntil(int ...$tokenType) : string { $s = ''; while (!in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, \true)) { $s .= $this->tokens[$this->index++][Lexer::VALUE_OFFSET]; } return $s; } public function next() : void { $this->index++; $this->skipIrrelevantTokens(); } private function skipIrrelevantTokens() : void { if (!isset($this->tokens[$this->index])) { return; } while (in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, \true)) { if (!isset($this->tokens[$this->index + 1])) { break; } $this->index++; } } public function addEndOfLineToSkippedTokens() : void { $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL]; } public function removeEndOfLineFromSkippedTokens() : void { $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS]; } /** @phpstan-impure */ public function forwardToTheEnd() : void { $lastToken = count($this->tokens) - 1; $this->index = $lastToken; } public function pushSavePoint() : void { $this->savePoints[] = [$this->index, $this->comments]; } public function dropSavePoint() : void { array_pop($this->savePoints); } public function rollback() : void { $savepoint = array_pop($this->savePoints); assert($savepoint !== null); [$this->index, $this->comments] = $savepoint; } /** * @throws ParserException */ private function throwError(int $expectedTokenType, ?string $expectedTokenValue = null) : void { throw new ParserException($this->currentTokenValue(), $this->currentTokenType(), $this->currentTokenOffset(), $expectedTokenType, $expectedTokenValue, $this->currentTokenLine()); } /** * Check whether the position is directly preceded by a certain token type. * * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped */ public function hasTokenImmediatelyBefore(int $pos, int $expectedTokenType) : bool { $tokens = $this->tokens; $pos--; for (; $pos >= 0; $pos--) { $token = $tokens[$pos]; $type = $token[Lexer::TYPE_OFFSET]; if ($type === $expectedTokenType) { return \true; } if (!in_array($type, [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL], \true)) { break; } } return \false; } /** * Check whether the position is directly followed by a certain token type. * * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped */ public function hasTokenImmediatelyAfter(int $pos, int $expectedTokenType) : bool { $tokens = $this->tokens; $pos++; for ($c = count($tokens); $pos < $c; $pos++) { $token = $tokens[$pos]; $type = $token[Lexer::TYPE_OFFSET]; if ($type === $expectedTokenType) { return \true; } if (!in_array($type, [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL], \true)) { break; } } return \false; } public function getDetectedNewline() : ?string { return $this->newline; } /** * Whether the given position is immediately surrounded by parenthesis. */ public function hasParentheses(int $startPos, int $endPos) : bool { return $this->hasTokenImmediatelyBefore($startPos, Lexer::TOKEN_OPEN_PARENTHESES) && $this->hasTokenImmediatelyAfter($endPos, Lexer::TOKEN_CLOSE_PARENTHESES); } } useLinesAttributes = $usedAttributes['lines'] ?? \false; $this->useIndexAttributes = $usedAttributes['indexes'] ?? \false; $this->useCommentsAttributes = $usedAttributes['comments'] ?? \false; } } parameterName = $parameterName; $this->description = $description; } public function __toString() : string { return trim("{$this->parameterName} {$this->description}"); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } name = $name; $this->bound = $bound; $this->lowerBound = $lowerBound; $this->default = $default; $this->description = $description; } public function __toString() : string { $upperBound = $this->bound !== null ? " of {$this->bound}" : ''; $lowerBound = $this->lowerBound !== null ? " super {$this->lowerBound}" : ''; $default = $this->default !== null ? " = {$this->default}" : ''; return trim("{$this->name}{$upperBound}{$lowerBound}{$default} {$this->description}"); } } type = $type; $this->parameter = $parameter; $this->isNegated = $isNegated; $this->isEquality = $isEquality; $this->description = $description; } public function __toString() : string { $isNegated = $this->isNegated ? '!' : ''; $isEquality = $this->isEquality ? '=' : ''; return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter} {$this->description}"); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } parameterName = $parameterName; $this->description = $description; } public function __toString() : string { return trim("{$this->parameterName} {$this->description}"); } } type = $type; $this->parameter = $parameter; $this->property = $property; $this->isNegated = $isNegated; $this->isEquality = $isEquality; $this->description = $description; } public function __toString() : string { $isNegated = $this->isNegated ? '!' : ''; $isEquality = $this->isEquality ? '=' : ''; return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->property} {$this->description}"); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } text = $text; } public function __toString() : string { return $this->text; } } children = $children; } /** * @return PhpDocTagNode[] */ public function getTags() : array { return array_filter($this->children, static fn(PhpDocChildNode $child): bool => $child instanceof PhpDocTagNode); } /** * @return PhpDocTagNode[] */ public function getTagsByName(string $tagName) : array { return array_filter($this->getTags(), static fn(PhpDocTagNode $tag): bool => $tag->name === $tagName); } /** * @return VarTagValueNode[] */ public function getVarTagValues(string $tagName = '@var') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof VarTagValueNode); } /** * @return ParamTagValueNode[] */ public function getParamTagValues(string $tagName = '@param') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamTagValueNode); } /** * @return TypelessParamTagValueNode[] */ public function getTypelessParamTagValues(string $tagName = '@param') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TypelessParamTagValueNode); } /** * @return ParamImmediatelyInvokedCallableTagValueNode[] */ public function getParamImmediatelyInvokedCallableTagValues(string $tagName = '@param-immediately-invoked-callable') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamImmediatelyInvokedCallableTagValueNode); } /** * @return ParamLaterInvokedCallableTagValueNode[] */ public function getParamLaterInvokedCallableTagValues(string $tagName = '@param-later-invoked-callable') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamLaterInvokedCallableTagValueNode); } /** * @return ParamClosureThisTagValueNode[] */ public function getParamClosureThisTagValues(string $tagName = '@param-closure-this') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamClosureThisTagValueNode); } /** * @return PureUnlessCallableIsImpureTagValueNode[] */ public function getPureUnlessCallableIsImpureTagValues(string $tagName = '@pure-unless-callable-is-impure') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PureUnlessCallableIsImpureTagValueNode); } /** * @return TemplateTagValueNode[] */ public function getTemplateTagValues(string $tagName = '@template') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TemplateTagValueNode); } /** * @return ExtendsTagValueNode[] */ public function getExtendsTagValues(string $tagName = '@extends') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ExtendsTagValueNode); } /** * @return ImplementsTagValueNode[] */ public function getImplementsTagValues(string $tagName = '@implements') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ImplementsTagValueNode); } /** * @return UsesTagValueNode[] */ public function getUsesTagValues(string $tagName = '@use') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof UsesTagValueNode); } /** * @return ReturnTagValueNode[] */ public function getReturnTagValues(string $tagName = '@return') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ReturnTagValueNode); } /** * @return ThrowsTagValueNode[] */ public function getThrowsTagValues(string $tagName = '@throws') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ThrowsTagValueNode); } /** * @return MixinTagValueNode[] */ public function getMixinTagValues(string $tagName = '@mixin') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof MixinTagValueNode); } /** * @return RequireExtendsTagValueNode[] */ public function getRequireExtendsTagValues(string $tagName = '@phpstan-require-extends') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof RequireExtendsTagValueNode); } /** * @return RequireImplementsTagValueNode[] */ public function getRequireImplementsTagValues(string $tagName = '@phpstan-require-implements') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof RequireImplementsTagValueNode); } /** * @return DeprecatedTagValueNode[] */ public function getDeprecatedTagValues() : array { return array_filter(array_column($this->getTagsByName('@deprecated'), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof DeprecatedTagValueNode); } /** * @return PropertyTagValueNode[] */ public function getPropertyTagValues(string $tagName = '@property') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PropertyTagValueNode); } /** * @return PropertyTagValueNode[] */ public function getPropertyReadTagValues(string $tagName = '@property-read') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PropertyTagValueNode); } /** * @return PropertyTagValueNode[] */ public function getPropertyWriteTagValues(string $tagName = '@property-write') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof PropertyTagValueNode); } /** * @return MethodTagValueNode[] */ public function getMethodTagValues(string $tagName = '@method') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof MethodTagValueNode); } /** * @return TypeAliasTagValueNode[] */ public function getTypeAliasTagValues(string $tagName = '@phpstan-type') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TypeAliasTagValueNode); } /** * @return TypeAliasImportTagValueNode[] */ public function getTypeAliasImportTagValues(string $tagName = '@phpstan-import-type') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof TypeAliasImportTagValueNode); } /** * @return AssertTagValueNode[] */ public function getAssertTagValues(string $tagName = '@phpstan-assert') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof AssertTagValueNode); } /** * @return AssertTagPropertyValueNode[] */ public function getAssertPropertyTagValues(string $tagName = '@phpstan-assert') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof AssertTagPropertyValueNode); } /** * @return AssertTagMethodValueNode[] */ public function getAssertMethodTagValues(string $tagName = '@phpstan-assert') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof AssertTagMethodValueNode); } /** * @return SelfOutTagValueNode[] */ public function getSelfOutTypeTagValues(string $tagName = '@phpstan-this-out') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof SelfOutTagValueNode); } /** * @return ParamOutTagValueNode[] */ public function getParamOutTypeTagValues(string $tagName = '@param-out') : array { return array_filter(array_column($this->getTagsByName($tagName), 'value'), static fn(PhpDocTagValueNode $value): bool => $value instanceof ParamOutTagValueNode); } public function __toString() : string { $children = array_map(static function (PhpDocChildNode $child) : string { $s = (string) $child; return $s === '' ? '' : ' ' . $s; }, $this->children); return "/**\n *" . implode("\n *", $children) . "\n */"; } } type = $type; $this->parameterName = $parameterName; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->parameterName} {$this->description}"); } } value = $value; } public function __toString() : string { return $this->value; } } alias = $alias; $this->type = $type; } public function __toString() : string { return trim("{$this->alias} {$this->type}"); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } type = $type; $this->isReference = $isReference; $this->isVariadic = $isVariadic; $this->parameterName = $parameterName; $this->defaultValue = $defaultValue; } public function __toString() : string { $type = $this->type !== null ? "{$this->type} " : ''; $isReference = $this->isReference ? '&' : ''; $isVariadic = $this->isVariadic ? '...' : ''; $default = $this->defaultValue !== null ? " = {$this->defaultValue}" : ''; return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}"; } } key = $key; $this->value = $value; } public function __toString() : string { if ($this->key === null) { return (string) $this->value; } return $this->key . '=' . $this->value; } } */ public array $arguments; /** * @param list $arguments */ public function __construct(string $name, array $arguments) { $this->name = $name; $this->arguments = $arguments; } public function __toString() : string { $arguments = implode(', ', $this->arguments); return $this->name . '(' . $arguments . ')'; } } annotation = $annotation; $this->description = $description; } public function __toString() : string { return trim("{$this->annotation} {$this->description}"); } } key = $key; $this->value = $value; } public function __toString() : string { if ($this->key === null) { return (string) $this->value; } return $this->key . '=' . $this->value; } } */ public array $items; /** * @param list $items */ public function __construct(array $items) { $this->items = $items; } public function __toString() : string { $items = implode(', ', $this->items); return '{' . $items . '}'; } } value = $value; $this->exceptionArgs = [$exception->getCurrentTokenValue(), $exception->getCurrentTokenType(), $exception->getCurrentOffset(), $exception->getExpectedTokenType(), $exception->getExpectedTokenValue(), $exception->getCurrentTokenLine()]; } public function __get(string $name) : ?ParserException { if ($name !== 'exception') { trigger_error(sprintf('Undefined property: %s::$%s', self::class, $name), E_USER_WARNING); return null; } return new ParserException(...$this->exceptionArgs); } public function __toString() : string { return $this->value; } } type = $type; $this->variableName = $variableName; $this->description = $description; } public function __toString() : string { return trim("{$this->type} " . trim("{$this->variableName} {$this->description}")); } } name = $name; $this->value = $value; } public function __toString() : string { if ($this->value instanceof DoctrineTagValueNode) { return (string) $this->value; } return trim("{$this->name} {$this->value}"); } } type = $type; $this->parameterName = $parameterName; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->parameterName} {$this->description}"); } } isReference = $isReference; $this->isVariadic = $isVariadic; $this->parameterName = $parameterName; $this->description = $description; } public function __toString() : string { $reference = $this->isReference ? '&' : ''; $variadic = $this->isVariadic ? '...' : ''; return trim("{$reference}{$variadic}{$this->parameterName} {$this->description}"); } } type = $type; $this->parameter = $parameter; $this->method = $method; $this->isNegated = $isNegated; $this->isEquality = $isEquality; $this->description = $description; } public function __toString() : string { $isNegated = $this->isNegated ? '!' : ''; $isEquality = $this->isEquality ? '=' : ''; return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->method}() {$this->description}"); } } importedAlias = $importedAlias; $this->importedFrom = $importedFrom; $this->importedAs = $importedAs; } public function __toString() : string { return trim("{$this->importedAlias} from {$this->importedFrom}" . ($this->importedAs !== null ? " as {$this->importedAs}" : '')); } } type = $type; $this->propertyName = $propertyName; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->propertyName} {$this->description}"); } } parameterName = $parameterName; $this->description = $description; } public function __toString() : string { return trim("{$this->parameterName} {$this->description}"); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } type = $type; $this->isReference = $isReference; $this->isVariadic = $isVariadic; $this->parameterName = $parameterName; $this->description = $description; } public function __toString() : string { $reference = $this->isReference ? '&' : ''; $variadic = $this->isVariadic ? '...' : ''; return trim("{$this->type} {$reference}{$variadic}{$this->parameterName} {$this->description}"); } } isStatic = $isStatic; $this->returnType = $returnType; $this->methodName = $methodName; $this->parameters = $parameters; $this->description = $description; $this->templateTypes = $templateTypes; } public function __toString() : string { $static = $this->isStatic ? 'static ' : ''; $returnType = $this->returnType !== null ? "{$this->returnType} " : ''; $parameters = implode(', ', $this->parameters); $description = $this->description !== '' ? " {$this->description}" : ''; $templateTypes = count($this->templateTypes) > 0 ? '<' . implode(', ', $this->templateTypes) . '>' : ''; return "{$static}{$returnType}{$this->methodName}{$templateTypes}({$parameters}){$description}"; } } type = $type; $this->description = $description; } public function __toString() : string { return trim($this->type . ' ' . $this->description); } } description = $description; } public function __toString() : string { return trim($this->description); } } type = $type; $this->description = $description; } public function __toString() : string { return trim("{$this->type} {$this->description}"); } } className = $className; $this->name = $name; } public function __toString() : string { if ($this->className === '') { return $this->name; } return "{$this->className}::{$this->name}"; } } items = $items; } public function __toString() : string { return '[' . implode(', ', $this->items) . ']'; } } value = $value; $this->quoteType = $quoteType; } public function __toString() : string { if ($this->quoteType === self::SINGLE_QUOTED) { // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1007 return sprintf("'%s'", addcslashes($this->value, '\'\\')); } // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1010-L1040 return sprintf('"%s"', $this->escapeDoubleQuotedString()); } private function escapeDoubleQuotedString() : string { $quote = '"'; $escaped = addcslashes($this->value, "\n\r\t\f\v\$" . $quote . '\\'); // Escape control characters and non-UTF-8 characters. // Regex based on https://stackoverflow.com/a/11709412/385378. $regex = '/( [\\x00-\\x08\\x0E-\\x1F] # Control characters | [\\xC0-\\xC1] # Invalid UTF-8 Bytes | [\\xF5-\\xFF] # Invalid UTF-8 Bytes | \\xE0(?=[\\x80-\\x9F]) # Overlong encoding of prior code point | \\xF0(?=[\\x80-\\x8F]) # Overlong encoding of prior code point | [\\xC2-\\xDF](?![\\x80-\\xBF]) # Invalid UTF-8 Sequence Start | [\\xE0-\\xEF](?![\\x80-\\xBF]{2}) # Invalid UTF-8 Sequence Start | [\\xF0-\\xF4](?![\\x80-\\xBF]{3}) # Invalid UTF-8 Sequence Start | (?<=[\\x00-\\x7F\\xF5-\\xFF])[\\x80-\\xBF] # Invalid UTF-8 Sequence Middle | (?value = $value; } public function __toString() : string { return $this->value; } } key = $key; $this->value = $value; } public function __toString() : string { if ($this->key !== null) { return sprintf('%s => %s', $this->key, $this->value); } return (string) $this->value; } } value = $value; } public function __toString() : string { return self::escape($this->value); } public static function unescape(string $value) : string { // from https://github.com/doctrine/annotations/blob/a9ec7af212302a75d1f92fa65d3abfbd16245a2a/lib/Doctrine/Common/Annotations/DocLexer.php#L103-L107 return str_replace('""', '"', substr($value, 1, strlen($value) - 2)); } private static function escape(string $value) : string { // from https://github.com/phpstan/phpdoc-parser/issues/205#issuecomment-1662323656 return sprintf('"%s"', str_replace('"', '""', $value)); } } value = $value; } public function __toString() : string { return $this->value; } } $node stays as-is * * array (of Nodes) * => The return value is merged into the parent array (at the position of the $node) * * NodeTraverser::REMOVE_NODE * => $node is removed from the parent array * * NodeTraverser::DONT_TRAVERSE_CHILDREN * => Children of $node are not traversed. $node stays as-is * * NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN * => Further visitors for the current node are skipped, and its children are not * traversed. $node stays as-is. * * NodeTraverser::STOP_TRAVERSAL * => Traversal is aborted. $node stays as-is * * otherwise * => $node is set to the return value * * @param Node $node Node * * @return Node|Node[]|NodeTraverser::*|null Replacement node (or special return value) */ public function enterNode(Node $node); /** * Called when leaving a node. * * Return value semantics: * * null * => $node stays as-is * * NodeTraverser::REMOVE_NODE * => $node is removed from the parent array * * NodeTraverser::STOP_TRAVERSAL * => Traversal is aborted. $node stays as-is * * array (of Nodes) * => The return value is merged into the parent array (at the position of the $node) * * otherwise * => $node is set to the return value * * @param Node $node Node * * @return Node|Node[]|NodeTraverser::REMOVE_NODE|NodeTraverser::STOP_TRAVERSAL|null Replacement node (or special return value) */ public function leaveNode(Node $node); /** * Called once after traversal. * * Return value semantics: * * null: $nodes stays as-is * * otherwise: $nodes is set to the return value * * @param Node[] $nodes Array of nodes * * @return Node[]|null Array of nodes */ public function afterTraverse(array $nodes) : ?array; } setAttribute(Attribute::ORIGINAL_NODE, $originalNode); return $node; } } types = $types; } public function __toString() : string { return '(' . implode(' | ', array_map(static function (TypeNode $type) : string { if ($type instanceof NullableTypeNode) { return '(' . $type . ')'; } return (string) $type; }, $this->types)) . ')'; } } types = $types; } public function __toString() : string { return '(' . implode(' & ', array_map(static function (TypeNode $type) : string { if ($type instanceof NullableTypeNode) { return '(' . $type . ')'; } return (string) $type; }, $this->types)) . ')'; } } name = $name; } public function __toString() : string { return $this->name; } } keyName = $keyName; $this->optional = $optional; $this->valueType = $valueType; } public function __toString() : string { if ($this->keyName !== null) { return sprintf('%s%s: %s', (string) $this->keyName, $this->optional ? '?' : '', (string) $this->valueType); } return (string) $this->valueType; } } constExpr = $constExpr; } public function __toString() : string { return $this->constExpr->__toString(); } } type = $type; $this->isReference = $isReference; $this->isVariadic = $isVariadic; $this->parameterName = $parameterName; $this->isOptional = $isOptional; } public function __toString() : string { $type = "{$this->type} "; $isReference = $this->isReference ? '&' : ''; $isVariadic = $this->isVariadic ? '...' : ''; $isOptional = $this->isOptional ? '=' : ''; return trim("{$type}{$isReference}{$isVariadic}{$this->parameterName}") . $isOptional; } } identifier = $identifier; $this->parameters = $parameters; $this->returnType = $returnType; $this->templateTypes = $templateTypes; } public function __toString() : string { $returnType = $this->returnType; if ($returnType instanceof self) { $returnType = "({$returnType})"; } $template = $this->templateTypes !== [] ? '<' . implode(', ', $this->templateTypes) . '>' : ''; $parameters = implode(', ', $this->parameters); return "{$this->identifier}{$template}({$parameters}): {$returnType}"; } } keyName = $keyName; $this->optional = $optional; $this->valueType = $valueType; } public function __toString() : string { if ($this->keyName !== null) { return sprintf('%s%s: %s', (string) $this->keyName, $this->optional ? '?' : '', (string) $this->valueType); } return (string) $this->valueType; } } items = $items; } public function __toString() : string { $items = $this->items; return 'object{' . implode(', ', $items) . '}'; } } exceptionArgs = [$exception->getCurrentTokenValue(), $exception->getCurrentTokenType(), $exception->getCurrentOffset(), $exception->getExpectedTokenType(), $exception->getExpectedTokenValue(), $exception->getCurrentTokenLine()]; } public function getException() : ParserException { return new ParserException(...$this->exceptionArgs); } public function __toString() : string { return '*Invalid type*'; } } type = $type; $this->offset = $offset; } public function __toString() : string { if ($this->type instanceof CallableTypeNode || $this->type instanceof NullableTypeNode) { return '(' . $this->type . ')[' . $this->offset . ']'; } return $this->type . '[' . $this->offset . ']'; } } subjectType = $subjectType; $this->targetType = $targetType; $this->if = $if; $this->else = $else; $this->negated = $negated; } public function __toString() : string { return sprintf('(%s %s %s ? %s : %s)', $this->subjectType, $this->negated ? 'is not' : 'is', $this->targetType, $this->if, $this->else); } } valueType = $valueType; $this->keyType = $keyType; } public function __toString() : string { if ($this->keyType !== null) { return sprintf('<%s, %s>', $this->keyType, $this->valueType); } return sprintf('<%s>', $this->valueType); } } parameterName = $parameterName; $this->targetType = $targetType; $this->if = $if; $this->else = $else; $this->negated = $negated; } public function __toString() : string { return sprintf('(%s %s %s ? %s : %s)', $this->parameterName, $this->negated ? 'is not' : 'is', $this->targetType, $this->if, $this->else); } } type = $type; } public function __toString() : string { return '?' . $this->type; } } items = $items; $this->sealed = $sealed; $this->unsealedType = $unsealedType; $this->kind = $kind; } /** * @param ArrayShapeItemNode[] $items * @param self::KIND_* $kind */ public static function createSealed(array $items, string $kind = self::KIND_ARRAY) : self { return new self($items, \true, null, $kind); } /** * @param ArrayShapeItemNode[] $items * @param self::KIND_* $kind */ public static function createUnsealed(array $items, ?ArrayShapeUnsealedTypeNode $unsealedType, string $kind = self::KIND_ARRAY) : self { return new self($items, \false, $unsealedType, $kind); } public function __toString() : string { $items = $this->items; if (!$this->sealed) { $items[] = '...' . $this->unsealedType; } return $this->kind . '{' . implode(', ', $items) . '}'; } } type = $type; $this->genericTypes = $genericTypes; $this->variances = $variances; } public function __toString() : string { $genericTypes = []; foreach ($this->genericTypes as $index => $type) { $variance = $this->variances[$index] ?? self::VARIANCE_INVARIANT; if ($variance === self::VARIANCE_INVARIANT) { $genericTypes[] = (string) $type; } elseif ($variance === self::VARIANCE_BIVARIANT) { $genericTypes[] = '*'; } else { $genericTypes[] = sprintf('%s %s', $variance, $type); } } return $this->type . '<' . implode(', ', $genericTypes) . '>'; } } type = $type; } public function __toString() : string { if ($this->type instanceof CallableTypeNode || $this->type instanceof ConstTypeNode || $this->type instanceof NullableTypeNode) { return '(' . $this->type . ')[]'; } return $this->type . '[]'; } } text = $text; $this->startLine = $startLine; $this->startIndex = $startIndex; } public function getReformattedText() : string { return trim($this->text); } } */ private array $attributes = []; /** * @param mixed $value */ public function setAttribute(string $key, $value) : void { if ($value === null) { unset($this->attributes[$key]); return; } $this->attributes[$key] = $value; } public function hasAttribute(string $key) : bool { return array_key_exists($key, $this->attributes); } /** * @return mixed */ public function getAttribute(string $key) { if ($this->hasAttribute($key)) { return $this->attributes[$key]; } return null; } } Visitors */ private array $visitors = []; /** @var bool Whether traversal should be stopped */ private bool $stopTraversal; /** * @param list $visitors */ public function __construct(array $visitors) { $this->visitors = $visitors; } /** * Traverses an array of nodes using the registered visitors. * * @param Node[] $nodes Array of nodes * * @return Node[] Traversed array of nodes */ public function traverse(array $nodes) : array { $this->stopTraversal = \false; foreach ($this->visitors as $visitor) { $return = $visitor->beforeTraverse($nodes); if ($return === null) { continue; } $nodes = $return; } $nodes = $this->traverseArray($nodes); foreach ($this->visitors as $visitor) { $return = $visitor->afterTraverse($nodes); if ($return === null) { continue; } $nodes = $return; } return $nodes; } /** * Recursively traverse a node. * * @param Node $node Node to traverse. * * @return Node Result of traversal (may be original node or new one) */ private function traverseNode(Node $node) : Node { $subNodeNames = array_keys(get_object_vars($node)); foreach ($subNodeNames as $name) { $subNode =& $node->{$name}; if (is_array($subNode)) { $subNode = $this->traverseArray($subNode); if ($this->stopTraversal) { break; } } elseif ($subNode instanceof Node) { $traverseChildren = \true; $breakVisitorIndex = null; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($subNode); if ($return === null) { continue; } if ($return instanceof Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $return; } elseif ($return === self::DONT_TRAVERSE_CHILDREN) { $traverseChildren = \false; } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) { $traverseChildren = \false; $breakVisitorIndex = $visitorIndex; break; } elseif ($return === self::STOP_TRAVERSAL) { $this->stopTraversal = \true; break 2; } else { throw new LogicException('enterNode() returned invalid value of type ' . gettype($return)); } } if ($traverseChildren) { $subNode = $this->traverseNode($subNode); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->leaveNode($subNode); if ($return !== null) { if ($return instanceof Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $return; } elseif ($return === self::STOP_TRAVERSAL) { $this->stopTraversal = \true; break 2; } elseif (is_array($return)) { throw new LogicException('leaveNode() may only return an array ' . 'if the parent structure is an array'); } else { throw new LogicException('leaveNode() returned invalid value of type ' . gettype($return)); } } if ($breakVisitorIndex === $visitorIndex) { break; } } } } return $node; } /** * Recursively traverse array (usually of nodes). * * @param mixed[] $nodes Array to traverse * * @return mixed[] Result of traversal (may be original array or changed one) */ private function traverseArray(array $nodes) : array { $doNodes = []; foreach ($nodes as $i => &$node) { if ($node instanceof Node) { $traverseChildren = \true; $breakVisitorIndex = null; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($node); if ($return === null) { continue; } if ($return instanceof Node) { $this->ensureReplacementReasonable($node, $return); $node = $return; } elseif (is_array($return)) { $doNodes[] = [$i, $return]; continue 2; } elseif ($return === self::REMOVE_NODE) { $doNodes[] = [$i, []]; continue 2; } elseif ($return === self::DONT_TRAVERSE_CHILDREN) { $traverseChildren = \false; } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) { $traverseChildren = \false; $breakVisitorIndex = $visitorIndex; break; } elseif ($return === self::STOP_TRAVERSAL) { $this->stopTraversal = \true; break 2; } else { throw new LogicException('enterNode() returned invalid value of type ' . gettype($return)); } } if ($traverseChildren) { $node = $this->traverseNode($node); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->leaveNode($node); if ($return !== null) { if ($return instanceof Node) { $this->ensureReplacementReasonable($node, $return); $node = $return; } elseif (is_array($return)) { $doNodes[] = [$i, $return]; break; } elseif ($return === self::REMOVE_NODE) { $doNodes[] = [$i, []]; break; } elseif ($return === self::STOP_TRAVERSAL) { $this->stopTraversal = \true; break 2; } else { throw new LogicException('leaveNode() returned invalid value of type ' . gettype($return)); } } if ($breakVisitorIndex === $visitorIndex) { break; } } } elseif (is_array($node)) { throw new LogicException('Invalid node structure: Contains nested arrays'); } } if (count($doNodes) > 0) { while ([$i, $replace] = array_pop($doNodes)) { array_splice($nodes, $i, 1, $replace); } } return $nodes; } private function ensureReplacementReasonable(Node $old, Node $new) : void { if ($old instanceof TypeNode && !$new instanceof TypeNode) { throw new LogicException(sprintf('Trying to replace TypeNode with %s', get_class($new))); } if ($old instanceof ConstExprNode && !$new instanceof ConstExprNode) { throw new LogicException(sprintf('Trying to replace ConstExprNode with %s', get_class($new))); } if ($old instanceof PhpDocChildNode && !$new instanceof PhpDocChildNode) { throw new LogicException(sprintf('Trying to replace PhpDocChildNode with %s', get_class($new))); } if ($old instanceof PhpDocTagValueNode && !$new instanceof PhpDocTagValueNode) { throw new LogicException(sprintf('Trying to replace PhpDocTagValueNode with %s', get_class($new))); } } } MIT License Copyright (c) 2017 Luís Cobucci 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. { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "local>lcobucci/.github:renovate-config" ] } { "name": "lcobucci\/clock", "description": "Yet another clock abstraction", "license": "MIT", "type": "library", "authors": [ { "name": "Lu\u00eds Cobucci", "email": "lcobucci@gmail.com" } ], "require": { "php": "~8.1.0 || ~8.2.0", "psr\/clock": "^1.0" }, "require-dev": { "infection\/infection": "^0.26", "lcobucci\/coding-standard": "^9.0", "phpstan\/extension-installer": "^1.2", "phpstan\/phpstan": "^1.9.4", "phpstan\/phpstan-deprecation-rules": "^1.1.1", "phpstan\/phpstan-phpunit": "^1.3.2", "phpstan\/phpstan-strict-rules": "^1.4.4", "phpunit\/phpunit": "^9.5.27" }, "autoload": { "psr-4": { "_ContaoManager\\Lcobucci\\Clock\\": "src" } }, "autoload-dev": { "psr-4": { "_ContaoManager\\Lcobucci\\Clock\\": "test" } }, "config": { "preferred-install": "dist", "sort-packages": true, "allow-plugins": { "dealerdirect\/phpcodesniffer-composer-installer": true, "infection\/extension-installer": true, "phpstan\/extension-installer": true } }, "provide": { "psr\/clock-implementation": "1.0" } }now = $now; } public function now() : DateTimeImmutable { return $this->now; } } timezone); } } #!/usr/bin/env php realpath = \realpath($opened_path) ?: $opened_path; $opened_path = $this->realpath; $this->handle = \fopen($this->realpath, $mode); $this->position = 0; return (bool) $this->handle; } public function stream_read($count) { $data = \fread($this->handle, $count); if ($this->position === 0) { $data = \preg_replace('{^#!.*\\r?\\n}', '', $data); } $this->position += \strlen($data); return $data; } public function stream_cast($castAs) { return $this->handle; } public function stream_close() { \fclose($this->handle); } public function stream_lock($operation) { return $operation ? \flock($this->handle, $operation) : \true; } public function stream_seek($offset, $whence) { if (0 === \fseek($this->handle, $offset, $whence)) { $this->position = \ftell($this->handle); return \true; } return \false; } public function stream_tell() { return $this->position; } public function stream_eof() { return \feof($this->handle); } public function stream_stat() { return array(); } public function stream_set_option($option, $arg1, $arg2) { return \true; } public function url_stat($path, $flags) { $path = \substr($path, 17); if (\file_exists($path)) { return \stat($path); } return \false; } } } if (\function_exists('stream_get_wrappers') && \in_array('phpvfscomposer', \stream_get_wrappers(), \true) || \function_exists('stream_wrapper_register') && \stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper')) { return include "phpvfscomposer://" . __DIR__ . '/..' . '/symfony/yaml/Resources/bin/yaml-lint'; } } return include __DIR__ . '/..' . '/symfony/yaml/Resources/bin/yaml-lint'; #!/usr/bin/env php realpath = \realpath($opened_path) ?: $opened_path; $opened_path = $this->realpath; $this->handle = \fopen($this->realpath, $mode); $this->position = 0; return (bool) $this->handle; } public function stream_read($count) { $data = \fread($this->handle, $count); if ($this->position === 0) { $data = \preg_replace('{^#!.*\\r?\\n}', '', $data); } $this->position += \strlen($data); return $data; } public function stream_cast($castAs) { return $this->handle; } public function stream_close() { \fclose($this->handle); } public function stream_lock($operation) { return $operation ? \flock($this->handle, $operation) : \true; } public function stream_seek($offset, $whence) { if (0 === \fseek($this->handle, $offset, $whence)) { $this->position = \ftell($this->handle); return \true; } return \false; } public function stream_tell() { return $this->position; } public function stream_eof() { return \feof($this->handle); } public function stream_stat() { return array(); } public function stream_set_option($option, $arg1, $arg2) { return \true; } public function url_stat($path, $flags) { $path = \substr($path, 17); if (\file_exists($path)) { return \stat($path); } return \false; } } } if (\function_exists('stream_get_wrappers') && \in_array('phpvfscomposer', \stream_get_wrappers(), \true) || \function_exists('stream_wrapper_register') && \stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper')) { return include "phpvfscomposer://" . __DIR__ . '/..' . '/symfony/error-handler/Resources/bin/patch-type-declarations'; } } return include __DIR__ . '/..' . '/symfony/error-handler/Resources/bin/patch-type-declarations'; #!/usr/bin/env php realpath = \realpath($opened_path) ?: $opened_path; $opened_path = $this->realpath; $this->handle = \fopen($this->realpath, $mode); $this->position = 0; return (bool) $this->handle; } public function stream_read($count) { $data = \fread($this->handle, $count); if ($this->position === 0) { $data = \preg_replace('{^#!.*\\r?\\n}', '', $data); } $this->position += \strlen($data); return $data; } public function stream_cast($castAs) { return $this->handle; } public function stream_close() { \fclose($this->handle); } public function stream_lock($operation) { return $operation ? \flock($this->handle, $operation) : \true; } public function stream_seek($offset, $whence) { if (0 === \fseek($this->handle, $offset, $whence)) { $this->position = \ftell($this->handle); return \true; } return \false; } public function stream_tell() { return $this->position; } public function stream_eof() { return \feof($this->handle); } public function stream_stat() { return array(); } public function stream_set_option($option, $arg1, $arg2) { return \true; } public function url_stat($path, $flags) { $path = \substr($path, 17); if (\file_exists($path)) { return \stat($path); } return \false; } } } if (\function_exists('stream_get_wrappers') && \in_array('phpvfscomposer', \stream_get_wrappers(), \true) || \function_exists('stream_wrapper_register') && \stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper')) { return include "phpvfscomposer://" . __DIR__ . '/..' . '/justinrainbow/json-schema/bin/validate-json'; } } return include __DIR__ . '/..' . '/justinrainbow/json-schema/bin/validate-json'; #!/usr/bin/env php realpath = \realpath($opened_path) ?: $opened_path; $opened_path = $this->realpath; $this->handle = \fopen($this->realpath, $mode); $this->position = 0; return (bool) $this->handle; } public function stream_read($count) { $data = \fread($this->handle, $count); if ($this->position === 0) { $data = \preg_replace('{^#!.*\\r?\\n}', '', $data); } $this->position += \strlen($data); return $data; } public function stream_cast($castAs) { return $this->handle; } public function stream_close() { \fclose($this->handle); } public function stream_lock($operation) { return $operation ? \flock($this->handle, $operation) : \true; } public function stream_seek($offset, $whence) { if (0 === \fseek($this->handle, $offset, $whence)) { $this->position = \ftell($this->handle); return \true; } return \false; } public function stream_tell() { return $this->position; } public function stream_eof() { return \feof($this->handle); } public function stream_stat() { return array(); } public function stream_set_option($option, $arg1, $arg2) { return \true; } public function url_stat($path, $flags) { $path = \substr($path, 17); if (\file_exists($path)) { return \stat($path); } return \false; } } } if (\function_exists('stream_get_wrappers') && \in_array('phpvfscomposer', \stream_get_wrappers(), \true) || \function_exists('stream_wrapper_register') && \stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper')) { return include "phpvfscomposer://" . __DIR__ . '/..' . '/composer/composer/bin/composer'; } } return include __DIR__ . '/..' . '/composer/composer/bin/composer'; #!/usr/bin/env php realpath = \realpath($opened_path) ?: $opened_path; $opened_path = $this->realpath; $this->handle = \fopen($this->realpath, $mode); $this->position = 0; return (bool) $this->handle; } public function stream_read($count) { $data = \fread($this->handle, $count); if ($this->position === 0) { $data = \preg_replace('{^#!.*\\r?\\n}', '', $data); } $this->position += \strlen($data); return $data; } public function stream_cast($castAs) { return $this->handle; } public function stream_close() { \fclose($this->handle); } public function stream_lock($operation) { return $operation ? \flock($this->handle, $operation) : \true; } public function stream_seek($offset, $whence) { if (0 === \fseek($this->handle, $offset, $whence)) { $this->position = \ftell($this->handle); return \true; } return \false; } public function stream_tell() { return $this->position; } public function stream_eof() { return \feof($this->handle); } public function stream_stat() { return array(); } public function stream_set_option($option, $arg1, $arg2) { return \true; } public function url_stat($path, $flags) { $path = \substr($path, 17); if (\file_exists($path)) { return \stat($path); } return \false; } } } if (\function_exists('stream_get_wrappers') && \in_array('phpvfscomposer', \stream_get_wrappers(), \true) || \function_exists('stream_wrapper_register') && \stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper')) { return include "phpvfscomposer://" . __DIR__ . '/..' . '/symfony/var-dumper/Resources/bin/var-dump-server'; } } return include __DIR__ . '/..' . '/symfony/var-dumper/Resources/bin/var-dump-server'; #!/usr/bin/env php realpath = \realpath($opened_path) ?: $opened_path; $opened_path = $this->realpath; $this->handle = \fopen($this->realpath, $mode); $this->position = 0; return (bool) $this->handle; } public function stream_read($count) { $data = \fread($this->handle, $count); if ($this->position === 0) { $data = \preg_replace('{^#!.*\\r?\\n}', '', $data); } $this->position += \strlen($data); return $data; } public function stream_cast($castAs) { return $this->handle; } public function stream_close() { \fclose($this->handle); } public function stream_lock($operation) { return $operation ? \flock($this->handle, $operation) : \true; } public function stream_seek($offset, $whence) { if (0 === \fseek($this->handle, $offset, $whence)) { $this->position = \ftell($this->handle); return \true; } return \false; } public function stream_tell() { return $this->position; } public function stream_eof() { return \feof($this->handle); } public function stream_stat() { return array(); } public function stream_set_option($option, $arg1, $arg2) { return \true; } public function url_stat($path, $flags) { $path = \substr($path, 17); if (\file_exists($path)) { return \stat($path); } return \false; } } } if (\function_exists('stream_get_wrappers') && \in_array('phpvfscomposer', \stream_get_wrappers(), \true) || \function_exists('stream_wrapper_register') && \stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper')) { return include "phpvfscomposer://" . __DIR__ . '/..' . '/seld/jsonlint/bin/jsonlint'; } } return include __DIR__ . '/..' . '/seld/jsonlint/bin/jsonlint'; MIT License Copyright (c) 2018-2022 Spomky-Labs 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. { "name": "web-auth\/webauthn-lib", "type": "library", "license": "MIT", "description": "FIDO2\/Webauthn Support For PHP", "keywords": [ "FIDO", "FIDO2", "webauthn" ], "homepage": "https:\/\/github.com\/web-auth", "authors": [ { "name": "Florent Morselli", "homepage": "https:\/\/github.com\/Spomky" }, { "name": "All contributors", "homepage": "https:\/\/github.com\/web-auth\/webauthn-library\/contributors" } ], "require": { "php": ">=8.1", "ext-json": "*", "ext-openssl": "*", "ext-mbstring": "*", "lcobucci\/clock": "^2.2|^3.0", "paragonie\/constant_time_encoding": "^2.6|^3.0", "psr\/clock": "^1.0", "psr\/event-dispatcher": "^1.0", "psr\/http-client": "^1.0", "psr\/http-factory": "^1.0", "psr\/log": "^1.0|^2.0|^3.0", "spomky-labs\/cbor-php": "^3.0", "spomky-labs\/pki-framework": "^1.0", "symfony\/uid": "^6.1|^7.0", "symfony\/deprecation-contracts": "^3.2", "web-auth\/cose-lib": "^4.2.3" }, "autoload": { "psr-4": { "_ContaoManager\\Webauthn\\": "src\/" } }, "extra": { "thanks": { "name": "web-auth\/webauthn-framework", "url": "https:\/\/github.com\/web-auth\/webauthn-framework" } }, "suggest": { "symfony\/serializer": "As of 4.5.x, the symfony\/serializer component will become mandatory for converting objects such as the Metadata Statement", "symfony\/property-access": "As of 4.5.x, the symfony\/serializer component will become mandatory for converting objects such as the Metadata Statement", "symfony\/property-info": "As of 4.5.x, the symfony\/serializer component will become mandatory for converting objects such as the Metadata Statement", "phpdocumentor\/reflection-docblock": "As of 4.5.x, the phpdocumentor\/reflection-docblock component will become mandatory for converting objects such as the Metadata Statement", "psr\/log-implementation": "Recommended to receive logs from the library", "symfony\/event-dispatcher": "Recommended to use dispatched events", "psr\/clock-implementation": "As of 4.5.x, the PSR Clock implementation will replace lcobucci\/clock", "web-token\/jwt-library": "Mandatory for fetching Metadata Statement from distant sources" } }length = \mb_strlen($data, '8bit'); $resource = fopen('php://memory', 'rb+'); fwrite($resource, $data); rewind($resource); $this->data = $resource; } public function read(int $length) : string { if ($length <= 0) { return ''; } $read = fread($this->data, $length); $bytesRead = \mb_strlen($read, '8bit'); \mb_strlen($read, '8bit') === $length || throw InvalidDataException::create(null, sprintf('Out of range. Expected: %d, read: %d.', $length, $bytesRead)); $this->totalRead += $bytesRead; return $read; } public function close() : void { fclose($this->data); } public function isEOF() : bool { return $this->totalRead === $this->length; } } getAttestedCredentialData()->credentialPublicKey; $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('No public key available.'); $algorithms = \array_map(fn($pubKeyCredParam) => $pubKeyCredParam->alg, $publicKeyCredentialOptions->pubKeyCredParams); if (count($algorithms) === 0) { $algorithms = [Algorithms::COSE_ALGORITHM_ES256, Algorithms::COSE_ALGORITHM_RS256]; } $coseKey = $this->getCoseKey($credentialPublicKey); in_array($coseKey->alg(), $algorithms, \true) || throw AuthenticatorResponseVerificationException::create(sprintf('Invalid algorithm. Expected one of %s but got %d', \implode(', ', $algorithms), $coseKey->alg())); } private function getCoseKey(string $credentialPublicKey) : Key { $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey); if ($isU2F === \true) { $credentialPublicKey = U2FPublicKey::convertToCoseKey($credentialPublicKey); } $stream = new StringStream($credentialPublicKey); $credentialPublicKeyStream = Decoder::create()->decode($stream); $stream->isEOF() || throw AuthenticatorResponseVerificationException::create('Invalid key. Presence of extra bytes.'); $stream->close(); $credentialPublicKeyStream instanceof Normalizable || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.'); $normalizedData = $credentialPublicKeyStream->normalize(); is_array($normalizedData) || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.'); /** @var array $normalizedData */ return Key::create($normalizedData); } } userHandle; $responseUserHandle = $authenticatorResponse->userHandle; if ($userHandle !== null) { //If the user was identified before the authentication ceremony was initiated, $credentialUserHandle === $userHandle || throw InvalidUserHandleException::create(); if ($responseUserHandle !== null && $responseUserHandle !== '') { $credentialUserHandle === $responseUserHandle || throw InvalidUserHandleException::create(); } } else { $responseUserHandle !== '' && $credentialUserHandle === $responseUserHandle || throw InvalidUserHandleException::create(); } } } authenticatorData : $authenticatorResponse->attestationObject->authData; $authData->hasAttestedCredentialData() || throw AuthenticatorResponseVerificationException::create('There is no attested credential data.'); $authData->attestedCredentialData !== null || throw AuthenticatorResponseVerificationException::create('There is no attested credential data.'); } } steps as $step) { $step->process($publicKeyCredentialSource, $authenticatorResponse, $publicKeyCredentialOptions, $userHandle, $host); } } } userVerification : $publicKeyCredentialOptions->authenticatorSelection?->userVerification; if ($userVerification !== AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED) { return; } $authData = $authenticatorResponse instanceof AuthenticatorAssertionResponse ? $authenticatorResponse->authenticatorData : $authenticatorResponse->attestationObject->authData; $authData->isUserVerified() || throw AuthenticatorResponseVerificationException::create('User authentication required.'); } } allowCredentials) === 0) { return; } foreach ($publicKeyCredentialOptions->allowCredentials as $allowedCredential) { if (\hash_equals($allowedCredential->id, $publicKeyCredentialSource->publicKeyCredentialId)) { return; } } throw AuthenticatorResponseVerificationException::create('The credential ID is not allowed.'); } } publicKeyCredentialId; \mb_strlen($credentialId) <= 1023 || throw new AuthenticatorResponseVerificationException('Credential ID too long.'); } } attestationObject; if ($attestationObject === null) { return; } $fmt = $attestationObject->attStmt->fmt; $this->attestationStatementSupportManager->has($fmt) || throw AuthenticatorResponseVerificationException::create('Unsupported attestation statement format.'); $attestationStatementSupport = $this->attestationStatementSupportManager->get($fmt); $clientDataJSONHash = \hash('sha256', $authenticatorResponse->clientDataJSON->rawData, \true); $attestationStatementSupport->isValid($clientDataJSONHash, $attestationObject->attStmt, $attestationObject->authData) || throw AuthenticatorResponseVerificationException::create('Invalid attestation statement.'); } } algorithmManager = $algorithmManager ?? Manager::create()->add(ES256::create(), RS256::create()); } public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host) : void { if (!$authenticatorResponse instanceof AuthenticatorAssertionResponse) { return; } $credentialPublicKey = $publicKeyCredentialSource->getAttestedCredentialData()->credentialPublicKey; $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('No public key available.'); $coseKey = $this->getCoseKey($credentialPublicKey); $getClientDataJSONHash = \hash('sha256', $authenticatorResponse->clientDataJSON->rawData, \true); $dataToVerify = $authenticatorResponse->authenticatorData->authData . $getClientDataJSONHash; $signature = $authenticatorResponse->signature; $algorithm = $this->algorithmManager->get($coseKey->alg()); $algorithm instanceof Signature || throw AuthenticatorResponseVerificationException::create('Invalid algorithm identifier. Should refer to a signature algorithm'); $signature = CoseSignatureFixer::fix($signature, $algorithm); $algorithm->verify($dataToVerify, $coseKey, $signature) || throw AuthenticatorResponseVerificationException::create('Invalid signature.'); } private function getCoseKey(string $credentialPublicKey) : Key { $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey); if ($isU2F === \true) { $credentialPublicKey = U2FPublicKey::convertToCoseKey($credentialPublicKey); } $stream = new StringStream($credentialPublicKey); $credentialPublicKeyStream = Decoder::create()->decode($stream); $stream->isEOF() || throw AuthenticatorResponseVerificationException::create('Invalid key. Presence of extra bytes.'); $stream->close(); $credentialPublicKeyStream instanceof Normalizable || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.'); $normalizedData = $credentialPublicKeyStream->normalize(); is_array($normalizedData) || throw AuthenticatorResponseVerificationException::create('Invalid attestation object. Unexpected object.'); /** @var array $normalizedData */ return Key::create($normalizedData); } } host || throw AuthenticatorResponseVerificationException::create('The top origin does not correspond to the host.'); } } authenticatorData : $authenticatorResponse->attestationObject->authData; $C = $authenticatorResponse->clientDataJSON; $attestedCredentialData = $publicKeyCredentialSource->getAttestedCredentialData(); $credentialPublicKey = $attestedCredentialData->credentialPublicKey; $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('No public key available.'); $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey); $rpId = $publicKeyCredentialOptions->rpId ?? $publicKeyCredentialOptions->rp->id ?? $host; $facetId = $this->getFacetId($rpId, $publicKeyCredentialOptions->extensions, $authData->extensions); $rpIdHash = \hash('sha256', $isU2F ? $C->origin : $facetId, \true); \hash_equals($rpIdHash, $authData->rpIdHash) || throw AuthenticatorResponseVerificationException::create('rpId hash mismatch.'); } private function getFacetId(string $rpId, AuthenticationExtensions $authenticationExtensionsClientInputs, null|AuthenticationExtensions $authenticationExtensionsClientOutputs) : string { if ($authenticationExtensionsClientOutputs === null || !$authenticationExtensionsClientInputs->has('appid') || !$authenticationExtensionsClientOutputs->has('appid')) { return $rpId; } $appId = $authenticationExtensionsClientInputs->get('appid')->value; $wasUsed = $authenticationExtensionsClientOutputs->get('appid')->value; if (!is_string($appId) || $wasUsed !== \true) { return $rpId; } return $appId; } } authenticatorData : $authenticatorResponse->attestationObject->authData; if ($authData->isBackupEligible()) { return; } $authData->isBackedUp() !== \true || throw AuthenticatorResponseVerificationException::create('Backup up bit is set but the backup is not eligible.'); } } authenticatorData : $authenticatorResponse->attestationObject->authData; $authData->isUserPresent() || throw AuthenticatorResponseVerificationException::create('User was not present'); } } clientDataCollectorManager = $clientDataCollectorManager ?? new ClientDataCollectorManager([new WebauthnAuthenticationCollector()]); } public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host) : void { $this->clientDataCollectorManager->collect($authenticatorResponse->clientDataJSON, $publicKeyCredentialOptions, $authenticatorResponse, $host); } } challenge !== '' || throw AuthenticatorResponseVerificationException::create('Invalid challenge.'); \hash_equals($publicKeyCredentialOptions->challenge, $authenticatorResponse->clientDataJSON->challenge) || throw AuthenticatorResponseVerificationException::create('Invalid challenge.'); } } authenticatorData : $authenticatorResponse->attestationObject->authData; $storedCounter = $publicKeyCredentialSource->counter; $responseCounter = $authData->signCount; if ($responseCounter !== 0 || $storedCounter !== 0) { $this->counterChecker->check($publicKeyCredentialSource, $responseCounter); } $publicKeyCredentialSource->counter = $responseCounter; } } clientDataJSON->topOrigin; if ($topOrigin === null) { return; } if ($authenticatorResponse->clientDataJSON->crossOrigin !== \true) { throw AuthenticatorResponseVerificationException::create('The response is not cross-origin.'); } if ($this->topOriginValidator === null) { (new HostTopOriginValidator($host))->validate($topOrigin); } else { $this->topOriginValidator->validate($topOrigin); } } } authenticatorData : $authenticatorResponse->attestationObject->authData; $C = $authenticatorResponse->clientDataJSON; $rpId = $publicKeyCredentialOptions->rpId ?? $publicKeyCredentialOptions->rp->id ?? $host; $facetId = $this->getFacetId($rpId, $publicKeyCredentialOptions->extensions, $authData->extensions); $parsedRelyingPartyId = \parse_url($C->origin); is_array($parsedRelyingPartyId) || throw AuthenticatorResponseVerificationException::create('Invalid origin'); if (!in_array($facetId, $this->securedRelyingPartyId, \true)) { $scheme = $parsedRelyingPartyId['scheme'] ?? ''; $scheme === 'https' || throw AuthenticatorResponseVerificationException::create('Invalid scheme. HTTPS required.'); } $clientDataRpId = $parsedRelyingPartyId['host'] ?? ''; $clientDataRpId !== '' || throw AuthenticatorResponseVerificationException::create('Invalid origin rpId.'); $rpIdLength = \mb_strlen($facetId); \mb_substr('.' . $clientDataRpId, -($rpIdLength + 1)) === '.' . $facetId || throw AuthenticatorResponseVerificationException::create('rpId mismatch.'); } private function getFacetId(string $rpId, AuthenticationExtensions $authenticationExtensionsClientInputs, null|AuthenticationExtensions $authenticationExtensionsClientOutputs) : string { if ($authenticationExtensionsClientOutputs === null || !$authenticationExtensionsClientInputs->has('appid') || !$authenticationExtensionsClientOutputs->has('appid')) { return $rpId; } $appId = $authenticationExtensionsClientInputs->get('appid')->value; $wasUsed = $authenticationExtensionsClientOutputs->get('appid')->value; if (!is_string($appId) || $wasUsed !== \true) { return $rpId; } return $appId; } } authenticatorData : $authenticatorResponse->attestationObject->authData; $extensionsClientOutputs = $authData->extensions; if ($extensionsClientOutputs !== null) { $this->extensionOutputCheckerHandler->check($publicKeyCredentialOptions->extensions, $extensionsClientOutputs); } } } logger = new NullLogger(); } public function enableMetadataStatementSupport(MetadataStatementRepository $metadataStatementRepository, StatusReportRepository $statusReportRepository, CertificateChainValidator $certificateChainValidator) : void { $this->metadataStatementRepository = $metadataStatementRepository; $this->statusReportRepository = $statusReportRepository; $this->certificateChainValidator = $certificateChainValidator; } public function enableCertificateChainValidator(CertificateChainValidator $certificateChainValidator) : void { $this->certificateChainValidator = $certificateChainValidator; } public function setLogger(LoggerInterface $logger) : void { $this->logger = $logger; } public function process(PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse|AuthenticatorAttestationResponse $authenticatorResponse, PublicKeyCredentialRequestOptions|PublicKeyCredentialCreationOptions $publicKeyCredentialOptions, ?string $userHandle, string $host) : void { if (!$publicKeyCredentialOptions instanceof PublicKeyCredentialCreationOptions || !$authenticatorResponse instanceof AuthenticatorAttestationResponse) { return; } $attestationStatement = $authenticatorResponse->attestationObject->attStmt; $attestedCredentialData = $authenticatorResponse->attestationObject->authData->attestedCredentialData; $attestedCredentialData !== null || throw AuthenticatorResponseVerificationException::create('No attested credential data found'); $aaguid = $attestedCredentialData->aaguid->__toString(); if ($publicKeyCredentialOptions->attestation === null || $publicKeyCredentialOptions->attestation === PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE) { $this->logger->debug('No attestation is asked.'); if ($aaguid === '00000000-0000-0000-0000-000000000000' && in_array($attestationStatement->type, [AttestationStatement::TYPE_NONE, AttestationStatement::TYPE_SELF], \true)) { $this->logger->debug('The Attestation Statement is anonymous.'); $this->checkCertificateChain($attestationStatement, null); return; } return; } // If no Attestation Statement has been returned or if null AAGUID (=00000000-0000-0000-0000-000000000000) // => nothing to check if ($attestationStatement->type === AttestationStatement::TYPE_NONE) { $this->logger->debug('No attestation returned.'); //No attestation is returned. We shall ensure that the AAGUID is a null one. //if ($aaguid !== '00000000-0000-0000-0000-000000000000') { //$this->logger->debug('Anonymization required. AAGUID and Attestation Statement changed.', [ // 'aaguid' => $aaguid, // 'AttestationStatement' => $attestationStatement, //]); //$attestedCredentialData->aaguid = Uuid::fromString('00000000-0000-0000-0000-000000000000'); // return; //} return; } if ($aaguid === '00000000-0000-0000-0000-000000000000') { //No need to continue if the AAGUID is null. // This could be the case e.g. with AnonCA type return; } //The MDS Repository is mandatory here $this->metadataStatementRepository !== null || throw AuthenticatorResponseVerificationException::create('The Metadata Statement Repository is mandatory when requesting attestation objects.'); $metadataStatement = $this->metadataStatementRepository->findOneByAAGUID($aaguid); // At this point, the Metadata Statement is mandatory $metadataStatement !== null || throw AuthenticatorResponseVerificationException::create(sprintf('The Metadata Statement for the AAGUID "%s" is missing', $aaguid)); // We check the last status report $this->checkStatusReport($aaguid); // We check the certificate chain (if any) $this->checkCertificateChain($attestationStatement, $metadataStatement); // Check Attestation Type is allowed if (count($metadataStatement->attestationTypes) !== 0) { $type = $this->getAttestationType($attestationStatement); in_array($type, $metadataStatement->attestationTypes, \true) || throw AuthenticatorResponseVerificationException::create(sprintf('Invalid attestation statement. The attestation type "%s" is not allowed for this authenticator.', $type)); } } private function getAttestationType(AttestationStatement $attestationStatement) : string { return match ($attestationStatement->type) { AttestationStatement::TYPE_BASIC => MetadataStatement::ATTESTATION_BASIC_FULL, AttestationStatement::TYPE_SELF => MetadataStatement::ATTESTATION_BASIC_SURROGATE, AttestationStatement::TYPE_ATTCA => MetadataStatement::ATTESTATION_ATTCA, AttestationStatement::TYPE_ECDAA => MetadataStatement::ATTESTATION_ECDAA, AttestationStatement::TYPE_ANONCA => MetadataStatement::ATTESTATION_ANONCA, default => throw AuthenticatorResponseVerificationException::create('Invalid attestation type'), }; } private function checkStatusReport(string $aaguid) : void { $statusReports = $this->statusReportRepository === null ? [] : $this->statusReportRepository->findStatusReportsByAAGUID($aaguid); if (count($statusReports) !== 0) { $lastStatusReport = \end($statusReports); if ($lastStatusReport->isCompromised()) { throw AuthenticatorResponseVerificationException::create('The authenticator is compromised and cannot be used'); } } } private function checkCertificateChain(AttestationStatement $attestationStatement, ?MetadataStatement $metadataStatement) : void { $trustPath = $attestationStatement->trustPath; if (!$trustPath instanceof CertificateTrustPath) { return; } $authenticatorCertificates = $trustPath->certificates; if ($metadataStatement === null) { $this->certificateChainValidator?->check($authenticatorCertificates, []); return; } $trustedCertificates = CertificateToolbox::fixPEMStructures($metadataStatement->attestationRootCertificates); $this->certificateChainValidator?->check($authenticatorCertificates, $trustedCertificates); } } counterChecker = new ThrowExceptionIfInvalid(); $this->algorithmManager = Manager::create()->add(ES256::create(), RS256::create()); $this->attestationStatementSupportManager = new AttestationStatementSupportManager([new NoneAttestationStatementSupport()]); $this->extensionOutputCheckerHandler = new ExtensionOutputCheckerHandler(); } public function setCounterChecker(CounterChecker $counterChecker) : void { $this->counterChecker = $counterChecker; } /** * @param string[] $securedRelyingPartyId */ public function setSecuredRelyingPartyId(array $securedRelyingPartyId) : void { $this->securedRelyingPartyId = $securedRelyingPartyId; } public function setExtensionOutputCheckerHandler(ExtensionOutputCheckerHandler $extensionOutputCheckerHandler) : void { $this->extensionOutputCheckerHandler = $extensionOutputCheckerHandler; } public function setAttestationStatementSupportManager(AttestationStatementSupportManager $attestationStatementSupportManager) : void { $this->attestationStatementSupportManager = $attestationStatementSupportManager; } public function setAlgorithmManager(Manager $algorithmManager) : void { $this->algorithmManager = $algorithmManager; } public function enableMetadataStatementSupport(MetadataStatementRepository $metadataStatementRepository, StatusReportRepository $statusReportRepository, CertificateChainValidator $certificateChainValidator) : void { $this->metadataStatementRepository = $metadataStatementRepository; $this->statusReportRepository = $statusReportRepository; $this->certificateChainValidator = $certificateChainValidator; } public function enableCertificateChainValidator(CertificateChainValidator $certificateChainValidator) : void { $this->certificateChainValidator = $certificateChainValidator; } public function enableTopOriginValidator(TopOriginValidator $topOriginValidator) : void { $this->topOriginValidator = $topOriginValidator; } /** * @param null|string[] $securedRelyingPartyId */ public function creationCeremony(null|array $securedRelyingPartyId = null) : CeremonyStepManager { $metadataStatementChecker = new CheckMetadataStatement(); if ($this->certificateChainValidator !== null) { $metadataStatementChecker->enableCertificateChainValidator($this->certificateChainValidator); } if ($this->metadataStatementRepository !== null && $this->statusReportRepository !== null && $this->certificateChainValidator !== null) { $metadataStatementChecker->enableMetadataStatementSupport($this->metadataStatementRepository, $this->statusReportRepository, $this->certificateChainValidator); } /* @see https://www.w3.org/TR/webauthn-3/#sctn-registering-a-new-credential */ return new CeremonyStepManager([new CheckClientDataCollectorType(), new CheckChallenge(), new CheckOrigin($this->securedRelyingPartyId ?? $securedRelyingPartyId ?? []), new CheckTopOrigin($this->topOriginValidator), new CheckRelyingPartyIdIdHash(), new CheckUserWasPresent(), new CheckUserVerification(), new CheckBackupBitsAreConsistent(), new CheckAlgorithm(), new CheckExtensions($this->extensionOutputCheckerHandler), new CheckAttestationFormatIsKnownAndValid($this->attestationStatementSupportManager), new CheckHasAttestedCredentialData(), $metadataStatementChecker, new CheckCredentialId()]); } /** * @param null|string[] $securedRelyingPartyId */ public function requestCeremony(null|array $securedRelyingPartyId = null) : CeremonyStepManager { /* @see https://www.w3.org/TR/webauthn-3/#sctn-verifying-assertion */ return new CeremonyStepManager([new CheckAllowedCredentialList(), new CheckUserHandle(), new CheckClientDataCollectorType(), new CheckChallenge(), new CheckOrigin($this->securedRelyingPartyId ?? $securedRelyingPartyId ?? []), new CheckTopOrigin(null), new CheckRelyingPartyIdIdHash(), new CheckUserWasPresent(), new CheckUserVerification(), new CheckBackupBitsAreConsistent(), new CheckExtensions($this->extensionOutputCheckerHandler), new CheckSignature($this->algorithmManager), new CheckCounter($this->counterChecker)]); } } id = $id; } public static function create(string $name, string $id, string $displayName, ?string $icon = null) : self { return new self($name, $id, $displayName, $icon); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getId() : string { return $this->id; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getDisplayName() : string { return $this->displayName; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromString(string $data) : self { $data = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); is_array($data) || throw InvalidDataException::create($data, 'Invalid data'); return self::createFromArray($data); } /** * @param mixed[] $json * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $json) : self { array_key_exists('name', $json) || throw InvalidDataException::create($json, 'Invalid input. "name" is missing.'); array_key_exists('id', $json) || throw InvalidDataException::create($json, 'Invalid input. "id" is missing.'); array_key_exists('displayName', $json) || throw InvalidDataException::create($json, 'Invalid input. "displayName" is missing.'); $id = Base64::decode($json['id'], \true); return self::create($json['name'], $id, $json['displayName'], $json['icon'] ?? null); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $json = parent::jsonSerialize(); $json['id'] = Base64UrlSafe::encodeUnpadded($this->id); $json['displayName'] = $this->displayName; return $json; } } * @final */ class AuthenticationExtensions implements JsonSerializable, Countable, IteratorAggregate, ArrayAccess { /** * @var array * @readonly */ public array $extensions; /** * @param array $extensions */ public function __construct(array $extensions = []) { $list = []; foreach ($extensions as $key => $extension) { if ($extension instanceof AuthenticationExtension) { $list[$extension->name] = $extension; continue; } if (is_string($key)) { $list[$key] = AuthenticationExtension::create($key, $extension); continue; } throw new AuthenticationExtensionException('Invalid extension'); } $this->extensions = $list; } /** * @param array $extensions */ public static function create(array $extensions = []) : static { return new static($extensions); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function add(AuthenticationExtension ...$extensions) : static { foreach ($extensions as $extension) { $this->extensions[$extension->name] = $extension; } return $this; } /** * @param array $json * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $json) : static { return static::create(\array_map(static fn(string $key, mixed $value): AuthenticationExtension => AuthenticationExtension::create($key, $value), \array_keys($json), $json)); } public function has(string $key) : bool { return array_key_exists($key, $this->extensions); } public function get(string $key) : AuthenticationExtension { $this->has($key) || throw AuthenticationExtensionException::create(sprintf('The extension with key "%s" is not available', $key)); return $this->extensions[$key]; } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return $this->extensions; } /** * @return Iterator */ public function getIterator() : Iterator { return new ArrayIterator($this->extensions); } public function count(int $mode = COUNT_NORMAL) : int { return count($this->extensions, $mode); } public function offsetExists(mixed $offset) : bool { return array_key_exists($offset, $this->extensions); } public function offsetGet(mixed $offset) : mixed { return $this->extensions[$offset]; } public function offsetSet(mixed $offset, mixed $value) : void { if ($value === null) { return; } if ($value instanceof AuthenticationExtension) { $this->extensions[$value->name] = $value; return; } if (is_string($offset)) { $this->extensions[$offset] = AuthenticationExtension::create($offset, $value); return; } throw new AuthenticationExtensionException('Invalid extension'); } public function offsetUnset(mixed $offset) : void { unset($this->extensions[$offset]); } } checkers[] = $checker; } public function check(AuthenticationExtensions $inputs, AuthenticationExtensions $outputs) : void { foreach ($this->checkers as $checker) { $checker->check($inputs, $outputs); } } } authenticationExtension; } } name; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function value() : mixed { return $this->value; } public function jsonSerialize() : mixed { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return $this->value; } } normalize(); return AuthenticationExtensionsClientOutputs::create(\array_map(fn(mixed $value, string $key) => AuthenticationExtension::create($key, $value), $data, \array_keys($data))); } } clock === null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$clock" will be required in 5.0.0. Please set a clock instance.'); } if (!\class_exists(RS256::class) || !\class_exists(JWKFactory::class)) { throw UnsupportedFeatureException::create('The algorithm RS256 is missing. Did you forget to install the package web-token/jwt-library?'); } $this->jwsSerializer = new CompactSerializer(); $this->initJwsVerifier(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create(null|ClockInterface $clock = null) : self { return new self($clock); } public function enableApiVerification(ClientInterface|HttpClientInterface $client, string $apiKey, ?RequestFactoryInterface $requestFactory = null) : self { $this->apiKey = $apiKey; $this->client = $client; $this->requestFactory = $requestFactory; if ($requestFactory !== null && !$client instanceof HttpClientInterface) { \trigger_deprecation('web-auth/metadata-service', '4.7.0', 'The parameter "$requestFactory" will be removed in 5.0.0. Please set it to null and set an Symfony\\Contracts\\HttpClient\\HttpClientInterface as "$client" argument.'); } return $this; } public function setMaxAge(int $maxAge) : self { $this->maxAge = $maxAge; return $this; } public function setLeeway(int $leeway) : self { $this->leeway = $leeway; return $this; } public function name() : string { return 'android-safetynet'; } /** * @param array $attestation */ public function load(array $attestation) : AttestationStatement { array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation); foreach (['ver', 'response'] as $key) { array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key)); $attestation['attStmt'][$key] !== '' || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is empty.', $key)); } $jws = $this->jwsSerializer->unserialize($attestation['attStmt']['response']); $jwsHeader = $jws->getSignature(0)->getProtectedHeader(); array_key_exists('x5c', $jwsHeader) || throw AttestationStatementLoadingException::create($attestation, 'The response in the attestation statement must contain a "x5c" header.'); (\is_countable($jwsHeader['x5c']) ? count($jwsHeader['x5c']) : 0) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The "x5c" parameter in the attestation statement response must contain at least one certificate.'); $certificates = $this->convertCertificatesToPem($jwsHeader['x5c']); $attestation['attStmt']['jws'] = $jws; $attestationStatement = AttestationStatement::createBasic($this->name(), $attestation['attStmt'], CertificateTrustPath::create($certificates)); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $trustPath = $attestationStatement->trustPath; $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path'); $certificates = $trustPath->certificates; $firstCertificate = \current($certificates); is_string($firstCertificate) || throw InvalidAttestationStatementException::create($attestationStatement, 'No certificate'); $parsedCertificate = \openssl_x509_parse($firstCertificate); is_array($parsedCertificate) || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object'); array_key_exists('subject', $parsedCertificate) || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object'); array_key_exists('CN', $parsedCertificate['subject']) || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object'); $parsedCertificate['subject']['CN'] === 'attest.android.com' || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation object'); /** @var JWS $jws */ $jws = $attestationStatement->get('jws'); $payload = $jws->getPayload(); $this->validatePayload($payload, $clientDataJSONHash, $authenticatorData); //Check the signature $this->validateSignature($jws, $trustPath); //Check against Google service $this->validateUsingGoogleApi($attestationStatement); return \true; } private function validatePayload(?string $payload, string $clientDataJSONHash, AuthenticatorData $authenticatorData) : void { $payload !== null || throw AttestationStatementVerificationException::create('Invalid attestation object'); $payload = \json_decode($payload, \true, flags: JSON_THROW_ON_ERROR); array_key_exists('nonce', $payload) || throw AttestationStatementVerificationException::create('Invalid attestation object. "nonce" is missing.'); $payload['nonce'] === \base64_encode(\hash('sha256', $authenticatorData->authData . $clientDataJSONHash, \true)) || throw AttestationStatementVerificationException::create('Invalid attestation object. Invalid nonce'); array_key_exists('ctsProfileMatch', $payload) || throw AttestationStatementVerificationException::create('Invalid attestation object. "ctsProfileMatch" is missing.'); $payload['ctsProfileMatch'] || throw AttestationStatementVerificationException::create('Invalid attestation object. "ctsProfileMatch" value is false.'); array_key_exists('timestampMs', $payload) || throw AttestationStatementVerificationException::create('Invalid attestation object. Timestamp is missing.'); is_int($payload['timestampMs']) || throw AttestationStatementVerificationException::create('Invalid attestation object. Timestamp shall be an integer.'); $currentTime = ($this->clock?->now()->getTimestamp() ?? \time()) * 1000; $payload['timestampMs'] <= $currentTime + $this->leeway || throw AttestationStatementVerificationException::create(sprintf('Invalid attestation object. Issued in the future. Current time: %d. Response time: %d', $currentTime, $payload['timestampMs'])); $currentTime - $payload['timestampMs'] <= $this->maxAge || throw AttestationStatementVerificationException::create(sprintf('Invalid attestation object. Too old. Current time: %d. Response time: %d', $currentTime, $payload['timestampMs'])); } private function validateSignature(JWS $jws, CertificateTrustPath $trustPath) : void { $jwk = JWKFactory::createFromCertificate($trustPath->certificates[0]); $isValid = $this->jwsVerifier?->verifyWithKey($jws, $jwk, 0); $isValid === \true || throw AttestationStatementVerificationException::create('Invalid response signature'); } private function validateUsingGoogleApi(AttestationStatement $attestationStatement) : void { if ($this->client === null || $this->apiKey === null) { return; } $uri = sprintf('https://www.googleapis.com/androidcheck/v1/attestations/verify?key=%s', \urlencode($this->apiKey)); $requestBody = sprintf('{"signedAttestation":"%s"}', $attestationStatement->get('response')); if ($this->client instanceof HttpClientInterface) { $responseBody = $this->validateUsingGoogleApiWithSymfonyClient($requestBody, $uri); } else { $responseBody = $this->validateUsingGoogleApiWithPsrClient($requestBody, $uri); } $responseBodyJson = \json_decode($responseBody, \true, flags: JSON_THROW_ON_ERROR); array_key_exists('isValidSignature', $responseBodyJson) || throw AttestationStatementVerificationException::create('Invalid response.'); $responseBodyJson['isValidSignature'] === \true || throw AttestationStatementVerificationException::create('Invalid response.'); } private function getResponseBody(ResponseInterface $response) : string { $responseBody = ''; $response->getBody()->rewind(); do { $tmp = $response->getBody()->read(1024); if ($tmp === '') { break; } $responseBody .= $tmp; } while (\true); return $responseBody; } /** * @param string[] $certificates * * @return string[] */ private function convertCertificatesToPem(array $certificates) : array { foreach ($certificates as $k => $v) { $certificates[$k] = CertificateToolbox::fixPEMStructure($v); } return $certificates; } private function initJwsVerifier() : void { $algorithmClasses = [RS256::class, RS384::class, RS512::class, PS256::class, PS384::class, PS512::class, ES256::class, ES384::class, ES512::class, EdDSA::class]; /** @var AlgorithmInterface[] $algorithms */ $algorithms = []; foreach ($algorithmClasses as $algorithm) { if (\class_exists($algorithm)) { $algorithms[] = new $algorithm(); } } $algorithmManager = new AlgorithmManager($algorithms); $this->jwsVerifier = new JWSVerifier($algorithmManager); } private function validateUsingGoogleApiWithSymfonyClient(string $requestBody, string $uri) : string { $response = $this->client->request('POST', $uri, ['headers' => ['content-type' => 'application/json'], 'body' => $requestBody]); $response->getStatusCode() === 200 || throw AttestationStatementVerificationException::create('Request did not succeeded'); return $response->getContent(); } private function validateUsingGoogleApiWithPsrClient(string $requestBody, string $uri) : string { $request = $this->requestFactory->createRequest('POST', $uri); $request = $request->withHeader('content-type', 'application/json'); $request->getBody()->write($requestBody); $response = $this->client->sendRequest($request); $response->getStatusCode() === 200 || throw AttestationStatementVerificationException::create('Request did not succeeded'); return $this->getResponseBody($response); } } decoder = Decoder::create(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create() : self { return new self(); } public function name() : string { return 'fido-u2f'; } /** * @param array $attestation */ public function load(array $attestation) : AttestationStatement { array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object'); foreach (['sig', 'x5c'] as $key) { array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key)); } $certificates = $attestation['attStmt']['x5c']; is_array($certificates) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with one certificate.'); count($certificates) === 1 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with one certificate.'); \reset($certificates); $certificates = CertificateToolbox::convertAllDERToPEM($certificates); $this->checkCertificate($certificates[0]); $attestationStatement = AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates)); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $authenticatorData->attestedCredentialData?->aaguid->__toString() === '00000000-0000-0000-0000-000000000000' || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid AAGUID for fido-u2f attestation statement. Shall be "00000000-0000-0000-0000-000000000000"'); $trustPath = $attestationStatement->trustPath; $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path'); $dataToVerify = "\x00"; $dataToVerify .= $authenticatorData->rpIdHash; $dataToVerify .= $clientDataJSONHash; $dataToVerify .= $authenticatorData->attestedCredentialData->credentialId; $dataToVerify .= $this->extractPublicKey($authenticatorData->attestedCredentialData->credentialPublicKey); return openssl_verify($dataToVerify, $attestationStatement->get('sig'), $trustPath->certificates[0], OPENSSL_ALGO_SHA256) === 1; } private function extractPublicKey(?string $publicKey) : string { $publicKey !== null || throw AttestationStatementVerificationException::create('The attested credential data does not contain a valid public key.'); $publicKeyStream = new StringStream($publicKey); $coseKey = $this->decoder->decode($publicKeyStream); $publicKeyStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key. Presence of extra bytes.'); $publicKeyStream->close(); $coseKey instanceof MapObject || throw AttestationStatementVerificationException::create('The attested credential data does not contain a valid public key.'); $coseKey = $coseKey->normalize(); $ec2Key = new Ec2Key($coseKey + [Ec2Key::TYPE => 2, Ec2Key::DATA_CURVE => Ec2Key::CURVE_P256]); return "\x04" . $ec2Key->x() . $ec2Key->y(); } private function checkCertificate(string $publicKey) : void { try { $resource = openssl_pkey_get_public($publicKey); $details = \openssl_pkey_get_details($resource); } catch (Throwable $throwable) { throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain', $throwable); } is_array($details) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain'); array_key_exists('ec', $details) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain'); array_key_exists('curve_name', $details['ec']) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain'); $details['ec']['curve_name'] === 'prime256v1' || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain'); array_key_exists('curve_oid', $details['ec']) || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain'); $details['ec']['curve_oid'] === '1.2.840.10045.3.1.7' || throw AttestationStatementVerificationException::create('Invalid certificate or certificate chain'); } } decoder = Decoder::create(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create() : self { return new self(); } public function name() : string { return 'apple'; } /** * @param array $attestation */ public function load(array $attestation) : AttestationStatement { array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object'); array_key_exists('x5c', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" is missing.'); $certificates = $attestation['attStmt']['x5c']; (\is_countable($certificates) ? count($certificates) : 0) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with at least one certificate.'); $certificates = CertificateToolbox::convertAllDERToPEM($certificates); $attestationStatement = AttestationStatement::createAnonymizationCA($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates)); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $trustPath = $attestationStatement->trustPath; $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path'); $certificates = $trustPath->certificates; //Decode leaf attestation certificate $leaf = $certificates[0]; $this->checkCertificateAndGetPublicKey($leaf, $clientDataJSONHash, $authenticatorData); return \true; } private function checkCertificateAndGetPublicKey(string $certificate, string $clientDataHash, AuthenticatorData $authenticatorData) : void { $resource = openssl_pkey_get_public($certificate); $details = \openssl_pkey_get_details($resource); is_array($details) || throw AttestationStatementVerificationException::create('Unable to read the certificate'); //Check that authData publicKey matches the public key in the attestation certificate $attestedCredentialData = $authenticatorData->attestedCredentialData; $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential data found'); $publicKeyData = $attestedCredentialData->credentialPublicKey; $publicKeyData !== null || throw AttestationStatementVerificationException::create('No attested public key found'); $publicDataStream = new StringStream($publicKeyData); $coseKey = $this->decoder->decode($publicDataStream); $coseKey instanceof Normalizable || throw AttestationStatementVerificationException::create('Invalid attested public key found'); $publicDataStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key data. Presence of extra bytes.'); $publicDataStream->close(); $publicKey = Key::createFromData($coseKey->normalize()); $publicKey instanceof Ec2Key || $publicKey instanceof RsaKey || throw AttestationStatementVerificationException::create('Unsupported key type'); //We check the attested key corresponds to the key in the certificate $publicKey->asPEM() === $details['key'] || throw AttestationStatementVerificationException::create('Invalid key'); /*---------------------------*/ $certDetails = \openssl_x509_parse($certificate); //Find Apple Extension with OID "1.2.840.113635.100.8.2" in certificate extensions is_array($certDetails) || throw AttestationStatementVerificationException::create('The certificate is not valid'); array_key_exists('extensions', $certDetails) || throw AttestationStatementVerificationException::create('The certificate has no extension'); is_array($certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate has no extension'); array_key_exists('1.2.840.113635.100.8.2', $certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate extension "1.2.840.113635.100.8.2" is missing'); $extension = $certDetails['extensions']['1.2.840.113635.100.8.2']; $nonceToHash = $authenticatorData->authData . $clientDataHash; $nonce = \hash('sha256', $nonceToHash); //'3024a1220420' corresponds to the Sequence+Explicitly Tagged Object + Octet Object '3024a1220420' . $nonce === \bin2hex((string) $extension) || throw AttestationStatementVerificationException::create('The client data hash is not valid'); } } dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create() : self { return new self(); } public function name() : string { return 'none'; } /** * @param array $attestation */ public function load(array $attestation) : AttestationStatement { $format = $attestation['fmt'] ?? null; $attestationStatement = $attestation['attStmt'] ?? []; is_string($format) && $format !== '' || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object'); is_array($attestationStatement) && $attestationStatement === [] || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object'); $attestationStatement = AttestationStatement::createNone($format, $attestationStatement, EmptyTrustPath::create()); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { return count($attestationStatement->attStmt) === 0; } } $attestation */ public function load(array $attestation) : AttestationStatement; public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool; } logger = new NullLogger(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create(AttestationStatementSupportManager $attestationStatementSupportManager) : self { return new self($attestationStatementSupportManager); } public function load(string $data) : AttestationObject { try { $this->logger->info('Trying to load the data', ['data' => $data]); $decodedData = Base64::decode($data); $stream = new StringStream($decodedData); $parsed = Decoder::create()->decode($stream); $this->logger->info('Loading the Attestation Statement'); $parsed instanceof Normalizable || throw InvalidDataException::create($parsed, 'Invalid attestation object. Unexpected object.'); $attestationObject = $parsed->normalize(); $stream->isEOF() || throw InvalidDataException::create(null, 'Invalid attestation object. Presence of extra bytes.'); $stream->close(); is_array($attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object'); array_key_exists('authData', $attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object'); array_key_exists('fmt', $attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object'); array_key_exists('attStmt', $attestationObject) || throw InvalidDataException::create($attestationObject, 'Invalid attestation object'); $attestationStatementSupport = $this->attestationStatementSupportManager->get($attestationObject['fmt']); $attestationStatement = $attestationStatementSupport->load($attestationObject); $this->logger->info('Attestation Statement loaded'); $this->logger->debug('Attestation Statement loaded', ['attestationStatement' => $attestationStatement]); $authData = $attestationObject['authData']; $authDataLoader = AuthenticatorDataLoader::create(); $authenticatorData = $authDataLoader->load($authData); $attestationObject = AttestationObject::create($data, $attestationStatement, $authenticatorData); $this->logger->info('Attestation Object loaded'); $this->logger->debug('Attestation Object', ['ed' => $attestationObject]); $this->dispatcher->dispatch(AttestationObjectLoaded::create($attestationObject)); return $attestationObject; } catch (Throwable $throwable) { $this->logger->error('An error occurred', ['exception' => $throwable]); throw $throwable; } } public function setLogger(LoggerInterface $logger) : void { $this->logger = $logger; } } decoder = Decoder::create(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create(Manager $algorithmManager) : self { return new self($algorithmManager); } public function name() : string { return 'packed'; } /** * @param array $attestation */ public function load(array $attestation) : AttestationStatement { array_key_exists('sig', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "sig" is missing.'); array_key_exists('alg', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "alg" is missing.'); is_string($attestation['attStmt']['sig']) || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "sig" is missing.'); return match (\true) { array_key_exists('x5c', $attestation['attStmt']) => $this->loadBasicType($attestation), array_key_exists('ecdaaKeyId', $attestation['attStmt']) => $this->loadEcdaaType($attestation['attStmt']), default => $this->loadEmptyType($attestation), }; } public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $trustPath = $attestationStatement->trustPath; return match (\true) { $trustPath instanceof CertificateTrustPath => $this->processWithCertificate($clientDataJSONHash, $attestationStatement, $authenticatorData, $trustPath), $trustPath instanceof EcdaaKeyIdTrustPath => $this->processWithECDAA(), $trustPath instanceof EmptyTrustPath => $this->processWithSelfAttestation($clientDataJSONHash, $attestationStatement, $authenticatorData), default => throw InvalidAttestationStatementException::create($attestationStatement, 'Unsupported attestation statement'), }; } /** * @param mixed[] $attestation */ private function loadBasicType(array $attestation) : AttestationStatement { $certificates = $attestation['attStmt']['x5c']; is_array($certificates) || throw AttestationStatementVerificationException::create('The attestation statement value "x5c" must be a list with at least one certificate.'); count($certificates) > 0 || throw AttestationStatementVerificationException::create('The attestation statement value "x5c" must be a list with at least one certificate.'); $certificates = CertificateToolbox::convertAllDERToPEM($certificates); $attestationStatement = AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates)); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } /** * @param array $attestation */ private function loadEcdaaType(array $attestation) : AttestationStatement { $ecdaaKeyId = $attestation['attStmt']['ecdaaKeyId']; is_string($ecdaaKeyId) || throw AttestationStatementVerificationException::create('The attestation statement value "ecdaaKeyId" is invalid.'); $attestationStatement = AttestationStatement::createEcdaa($attestation['fmt'], $attestation['attStmt'], new EcdaaKeyIdTrustPath($attestation['ecdaaKeyId'])); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } /** * @param mixed[] $attestation */ private function loadEmptyType(array $attestation) : AttestationStatement { $attestationStatement = AttestationStatement::createSelf($attestation['fmt'], $attestation['attStmt'], EmptyTrustPath::create()); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } private function checkCertificate(string $attestnCert, AuthenticatorData $authenticatorData) : void { $parsed = \openssl_x509_parse($attestnCert); is_array($parsed) || throw AttestationStatementVerificationException::create('Invalid certificate'); //Check version isset($parsed['version']) || throw AttestationStatementVerificationException::create('Invalid certificate version'); $parsed['version'] === 2 || throw AttestationStatementVerificationException::create('Invalid certificate version'); //Check subject field isset($parsed['name']) || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject Organization Unit must be "Authenticator Attestation"'); \str_contains((string) $parsed['name'], '/OU=Authenticator Attestation') || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject Organization Unit must be "Authenticator Attestation"'); //Check extensions isset($parsed['extensions']) || throw AttestationStatementVerificationException::create('Certificate extensions are missing'); is_array($parsed['extensions']) || throw AttestationStatementVerificationException::create('Certificate extensions are missing'); //Check certificate is not a CA cert isset($parsed['extensions']['basicConstraints']) || throw AttestationStatementVerificationException::create('The Basic Constraints extension must have the CA component set to false'); $parsed['extensions']['basicConstraints'] === 'CA:FALSE' || throw AttestationStatementVerificationException::create('The Basic Constraints extension must have the CA component set to false'); $attestedCredentialData = $authenticatorData->attestedCredentialData; $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential available'); // id-fido-gen-ce-aaguid OID check if (in_array('1.3.6.1.4.1.45724.1.1.4', $parsed['extensions'], \true)) { \hash_equals($attestedCredentialData->aaguid->toBinary(), $parsed['extensions']['1.3.6.1.4.1.45724.1.1.4']) || throw AttestationStatementVerificationException::create('The value of the "aaguid" does not match with the certificate'); } } private function processWithCertificate(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData, CertificateTrustPath $trustPath) : bool { $certificates = $trustPath->certificates; // Check leaf certificate $this->checkCertificate($certificates[0], $authenticatorData); // Get the COSE algorithm identifier and the corresponding OpenSSL one $coseAlgorithmIdentifier = (int) $attestationStatement->get('alg'); $opensslAlgorithmIdentifier = Algorithms::getOpensslAlgorithmFor($coseAlgorithmIdentifier); // Verification of the signature $signedData = $authenticatorData->authData . $clientDataJSONHash; $result = openssl_verify($signedData, $attestationStatement->get('sig'), $certificates[0], $opensslAlgorithmIdentifier); return $result === 1; } private function processWithECDAA() : never { throw UnsupportedFeatureException::create('ECDAA not supported'); } private function processWithSelfAttestation(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $attestedCredentialData = $authenticatorData->attestedCredentialData; $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential available'); $credentialPublicKey = $attestedCredentialData->credentialPublicKey; $credentialPublicKey !== null || throw AttestationStatementVerificationException::create('No credential public key available'); $publicKeyStream = new StringStream($credentialPublicKey); $publicKey = $this->decoder->decode($publicKeyStream); $publicKeyStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key. Presence of extra bytes.'); $publicKeyStream->close(); $publicKey instanceof MapObject || throw AttestationStatementVerificationException::create('The attested credential data does not contain a valid public key.'); $publicKey = $publicKey->normalize(); $publicKey = new Key($publicKey); $publicKey->alg() === (int) $attestationStatement->get('alg') || throw AttestationStatementVerificationException::create('The algorithm of the attestation statement and the key are not identical.'); $dataToVerify = $authenticatorData->authData . $clientDataJSONHash; $algorithm = $this->algorithmManager->get((int) $attestationStatement->get('alg')); if (!$algorithm instanceof Signature) { throw InvalidDataException::create($algorithm, 'Invalid algorithm'); } $signature = CoseSignatureFixer::fix($attestationStatement->get('sig'), $algorithm); return $algorithm->verify($dataToVerify, $publicKey, $signature); } } rawAttestationObject; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttStmt() : AttestationStatement { return $this->attStmt; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setAttStmt(AttestationStatement $attStmt) : void { $this->attStmt = $attStmt; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAuthData() : AuthenticatorData { return $this->authData; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMetadataStatement() : ?MetadataStatement { return $this->metadataStatement; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setMetadataStatement(MetadataStatement $metadataStatement) : self { $this->metadataStatement = $metadataStatement; return $this; } } decoder = Decoder::create(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create() : self { return new self(); } public function name() : string { return 'android-key'; } /** * @param array $attestation */ public function load(array $attestation) : AttestationStatement { array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation); foreach (['sig', 'x5c', 'alg'] as $key) { array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key)); } $certificates = $attestation['attStmt']['x5c']; (\is_countable($certificates) ? count($certificates) : 0) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with at least one certificate.'); $certificates = CertificateToolbox::convertAllDERToPEM($certificates); $attestationStatement = AttestationStatement::createBasic($attestation['fmt'], $attestation['attStmt'], CertificateTrustPath::create($certificates)); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $trustPath = $attestationStatement->trustPath; $trustPath instanceof CertificateTrustPath || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid trust path. Shall contain certificates.'); $certificates = $trustPath->certificates; //Decode leaf attestation certificate $leaf = $certificates[0]; $this->checkCertificate($leaf, $clientDataJSONHash, $authenticatorData); $signedData = $authenticatorData->authData . $clientDataJSONHash; $alg = $attestationStatement->get('alg'); return openssl_verify($signedData, $attestationStatement->get('sig'), $leaf, Algorithms::getOpensslAlgorithmFor((int) $alg)) === 1; } private function checkCertificate(string $certificate, string $clientDataHash, AuthenticatorData $authenticatorData) : void { $resource = openssl_pkey_get_public($certificate); $details = \openssl_pkey_get_details($resource); is_array($details) || throw AttestationStatementVerificationException::create('Unable to read the certificate'); //Check that authData publicKey matches the public key in the attestation certificate $attestedCredentialData = $authenticatorData->attestedCredentialData; $attestedCredentialData !== null || throw AttestationStatementVerificationException::create('No attested credential data found'); $publicKeyData = $attestedCredentialData->credentialPublicKey; $publicKeyData !== null || throw AttestationStatementVerificationException::create('No attested public key found'); $publicDataStream = new StringStream($publicKeyData); $coseKey = $this->decoder->decode($publicDataStream); $coseKey instanceof Normalizable || throw AttestationStatementVerificationException::create('Invalid attested public key found'); $publicDataStream->isEOF() || throw AttestationStatementVerificationException::create('Invalid public key data. Presence of extra bytes.'); $publicDataStream->close(); $publicKey = Key::createFromData($coseKey->normalize()); $publicKey instanceof Ec2Key || $publicKey instanceof RsaKey || throw AttestationStatementVerificationException::create('Unsupported key type'); $publicKey->asPEM() === $details['key'] || throw AttestationStatementVerificationException::create('Invalid key'); /*---------------------------*/ $certDetails = \openssl_x509_parse($certificate); //Find Android KeyStore Extension with OID "1.3.6.1.4.1.11129.2.1.17" in certificate extensions is_array($certDetails) || throw AttestationStatementVerificationException::create('The certificate is not valid'); array_key_exists('extensions', $certDetails) || throw AttestationStatementVerificationException::create('The certificate has no extension'); is_array($certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate has no extension'); array_key_exists('1.3.6.1.4.1.11129.2.1.17', $certDetails['extensions']) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is missing'); $extension = $certDetails['extensions']['1.3.6.1.4.1.11129.2.1.17']; $extensionAsAsn1 = Sequence::fromDER($extension); $extensionAsAsn1->has(4); //Check that attestationChallenge is set to the clientDataHash. $extensionAsAsn1->has(4) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); $ext = $extensionAsAsn1->at(4)->asElement(); $ext instanceof OctetString || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); $clientDataHash === $ext->string() || throw AttestationStatementVerificationException::create('The client data hash is not valid'); //Check that both teeEnforced and softwareEnforced structures don't contain allApplications(600) tag. $extensionAsAsn1->has(6) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); $softwareEnforcedFlags = $extensionAsAsn1->at(6)->asElement(); $softwareEnforcedFlags instanceof Sequence || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); $this->checkAbsenceOfAllApplicationsTag($softwareEnforcedFlags); $extensionAsAsn1->has(7) || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); $teeEnforcedFlags = $extensionAsAsn1->at(7)->asElement(); $teeEnforcedFlags instanceof Sequence || throw AttestationStatementVerificationException::create('The certificate extension "1.3.6.1.4.1.11129.2.1.17" is invalid'); $this->checkAbsenceOfAllApplicationsTag($teeEnforcedFlags); } private function checkAbsenceOfAllApplicationsTag(Sequence $sequence) : void { foreach ($sequence->elements() as $tag) { $tag->asElement() instanceof ExplicitTagging || throw AttestationStatementVerificationException::create('Invalid tag'); $tag->asElement()->tag() !== 600 || throw AttestationStatementVerificationException::create('Forbidden tag 600 found'); } } } add(new NoneAttestationStatementSupport()); foreach ($attestationStatementSupports as $attestationStatementSupport) { $this->add($attestationStatementSupport); } } /** * @param AttestationStatementSupport[] $attestationStatementSupports */ public static function create(array $attestationStatementSupports = []) : self { return new self($attestationStatementSupports); } public function add(AttestationStatementSupport $attestationStatementSupport) : void { $this->attestationStatementSupports[$attestationStatementSupport->name()] = $attestationStatementSupport; } public function has(string $name) : bool { return array_key_exists($name, $this->attestationStatementSupports); } public function get(string $name) : AttestationStatementSupport { $this->has($name) || throw InvalidDataException::create($name, sprintf('The attestation statement format "%s" is not supported.', $name)); return $this->attestationStatementSupports[$name]; } } clock = $clock; $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create(null|Clock|ClockInterface $clock = null) : self { return new self($clock); } public function name() : string { return 'tpm'; } /** * @param array $attestation */ public function load(array $attestation) : AttestationStatement { array_key_exists('attStmt', $attestation) || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object'); !array_key_exists('ecdaaKeyId', $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, 'ECDAA not supported'); foreach (['ver', 'ver', 'sig', 'alg', 'certInfo', 'pubArea'] as $key) { array_key_exists($key, $attestation['attStmt']) || throw AttestationStatementLoadingException::create($attestation, sprintf('The attestation statement value "%s" is missing.', $key)); } $attestation['attStmt']['ver'] === '2.0' || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object'); $certInfo = $this->checkCertInfo($attestation['attStmt']['certInfo']); \bin2hex((string) $certInfo['type']) === '8017' || throw AttestationStatementLoadingException::create($attestation, 'Invalid attestation object'); $pubArea = $this->checkPubArea($attestation['attStmt']['pubArea']); $pubAreaAttestedNameAlg = \mb_substr((string) $certInfo['attestedName'], 0, 2, '8bit'); $pubAreaHash = \hash($this->getTPMHash($pubAreaAttestedNameAlg), (string) $attestation['attStmt']['pubArea'], \true); $attestedName = $pubAreaAttestedNameAlg . $pubAreaHash; $attestedName === $certInfo['attestedName'] || throw AttestationStatementLoadingException::create($attestation, 'Invalid attested name'); $attestation['attStmt']['parsedCertInfo'] = $certInfo; $attestation['attStmt']['parsedPubArea'] = $pubArea; $certificates = CertificateToolbox::convertAllDERToPEM($attestation['attStmt']['x5c']); count($certificates) > 0 || throw AttestationStatementLoadingException::create($attestation, 'The attestation statement value "x5c" must be a list with at least one certificate.'); $attestationStatement = AttestationStatement::createAttCA($this->name(), $attestation['attStmt'], CertificateTrustPath::create($certificates)); $this->dispatcher->dispatch(AttestationStatementLoaded::create($attestationStatement)); return $attestationStatement; } public function isValid(string $clientDataJSONHash, AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $attToBeSigned = $authenticatorData->authData . $clientDataJSONHash; $attToBeSignedHash = \hash(Algorithms::getHashAlgorithmFor((int) $attestationStatement->get('alg')), $attToBeSigned, \true); $attestationStatement->get('parsedCertInfo')['extraData'] === $attToBeSignedHash || throw InvalidAttestationStatementException::create($attestationStatement, 'Invalid attestation hash'); $credentialPublicKey = $authenticatorData->attestedCredentialData?->credentialPublicKey; $credentialPublicKey !== null || throw InvalidAttestationStatementException::create($attestationStatement, 'Not credential public key available in the attested credential data'); $this->checkUniquePublicKey($attestationStatement->get('parsedPubArea')['unique'], $credentialPublicKey); return match (\true) { $attestationStatement->trustPath instanceof CertificateTrustPath => $this->processWithCertificate($attestationStatement, $authenticatorData), $attestationStatement->trustPath instanceof EcdaaKeyIdTrustPath => $this->processWithECDAA(), default => throw InvalidAttestationStatementException::create($attestationStatement, 'Unsupported attestation statement'), }; } private function checkUniquePublicKey(string $unique, string $cborPublicKey) : void { $cborDecoder = Decoder::create(); $publicKey = $cborDecoder->decode(new StringStream($cborPublicKey)); $publicKey instanceof MapObject || throw AttestationStatementVerificationException::create('Invalid public key'); $key = Key::create($publicKey->normalize()); switch ($key->type()) { case Key::TYPE_OKP: $uniqueFromKey = (new OkpKey($key->getData()))->x(); break; case Key::TYPE_EC2: $ec2Key = new Ec2Key($key->getData()); $uniqueFromKey = "\x04" . $ec2Key->x() . $ec2Key->y(); break; case Key::TYPE_RSA: $uniqueFromKey = (new RsaKey($key->getData()))->n(); break; default: throw AttestationStatementVerificationException::create('Invalid or unsupported key type.'); } $unique === $uniqueFromKey || throw AttestationStatementVerificationException::create('Invalid pubArea.unique value'); } /** * @return mixed[] */ private function checkCertInfo(string $data) : array { $certInfo = new StringStream($data); $magic = $certInfo->read(4); \bin2hex($magic) === 'ff544347' || throw AttestationStatementVerificationException::create('Invalid attestation object'); $type = $certInfo->read(2); $qualifiedSignerLength = unpack('n', $certInfo->read(2))[1]; $qualifiedSigner = $certInfo->read($qualifiedSignerLength); //Ignored $extraDataLength = unpack('n', $certInfo->read(2))[1]; $extraData = $certInfo->read($extraDataLength); $clockInfo = $certInfo->read(17); //Ignore $firmwareVersion = $certInfo->read(8); $attestedNameLength = unpack('n', $certInfo->read(2))[1]; $attestedName = $certInfo->read($attestedNameLength); $attestedQualifiedNameLength = unpack('n', $certInfo->read(2))[1]; $attestedQualifiedName = $certInfo->read($attestedQualifiedNameLength); //Ignore $certInfo->isEOF() || throw AttestationStatementVerificationException::create('Invalid certificate information. Presence of extra bytes.'); $certInfo->close(); return ['magic' => $magic, 'type' => $type, 'qualifiedSigner' => $qualifiedSigner, 'extraData' => $extraData, 'clockInfo' => $clockInfo, 'firmwareVersion' => $firmwareVersion, 'attestedName' => $attestedName, 'attestedQualifiedName' => $attestedQualifiedName]; } /** * @return mixed[] */ private function checkPubArea(string $data) : array { $pubArea = new StringStream($data); $type = $pubArea->read(2); $nameAlg = $pubArea->read(2); $objectAttributes = $pubArea->read(4); $authPolicyLength = unpack('n', $pubArea->read(2))[1]; $authPolicy = $pubArea->read($authPolicyLength); $parameters = $this->getParameters($type, $pubArea); $unique = $this->getUnique($type, $pubArea); $pubArea->isEOF() || throw AttestationStatementVerificationException::create('Invalid public area. Presence of extra bytes.'); $pubArea->close(); return ['type' => $type, 'nameAlg' => $nameAlg, 'objectAttributes' => $objectAttributes, 'authPolicy' => $authPolicy, 'parameters' => $parameters, 'unique' => $unique]; } /** * @return mixed[] */ private function getParameters(string $type, StringStream $stream) : array { return match (\bin2hex($type)) { '0001' => ['symmetric' => $stream->read(2), 'scheme' => $stream->read(2), 'keyBits' => unpack('n', $stream->read(2))[1], 'exponent' => $this->getExponent($stream->read(4))], '0023' => ['symmetric' => $stream->read(2), 'scheme' => $stream->read(2), 'curveId' => $stream->read(2), 'kdf' => $stream->read(2)], default => throw AttestationStatementVerificationException::create('Unsupported type'), }; } private function getUnique(string $type, StringStream $stream) : string { switch (\bin2hex($type)) { case '0001': $uniqueLength = unpack('n', $stream->read(2))[1]; return $stream->read($uniqueLength); case '0023': $xLen = unpack('n', $stream->read(2))[1]; $x = $stream->read($xLen); $yLen = unpack('n', $stream->read(2))[1]; $y = $stream->read($yLen); return "\x04" . $x . $y; default: throw AttestationStatementVerificationException::create('Unsupported type'); } } private function getExponent(string $exponent) : string { return \bin2hex($exponent) === '00000000' ? Base64UrlSafe::decodeNoPadding('AQAB') : $exponent; } private function getTPMHash(string $nameAlg) : string { return match (\bin2hex($nameAlg)) { '0004' => 'sha1', '000b' => 'sha256', '000c' => 'sha384', '000d' => 'sha512', default => throw AttestationStatementVerificationException::create('Unsupported hash algorithm'), }; } private function processWithCertificate(AttestationStatement $attestationStatement, AuthenticatorData $authenticatorData) : bool { $trustPath = $attestationStatement->trustPath; $trustPath instanceof CertificateTrustPath || throw AttestationStatementVerificationException::create('Invalid trust path'); $certificates = $trustPath->certificates; // Check certificate CA chain and returns the Attestation Certificate $this->checkCertificate($certificates[0], $authenticatorData); // Get the COSE algorithm identifier and the corresponding OpenSSL one $coseAlgorithmIdentifier = (int) $attestationStatement->get('alg'); $opensslAlgorithmIdentifier = Algorithms::getOpensslAlgorithmFor($coseAlgorithmIdentifier); $result = openssl_verify($attestationStatement->get('certInfo'), $attestationStatement->get('sig'), $certificates[0], $opensslAlgorithmIdentifier); return $result === 1; } private function checkCertificate(string $attestnCert, AuthenticatorData $authenticatorData) : void { $parsed = \openssl_x509_parse($attestnCert); is_array($parsed) || throw AttestationStatementVerificationException::create('Invalid certificate'); //Check version isset($parsed['version']) && $parsed['version'] === 2 || throw AttestationStatementVerificationException::create('Invalid certificate version'); //Check subject field is empty isset($parsed['subject']) || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject should be empty'); is_array($parsed['subject']) || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject should be empty'); count($parsed['subject']) === 0 || throw AttestationStatementVerificationException::create('Invalid certificate name. The Subject should be empty'); // Check period of validity array_key_exists('validFrom_time_t', $parsed) || throw AttestationStatementVerificationException::create('Invalid certificate start date.'); is_int($parsed['validFrom_time_t']) || throw AttestationStatementVerificationException::create('Invalid certificate start date.'); $startDate = (new DateTimeImmutable())->setTimestamp($parsed['validFrom_time_t']); $startDate < $this->clock->now() || throw AttestationStatementVerificationException::create('Invalid certificate start date.'); array_key_exists('validTo_time_t', $parsed) || throw AttestationStatementVerificationException::create('Invalid certificate end date.'); is_int($parsed['validTo_time_t']) || throw AttestationStatementVerificationException::create('Invalid certificate end date.'); $endDate = (new DateTimeImmutable())->setTimestamp($parsed['validTo_time_t']); $endDate > $this->clock->now() || throw AttestationStatementVerificationException::create('Invalid certificate end date.'); //Check extensions isset($parsed['extensions']) && is_array($parsed['extensions']) || throw AttestationStatementVerificationException::create('Certificate extensions are missing'); //Check subjectAltName isset($parsed['extensions']['subjectAltName']) || throw AttestationStatementVerificationException::create('The "subjectAltName" is missing'); //Check extendedKeyUsage isset($parsed['extensions']['extendedKeyUsage']) || throw AttestationStatementVerificationException::create('The "subjectAltName" is missing'); $parsed['extensions']['extendedKeyUsage'] === '2.23.133.8.3' || throw AttestationStatementVerificationException::create('The "extendedKeyUsage" is invalid'); // id-fido-gen-ce-aaguid OID check in_array('1.3.6.1.4.1.45724.1.1.4', $parsed['extensions'], \true) && !\hash_equals($authenticatorData->attestedCredentialData?->aaguid->toBinary() ?? '', $parsed['extensions']['1.3.6.1.4.1.45724.1.1.4']) && throw AttestationStatementVerificationException::create('The value of the "aaguid" does not match with the certificate'); } private function processWithECDAA() : never { throw UnsupportedFeatureException::create('ECDAA not supported'); } } $attStmt */ public function __construct(public readonly string $fmt, public readonly array $attStmt, public readonly string $type, public readonly TrustPath $trustPath) { } public static function create(string $fmt, array $attStmt, string $type, TrustPath $trustPath) : self { return new self($fmt, $attStmt, $type, $trustPath); } /** * @param array $attStmt */ public static function createNone(string $fmt, array $attStmt, TrustPath $trustPath) : self { return self::create($fmt, $attStmt, self::TYPE_NONE, $trustPath); } /** * @param array $attStmt */ public static function createBasic(string $fmt, array $attStmt, TrustPath $trustPath) : self { return self::create($fmt, $attStmt, self::TYPE_BASIC, $trustPath); } /** * @param array $attStmt */ public static function createSelf(string $fmt, array $attStmt, TrustPath $trustPath) : self { return self::create($fmt, $attStmt, self::TYPE_SELF, $trustPath); } /** * @param array $attStmt */ public static function createAttCA(string $fmt, array $attStmt, TrustPath $trustPath) : self { return self::create($fmt, $attStmt, self::TYPE_ATTCA, $trustPath); } /** * @param array $attStmt * * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification. * @infection-ignore-all */ public static function createEcdaa(string $fmt, array $attStmt, TrustPath $trustPath) : self { return self::create($fmt, $attStmt, self::TYPE_ECDAA, $trustPath); } /** * @param array $attStmt */ public static function createAnonymizationCA(string $fmt, array $attStmt, TrustPath $trustPath) : self { return self::create($fmt, $attStmt, self::TYPE_ANONCA, $trustPath); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getFmt() : string { return $this->fmt; } /** * @return mixed[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttStmt() : array { return $this->attStmt; } public function has(string $key) : bool { return array_key_exists($key, $this->attStmt); } public function get(string $key) : mixed { $this->has($key) || throw InvalidDataException::create($this->attStmt, sprintf('The attestation statement has no key "%s".', $key)); return $this->attStmt[$key]; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTrustPath() : TrustPath { return $this->trustPath; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getType() : string { return $this->type; } /** * @param mixed[] $data * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { foreach (['fmt', 'attStmt', 'trustPath', 'type'] as $key) { array_key_exists($key, $data) || throw InvalidDataException::create($data, sprintf('The key "%s" is missing', $key)); } return self::create($data['fmt'], $data['attStmt'], $data['type'], TrustPathLoader::loadTrustPath($data['trustPath'])); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return ['fmt' => $this->fmt, 'attStmt' => $this->attStmt, 'trustPath' => $this->trustPath, 'type' => $this->type]; } } attestationObjectLoader === null && $this->serializer === null) { throw new InvalidArgumentException('You must provide an attestation object loader or a serializer'); } $this->logger = new NullLogger(); } public static function create(null|AttestationObjectLoader $attestationObjectLoader, null|SerializerInterface $serializer = null) : self { return new self($attestationObjectLoader, $serializer); } public function setLogger(LoggerInterface $logger) : void { $this->logger = $logger; } /** * @param mixed[] $json * @infection-ignore-all */ public function loadArray(array $json) : PublicKeyCredential { $this->logger->info('Trying to load data from an array', ['data' => $json]); try { foreach (['id', 'rawId', 'type'] as $key) { array_key_exists($key, $json) || throw InvalidDataException::create($json, sprintf('The parameter "%s" is missing', $key)); is_string($json[$key]) || throw InvalidDataException::create($json, sprintf('The parameter "%s" shall be a string', $key)); } array_key_exists('response', $json) || throw InvalidDataException::create($json, 'The parameter "response" is missing'); is_array($json['response']) || throw InvalidDataException::create($json, 'The parameter "response" shall be an array'); $json['type'] === 'public-key' || throw InvalidDataException::create($json, sprintf('Unsupported type "%s"', $json['type'])); $id = Base64UrlSafe::decodeNoPadding($json['id']); $rawId = Base64::decode($json['rawId']); \hash_equals($id, $rawId) || throw InvalidDataException::create($json, 'Invalid ID'); $publicKeyCredential = PublicKeyCredential::create(null, $json['type'], $rawId, $this->createResponse($json['response'])); $this->logger->info('The data has been loaded'); $this->logger->debug('Public Key Credential', ['publicKeyCredential' => $publicKeyCredential]); return $publicKeyCredential; } catch (Throwable $throwable) { $this->logger->error('An error occurred', ['exception' => $throwable]); throw $throwable; } } public function load(string $data) : PublicKeyCredential { $this->logger->info('Trying to load data from a string', ['data' => $data]); try { if ($this->serializer !== null) { return $this->serializer->deserialize($data, PublicKeyCredential::class, 'json'); } $json = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); return $this->loadArray($json); } catch (Throwable $throwable) { $this->logger->error('An error occurred', ['exception' => $throwable]); throw InvalidDataException::create($data, 'Unable to load the data', $throwable); } } /** * @param mixed[] $response */ private function createResponse(array $response) : AuthenticatorResponse { array_key_exists('clientDataJSON', $response) || throw InvalidDataException::create($response, 'Invalid data. The parameter "clientDataJSON" is missing'); is_string($response['clientDataJSON']) || throw InvalidDataException::create($response, 'Invalid data. The parameter "clientDataJSON" is invalid'); $userHandle = $response['userHandle'] ?? null; $userHandle === null || is_string($userHandle) || throw InvalidDataException::create($response, 'Invalid data. The parameter "userHandle" is invalid'); /** @var string[] $transports */ $transports = $response['transports'] ?? []; is_array($transports) || throw InvalidDataException::create($response, 'Invalid data. The parameter "transports" is invalid'); if ($this->serializer !== null) { return $this->serializer->deserialize($response, AuthenticatorResponse::class, 'json'); } switch (\true) { case array_key_exists('attestationObject', $response): $attestationObject = $this->attestationObjectLoader->load($response['attestationObject']); return AuthenticatorAttestationResponse::create(CollectedClientData::createFormJson($response['clientDataJSON']), $attestationObject, $transports); case array_key_exists('signature', $response): $authDataLoader = AuthenticatorDataLoader::create(); $authData = Base64UrlSafe::decodeNoPadding($response['authenticatorData'] ?? ''); $authenticatorData = $authDataLoader->load($authData); try { $signature = Base64::decode($response['signature']); } catch (Throwable $e) { throw InvalidDataException::create($response['signature'], 'The signature shall be Base64 Url Safe encoded', $e); } $userHandle = $response['userHandle'] ?? null; if ($userHandle !== '' && $userHandle !== null) { $userHandle = Base64::decode($userHandle); } return AuthenticatorAssertionResponse::create(CollectedClientData::createFormJson($response['clientDataJSON']), $authenticatorData, $signature, $userHandle); default: throw InvalidDataException::create($response, 'Unable to create the response object'); } } } cache === null) { return $this->generateCredentials($username); } $cacheKey = 'fake_credentials_' . \hash('xxh128', $username); $cacheItem = $this->cache->getItem($cacheKey); if ($cacheItem->isHit()) { return $cacheItem->get(); } $credentials = $this->generateCredentials($username); $cacheItem->set($credentials); $this->cache->save($cacheItem); return $credentials; } /** * @return PublicKeyCredentialDescriptor[] */ private function generateCredentials(string $username) : array { $transports = [PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_USB, PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_NFC, PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_BLE]; $credentials = []; for ($i = 0; $i < \random_int(1, 3); $i++) { $randomTransportKeys = \array_rand($transports, \random_int(1, count($transports))); if (is_int($randomTransportKeys)) { $randomTransportKeys = [$randomTransportKeys]; } $randomTransports = \array_values(\array_intersect_key($transports, \array_flip($randomTransportKeys))); $credentials[] = PublicKeyCredentialDescriptor::create(PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, \hash('sha256', \random_bytes(16) . $username), $randomTransports); } return $credentials; } } status = $status; $this->id = $id; } /** * @param mixed[] $json */ public static function createFormArray(array $json) : self { array_key_exists('status', $json) || throw InvalidDataException::create($json, 'The member "status" is required'); $status = $json['status']; in_array($status, self::getSupportedStatus(), \true) || throw InvalidDataException::create($json, sprintf('The member "status" is invalid. Supported values are: %s', \implode(', ', self::getSupportedStatus()))); $id = array_key_exists('id', $json) ? Base64UrlSafe::decodeNoPadding($json['id']) : null; return new self($status, $id); } public function getStatus() : string { return $this->status; } public function getId() : ?string { return $this->id; } /** * @return string[] */ private static function getSupportedStatus() : array { return [self::TOKEN_BINDING_STATUS_PRESENT, self::TOKEN_BINDING_STATUS_SUPPORTED, self::TOKEN_BINDING_STATUS_NOT_SUPPORTED]; } } getStatus() !== TokenBinding::TOKEN_BINDING_STATUS_PRESENT) { return; } $request->hasHeader('Sec-Token-Binding') || throw InvalidDataException::create($tokenBinding, 'The header parameter "Sec-Token-Binding" is missing.'); $tokenBindingIds = $request->getHeader('Sec-Token-Binding'); count($tokenBindingIds) === 1 || throw InvalidDataException::create($tokenBinding, 'The header parameter "Sec-Token-Binding" is invalid.'); $tokenBindingId = \reset($tokenBindingIds); $tokenBindingId === $tokenBinding->getId() || throw InvalidDataException::create($tokenBinding, 'The header parameter "Sec-Token-Binding" is invalid.'); } } getStatus() !== TokenBinding::TOKEN_BINDING_STATUS_PRESENT || throw InvalidDataException::create($tokenBinding, 'Token binding not supported.'); } } aaguid; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setAaguid(Uuid $aaguid) : void { $this->aaguid = $aaguid; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCredentialId() : string { return $this->credentialId; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCredentialPublicKey() : ?string { return $this->credentialPublicKey; } /** * @param mixed[] $json * @deprecated since 4.9.0 and will be removed in 5.0.0. Please use the serializer instead. */ public static function createFromArray(array $json) : self { array_key_exists('aaguid', $json) || throw InvalidDataException::create($json, 'Invalid input. "aaguid" is missing.'); $aaguid = $json['aaguid']; is_string($aaguid) || throw InvalidDataException::create($json, 'Invalid input. "aaguid" shall be a string of 36 characters'); \mb_strlen($aaguid, '8bit') === 36 || throw InvalidDataException::create($json, 'Invalid input. "aaguid" shall be a string of 36 characters'); $uuid = Uuid::fromString($aaguid); array_key_exists('credentialId', $json) || throw InvalidDataException::create($json, 'Invalid input. "credentialId" is missing.'); $credentialId = $json['credentialId']; is_string($credentialId) || throw InvalidDataException::create($json, 'Invalid input. "credentialId" shall be a string'); $credentialId = Base64::decode($credentialId, \true); $credentialPublicKey = null; if (isset($json['credentialPublicKey'])) { $credentialPublicKey = Base64::decode($json['credentialPublicKey'], \true); } return self::create($uuid, $credentialId, $credentialPublicKey); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $result = ['aaguid' => $this->aaguid->__toString(), 'credentialId' => \base64_encode($this->credentialId)]; if ($this->credentialPublicKey !== null) { $result['credentialPublicKey'] = \base64_encode($this->credentialPublicKey); } return $result; } } id = $id; $this->rawId = $rawId ?? Base64UrlSafe::decodeNoPadding($id); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getId() : string { return $this->id; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getType() : string { return $this->type; } } publicKeyCredentialSourceRepository !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'The parameter "$publicKeyCredentialSourceRepository" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set "null" instead.'); } if ($this->tokenBindingHandler !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.3.0', 'The parameter "$tokenBindingHandler" is deprecated since 4.3.0 and will be removed in 5.0.0. Please set "null" instead.'); } if ($extensionOutputCheckerHandler !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$extensionOutputCheckerHandler" is deprecated since 4.8.0 and will be removed in 5.0.0. Please set "null" instead and inject a CheckExtensions object into the CeremonyStepManager.'); } $this->eventDispatcher = $eventDispatcher ?? new NullEventDispatcher(); if ($eventDispatcher !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', 'The parameter "$eventDispatcher" is deprecated since 4.5.0 will be removed in 5.0.0. Please use `setEventDispatcher` instead.'); } if ($this->ceremonyStepManager === null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$ceremonyStepManager" will mandatory in 5.0.0. Please set a CeremonyStepManager object instead and set null for $attestationStatementSupportManager and $extensionOutputCheckerHandler.'); } $this->logger = new NullLogger(); $this->ceremonyStepManagerFactory = new CeremonyStepManagerFactory(); if ($attestationStatementSupportManager !== null) { $this->ceremonyStepManagerFactory->setAttestationStatementSupportManager($attestationStatementSupportManager); \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$attestationStatementSupportManager" is deprecated since 4.8.0 will be removed in 5.0.0. Please set a CheckAttestationFormatIsKnownAndValid object into CeremonyStepManager object instead.'); } if ($extensionOutputCheckerHandler !== null) { $this->ceremonyStepManagerFactory->setExtensionOutputCheckerHandler($extensionOutputCheckerHandler); } } /** * @private Will become private in 5.0.0 */ public static function create(null|AttestationStatementSupportManager $attestationStatementSupportManager = null, null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository = null, null|TokenBindingHandler $tokenBindingHandler = null, null|ExtensionOutputCheckerHandler $extensionOutputCheckerHandler = null, null|EventDispatcherInterface $eventDispatcher = null, null|CeremonyStepManager $ceremonyStepManager = null) : self { return new self($attestationStatementSupportManager, $publicKeyCredentialSourceRepository, $tokenBindingHandler, $extensionOutputCheckerHandler, $eventDispatcher, $ceremonyStepManager); } public function setLogger(LoggerInterface $logger) : void { $this->logger = $logger; } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->eventDispatcher = $eventDispatcher; } /** * @deprecated since 4.8.0 and will be removed in 5.0.0. Please use the CheckMetadataStatement object from the CeremonyStepManager instead. */ public function setCertificateChainValidator(CertificateChainValidator $certificateChainValidator) : self { $this->ceremonyStepManagerFactory->enableCertificateChainValidator($certificateChainValidator); return $this; } /** * @deprecated since 4.8.0 and will be removed in 5.0.0. Please use the CheckMetadataStatement object from the CeremonyStepManager instead. */ public function enableMetadataStatementSupport(MetadataStatementRepository $metadataStatementRepository, StatusReportRepository $statusReportRepository, CertificateChainValidator $certificateChainValidator) : self { $this->ceremonyStepManagerFactory->enableMetadataStatementSupport($metadataStatementRepository, $statusReportRepository, $certificateChainValidator); return $this; } /** * @param string[] $securedRelyingPartyId * * @see https://www.w3.org/TR/webauthn/#registering-a-new-credential */ public function check(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface|string $request, null|array $securedRelyingPartyId = null) : PublicKeyCredentialSource { if ($request instanceof ServerRequestInterface) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `check` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class)); } if ($securedRelyingPartyId !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', sprintf('Passing a list or secured relying party IDs to the method `check` of the class "%s" is deprecated since 4.8.0 and will be removed in 5.0.0. Please inject the list instead.', self::class)); } $host = is_string($request) ? $request : $request->getUri()->getHost(); try { $this->logger->info('Checking the authenticator attestation response', ['authenticatorAttestationResponse' => $authenticatorAttestationResponse, 'publicKeyCredentialCreationOptions' => $publicKeyCredentialCreationOptions, 'host' => $host]); if ($this->ceremonyStepManager === null) { $this->ceremonyStepManager = $this->ceremonyStepManagerFactory->creationCeremony($securedRelyingPartyId); } $publicKeyCredentialSource = $this->createPublicKeyCredentialSource($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions); $this->ceremonyStepManager->process($publicKeyCredentialSource, $authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $publicKeyCredentialCreationOptions->user->id, $host); $publicKeyCredentialSource->counter = $authenticatorAttestationResponse->attestationObject->authData->signCount; $publicKeyCredentialSource->backupEligible = $authenticatorAttestationResponse->attestationObject->authData->isBackupEligible(); $publicKeyCredentialSource->backupStatus = $authenticatorAttestationResponse->attestationObject->authData->isBackedUp(); $publicKeyCredentialSource->uvInitialized = $authenticatorAttestationResponse->attestationObject->authData->isUserVerified(); $this->logger->info('The attestation is valid'); $this->logger->debug('Public Key Credential Source', ['publicKeyCredentialSource' => $publicKeyCredentialSource]); $this->eventDispatcher->dispatch($this->createAuthenticatorAttestationResponseValidationSucceededEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $publicKeyCredentialSource)); return $publicKeyCredentialSource; } catch (Throwable $throwable) { $this->logger->error('An error occurred', ['exception' => $throwable]); $this->eventDispatcher->dispatch($this->createAuthenticatorAttestationResponseValidationFailedEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $throwable)); throw $throwable; } } protected function createAuthenticatorAttestationResponseValidationSucceededEvent(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface|string $host, PublicKeyCredentialSource $publicKeyCredentialSource) : AuthenticatorAttestationResponseValidationSucceededEvent { if ($host instanceof ServerRequestInterface) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAttestationResponseValidationSucceededEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class)); } return new AuthenticatorAttestationResponseValidationSucceededEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $publicKeyCredentialSource); } protected function createAuthenticatorAttestationResponseValidationFailedEvent(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface|string $host, Throwable $throwable) : AuthenticatorAttestationResponseValidationFailedEvent { if ($host instanceof ServerRequestInterface) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAttestationResponseValidationFailedEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class)); } return new AuthenticatorAttestationResponseValidationFailedEvent($authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, $host, $throwable); } private function createPublicKeyCredentialSource(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions) : PublicKeyCredentialSource { $attestationObject = $authenticatorAttestationResponse->attestationObject; $attestedCredentialData = $attestationObject->authData->attestedCredentialData; $attestedCredentialData !== null || throw AuthenticatorResponseVerificationException::create('Not attested credential data'); $credentialId = $attestedCredentialData->credentialId; $credentialPublicKey = $attestedCredentialData->credentialPublicKey; $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create('Not credential public key available in the attested credential data'); $userHandle = $publicKeyCredentialCreationOptions->user->id; $transports = $authenticatorAttestationResponse->transports; return PublicKeyCredentialSource::create($credentialId, PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, $transports, $attestationObject->attStmt->type, $attestationObject->attStmt->trustPath, $attestedCredentialData->aaguid, $credentialPublicKey, $userHandle, $attestationObject->authData->signCount); } } type; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAlg() : int { return $this->alg; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromString(string $data) : self { $data = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); return self::createFromArray($data); } /** * @param mixed[] $json * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $json) : self { array_key_exists('type', $json) || throw InvalidDataException::create($json, 'Invalid input. "type" is missing.'); array_key_exists('alg', $json) || throw InvalidDataException::create($json, 'Invalid input. "alg" is missing.'); return self::create($json['type'], $json['alg']); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return ['type' => $this->type, 'alg' => $this->alg]; } } type; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getId() : string { return $this->id; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTransports() : array { return $this->transports; } /** * @deprecated since 4.9.0 and will be removed in 5.0.0. Please use the serializer instead. */ public static function createFromString(string $data) : self { $data = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); return self::createFromArray($data); } /** * @param mixed[] $json * @deprecated since 4.9.0 and will be removed in 5.0.0. Please use the serializer instead. */ public static function createFromArray(array $json) : self { array_key_exists('type', $json) || throw InvalidDataException::create($json, 'Invalid input. "type" is missing.'); array_key_exists('id', $json) || throw InvalidDataException::create($json, 'Invalid input. "id" is missing.'); $id = Base64UrlSafe::decodeNoPadding($json['id']); return self::create($json['type'], $id, $json['transports'] ?? []); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $json = ['type' => $this->type, 'id' => Base64UrlSafe::encodeUnpadded($this->id)]; if (count($this->transports) !== 0) { $json['transports'] = $this->transports; } return $json; } } id; } /** * @param mixed[] $json * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $json) : self { array_key_exists('name', $json) || throw InvalidDataException::create($json, 'Invalid input. "name" is missing.'); return self::create($json['name'], $json['id'] ?? null, $json['icon'] ?? null); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $json = parent::jsonSerialize(); if ($this->id !== null) { $json['id'] = $this->id; } return $json; } } attestationObject; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all * * @return string[] */ public function getTransports() : array { return $this->transports; } } $extensions * @protected */ public function __construct(public readonly string $challenge, public null|int $timeout = null, null|array|AuthenticationExtensions $extensions = null) { $this->timeout === null || $this->timeout > 0 || throw new InvalidArgumentException('Invalid timeout'); if ($extensions === null) { $this->extensions = AuthenticationExtensionsClientInputs::create(); } elseif ($extensions instanceof AuthenticationExtensions) { $this->extensions = $extensions; } else { $this->extensions = AuthenticationExtensions::create($extensions); } } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function setTimeout(?int $timeout) : static { $this->timeout = $timeout; return $this; } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function addExtension(AuthenticationExtension $extension) : static { $this->extensions[$extension->name] = $extension; return $this; } /** * @param AuthenticationExtension[] $extensions * @deprecated since 4.7.0. No replacement. Please use the {self::create} instead. * @infection-ignore-all */ public function addExtensions(array $extensions) : static { foreach ($extensions as $extension) { $this->extensions[$extension->name] = $extension; } return $this; } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function setExtensions(AuthenticationExtensions $extensions) : static { $this->extensions = $extensions; return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getChallenge() : string { return $this->challenge; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTimeout() : ?int { return $this->timeout; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getExtensions() : AuthenticationExtensions { return $this->extensions; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static abstract function createFromString(string $data) : static; /** * @param mixed[] $json * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static abstract function createFromArray(array $json) : static; } authData; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRpIdHash() : string { return $this->rpIdHash; } public function isUserPresent() : bool { return 0 !== (ord($this->flags) & self::FLAG_UP); } public function isUserVerified() : bool { return 0 !== (ord($this->flags) & self::FLAG_UV); } public function isBackupEligible() : bool { return 0 !== (ord($this->flags) & self::FLAG_BE); } public function isBackedUp() : bool { return 0 !== (ord($this->flags) & self::FLAG_BS); } public function hasAttestedCredentialData() : bool { return 0 !== (ord($this->flags) & self::FLAG_AT); } public function hasExtensions() : bool { return 0 !== (ord($this->flags) & self::FLAG_ED); } public function getReservedForFutureUse1() : int { return ord($this->flags) & self::FLAG_RFU1; } public function getReservedForFutureUse2() : int { return ord($this->flags) & self::FLAG_RFU2; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getSignCount() : int { return $this->signCount; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttestedCredentialData() : ?AttestedCredentialData { return $this->attestedCredentialData; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getExtensions() : ?AuthenticationExtensions { return $this->extensions !== null && $this->hasExtensions() ? $this->extensions : null; } } * @deprecated since 4.8.0 and will be removed in 5.0.0. * @infection-ignore-all */ class PublicKeyCredentialDescriptorCollection implements JsonSerializable, Countable, IteratorAggregate { /** * @var array * @readonly */ public array $publicKeyCredentialDescriptors; /** * @private * @param PublicKeyCredentialDescriptor[] $pkCredentialDescriptors */ public function __construct(array $pkCredentialDescriptors = []) { $this->publicKeyCredentialDescriptors = []; foreach ($pkCredentialDescriptors as $pkCredentialDescriptor) { $pkCredentialDescriptor instanceof PublicKeyCredentialDescriptor || throw new InvalidArgumentException('Expected only instances of ' . PublicKeyCredentialDescriptor::class); $this->publicKeyCredentialDescriptors[$pkCredentialDescriptor->id] = $pkCredentialDescriptor; } } /** * @param PublicKeyCredentialDescriptor[] $publicKeyCredentialDescriptors */ public static function create(array $publicKeyCredentialDescriptors) : self { return new self($publicKeyCredentialDescriptors); } /** * @infection-ignore-all */ public function add(PublicKeyCredentialDescriptor ...$publicKeyCredentialDescriptors) : void { foreach ($publicKeyCredentialDescriptors as $publicKeyCredentialDescriptor) { $this->publicKeyCredentialDescriptors[$publicKeyCredentialDescriptor->id] = $publicKeyCredentialDescriptor; } } /** * @infection-ignore-all */ public function has(string $id) : bool { return array_key_exists($id, $this->publicKeyCredentialDescriptors); } /** * @infection-ignore-all */ public function remove(string $id) : void { if (!array_key_exists($id, $this->publicKeyCredentialDescriptors)) { return; } unset($this->publicKeyCredentialDescriptors[$id]); } /** * @return Iterator */ public function getIterator() : Iterator { return new ArrayIterator($this->publicKeyCredentialDescriptors); } public function count(int $mode = COUNT_NORMAL) : int { return count($this->publicKeyCredentialDescriptors, $mode); } /** * @return array[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return $this->publicKeyCredentialDescriptors; } /** * @infection-ignore-all */ public static function createFromString(string $data) : self { $data = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); return self::createFromArray($data); } /** * @param mixed[] $json * @infection-ignore-all */ public static function createFromArray(array $json) : self { return self::create(\array_map(static fn(array $item): PublicKeyCredentialDescriptor => PublicKeyCredentialDescriptor::createFromArray($item), $json)); } } clientDataJSON; } } publicKeyCredentialSourceRepository !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'The parameter "$publicKeyCredentialSourceRepository" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set "null" instead.'); } if ($this->tokenBindingHandler !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.3.0', 'The parameter "$tokenBindingHandler" is deprecated since 4.3.0 and will be removed in 5.0.0. Please set "null" instead.'); } if ($extensionOutputCheckerHandler !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$extensionOutputCheckerHandler" is deprecated since 4.8.0 and will be removed in 5.0.0. Please set "null" instead and inject a CheckExtensions object into the CeremonyStepManager.'); } if ($algorithmManager !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$algorithmManager" is deprecated since 4.8.0 and will be removed in 5.0.0. Please set "null" instead and inject a CheckSignature object into the CeremonyStepManager.'); } $this->eventDispatcher = $eventDispatcher ?? new NullEventDispatcher(); if ($eventDispatcher !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', 'The parameter "$eventDispatcher" is deprecated since 4.5.0 will be removed in 5.0.0. Please use `setEventDispatcher` instead.'); } if ($this->ceremonyStepManager === null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$ceremonyStepManager" will mandatory in 5.0.0. Please set a CeremonyStepManager object instead and set null for $algorithmManager and $extensionOutputCheckerHandler.'); } $this->logger = new NullLogger(); $this->ceremonyStepManagerFactory = new CeremonyStepManagerFactory(); if ($extensionOutputCheckerHandler !== null) { $this->ceremonyStepManagerFactory->setExtensionOutputCheckerHandler($extensionOutputCheckerHandler); } if ($algorithmManager !== null) { $this->ceremonyStepManagerFactory->setAlgorithmManager($algorithmManager); } } public static function create(null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository = null, null|TokenBindingHandler $tokenBindingHandler = null, null|ExtensionOutputCheckerHandler $extensionOutputCheckerHandler = null, null|Manager $algorithmManager = null, null|EventDispatcherInterface $eventDispatcher = null, null|CeremonyStepManager $ceremonyStepManager = null) : self { return new self($publicKeyCredentialSourceRepository, $tokenBindingHandler, $extensionOutputCheckerHandler, $algorithmManager, $eventDispatcher, $ceremonyStepManager); } /** * @param string[] $securedRelyingPartyId * * @see https://www.w3.org/TR/webauthn/#verifying-assertion */ public function check(string|PublicKeyCredentialSource $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $request, ?string $userHandle, null|array $securedRelyingPartyId = null) : PublicKeyCredentialSource { if ($request instanceof ServerRequestInterface) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `check` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class)); } if (is_string($credentialId)) { \trigger_deprecation('web-auth/webauthn-lib', '4.6.0', sprintf('Passing a string as first to the method `check` of the class "%s" is deprecated since 4.6.0. Please inject a %s object instead.', self::class, PublicKeyCredentialSource::class)); } if ($securedRelyingPartyId !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', sprintf('Passing a list or secured relying party IDs to the method `check` of the class "%s" is deprecated since 4.8.0 and will be removed in 5.0.0. Please inject a CheckOrigin into the CeremonyStepManager instead.', self::class)); } if ($credentialId instanceof PublicKeyCredentialSource) { $publicKeyCredentialSource = $credentialId; } else { $this->publicKeyCredentialSourceRepository instanceof PublicKeyCredentialSourceRepository || throw AuthenticatorResponseVerificationException::create('Please pass the Public Key Credential Source to the method "check".'); $publicKeyCredentialSource = $this->publicKeyCredentialSourceRepository->findOneByCredentialId($credentialId); } $publicKeyCredentialSource !== null || throw AuthenticatorResponseVerificationException::create('The credential ID is invalid.'); $host = is_string($request) ? $request : $request->getUri()->getHost(); if ($this->ceremonyStepManager === null) { $this->ceremonyStepManager = $this->ceremonyStepManagerFactory->requestCeremony($securedRelyingPartyId); } try { $this->logger->info('Checking the authenticator assertion response', ['credentialId' => $credentialId, 'publicKeyCredentialSource' => $publicKeyCredentialSource, 'authenticatorAssertionResponse' => $authenticatorAssertionResponse, 'publicKeyCredentialRequestOptions' => $publicKeyCredentialRequestOptions, 'host' => $host, 'userHandle' => $userHandle]); $this->ceremonyStepManager->process($publicKeyCredentialSource, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $userHandle, $host); $publicKeyCredentialSource->counter = $authenticatorAssertionResponse->authenticatorData->signCount; //26.1. $publicKeyCredentialSource->backupEligible = $authenticatorAssertionResponse->authenticatorData->isBackupEligible(); //26.2. $publicKeyCredentialSource->backupStatus = $authenticatorAssertionResponse->authenticatorData->isBackedUp(); //26.2. if ($publicKeyCredentialSource->uvInitialized === \false) { $publicKeyCredentialSource->uvInitialized = $authenticatorAssertionResponse->authenticatorData->isUserVerified(); //26.3. } /* * 26.3. * OPTIONALLY, if response.attestationObject is present, update credentialRecord.attestationObject to the value of response.attestationObject and update credentialRecord.attestationClientDataJSON to the value of response.clientDataJSON. */ if (is_string($credentialId) && $this->publicKeyCredentialSourceRepository instanceof PublicKeyCredentialSourceRepository) { $this->publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource); } //All good. We can continue. $this->logger->info('The assertion is valid'); $this->logger->debug('Public Key Credential Source', ['publicKeyCredentialSource' => $publicKeyCredentialSource]); $this->eventDispatcher->dispatch($this->createAuthenticatorAssertionResponseValidationSucceededEvent(null, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $publicKeyCredentialSource)); // 27. return $publicKeyCredentialSource; } catch (AuthenticatorResponseVerificationException $throwable) { $this->logger->error('An error occurred', ['exception' => $throwable]); $this->eventDispatcher->dispatch($this->createAuthenticatorAssertionResponseValidationFailedEvent($publicKeyCredentialSource, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $throwable)); throw $throwable; } } public function setLogger(LoggerInterface $logger) : void { $this->logger = $logger; } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->eventDispatcher = $eventDispatcher; } /** * @deprecated since 4.8.0 and will be removed in 5.0.0. Please inject a CheckCounter object into a CeremonyStepManager instead. */ public function setCounterChecker(CounterChecker $counterChecker) : self { $this->ceremonyStepManagerFactory->setCounterChecker($counterChecker); return $this; } protected function createAuthenticatorAssertionResponseValidationSucceededEvent(null|string $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $host, ?string $userHandle, PublicKeyCredentialSource $publicKeyCredentialSource) : AuthenticatorAssertionResponseValidationSucceededEvent { if ($host instanceof ServerRequestInterface) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAssertionResponseValidationSucceededEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class)); } return new AuthenticatorAssertionResponseValidationSucceededEvent($credentialId, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $publicKeyCredentialSource); } protected function createAuthenticatorAssertionResponseValidationFailedEvent(string|PublicKeyCredentialSource $publicKeyCredentialSource, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $host, ?string $userHandle, Throwable $throwable) : AuthenticatorAssertionResponseValidationFailedEvent { if ($host instanceof ServerRequestInterface) { \trigger_deprecation('web-auth/webauthn-lib', '4.5.0', sprintf('Passing a %s to the method `createAuthenticatorAssertionResponseValidationFailedEvent` of the class "%s" is deprecated since 4.5.0 and will be removed in 5.0.0. Please inject the host as a string instead.', ServerRequestInterface::class, self::class)); } return new AuthenticatorAssertionResponseValidationFailedEvent($publicKeyCredentialSource, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $host, $userHandle, $throwable); } } signature; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUserHandle() : ?string { return $this->userHandle; } } $extensions */ public function __construct(string $challenge, public null|string $rpId = null, public array $allowCredentials = [], public null|string $userVerification = null, null|int $timeout = null, null|array|AuthenticationExtensions $extensions = null) { in_array($userVerification, self::USER_VERIFICATION_REQUIREMENTS, \true) || throw InvalidDataException::create($userVerification, 'Invalid user verification requirement'); parent::__construct($challenge, $timeout, $extensions); } /** * @param PublicKeyCredentialDescriptor[] $allowCredentials * @param positive-int $timeout * @param null|AuthenticationExtensions|array $extensions */ public static function create(string $challenge, null|string $rpId = null, array $allowCredentials = [], null|string $userVerification = null, null|int $timeout = null, null|array|AuthenticationExtensions $extensions = null) : self { return new self($challenge, $rpId, $allowCredentials, $userVerification, $timeout, $extensions); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setRpId(?string $rpId) : self { $this->rpId = $rpId; return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function allowCredential(PublicKeyCredentialDescriptor $allowCredential) : self { $this->allowCredentials[] = $allowCredential; return $this; } /** * @deprecated since 4.7.0. No replacement. Please use the property directly. * @infection-ignore-all */ public function allowCredentials(PublicKeyCredentialDescriptor ...$allowCredentials) : self { foreach ($allowCredentials as $allowCredential) { $this->allowCredentials[] = $allowCredential; } return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setUserVerification(?string $userVerification) : self { if ($userVerification === null) { $this->rpId = null; return $this; } in_array($userVerification, [self::USER_VERIFICATION_REQUIREMENT_REQUIRED, self::USER_VERIFICATION_REQUIREMENT_PREFERRED, self::USER_VERIFICATION_REQUIREMENT_DISCOURAGED], \true) || throw InvalidDataException::create($userVerification, 'Invalid user verification requirement'); $this->userVerification = $userVerification; return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRpId() : ?string { return $this->rpId; } /** * @return PublicKeyCredentialDescriptor[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAllowCredentials() : array { return $this->allowCredentials; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUserVerification() : ?string { return $this->userVerification; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromString(string $data) : static { $data = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); return self::createFromArray($data); } /** * @param mixed[] $json * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $json) : static { array_key_exists('challenge', $json) || throw InvalidDataException::create($json, 'Invalid input. "challenge" is missing.'); $allowCredentials = []; $allowCredentialList = $json['allowCredentials'] ?? []; foreach ($allowCredentialList as $allowCredential) { $allowCredentials[] = PublicKeyCredentialDescriptor::createFromArray($allowCredential); } $challenge = Base64::decode($json['challenge']); $extensions = isset($json['extensions']) ? AuthenticationExtensionsClientInputs::createFromArray($json['extensions']) : AuthenticationExtensionsClientInputs::create(); return self::create($challenge, $json['rpId'] ?? null, $allowCredentials, $json['userVerification'] ?? null, $json['timeout'] ?? null, $extensions); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $json = ['challenge' => Base64UrlSafe::encodeUnpadded($this->challenge)]; if ($this->rpId !== null) { $json['rpId'] = $this->rpId; } if ($this->userVerification !== null) { $json['userVerification'] = $this->userVerification; } if (count($this->allowCredentials) !== 0) { $json['allowCredentials'] = $this->allowCredentials; } if ($this->extensions->count() !== 0) { $json['extensions'] = $this->extensions; } if ($this->timeout !== null) { $json['timeout'] = $this->timeout; } return $json; } } decoder = Decoder::create(); } public static function create() : self { return new self(); } public function load(string $authData) : AuthenticatorData { $authData = $this->fixIncorrectEdDSAKey($authData); $authDataStream = new StringStream($authData); $rp_id_hash = $authDataStream->read(32); $flags = $authDataStream->read(1); $signCount = $authDataStream->read(4); $signCount = \unpack('N', $signCount); $attestedCredentialData = null; if (0 !== (ord($flags) & AuthenticatorData::FLAG_AT)) { $aaguid = Uuid::fromBinary($authDataStream->read(16)); $credentialLength = $authDataStream->read(2); $credentialLength = \unpack('n', $credentialLength); $credentialId = $authDataStream->read($credentialLength[1]); $credentialPublicKey = $this->decoder->decode($authDataStream); $credentialPublicKey instanceof MapObject || throw InvalidDataException::create($authData, 'The data does not contain a valid credential public key.'); $attestedCredentialData = AttestedCredentialData::create($aaguid, $credentialId, (string) $credentialPublicKey); } $extension = null; if (0 !== (ord($flags) & AuthenticatorData::FLAG_ED)) { $extension = $this->decoder->decode($authDataStream); $extension = AuthenticationExtensionsClientOutputsLoader::load($extension); } $authDataStream->isEOF() || throw InvalidDataException::create($authData, 'Invalid authentication data. Presence of extra bytes.'); $authDataStream->close(); return AuthenticatorData::create($authData, $rp_id_hash, $flags, $signCount[1], $attestedCredentialData, $extension); } private function fixIncorrectEdDSAKey(string $data) : string { $needle = \hex2bin('a301634f4b500327206745643235353139'); $correct = \hex2bin('a401634f4b500327206745643235353139'); $position = \mb_strpos($data, $needle, 0, '8bit'); if ($position === \false) { return $data; } $begin = \mb_substr($data, 0, $position, '8bit'); $end = \mb_substr($data, $position, null, '8bit'); $end = \str_replace($needle, $correct, $end); $cbor = new StringStream($end); $badKey = $this->decoder->decode($cbor); $badKey instanceof MapObject && $cbor->isEOF() || throw InvalidDataException::create($end, 'Invalid authentication data. Presence of extra bytes.'); $badX = $badKey->get(-2); $badX instanceof ListObject || throw InvalidDataException::create($end, 'Invalid authentication data.'); $keyBytes = \array_reduce($badX->normalize(), static fn(string $carry, string $item): string => $carry . chr((int) $item), ''); $correctX = ByteStringObject::create($keyBytes); $correctKey = MapObject::create()->add(UnsignedIntegerObject::create(1), TextStringObject::create('OKP'))->add(UnsignedIntegerObject::create(3), NegativeIntegerObject::create(-8))->add(NegativeIntegerObject::create(-1), TextStringObject::create('Ed25519'))->add(NegativeIntegerObject::create(-2), $correctX); return $begin . $correctKey; } } EmptyTrustPath::class] => EmptyTrustPath::create(), array_key_exists('x5c', $data) && is_array($data['x5c']) => CertificateTrustPath::create($data['x5c']), array_key_exists('ecdaaKeyId', $data) && is_string($data['ecdaaKeyId']) => new EcdaaKeyIdTrustPath($data['ecdaaKeyId']), default => throw InvalidTrustPathException::create('Unsupported trust path'), }; } } ecdaaKeyId; } /** * @return string[] */ public function jsonSerialize() : array { return ['type' => self::class, 'ecdaaKeyId' => $this->ecdaaKeyId]; } public static function createFromArray(array $data) : static { array_key_exists('ecdaaKeyId', $data) || throw InvalidTrustPathException::create('The trust path type is invalid'); return new self($data['ecdaaKeyId']); } } $data * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : static; } self::class]; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : static { return self::create(); } } certificates; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : static { array_key_exists('x5c', $data) || throw InvalidTrustPathException::create('The trust path type is invalid'); $x5c = $data['x5c']; is_array($x5c) || throw InvalidTrustPathException::create('The trust path type is invalid. The parameter "x5c" shall contain strings.'); return self::create($x5c); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return ['type' => self::class, 'x5c' => $this->certificates]; } } name; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getIcon() : ?string { return $this->icon; } /** * @return mixed[] */ public function jsonSerialize() : array { $json = ['name' => $this->name]; if ($this->icon !== null) { $json['icon'] = $this->icon; } return $json; } } clientDataCollectors as $clientDataCollector) { if (in_array($collectedClientData->type, $clientDataCollector->supportedTypes(), \true)) { $clientDataCollector->verifyCollectedClientData($collectedClientData, $publicKeyCredentialOptions, $authenticatorResponse, $host); return; } } throw AuthenticatorResponseVerificationException::create('No client data collector found.'); } } type, $this->supportedTypes(), \true) || throw AuthenticatorResponseVerificationException::create(sprintf('The client data type is not "%s" supported.', \implode('", "', $this->supportedTypes()))); } } logger = $logger; } public function check(PublicKeyCredentialSource $publicKeyCredentialSource, int $currentCounter) : void { try { $currentCounter > $publicKeyCredentialSource->counter || throw CounterException::create($currentCounter, $publicKeyCredentialSource->counter, 'Invalid counter.'); } catch (CounterException $throwable) { $this->logger->error('The counter is invalid', ['current' => $currentCounter, 'new' => $publicKeyCredentialSource->counter]); throw $throwable; } } } extensions); } assert(is_array($data), 'The data should be an array.'); foreach ($data as $key => $value) { if (!is_string($key)) { continue; } $data[$key] = AuthenticationExtension::create($key, $value); } return AuthenticationExtensions::create($data); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return in_array($type, [AuthenticationExtensions::class, AuthenticationExtensionsClientOutputs::class, AuthenticationExtensionsClientInputs::class], \true); } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [AuthenticationExtensions::class => \true, AuthenticationExtensionsClientInputs::class => \true, AuthenticationExtensionsClientOutputs::class => \true]; } /** * @return array */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof AuthenticationExtensions); $extensions = []; foreach ($data->extensions as $extension) { $extensions[$extension->name] = $extension->value; } return $extensions; } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof AuthenticationExtensions; } } attestationStatementSupportManager->get($data['fmt']); return $attestationStatementSupport->load($data); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === AttestationStatement::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [AttestationStatement::class => \true]; } } */ public function getSupportedTypes(?string $format) : array { return [AuthenticationExtension::class => \true]; } /** * @return array */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof AuthenticationExtension); return $data->value; } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof AuthenticationExtension; } } new EcdaaKeyIdTrustPath($data), array_key_exists('x5c', $data) => CertificateTrustPath::create($data), $data === [], isset($data['type']) && $data['type'] === EmptyTrustPath::class => EmptyTrustPath::create(), default => throw new InvalidTrustPathException('Unsupported trust path type'), }; } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === TrustPath::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [TrustPath::class => \true]; } /** * @return array */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof TrustPath); return match (\true) { $data instanceof EcdaaKeyIdTrustPath => ['ecdaaKeyId' => $data->getEcdaaKeyId()], $data instanceof CertificateTrustPath => ['x5c' => $data->certificates], $data instanceof EmptyTrustPath => [], default => throw new InvalidTrustPathException('Unsupported trust path type'), }; } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof TrustPath; } } denormalizer->denormalize($data['response'], AuthenticatorResponse::class, $format, $context)); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === PublicKeyCredential::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [PublicKeyCredential::class => \true]; } } $package) { if (!\class_exists($class)) { throw new RuntimeException(sprintf('The class "%s" is required. Please install the package "%s" to use this feature.', $class, $package)); } } $denormalizers = [new ExtensionDescriptorDenormalizer(), new VerificationMethodANDCombinationsDenormalizer(), new AuthenticationExtensionNormalizer(), new PublicKeyCredentialDescriptorNormalizer(), new AttestedCredentialDataNormalizer(), new AttestationObjectDenormalizer(), new AttestationStatementDenormalizer($this->attestationStatementSupportManager), new AuthenticationExtensionsDenormalizer(), new AuthenticatorAssertionResponseDenormalizer(), new AuthenticatorAttestationResponseDenormalizer(), new AuthenticatorDataDenormalizer(), new AuthenticatorResponseDenormalizer(), new CollectedClientDataDenormalizer(), new PublicKeyCredentialDenormalizer(), new PublicKeyCredentialOptionsDenormalizer(), new PublicKeyCredentialSourceDenormalizer(), new PublicKeyCredentialUserEntityDenormalizer(), new TrustPathDenormalizer(), new UidNormalizer(), new ArrayDenormalizer(), new ObjectNormalizer(propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpDocExtractor(), new ReflectionExtractor()]))]; return new Serializer($denormalizers, [new JsonEncoder()]); } /** * @return array */ private static function getRequiredSerializerClasses() : array { return [UidNormalizer::class => self::PACKAGE_SYMFONY_SERIALIZER, ArrayDenormalizer::class => self::PACKAGE_SYMFONY_SERIALIZER, ObjectNormalizer::class => self::PACKAGE_SYMFONY_SERIALIZER, PropertyInfoExtractor::class => self::PACKAGE_SYMFONY_PROPERTY_INFO, PhpDocExtractor::class => self::PACKAGE_PHPDOCUMENTOR_REFLECTION_DOCBLOCK, ReflectionExtractor::class => self::PACKAGE_SYMFONY_PROPERTY_INFO, JsonEncoder::class => self::PACKAGE_SYMFONY_SERIALIZER, Serializer::class => self::PACKAGE_SYMFONY_SERIALIZER]; } } */ public function getSupportedTypes(?string $format) : array { return [CollectedClientData::class => \true]; } } */ public function getSupportedTypes(?string $format) : array { return [PublicKeyCredentialParameters::class => \true]; } } denormalizer->denormalize($data['clientDataJSON'], CollectedClientData::class, $format, $context); $attestationObject = $this->denormalizer->denormalize($data['attestationObject'], AttestationObject::class, $format, $context); return AuthenticatorAttestationResponse::create($clientDataJSON, $attestationObject, $data['transports'] ?? []); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === AuthenticatorAttestationResponse::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [AuthenticatorAttestationResponse::class => \true]; } } */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof AttestedCredentialData); $result = ['aaguid' => $this->normalizer->normalize($data->aaguid, $format, $context), 'credentialId' => \base64_encode($data->credentialId)]; if ($data->credentialPublicKey !== null) { $result['credentialPublicKey'] = \base64_encode($data->credentialPublicKey); } return $result; } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof AttestedCredentialData; } public function getSupportedTypes(?string $format) : array { return [AttestedCredentialData::class => \true]; } } */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof PublicKeyCredentialDescriptor); $result = ['type' => $data->type, 'id' => Base64UrlSafe::encodeUnpadded($data->id)]; if (count($data->transports) !== 0) { $result['transports'] = $data->transports; } return $result; } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof PublicKeyCredentialDescriptor; } public function getSupportedTypes(?string $format) : array { return [PublicKeyCredentialDescriptor::class => \true]; } } decoder = Decoder::create(); } public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []) : mixed { $authData = $this->fixIncorrectEdDSAKey($data); $authDataStream = new StringStream($authData); $rp_id_hash = $authDataStream->read(32); $flags = $authDataStream->read(1); $signCount = $authDataStream->read(4); $signCount = \unpack('N', $signCount); $attestedCredentialData = null; if (0 !== (ord($flags) & AuthenticatorData::FLAG_AT)) { $aaguid = Uuid::fromBinary($authDataStream->read(16)); $credentialLength = $authDataStream->read(2); $credentialLength = \unpack('n', $credentialLength); $credentialId = $authDataStream->read($credentialLength[1]); $credentialPublicKey = $this->decoder->decode($authDataStream); $credentialPublicKey instanceof MapObject || throw InvalidDataException::create($authData, 'The data does not contain a valid credential public key.'); $attestedCredentialData = AttestedCredentialData::create($aaguid, $credentialId, (string) $credentialPublicKey); } $extension = null; if (0 !== (ord($flags) & AuthenticatorData::FLAG_ED)) { $extension = $this->decoder->decode($authDataStream); $extension = AuthenticationExtensionsClientOutputsLoader::load($extension); } $authDataStream->isEOF() || throw InvalidDataException::create($authData, 'Invalid authentication data. Presence of extra bytes.'); $authDataStream->close(); return AuthenticatorData::create($authData, $rp_id_hash, $flags, $signCount[1], $attestedCredentialData, $extension === null ? null : $this->denormalizer->denormalize($extension, AuthenticationExtensions::class, $format, $context)); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === AuthenticatorData::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [AuthenticatorData::class => \true]; } private function fixIncorrectEdDSAKey(string $data) : string { $needle = \hex2bin('a301634f4b500327206745643235353139'); $correct = \hex2bin('a401634f4b500327206745643235353139'); $position = \mb_strpos($data, $needle, 0, '8bit'); if ($position === \false) { return $data; } $begin = \mb_substr($data, 0, $position, '8bit'); $end = \mb_substr($data, $position, null, '8bit'); $end = \str_replace($needle, $correct, $end); $cbor = new StringStream($end); $badKey = $this->decoder->decode($cbor); $badKey instanceof MapObject && $cbor->isEOF() || throw InvalidDataException::create($end, 'Invalid authentication data. Presence of extra bytes.'); $badX = $badKey->get(-2); $badX instanceof ListObject || throw InvalidDataException::create($end, 'Invalid authentication data.'); $keyBytes = \array_reduce($badX->normalize(), static fn(string $carry, string $item): string => $carry . chr((int) $item), ''); $correctX = ByteStringObject::create($keyBytes); $correctKey = MapObject::create()->add(UnsignedIntegerObject::create(1), TextStringObject::create('OKP'))->add(UnsignedIntegerObject::create(3), NegativeIntegerObject::create(-8))->add(NegativeIntegerObject::create(-1), TextStringObject::create('Ed25519'))->add(NegativeIntegerObject::create(-2), $correctX); return $begin . $correctKey; } } decode($stream); $parsed instanceof Normalizable || throw InvalidDataException::create($parsed, 'Invalid attestation object. Unexpected object.'); $attestationObject = $parsed->normalize(); $stream->isEOF() || throw InvalidDataException::create(null, 'Invalid attestation object. Presence of extra bytes.'); $stream->close(); $authData = $attestationObject['authData'] ?? throw InvalidDataException::create($attestationObject, 'Invalid attestation object. Missing "authData" field.'); return AttestationObject::create($data, $this->denormalizer->denormalize($attestationObject, AttestationStatement::class, $format, $context), $this->denormalizer->denormalize($authData, AuthenticatorData::class, $format, $context)); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === AttestationObject::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [AttestationObject::class => \true]; } } denormalizer->denormalize($data['trustPath'], TrustPath::class, $format, $context), Uuid::fromString($data['aaguid']), $data['credentialPublicKey'], $data['userHandle'], $data['counter'], $data['otherUI'] ?? null, $data['backupEligible'] ?? null, $data['backupStatus'] ?? null, $data['uvInitialized'] ?? null); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === PublicKeyCredentialSource::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [PublicKeyCredentialSource::class => \true]; } /** * @return array */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof PublicKeyCredentialSource); $result = ['publicKeyCredentialId' => Base64UrlSafe::encodeUnpadded($data->publicKeyCredentialId), 'type' => $data->type, 'transports' => $data->transports, 'attestationType' => $data->attestationType, 'trustPath' => $this->normalizer->normalize($data->trustPath, $format, $context), 'aaguid' => $this->normalizer->normalize($data->aaguid, $format, $context), 'credentialPublicKey' => Base64UrlSafe::encodeUnpadded($data->credentialPublicKey), 'userHandle' => Base64UrlSafe::encodeUnpadded($data->userHandle), 'counter' => $data->counter, 'otherUI' => $data->otherUI, 'backupEligible' => $data->backupEligible, 'backupStatus' => $data->backupStatus, 'uvInitialized' => $data->uvInitialized]; return \array_filter($result, static fn($value): bool => $value !== null); } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof PublicKeyCredentialSource; } } */ public function getSupportedTypes(?string $format) : array { return [PublicKeyCredentialUserEntity::class => \true]; } /** * @return array */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof PublicKeyCredentialUserEntity); $normalized = ['id' => Base64UrlSafe::encodeUnpadded($data->id), 'name' => $data->name, 'displayName' => $data->displayName, 'icon' => $data->icon]; return \array_filter($normalized, fn($value) => $value !== null); } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof PublicKeyCredentialUserEntity; } } denormalizer->denormalize($data, $type, $format, $context); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { if ($context[self::ALREADY_CALLED] ?? \false) { return \false; } return $type === ExtensionDescriptor::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [ExtensionDescriptor::class => \false]; } } */ public function getSupportedTypes(?string $format) : array { return [VerificationMethodANDCombinations::class => \true]; } /** * @return array */ public function normalize(mixed $object, ?string $format = null, array $context = []) : array { assert($object instanceof VerificationMethodANDCombinations); return \array_map(fn($verificationMethod) => $this->normalizer->normalize($verificationMethod, $format, $context), $object->verificationMethods); } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof VerificationMethodANDCombinations; } } denormalizer->denormalize($data['clientDataJSON'], CollectedClientData::class, $format, $context), $this->denormalizer->denormalize($data['authenticatorData'], AuthenticatorData::class, $format, $context), $data['signature'], $userHandle ?? null, !isset($data['attestationObject']) ? null : $this->denormalizer->denormalize($data['attestationObject'], AttestationObject::class, $format, $context)); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === AuthenticatorAssertionResponse::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [AuthenticatorAssertionResponse::class => \true]; } } AuthenticatorAttestationResponse::class, array_key_exists('signature', $data) => AuthenticatorAssertionResponse::class, default => throw InvalidDataException::create($data, 'Unable to create the response object'), }; return $this->denormalizer->denormalize($data, $realType, $format, $context); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return $type === AuthenticatorResponse::class; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [AuthenticatorResponse::class => \true]; } } $allowCredential) { $data[$key][$item]['id'] = Base64UrlSafe::decodeNoPadding($allowCredential['id']); } } } if ($type === PublicKeyCredentialCreationOptions::class) { return PublicKeyCredentialCreationOptions::create($this->denormalizer->denormalize($data['rp'], PublicKeyCredentialRpEntity::class, $format, $context), $this->denormalizer->denormalize($data['user'], PublicKeyCredentialUserEntity::class, $format, $context), $data['challenge'], !isset($data['pubKeyCredParams']) ? [] : $this->denormalizer->denormalize($data['pubKeyCredParams'], PublicKeyCredentialParameters::class . '[]', $format, $context), !isset($data['authenticatorSelection']) ? null : $this->denormalizer->denormalize($data['authenticatorSelection'], AuthenticatorSelectionCriteria::class, $format, $context), $data['attestation'] ?? null, !isset($data['excludeCredentials']) ? [] : $this->denormalizer->denormalize($data['excludeCredentials'], PublicKeyCredentialDescriptor::class . '[]', $format, $context), $data['timeout'] ?? null, !isset($data['extensions']) ? null : $this->denormalizer->denormalize($data['extensions'], AuthenticationExtensions::class, $format, $context)); } if ($type === PublicKeyCredentialRequestOptions::class) { return PublicKeyCredentialRequestOptions::create($data['challenge'], $data['rpId'] ?? null, !isset($data['allowCredentials']) ? [] : $this->denormalizer->denormalize($data['allowCredentials'], PublicKeyCredentialDescriptor::class . '[]', $format, $context), $data['userVerification'] ?? null, $data['timeout'] ?? null, !isset($data['extensions']) ? null : $this->denormalizer->denormalize($data['extensions'], AuthenticationExtensions::class, $format, $context)); } throw new BadMethodCallException('Unsupported type'); } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []) : bool { return in_array($type, [PublicKeyCredentialCreationOptions::class, PublicKeyCredentialRequestOptions::class], \true); } public function supportsNormalization(mixed $data, ?string $format = null, array $context = []) : bool { return $data instanceof PublicKeyCredentialCreationOptions || $data instanceof PublicKeyCredentialRequestOptions; } /** * @return array */ public function getSupportedTypes(?string $format) : array { return [PublicKeyCredentialCreationOptions::class => \true, PublicKeyCredentialRequestOptions::class => \true]; } /** * @return array */ public function normalize(mixed $data, ?string $format = null, array $context = []) : array { assert($data instanceof PublicKeyCredentialCreationOptions || $data instanceof PublicKeyCredentialRequestOptions); $json = ['challenge' => Base64UrlSafe::encodeUnpadded($data->challenge), 'timeout' => $data->timeout, 'extensions' => $data->extensions->count() === 0 ? null : $this->normalizer->normalize($data->extensions, $format, $context)]; if ($data instanceof PublicKeyCredentialCreationOptions) { $json = [...$json, 'rp' => $this->normalizer->normalize($data->rp, $format, $context), 'user' => $this->normalizer->normalize($data->user, $format, $context), 'pubKeyCredParams' => $this->normalizer->normalize($data->pubKeyCredParams, PublicKeyCredentialParameters::class . '[]', $context), 'authenticatorSelection' => $data->authenticatorSelection === null ? null : $this->normalizer->normalize($data->authenticatorSelection, $format, $context), 'attestation' => $data->attestation, 'excludeCredentials' => $this->normalizer->normalize($data->excludeCredentials, $format, $context)]; } if ($data instanceof PublicKeyCredentialRequestOptions) { $json = [...$json, 'rpId' => $data->rpId, 'allowCredentials' => $this->normalizer->normalize($data->allowCredentials, $format, $context), 'userVerification' => $data->userVerification]; } return \array_filter($json, static fn($value) => $value !== null && $value !== []); } } getPublicKeyCredentialDescriptor(), JSON_THROW_ON_ERROR); } public static function create(null|string $id, string $type, string $rawId, AuthenticatorResponse $response) : self { return new self($id, $type, $rawId, $response); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRawId() : string { return $this->rawId; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getResponse() : AuthenticatorResponse { return $this->response; } /** * @param string[] $transport */ public function getPublicKeyCredentialDescriptor(null|array $transport = null) : PublicKeyCredentialDescriptor { if ($transport !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.8.0', 'The parameter "$transport" is deprecated and will be removed in 5.0.0.'); @\trigger_error(sprintf('The $transport argument of %s() is deprecated since 4.8.0 and will be removed in 5.0.0.', __METHOD__), E_USER_DEPRECATED); } $transport ??= $this->response instanceof AuthenticatorAttestationResponse ? $this->response->transports : []; return PublicKeyCredentialDescriptor::create($this->type, $this->rawId, $transport); } } requestFactory->createRequest($method, $baseUri . $url); $body = $options['body'] ?? null; if ($body !== null) { $request = $request->withBody($this->streamFactory->createStream($body)); } foreach ($this->options as $name => $value) { $request = $request->withHeader($name, $value); } foreach ($options['headers'] ?? [] as $name => $value) { $request = $request->withHeader($name, $value); } $response = $this->client->sendRequest($request); return static::fromPsr17($response); } /** * @param ResponseInterface|iterable $responses */ public function stream(iterable|ResponseInterface $responses, ?float $timeout = null) : ResponseStreamInterface { throw new LogicException('Not implemented'); } public function withOptions(array $options) : static { $this->options = $options; return $this; } protected static function fromPsr17(Psr17ResponseInterface $response) : ResponseInterface { $headers = $response->getHeaders(); $content = $response->getBody()->getContents(); $status = $response->getStatusCode(); return new class($status, $headers, $content) implements ResponseInterface { /** * @param array $headers */ public function __construct(private readonly int $status, private readonly array $headers, private readonly string $content) { } public function getStatusCode() : int { return $this->status; } /** * @return array */ public function getHeaders(bool $throw = \true) : array { return $this->headers; } public function getContent(bool $throw = \true) : string { return $this->content; } /** * @return array */ public function toArray(bool $throw = \true) : array { $result = \json_decode($this->content, \true); if (!is_array($result) || \json_last_error() !== JSON_ERROR_NONE) { throw new JsonException('Failed to decode JSON response: ' . \json_last_error_msg()); } return $result; } public function cancel() : void { // noop } public function getInfo(?string $type = null) : mixed { return null; } }; } } self::fixPEMStructure($d, $type), $data); } public static function fixPEMStructure(string $data, string $type = 'CERTIFICATE') : string { if (\str_contains($data, self::PEM_HEADER)) { return \trim($data); } $pem = self::PEM_HEADER . $type . '-----' . PHP_EOL; $pem .= \chunk_split($data, 64, PHP_EOL); return $pem . (self::PEM_FOOTER . $type . '-----' . PHP_EOL); } /** * @deprecated since 4.7.0 and will be removed in 5.0.0. No replacement as not used internally. * @infection-ignore-all */ public static function convertPEMToDER(string $data) : string { if (!\str_contains($data, self::PEM_HEADER)) { return $data; } $data = preg_replace('/\\-{5}.*\\-{5}[\\r\\n]*/', '', $data); $data = preg_replace("/[\r\n]*/", '', (string) $data); return Base64::decode(\trim((string) $data), \true); } public static function convertDERToPEM(string $data, string $type = 'CERTIFICATE') : string { if (\str_contains($data, self::PEM_HEADER)) { return $data; } return self::fixPEMStructure(\base64_encode($data), $type); } /** * @param string[] $data * * @return string[] */ public static function convertAllDERToPEM(iterable $data, string $type = 'CERTIFICATE') : array { return \array_map(static fn($d): string => self::convertDERToPEM($d, $type), $data); } } clock = $clock; $this->dispatcher = new NullEventDispatcher(); } public static function create(HttpClientInterface $client, null|Clock|ClockInterface $clock = null, bool $allowFailures = \true) : self { return new self($client, null, $clock, $allowFailures); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } /** * @param string[] $untrustedCertificates * @param string[] $trustedCertificates */ public function check(array $untrustedCertificates, array $trustedCertificates) : void { foreach ($trustedCertificates as $trustedCertificate) { $this->dispatcher->dispatch(BeforeCertificateChainValidation::create($untrustedCertificates, $trustedCertificate)); try { if ($this->validateChain($untrustedCertificates, $trustedCertificate)) { $this->dispatcher->dispatch(CertificateChainValidationSucceeded::create($untrustedCertificates, $trustedCertificate)); return; } } catch (Throwable $exception) { $this->dispatcher->dispatch(CertificateChainValidationFailed::create($untrustedCertificates, $trustedCertificate)); throw $exception; } } throw CertificateChainException::create($untrustedCertificates, $trustedCertificates); } /** * @param string[] $untrustedCertificates */ private function validateChain(array $untrustedCertificates, string $trustedCertificate) : bool { $untrustedCertificates = \array_map(static fn(string $cert): Certificate => Certificate::fromPEM(PEM::fromString($cert)), \array_reverse($untrustedCertificates)); $trustedCertificate = Certificate::fromPEM(PEM::fromString($trustedCertificate)); // The trust path and the authenticator certificate are the same if (count($untrustedCertificates) === 1 && $untrustedCertificates[0]->toPEM()->string() === $trustedCertificate->toPEM()->string()) { return \true; } $uniqueCertificates = \array_map(static fn(Certificate $cert): string => $cert->toPEM()->string(), [...$untrustedCertificates, $trustedCertificate]); count(\array_unique($uniqueCertificates)) === count($uniqueCertificates) || throw CertificateChainException::create($untrustedCertificates, [$trustedCertificate], 'Invalid certificate chain with duplicated certificates.'); if (!$this->validateCertificates($trustedCertificate, ...$untrustedCertificates)) { return \false; } $certificates = [$trustedCertificate, ...$untrustedCertificates]; $numCerts = count($certificates); for ($i = 1; $i < $numCerts; $i++) { if ($this->isRevoked($certificates[$i])) { throw CertificateChainException::create($untrustedCertificates, [$trustedCertificate], 'Unable to validate the certificate chain. Revoked certificate found.'); } } return \true; } private function isRevoked(Certificate $subject) : bool { try { $csn = $subject->tbsCertificate()->serialNumber(); } catch (Throwable $e) { throw InvalidCertificateException::create($subject->toPEM()->string(), sprintf('Failed to parse certificate: %s', $e->getMessage()), $e); } try { $urls = $this->getCrlUrlList($subject); } catch (Throwable $e) { if ($this->allowFailures) { return \false; } throw InvalidCertificateException::create($subject->toPEM()->string(), 'Failed to get CRL distribution points: ' . $e->getMessage(), $e); } foreach ($urls as $url) { try { $revokedCertificates = $this->retrieveRevokedSerialNumbers($url); if (in_array($csn, $revokedCertificates, \true)) { return \true; } } catch (Throwable $e) { if ($this->allowFailures) { return \false; } throw CertificateRevocationListException::create($url, sprintf('Failed to retrieve the CRL:' . PHP_EOL . '%s', $e->getMessage()), $e); } } return \false; } private function validateCertificates(Certificate ...$certificates) : bool { try { $config = PathValidationConfig::create($this->clock->now(), self::MAX_VALIDATION_LENGTH); CertificationPath::create(...$certificates)->validate($config); return \true; } catch (Throwable) { return \false; } } /** * @return string[] */ private function retrieveRevokedSerialNumbers(string $url) : array { try { if ($this->client instanceof HttpClientInterface) { $crlData = $this->client->request('GET', $url)->getContent(); } else { $crlData = $this->sendPsrRequest($url); } $crl = UnspecifiedType::fromDER($crlData)->asSequence(); count($crl) === 3 || throw CertificateRevocationListException::create($url); $tbsCertList = $crl->at(0)->asSequence(); count($tbsCertList) >= 6 || throw CertificateRevocationListException::create($url); $list = $tbsCertList->at(5)->asSequence(); return \array_map(static function (UnspecifiedType $r) use($url) : string { $sequence = $r->asSequence(); count($sequence) >= 1 || throw CertificateRevocationListException::create($url); return $sequence->at(0)->asInteger()->number(); }, $list->elements()); } catch (Throwable $e) { throw CertificateRevocationListException::create($url, 'Failed to download the CRL', $e); } } /** * @return string[] */ private function getCrlUrlList(Certificate $subject) : array { try { $urls = []; $extensions = $subject->tbsCertificate()->extensions(); if ($extensions->hasCRLDistributionPoints()) { $crlDists = $extensions->crlDistributionPoints(); foreach ($crlDists->distributionPoints() as $dist) { $url = $dist->fullName()->names()->firstURI(); $scheme = parse_url($url, PHP_URL_SCHEME); if (!in_array($scheme, ['http', 'https'], \true)) { continue; } $urls[] = $url; } } return $urls; } catch (Throwable $e) { throw InvalidCertificateException::create($subject->toPEM()->string(), 'Failed to get CRL distribution points from certificate: ' . $e->getMessage(), $e); } } private function sendPsrRequest(string $url) : string { $request = $this->requestFactory->createRequest('GET', $url); $response = $this->client->sendRequest($request); if ($response->getStatusCode() !== 200) { throw CertificateRevocationListException::create($url, 'Failed to download the CRL'); } return $response->getBody()->getContents(); } } = 0 || throw MetadataStatementLoadingException::create('Invalid data. The parameter "tag" shall be a positive integer'); } } public static function create(string $id, ?int $tag = null, ?string $data = null, bool $failIfUnknown = \false) : self { return new self($id, $tag, $data, $failIfUnknown); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getId() : string { return $this->id; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTag() : ?int { return $this->tag; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getData() : ?string { return $this->data; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function isFailIfUnknown() : bool { return $this->failIfUnknown; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); array_key_exists('id', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "id" is missing'); array_key_exists('fail_if_unknown', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "fail_if_unknown" is missing'); return new self($data['id'], $data['tag'] ?? null, $data['data'] ?? null, $data['fail_if_unknown']); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $result = ['id' => $this->id, 'tag' => $this->tag, 'data' => $this->data, 'fail_if_unknown' => $this->failIfUnknown]; return self::filterNullValues($result); } } = 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "base" must be a positive integer'); $minLength >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "minLength" must be a positive integer'); parent::__construct($maxRetries, $blockSlowdown); } public static function create(int $base, int $minLength, ?int $maxRetries = null, ?int $blockSlowdown = null) : self { return new self($base, $minLength, $maxRetries, $blockSlowdown); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getBase() : int { return $this->base; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMinLength() : int { return $this->minLength; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { array_key_exists('base', $data) || throw MetadataStatementLoadingException::create('The parameter "base" is missing'); array_key_exists('minLength', $data) || throw MetadataStatementLoadingException::create('The parameter "minLength" is missing'); return self::create($data['base'], $data['minLength'], $data['maxRetries'] ?? null, $data['blockSlowdown'] ?? null); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['base' => $this->base, 'minLength' => $this->minLength, 'maxRetries' => $this->maxRetries, 'blockSlowdown' => $this->blockSlowdown]; return self::filterNullValues($data); } } = 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "minComplexity" must be a positive integer'); parent::__construct($maxRetries, $blockSlowdown); } public static function create(int $minComplexity, ?int $maxRetries = null, ?int $blockSlowdown = null) : self { return new self($minComplexity, $maxRetries, $blockSlowdown); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMinComplexity() : int { return $this->minComplexity; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); array_key_exists('minComplexity', $data) || throw MetadataStatementLoadingException::create('The key "minComplexity" is missing'); foreach (['minComplexity', 'maxRetries', 'blockSlowdown'] as $key) { if (array_key_exists($key, $data)) { is_int($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The value of "%s" must be a positive integer', $key)); } } return self::create($data['minComplexity'], $data['maxRetries'] ?? null, $data['blockSlowdown'] ?? null); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['minComplexity' => $this->minComplexity, 'maxRetries' => $this->maxRetries, 'blockSlowdown' => $this->blockSlowdown]; return self::filterNullValues($data); } } authenticatorGetInfo = $authenticatorGetInfo ?? AuthenticatorGetInfo::create($attestationTypes); } public static function create(string $description, int $authenticatorVersion, string $protocolFamily, int $schema, array $upv, array $authenticationAlgorithms, array $publicKeyAlgAndEncodings, array $attestationTypes, array $userVerificationDetails, array $matcherProtection, array $tcDisplay, array $attestationRootCertificates, array $alternativeDescriptions = [], ?string $legalHeader = null, ?string $aaid = null, ?string $aaguid = null, array $attestationCertificateKeyIdentifiers = [], array $keyProtection = [], ?bool $isKeyRestricted = null, ?bool $isFreshUserVerificationRequired = null, ?int $cryptoStrength = null, array $attachmentHint = [], ?string $tcDisplayContentType = null, array $tcDisplayPNGCharacteristics = [], array $ecdaaTrustAnchors = [], ?string $icon = null, array $supportedExtensions = [], ?AuthenticatorGetInfo $authenticatorGetInfo = null) : self { return new self($description, $authenticatorVersion, $protocolFamily, $schema, $upv, $authenticationAlgorithms, $publicKeyAlgAndEncodings, $attestationTypes, $userVerificationDetails, $matcherProtection, $tcDisplay, $attestationRootCertificates, AlternativeDescriptions::create($alternativeDescriptions), $legalHeader, $aaid, $aaguid, $attestationCertificateKeyIdentifiers, $keyProtection, $isKeyRestricted, $isFreshUserVerificationRequired, $cryptoStrength, $attachmentHint, $tcDisplayContentType, $tcDisplayPNGCharacteristics, $ecdaaTrustAnchors, $icon, $supportedExtensions, $authenticatorGetInfo); } /** * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromString(string $statement) : self { $data = \json_decode($statement, \true, flags: JSON_THROW_ON_ERROR); return self::createFromArray($data); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getLegalHeader() : ?string { return $this->legalHeader; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAaid() : ?string { return $this->aaid; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAaguid() : ?string { return $this->aaguid; } public function isKeyRestricted() : ?bool { return $this->isKeyRestricted; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function isFreshUserVerificationRequired() : ?bool { return $this->isFreshUserVerificationRequired; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAuthenticatorGetInfo() : AuthenticatorGetInfo|null { return $this->authenticatorGetInfo; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttestationCertificateKeyIdentifiers() : array { return $this->attestationCertificateKeyIdentifiers; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getDescription() : string { return $this->description; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAlternativeDescriptions() : null|AlternativeDescriptions { return $this->alternativeDescriptions; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAuthenticatorVersion() : int { return $this->authenticatorVersion; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getProtocolFamily() : string { return $this->protocolFamily; } /** * @return Version[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUpv() : array { return $this->upv; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getSchema() : ?int { return $this->schema; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAuthenticationAlgorithms() : array { return $this->authenticationAlgorithms; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getPublicKeyAlgAndEncodings() : array { return $this->publicKeyAlgAndEncodings; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttestationTypes() : array { return $this->attestationTypes; } /** * @return VerificationMethodANDCombinations[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUserVerificationDetails() : array { return $this->userVerificationDetails; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getKeyProtection() : array { return $this->keyProtection; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMatcherProtection() : array { return $this->matcherProtection; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCryptoStrength() : ?int { return $this->cryptoStrength; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttachmentHint() : array { return $this->attachmentHint; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTcDisplay() : array { return $this->tcDisplay; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTcDisplayContentType() : ?string { return $this->tcDisplayContentType; } /** * @return DisplayPNGCharacteristicsDescriptor[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTcDisplayPNGCharacteristics() : array { return $this->tcDisplayPNGCharacteristics; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttestationRootCertificates() : array { return $this->attestationRootCertificates; } /** * @return EcdaaTrustAnchor[] * * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification. * @infection-ignore-all */ public function getEcdaaTrustAnchors() : array { return $this->ecdaaTrustAnchors; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getIcon() : ?string { return $this->icon; } /** * @return ExtensionDescriptor[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getSupportedExtensions() : array { return $this->supportedExtensions; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $requiredKeys = ['description', 'authenticatorVersion', 'protocolFamily', 'schema', 'upv', 'authenticationAlgorithms', 'publicKeyAlgAndEncodings', 'attestationTypes', 'userVerificationDetails', 'matcherProtection', 'tcDisplay', 'attestationRootCertificates']; foreach ($requiredKeys as $key) { array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The key "%s" is missing', $key)); } $subObjects = ['authenticationAlgorithms', 'publicKeyAlgAndEncodings', 'attestationTypes', 'matcherProtection', 'tcDisplay', 'attestationRootCertificates']; foreach ($subObjects as $subObject) { is_array($data[$subObject]) || throw MetadataStatementLoadingException::create(sprintf('Invalid Metadata Statement. The parameter "%s" shall be a list of strings.', $subObject)); foreach ($data[$subObject] as $datum) { is_string($datum) || throw MetadataStatementLoadingException::create(sprintf('Invalid Metadata Statement. The parameter "%s" shall be a list of strings.', $subObject)); } } return self::create($data['description'], $data['authenticatorVersion'], $data['protocolFamily'], $data['schema'], \array_map(static function ($upv) : Version { is_array($upv) || throw MetadataStatementLoadingException::create('Invalid Metadata Statement. The parameter "upv" shall be a list of objects.'); return Version::createFromArray($upv); }, $data['upv']), $data['authenticationAlgorithms'], $data['publicKeyAlgAndEncodings'], $data['attestationTypes'], \array_map(static function ($userVerificationDetails) : VerificationMethodANDCombinations { is_array($userVerificationDetails) || throw MetadataStatementLoadingException::create('Invalid Metadata Statement. The parameter "userVerificationDetails" shall be a list of objects.'); return VerificationMethodANDCombinations::createFromArray($userVerificationDetails); }, $data['userVerificationDetails']), $data['matcherProtection'], $data['tcDisplay'], CertificateToolbox::fixPEMStructures($data['attestationRootCertificates']), $data['alternativeDescriptions'] ?? [], $data['legalHeader'] ?? null, $data['aaid'] ?? null, $data['aaguid'] ?? null, $data['attestationCertificateKeyIdentifiers'] ?? [], $data['keyProtection'] ?? [], $data['isKeyRestricted'] ?? null, $data['isFreshUserVerificationRequired'] ?? null, $data['cryptoStrength'] ?? null, $data['attachmentHint'] ?? [], $data['tcDisplayContentType'] ?? null, \array_map(static fn(array $data): DisplayPNGCharacteristicsDescriptor => DisplayPNGCharacteristicsDescriptor::createFromArray($data), $data['tcDisplayPNGCharacteristics'] ?? []), $data['ecdaaTrustAnchors'] ?? [], $data['icon'] ?? null, \array_map(static fn($supportedExtension): ExtensionDescriptor => ExtensionDescriptor::createFromArray($supportedExtension), $data['supportedExtensions'] ?? []), isset($data['authenticatorGetInfo']) ? AuthenticatorGetInfo::create($data['authenticatorGetInfo']) : null); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['legalHeader' => $this->legalHeader, 'aaid' => $this->aaid, 'aaguid' => $this->aaguid, 'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, 'description' => $this->description, 'alternativeDescriptions' => $this->alternativeDescriptions, 'authenticatorVersion' => $this->authenticatorVersion, 'protocolFamily' => $this->protocolFamily, 'schema' => $this->schema, 'upv' => $this->upv, 'authenticationAlgorithms' => $this->authenticationAlgorithms, 'publicKeyAlgAndEncodings' => $this->publicKeyAlgAndEncodings, 'attestationTypes' => $this->attestationTypes, 'userVerificationDetails' => $this->userVerificationDetails, 'keyProtection' => $this->keyProtection, 'isKeyRestricted' => $this->isKeyRestricted, 'isFreshUserVerificationRequired' => $this->isFreshUserVerificationRequired, 'matcherProtection' => $this->matcherProtection, 'cryptoStrength' => $this->cryptoStrength, 'attachmentHint' => $this->attachmentHint, 'tcDisplay' => $this->tcDisplay, 'tcDisplayContentType' => $this->tcDisplayContentType, 'tcDisplayPNGCharacteristics' => $this->tcDisplayPNGCharacteristics, 'attestationRootCertificates' => CertificateToolbox::fixPEMStructures($this->attestationRootCertificates), 'ecdaaTrustAnchors' => $this->ecdaaTrustAnchors, 'icon' => $this->icon, 'authenticatorGetInfo' => $this->authenticatorGetInfo, 'supportedExtensions' => $this->supportedExtensions]; return self::filterNullValues($data); } } $info */ public function __construct(public array $info = []) { } /** * @param array $info */ public static function create(array $info = []) : self { return new self($info); } /** * @deprecated since 4.7.0. Please use the constructor directly. * @infection-ignore-all */ public function add(string|int $key, mixed $value) : self { $this->info[$key] = $value; return $this; } /** * @return string[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return $this->info; } } verificationMethods[] = $verificationMethodDescriptor; return $this; } /** * @return VerificationMethodDescriptor[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getVerificationMethods() : array { return $this->verificationMethods; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { return self::create(\array_map(static fn(array $datum): VerificationMethodDescriptor => VerificationMethodDescriptor::createFromArray($datum), $data)); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return $this->verificationMethods; } } certLevel; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getModality() : int|null { return $this->modality; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getEffectiveDate() : ?string { return $this->effectiveDate; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificationDescriptor() : ?string { return $this->certificationDescriptor; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificateNumber() : ?string { return $this->certificateNumber; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificationPolicyVersion() : ?string { return $this->certificationPolicyVersion; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificationRequirementsVersion() : ?string { return $this->certificationRequirementsVersion; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { return self::create($data['certLevel'] ?? null, $data['modality'] ?? null, $data['effectiveDate'] ?? null, $data['certificationDescriptor'] ?? null, $data['certificateNumber'] ?? null, $data['certificationPolicyVersion'] ?? null, $data['certificationRequirementsVersion'] ?? null); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['certLevel' => $this->certLevel, 'modality' => $this->modality, 'effectiveDate' => $this->effectiveDate, 'certificationDescriptor' => $this->certificationDescriptor, 'certificateNumber' => $this->certificateNumber, 'certificationPolicyVersion' => $this->certificationPolicyVersion, 'certificationRequirementsVersion' => $this->certificationRequirementsVersion]; return \array_filter($data, static fn($var): bool => $var !== null); } } = 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "maxRetries" must be a positive integer'); $blockSlowdown >= 0 || throw MetadataStatementLoadingException::create('Invalid data. The value of "blockSlowdown" must be a positive integer'); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMaxRetries() : ?int { return $this->maxRetries; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getBlockSlowdown() : ?int { return $this->blockSlowdown; } } X; } public function getY() : string { return $this->Y; } public function getC() : string { return $this->c; } public function getSx() : string { return $this->sx; } public function getSy() : string { return $this->sy; } public function getG1Curve() : string { return $this->G1Curve; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); foreach (['X', 'Y', 'c', 'sx', 'sy', 'G1Curve'] as $key) { array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The key "%s" is missing', $key)); } return new self(Base64UrlSafe::decode($data['X']), Base64UrlSafe::decode($data['Y']), Base64UrlSafe::decode($data['c']), Base64UrlSafe::decode($data['sx']), Base64UrlSafe::decode($data['sy']), $data['G1Curve']); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['X' => Base64UrlSafe::encodeUnpadded($this->X), 'Y' => Base64UrlSafe::encodeUnpadded($this->Y), 'c' => Base64UrlSafe::encodeUnpadded($this->c), 'sx' => Base64UrlSafe::encodeUnpadded($this->sx), 'sy' => Base64UrlSafe::encodeUnpadded($this->sy), 'G1Curve' => $this->G1Curve]; return self::filterNullValues($data); } } status, [AuthenticatorStatus::ATTESTATION_KEY_COMPROMISE, AuthenticatorStatus::USER_KEY_PHYSICAL_COMPROMISE, AuthenticatorStatus::USER_KEY_REMOTE_COMPROMISE, AuthenticatorStatus::USER_VERIFICATION_BYPASS, AuthenticatorStatus::REVOKED], \true); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getStatus() : string { return $this->status; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getEffectiveDate() : ?string { return $this->effectiveDate; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificate() : ?string { return $this->certificate; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUrl() : ?string { return $this->url; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificationDescriptor() : ?string { return $this->certificationDescriptor; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificateNumber() : ?string { return $this->certificateNumber; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificationPolicyVersion() : ?string { return $this->certificationPolicyVersion; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCertificationRequirementsVersion() : ?string { return $this->certificationRequirementsVersion; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); array_key_exists('status', $data) || throw MetadataStatementLoadingException::create('The key "status" is missing'); foreach (['effectiveDate', 'certificate', 'url', 'certificationDescriptor', 'certificateNumber', 'certificationPolicyVersion', 'certificationRequirementsVersion'] as $key) { if (isset($data[$key])) { $value = $data[$key]; $value === null || is_string($value) || throw MetadataStatementLoadingException::create(sprintf('The value of the key "%s" is invalid', $key)); } } return self::create($data['status'], $data['effectiveDate'] ?? null, $data['certificate'] ?? null, $data['url'] ?? null, $data['certificationDescriptor'] ?? null, $data['certificateNumber'] ?? null, $data['certificationPolicyVersion'] ?? null, $data['certificationRequirementsVersion'] ?? null); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['status' => $this->status, 'effectiveDate' => $this->effectiveDate, 'certificate' => $this->certificate, 'url' => $this->url, 'certificationDescriptor' => $this->certificationDescriptor, 'certificateNumber' => $this->certificateNumber, 'certificationPolicyVersion' => $this->certificationPolicyVersion, 'certificationRequirementsVersion' => $this->certificationRequirementsVersion]; return self::filterNullValues($data); } } = 0 || throw MetadataStatementLoadingException::create('The parameter "userVerificationMethod" is invalid'); } public static function create(string $userVerificationMethod, ?CodeAccuracyDescriptor $caDesc = null, ?BiometricAccuracyDescriptor $baDesc = null, ?PatternAccuracyDescriptor $paDesc = null) : self { return new self($userVerificationMethod, $caDesc, $baDesc, $paDesc); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUserVerificationMethod() : string { return $this->userVerificationMethod; } public function userPresence() : bool { return $this->userVerificationMethod === self::USER_VERIFY_PRESENCE_INTERNAL; } public function fingerprint() : bool { return $this->userVerificationMethod === self::USER_VERIFY_FINGERPRINT_INTERNAL; } public function passcodeInternal() : bool { return $this->userVerificationMethod === self::USER_VERIFY_PASSCODE_INTERNAL; } public function voicePrint() : bool { return $this->userVerificationMethod === self::USER_VERIFY_VOICEPRINT_INTERNAL; } public function facePrint() : bool { return $this->userVerificationMethod === self::USER_VERIFY_FACEPRINT_INTERNAL; } public function location() : bool { return $this->userVerificationMethod === self::USER_VERIFY_LOCATION_INTERNAL; } public function eyePrint() : bool { return $this->userVerificationMethod === self::USER_VERIFY_EYEPRINT_INTERNAL; } public function patternInternal() : bool { return $this->userVerificationMethod === self::USER_VERIFY_PATTERN_INTERNAL; } public function handprint() : bool { return $this->userVerificationMethod === self::USER_VERIFY_HANDPRINT_INTERNAL; } public function passcodeExternal() : bool { return $this->userVerificationMethod === self::USER_VERIFY_PASSCODE_EXTERNAL; } public function patternExternal() : bool { return $this->userVerificationMethod === self::USER_VERIFY_PATTERN_EXTERNAL; } public function none() : bool { return $this->userVerificationMethod === self::USER_VERIFY_NONE; } public function all() : bool { return $this->userVerificationMethod === self::USER_VERIFY_ALL; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCaDesc() : ?CodeAccuracyDescriptor { return $this->caDesc; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getBaDesc() : ?BiometricAccuracyDescriptor { return $this->baDesc; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getPaDesc() : ?PatternAccuracyDescriptor { return $this->paDesc; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); if (isset($data['userVerification']) && !isset($data['userVerificationMethod'])) { $data['userVerificationMethod'] = $data['userVerification']; unset($data['userVerification']); } array_key_exists('userVerificationMethod', $data) || throw MetadataStatementLoadingException::create('The parameters "userVerificationMethod" is missing'); foreach (['caDesc', 'baDesc', 'paDesc'] as $key) { if (isset($data[$key])) { is_array($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('Invalid parameter "%s"', $key)); } } $caDesc = isset($data['caDesc']) ? CodeAccuracyDescriptor::createFromArray($data['caDesc']) : null; $baDesc = isset($data['baDesc']) ? BiometricAccuracyDescriptor::createFromArray($data['baDesc']) : null; $paDesc = isset($data['paDesc']) ? PatternAccuracyDescriptor::createFromArray($data['paDesc']) : null; return self::create($data['userVerificationMethod'], $caDesc, $baDesc, $paDesc); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['userVerificationMethod' => $this->userVerificationMethod, 'caDesc' => $this->caDesc, 'baDesc' => $this->baDesc, 'paDesc' => $this->paDesc]; return self::filterNullValues($data); } } $descriptions */ public function __construct(public array $descriptions = []) { } /** * @param array $descriptions */ public static function create(array $descriptions = []) : self { return new self($descriptions); } /** * @return array * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function all() : array { return $this->descriptions; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function add(string $locale, string $description) : self { $this->descriptions[$locale] = $description; return $this; } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return $this->descriptions; } } selfAttestedFRR; } /** * @deprecated since 4.7.0. Please use the property directly. */ public function getSelfAttestedFAR() : ?float { return $this->selfAttestedFAR; } /** * @deprecated since 4.7.0. Please use the property directly. */ public function getMaxTemplates() : ?float { return $this->maxTemplates; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. */ public static function createFromArray(array $data) : self { return self::create($data['selfAttestedFRR'] ?? null, $data['selfAttestedFAR'] ?? null, $data['maxTemplates'] ?? null, $data['maxRetries'] ?? null, $data['blockSlowdown'] ?? null); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['selfAttestedFRR' => $this->selfAttestedFRR, 'selfAttestedFAR' => $this->selfAttestedFAR, 'maxTemplates' => $this->maxTemplates, 'maxRetries' => $this->maxRetries, 'blockSlowdown' => $this->blockSlowdown]; return self::filterNullValues($data); } } = 0 || throw MetadataStatementLoadingException::create('Invalid argument "major"'); $minor >= 0 || throw MetadataStatementLoadingException::create('Invalid argument "minor"'); } public static function create(?int $major, ?int $minor) : self { return new self($major, $minor); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMajor() : ?int { return $this->major; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMinor() : ?int { return $this->minor; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); foreach (['major', 'minor'] as $key) { if (array_key_exists($key, $data)) { is_int($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('Invalid value for key "%s"', $key)); } } return self::create($data['major'] ?? null, $data['minor'] ?? null); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['major' => $this->major, 'minor' => $this->minor]; return self::filterNullValues($data); } } = 0 && $r <= 255 || throw MetadataStatementLoadingException::create('The key "r" is invalid'); $g >= 0 && $g <= 255 || throw MetadataStatementLoadingException::create('The key "g" is invalid'); $b >= 0 && $b <= 255 || throw MetadataStatementLoadingException::create('The key "b" is invalid'); } public static function create(int $r, int $g, int $b) : self { return new self($r, $g, $b); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getR() : int { return $this->r; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getG() : int { return $this->g; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getB() : int { return $this->b; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { foreach (['r', 'g', 'b'] as $key) { array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('The key "%s" is missing', $key)); is_int($data[$key]) || throw MetadataStatementLoadingException::create(sprintf('The key "%s" is invalid', $key)); } return self::create($data['r'], $data['g'], $data['b']); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return ['r' => $this->r, 'g' => $this->g, 'b' => $this->b]; } } sk; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getDate() : ?string { return $this->date; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { array_key_exists('sk', $data) || throw MetadataStatementLoadingException::create('The key "sk" is missing'); is_string($data['sk']) || throw MetadataStatementLoadingException::create('The key "date" is invalid'); array_key_exists('date', $data) || throw MetadataStatementLoadingException::create('The key "date" is missing'); is_string($data['date']) || throw MetadataStatementLoadingException::create('The key "date" is invalid'); return self::create($data['sk'], $data['date']); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); return ['sk' => $this->sk, 'date' => $this->date]; } } = 0 || throw MetadataStatementLoadingException::create('Invalid width'); $height >= 0 || throw MetadataStatementLoadingException::create('Invalid height'); $bitDepth >= 0 && $bitDepth <= 254 || throw MetadataStatementLoadingException::create('Invalid bit depth'); $colorType >= 0 && $colorType <= 254 || throw MetadataStatementLoadingException::create('Invalid color type'); $compression >= 0 && $compression <= 254 || throw MetadataStatementLoadingException::create('Invalid compression'); $filter >= 0 && $filter <= 254 || throw MetadataStatementLoadingException::create('Invalid filter'); $interlace >= 0 && $interlace <= 254 || throw MetadataStatementLoadingException::create('Invalid interlace'); } /** * @param RgbPaletteEntry[] $plte */ public static function create(int $width, int $height, int $bitDepth, int $colorType, int $compression, int $filter, int $interlace, array $plte = []) : self { return new self($width, $height, $bitDepth, $colorType, $compression, $filter, $interlace, $plte); } /** * @deprecated since 4.7.0. Please use {self::create} directly. * @infection-ignore-all */ public function addPalettes(RgbPaletteEntry ...$rgbPaletteEntries) : self { foreach ($rgbPaletteEntries as $rgbPaletteEntry) { $this->plte[] = $rgbPaletteEntry; } return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getWidth() : int { return $this->width; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getHeight() : int { return $this->height; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getBitDepth() : int { return $this->bitDepth; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getColorType() : int { return $this->colorType; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCompression() : int { return $this->compression; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getFilter() : int { return $this->filter; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getInterlace() : int { return $this->interlace; } /** * @return RgbPaletteEntry[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getPaletteEntries() : array { return $this->plte; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); foreach (['width', 'compression', 'height', 'bitDepth', 'colorType', 'compression', 'filter', 'interlace'] as $key) { array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The key "%s" is missing', $key)); } return self::create($data['width'], $data['height'], $data['bitDepth'], $data['colorType'], $data['compression'], $data['filter'], $data['interlace'], \array_map(static fn(array $item) => RgbPaletteEntry::createFromArray($item), $data['plte'] ?? [])); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['width' => $this->width, 'height' => $this->height, 'bitDepth' => $this->bitDepth, 'colorType' => $this->colorType, 'compression' => $this->compression, 'filter' => $this->filter, 'interlace' => $this->interlace, 'plte' => $this->plte]; return self::filterNullValues($data); } } $data * * @return array */ private static function filterNullValues(array $data) : array { return \array_filter($data, static fn($var): bool => $var !== null); } } create(); } } > */ private array $statusReports = []; private EventDispatcherInterface $dispatcher; private readonly ?SerializerInterface $serializer; /** * @param array $additionalHeaderParameters */ public function __construct(private readonly ?RequestFactoryInterface $requestFactory, private readonly ClientInterface|HttpClientInterface $httpClient, private readonly string $uri, private readonly array $additionalHeaderParameters = [], private readonly ?CertificateChainValidator $certificateChainValidator = null, private readonly ?string $rootCertificateUri = null, ?SerializerInterface $serializer = null) { if ($requestFactory !== null && !$httpClient instanceof HttpClientInterface) { \trigger_deprecation('web-auth/metadata-service', '4.7.0', 'The parameter "$requestFactory" will be removed in 5.0.0. Please set it to null and set an Symfony\\Contracts\\HttpClient\\HttpClientInterface as "$httpClient" argument.'); } $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } /** * @param array $additionalHeaderParameters */ public static function create(?RequestFactoryInterface $requestFactory, ClientInterface|HttpClientInterface $httpClient, string $uri, array $additionalHeaderParameters = [], ?CertificateChainValidator $certificateChainValidator = null, ?string $rootCertificateUri = null, ?SerializerInterface $serializer = null) : self { return new self($requestFactory, $httpClient, $uri, $additionalHeaderParameters, $certificateChainValidator, $rootCertificateUri, $serializer); } /** * @return string[] */ public function list() : iterable { $this->loadData(); yield from \array_keys($this->statements); } public function has(string $aaguid) : bool { $this->loadData(); return array_key_exists($aaguid, $this->statements); } public function get(string $aaguid) : MetadataStatement { $this->loadData(); array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid); $mds = $this->statements[$aaguid]; $this->dispatcher->dispatch(MetadataStatementFound::create($mds)); return $mds; } /** * @return StatusReport[] */ public function getStatusReports(string $aaguid) : iterable { $this->loadData(); return $this->statusReports[$aaguid] ?? []; } private function loadData() : void { if ($this->loaded) { return; } $content = $this->fetch($this->uri, $this->additionalHeaderParameters); $jwtCertificates = []; try { $payload = $this->getJwsPayload($content, $jwtCertificates); $this->validateCertificates(...$jwtCertificates); if ($this->serializer !== null) { $blob = $this->serializer->deserialize($payload, MetadataBLOBPayload::class, 'json'); foreach ($blob->entries as $entry) { $mds = $entry->metadataStatement; if ($mds !== null && $entry->aaguid !== null) { $this->statements[$entry->aaguid] = $mds; $this->statusReports[$entry->aaguid] = $entry->statusReports; } } $this->loaded = \true; return; } $data = \json_decode($payload, \true, flags: JSON_THROW_ON_ERROR); foreach ($data['entries'] as $datum) { $entry = MetadataBLOBPayloadEntry::createFromArray($datum); $mds = $entry->metadataStatement; if ($mds !== null && $entry->aaguid !== null) { $this->statements[$entry->aaguid] = $mds; $this->statusReports[$entry->aaguid] = $entry->statusReports; } } } catch (Throwable) { // Nothing to do } $this->loaded = \true; } /** * @param array $headerParameters */ private function fetch(string $uri, array $headerParameters) : string { if ($this->httpClient instanceof HttpClientInterface) { $content = $this->sendSymfonyRequest($uri, $headerParameters); } else { $content = $this->sendPsrRequest($uri, $headerParameters); } $content !== '' || throw MetadataStatementLoadingException::create('Unable to contact the server. The response has no content'); return $content; } /** * @param string[] $rootCertificates */ private function getJwsPayload(string $token, array &$rootCertificates) : string { $jws = (new CompactSerializer())->unserialize($token); $jws->countSignatures() === 1 || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. Only one signature shall be present.'); $signature = $jws->getSignature(0); $payload = $jws->getPayload(); $payload !== '' || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. The token payload is empty.'); $header = $signature->getProtectedHeader(); array_key_exists('alg', $header) || throw MetadataStatementLoadingException::create('The "alg" parameter is missing.'); array_key_exists('x5c', $header) || throw MetadataStatementLoadingException::create('The "x5c" parameter is missing.'); is_array($header['x5c']) || throw MetadataStatementLoadingException::create('The "x5c" parameter should be an array.'); $key = JWKFactory::createFromX5C($header['x5c']); $rootCertificates = $header['x5c']; $verifier = new JWSVerifier(new AlgorithmManager([new ES256(), new RS256()])); $isValid = $verifier->verifyWithKey($jws, $key, 0); $isValid || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. The token signature is invalid.'); $payload = $jws->getPayload(); $payload !== null || throw MetadataStatementLoadingException::create('Invalid response from the metadata service. The payload is missing.'); return $payload; } private function validateCertificates(string ...$untrustedCertificates) : void { if ($this->certificateChainValidator === null || $this->rootCertificateUri === null) { return; } $untrustedCertificates = CertificateToolbox::fixPEMStructures($untrustedCertificates); $rootCertificate = CertificateToolbox::convertDERToPEM($this->fetch($this->rootCertificateUri, [])); $this->certificateChainValidator->check($untrustedCertificates, [$rootCertificate]); } /** * @param array $headerParameters */ private function sendPsrRequest(string $uri, array $headerParameters) : string { $request = $this->requestFactory->createRequest('GET', $uri); foreach ($headerParameters as $k => $v) { $request = $request->withHeader($k, $v); } $response = $this->httpClient->sendRequest($request); $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); $response->getBody()->rewind(); return $response->getBody()->getContents(); } /** * @param array $headerParameters */ private function sendSymfonyRequest(string $uri, array $headerParameters) : string { $response = $this->httpClient->request('GET', $uri, ['headers' => $headerParameters]); $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); return $response->getContent(); } } dispatcher = new NullEventDispatcher(); $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create(); foreach ($statements as $statement) { $this->addStatement($statement); } } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public function list() : iterable { yield from \array_keys($this->statements); } public function has(string $aaguid) : bool { return array_key_exists($aaguid, $this->statements); } public function get(string $aaguid) : MetadataStatement { array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid); $mds = $this->statements[$aaguid]; $this->dispatcher->dispatch(MetadataStatementFound::create($mds)); return $mds; } private function addStatement(string $statement) : void { if ($this->serializer === null) { $mds = MetadataStatement::createFromString($statement); } else { $mds = $this->serializer->deserialize($statement, MetadataStatement::class, 'json'); } if ($mds->aaguid === null) { return; } $this->statements[$mds->aaguid] = $mds; } } addStatements(MetadataStatement::createFromString($statement)); } $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create(string ...$statements) : self { return new self(...$statements); } public function addStatements(MetadataStatement ...$statements) : self { foreach ($statements as $statement) { $aaguid = $statement->aaguid; if ($aaguid === null) { continue; } $this->statements[$aaguid] = $statement; } return $this; } public function list() : iterable { yield from \array_keys($this->statements); } public function has(string $aaguid) : bool { return array_key_exists($aaguid, $this->statements); } public function get(string $aaguid) : MetadataStatement { array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid); $mds = $this->statements[$aaguid]; $this->dispatcher->dispatch(MetadataStatementFound::create($mds)); return $mds; } } aaid; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAaguid() : ?string { return $this->aaguid; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttestationCertificateKeyIdentifiers() : array { return $this->attestationCertificateKeyIdentifiers; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getMetadataStatement() : ?MetadataStatement { return $this->metadataStatement; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function addBiometricStatusReports(BiometricStatusReport ...$biometricStatusReports) : self { foreach ($biometricStatusReports as $biometricStatusReport) { $this->biometricStatusReports[] = $biometricStatusReport; } return $this; } /** * @return BiometricStatusReport[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getBiometricStatusReports() : array { return $this->biometricStatusReports; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function addStatusReports(StatusReport ...$statusReports) : self { foreach ($statusReports as $statusReport) { $this->statusReports[] = $statusReport; } return $this; } /** * @return StatusReport[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getStatusReports() : array { return $this->statusReports; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTimeOfLastStatusChange() : string { return $this->timeOfLastStatusChange; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRogueListURL() : string|null { return $this->rogueListURL; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRogueListHash() : string|null { return $this->rogueListHash; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); array_key_exists('timeOfLastStatusChange', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "timeOfLastStatusChange" is missing'); array_key_exists('statusReports', $data) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "statusReports" is missing'); is_array($data['statusReports']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "statusReports" shall be an array of StatusReport objects'); return new self($data['timeOfLastStatusChange'], \array_map(static fn(array $statusReport) => StatusReport::createFromArray($statusReport), $data['statusReports']), $data['aaid'] ?? null, $data['aaguid'] ?? null, $data['attestationCertificateKeyIdentifiers'] ?? [], isset($data['metadataStatement']) ? MetadataStatement::createFromArray($data['metadataStatement']) : null, $data['rogueListURL'] ?? null, $data['rogueListHash'] ?? null, \array_map(static fn(array $biometricStatusReport) => BiometricStatusReport::createFromArray($biometricStatusReport), $data['biometricStatusReports'] ?? [])); } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['aaid' => $this->aaid, 'aaguid' => $this->aaguid, 'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, 'statusReports' => $this->statusReports, 'timeOfLastStatusChange' => $this->timeOfLastStatusChange, 'rogueListURL' => $this->rogueListURL, 'rogueListHash' => $this->rogueListHash]; return self::filterNullValues($data); } } $additionalHeaderParameters */ public function __construct(private readonly ?RequestFactoryInterface $requestFactory, private readonly ClientInterface|HttpClientInterface $httpClient, private readonly string $uri, private readonly bool $isBase64Encoded = \false, private readonly array $additionalHeaderParameters = [], ?SerializerInterface $serializer = null) { if ($requestFactory !== null && !$httpClient instanceof HttpClientInterface) { \trigger_deprecation('web-auth/metadata-service', '4.7.0', 'The parameter "$requestFactory" will be removed in 5.0.0. Please set it to null and set an Symfony\\Contracts\\HttpClient\\HttpClientInterface as "$httpClient" argument.'); } $this->serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create(); $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } /** * @param array $additionalHeaderParameters */ public static function create(?RequestFactoryInterface $requestFactory, ClientInterface|HttpClientInterface $httpClient, string $uri, bool $isBase64Encoded = \false, array $additionalHeaderParameters = [], ?SerializerInterface $serializer = null) : self { return new self($requestFactory, $httpClient, $uri, $isBase64Encoded, $additionalHeaderParameters, $serializer); } public function list() : iterable { $this->loadData(); $this->statement !== null || throw MetadataStatementLoadingException::create(); $aaguid = $this->statement->aaguid; if ($aaguid === null) { yield from []; } else { yield from [$aaguid]; } } public function has(string $aaguid) : bool { $this->loadData(); $this->statement !== null || throw MetadataStatementLoadingException::create(); return $aaguid === $this->statement->aaguid; } public function get(string $aaguid) : MetadataStatement { $this->loadData(); $this->statement !== null || throw MetadataStatementLoadingException::create(); if ($aaguid === $this->statement->aaguid) { $this->dispatcher->dispatch(MetadataStatementFound::create($this->statement)); return $this->statement; } throw MissingMetadataStatementException::create($aaguid); } private function loadData() : void { if ($this->statement !== null) { return; } $content = $this->fetch(); if ($this->isBase64Encoded) { $content = Base64::decode($content, \true); } if ($this->serializer !== null) { $this->statement = $this->serializer->deserialize($content, MetadataStatement::class, 'json'); return; } $this->statement = MetadataStatement::createFromString($content); } private function fetch() : string { if ($this->httpClient instanceof HttpClientInterface) { $content = $this->sendSymfonyRequest(); } else { $content = $this->sendPsrRequest(); } $content !== '' || throw MetadataStatementLoadingException::create('Unable to contact the server. The response has no content'); return $content; } private function sendPsrRequest() : string { $request = $this->requestFactory->createRequest('GET', $this->uri); foreach ($this->additionalHeaderParameters as $k => $v) { $request = $request->withHeader($k, $v); } $response = $this->httpClient->sendRequest($request); $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); $response->getBody()->rewind(); return $response->getBody()->getContents(); } private function sendSymfonyRequest() : string { $response = $this->httpClient->request('GET', $this->uri, ['headers' => $this->additionalHeaderParameters]); $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); return $response->getContent(); } } entries[] = $entry; return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getLegalHeader() : ?string { return $this->legalHeader; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getNo() : int { return $this->no; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getNextUpdate() : string { return $this->nextUpdate; } /** * @return MetadataBLOBPayloadEntry[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getEntries() : array { return $this->entries; } /** * @param array $data * @deprecated since 4.7.0. Please use the symfony/serializer for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $data = self::filterNullValues($data); foreach (['no', 'nextUpdate', 'entries'] as $key) { array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf('Invalid data. The parameter "%s" is missing', $key)); } is_int($data['no']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "no" shall be an integer'); is_string($data['nextUpdate']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "nextUpdate" shall be a string'); is_array($data['entries']) || throw MetadataStatementLoadingException::create('Invalid data. The parameter "entries" shall be a n array of entries'); $object = new self($data['no'], $data['nextUpdate'], $data['legalHeader'] ?? null); foreach ($data['entries'] as $entry) { $object->entries[] = MetadataBLOBPayloadEntry::createFromArray($entry); } return $object; } /** * @return array */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $data = ['legalHeader' => $this->legalHeader, 'nextUpdate' => $this->nextUpdate, 'no' => $this->no, 'entries' => $this->entries]; return self::filterNullValues($data); } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRootCertificates() : array { return $this->rootCertificates; } /** * @param string[] $rootCertificates * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setRootCertificates(array $rootCertificates) : self { $this->rootCertificates = $rootCertificates; return $this; } } serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create(); $this->dispatcher = new NullEventDispatcher(); } public static function create(string $filename, bool $isBase64Encoded = \false, ?SerializerInterface $serializer = null) : self { return new self($filename, $isBase64Encoded, $serializer); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public function list() : iterable { $this->loadData(); $this->statement !== null || throw MetadataStatementLoadingException::create(); $aaguid = $this->statement->aaguid; if ($aaguid === null) { yield from []; } else { yield from [$aaguid]; } } public function has(string $aaguid) : bool { $this->loadData(); $this->statement !== null || throw MetadataStatementLoadingException::create(); return $aaguid === $this->statement->aaguid; } public function get(string $aaguid) : MetadataStatement { $this->loadData(); $this->statement !== null || throw MetadataStatementLoadingException::create(); if ($aaguid === $this->statement->aaguid) { $this->dispatcher->dispatch(MetadataStatementFound::create($this->statement)); return $this->statement; } throw MissingMetadataStatementException::create($aaguid); } private function loadData() : void { if ($this->statement !== null) { return; } $content = file_get_contents($this->filename); if ($this->isBase64Encoded) { $content = Base64::decode($content, \true); } if ($this->serializer !== null) { $this->statement = $this->serializer->deserialize($content, MetadataStatement::class, 'json'); } else { $this->statement = MetadataStatement::createFromString($content); } } } addServices($service); } } public static function create(MetadataService ...$services) : self { return new self(...$services); } public function addServices(MetadataService ...$services) : self { foreach ($services as $service) { $this->services[] = $service; } return $this; } public function list() : iterable { foreach ($this->services as $service) { yield from $service->list(); } } public function has(string $aaguid) : bool { foreach ($this->services as $service) { if ($service->has($aaguid)) { return \true; } } return \false; } public function get(string $aaguid) : MetadataStatement { foreach ($this->services as $service) { if ($service->has($aaguid)) { return $service->get($aaguid); } } throw MissingMetadataStatementException::create($aaguid); } } serializer = $serializer ?? (new WebauthnSerializerFactory(AttestationStatementSupportManager::create()))->create(); $this->rootPath = \rtrim($rootPath, DIRECTORY_SEPARATOR); \is_dir($this->rootPath) || throw new InvalidArgumentException('The given parameter is not a valid folder.'); \is_readable($this->rootPath) || throw new InvalidArgumentException('The given parameter is not a valid folder.'); } public static function create(string $rootPath, ?SerializerInterface $serializer = null) : self { return new self($rootPath, $serializer); } public function list() : iterable { $files = \glob($this->rootPath . DIRECTORY_SEPARATOR . '*'); is_array($files) || throw MetadataStatementLoadingException::create('Unable to read files.'); foreach ($files as $file) { if (\is_dir($file) || !\is_readable($file)) { continue; } (yield \basename($file)); } } public function has(string $aaguid) : bool { $filename = $this->rootPath . DIRECTORY_SEPARATOR . $aaguid; return \is_file($filename) && \is_readable($filename); } public function get(string $aaguid) : MetadataStatement { $this->has($aaguid) || throw new InvalidArgumentException(sprintf('The MDS with the AAGUID "%s" does not exist.', $aaguid)); $filename = $this->rootPath . DIRECTORY_SEPARATOR . $aaguid; $data = \trim(file_get_contents($filename)); if ($this->serializer !== null) { $mds = $this->serializer->deserialize($data, MetadataStatement::class, 'json'); } else { $mds = MetadataStatement::createFromString($data); } $mds->aaguid !== null || throw MetadataStatementLoadingException::create('Invalid Metadata Statement.'); return $mds; } } addStatements($statement); } $this->dispatcher = new NullEventDispatcher(); } public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) : void { $this->dispatcher = $eventDispatcher; } public static function create(MetadataStatement ...$statements) : self { return new self(...$statements); } public function addStatements(MetadataStatement ...$statements) : self { foreach ($statements as $statement) { $aaguid = $statement->aaguid; if ($aaguid === null) { continue; } $this->statements[$aaguid] = $statement; } return $this; } public function list() : iterable { yield from \array_keys($this->statements); } public function has(string $aaguid) : bool { return array_key_exists($aaguid, $this->statements); } public function get(string $aaguid) : MetadataStatement { array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid); $mds = $this->statements[$aaguid]; $this->dispatcher->dispatch(MetadataStatementFound::create($mds)); return $mds; } } residentKey === null && $this->requireResidentKey === \true) { $this->residentKey = self::RESIDENT_KEY_REQUIREMENT_REQUIRED; } $this->requireResidentKey = $requireResidentKey ?? ($residentKey === null ? null : $residentKey === self::RESIDENT_KEY_REQUIREMENT_REQUIRED); } public static function create(?string $authenticatorAttachment = null, string $userVerification = self::USER_VERIFICATION_REQUIREMENT_PREFERRED, null|string $residentKey = self::RESIDENT_KEY_REQUIREMENT_NO_PREFERENCE, null|bool $requireResidentKey = null) : self { return new self($authenticatorAttachment, $userVerification, $residentKey, $requireResidentKey); } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function setAuthenticatorAttachment(?string $authenticatorAttachment) : self { $this->authenticatorAttachment = $authenticatorAttachment; return $this; } /** * @deprecated since v4.1. Please use the {self::create} instead. * @infection-ignore-all */ public function setRequireResidentKey(bool $requireResidentKey) : self { $this->requireResidentKey = $requireResidentKey; if ($requireResidentKey === \true) { $this->residentKey = self::RESIDENT_KEY_REQUIREMENT_REQUIRED; } return $this; } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function setUserVerification(string $userVerification) : self { $this->userVerification = $userVerification; return $this; } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function setResidentKey(null|string $residentKey) : self { $this->residentKey = $residentKey; $this->requireResidentKey = $residentKey === self::RESIDENT_KEY_REQUIREMENT_REQUIRED; return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAuthenticatorAttachment() : ?string { return $this->authenticatorAttachment; } /** * @deprecated Will be removed in 5.0. Please use the property directly. * @infection-ignore-all */ public function isRequireResidentKey() : bool { return $this->requireResidentKey; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUserVerification() : string { return $this->userVerification; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getResidentKey() : null|string { return $this->residentKey; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromString(string $data) : self { $data = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); return self::createFromArray($data); } /** * @param mixed[] $json * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $json) : self { $authenticatorAttachment = $json['authenticatorAttachment'] ?? null; $requireResidentKey = $json['requireResidentKey'] ?? null; $userVerification = $json['userVerification'] ?? self::USER_VERIFICATION_REQUIREMENT_PREFERRED; $residentKey = $json['residentKey'] ?? null; $authenticatorAttachment === null || is_string($authenticatorAttachment) || throw InvalidDataException::create($json, 'Invalid "authenticatorAttachment" value'); $requireResidentKey === null || is_bool($requireResidentKey) || throw InvalidDataException::create($json, 'Invalid "requireResidentKey" value'); is_string($userVerification) || throw InvalidDataException::create($json, 'Invalid "userVerification" value'); $residentKey === null || is_string($residentKey) || throw InvalidDataException::create($json, 'Invalid "residentKey" value'); return self::create($authenticatorAttachment ?? null, $userVerification, $residentKey, $requireResidentKey); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $json = ['requireResidentKey' => $this->requireResidentKey, 'userVerification' => $this->userVerification, 'residentKey' => $this->residentKey, 'authenticatorAttachment' => $this->authenticatorAttachment]; foreach ($json as $key => $value) { if ($value === null) { unset($json[$key]); } } return $json; } } $untrustedCertificates * @param array $trustedCertificates */ public function __construct(public readonly array $untrustedCertificates, public readonly array $trustedCertificates, string $message, ?Throwable $previous = null) { parent::__construct($message, $previous); } /** * @param array $untrustedCertificates * @param array $trustedCertificates */ public static function create(array $untrustedCertificates, array $trustedCertificates, string $message = 'Unable to validate the certificate chain.', ?Throwable $previous = null) : self { return new self($untrustedCertificates, $trustedCertificates, $message, $previous); } } $attestation */ public function __construct(public readonly array $attestation, string $message, ?Throwable $previous = null) { parent::__construct($message, $previous); } /** * @param array $attestation */ public static function create(array $attestation, string $message = 'Invalid attestation object', ?Throwable $previous = null) : self { return new self($attestation, $message, $previous); } } __toString(); } } authenticatorAttestationResponse; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getPublicKeyCredentialCreationOptions() : PublicKeyCredentialCreationOptions { return $this->publicKeyCredentialCreationOptions; } /** * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead * @infection-ignore-all */ public function getRequest() : ServerRequestInterface|string { return $this->host; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getPublicKeyCredentialSource() : PublicKeyCredentialSource { return $this->publicKeyCredentialSource; } } credentialId !== null) { \trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'The argument "$credentialId" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set null instead.'); } } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getCredentialId() : string { return $this->publicKeyCredentialSource->publicKeyCredentialId; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getAuthenticatorAssertionResponse() : AuthenticatorAssertionResponse { return $this->authenticatorAssertionResponse; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getPublicKeyCredentialRequestOptions() : PublicKeyCredentialRequestOptions { return $this->publicKeyCredentialRequestOptions; } /** * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead * @infection-ignore-all */ public function getRequest() : ServerRequestInterface|string { return $this->host; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getUserHandle() : ?string { return $this->userHandle; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getPublicKeyCredentialSource() : PublicKeyCredentialSource { return $this->publicKeyCredentialSource; } } credentialId instanceof PublicKeyCredentialSource) { \trigger_deprecation('web-auth/webauthn-lib', '4.6.0', 'Passing a string for the argument "$credentialId" is deprecated since 4.6.0. Please set the PublicKeyCredentialSource instead.'); } } /** * @deprecated since 4.7.0 and will be removed in 5.0.0. Please use the `getCredential()` method instead * @infection-ignore-all */ public function getCredentialId() : string { return $this->credentialId instanceof PublicKeyCredentialSource ? $this->credentialId->publicKeyCredentialId : $this->credentialId; } public function getCredential() : ?PublicKeyCredentialSource { return $this->credentialId instanceof PublicKeyCredentialSource ? $this->credentialId : null; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getAuthenticatorAssertionResponse() : AuthenticatorAssertionResponse { return $this->authenticatorAssertionResponse; } public function getPublicKeyCredentialRequestOptions() : PublicKeyCredentialRequestOptions { return $this->publicKeyCredentialRequestOptions; } /** * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead * @infection-ignore-all */ public function getRequest() : ServerRequestInterface|string { return $this->host; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getUserHandle() : ?string { return $this->userHandle; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getThrowable() : Throwable { return $this->throwable; } } authenticatorAttestationResponse; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getPublicKeyCredentialCreationOptions() : PublicKeyCredentialCreationOptions { return $this->publicKeyCredentialCreationOptions; } /** * @deprecated since 4.5.0 and will be removed in 5.0.0. Please use the `host` property instead * @infection-ignore-all */ public function getRequest() : ServerRequestInterface|string { return $this->host; } /** * @deprecated since 4.8.0. Will be removed in 5.0.0. Please use the property instead. */ public function getThrowable() : Throwable { return $this->throwable; } } |null $otherUI */ public function __construct(public string $publicKeyCredentialId, public string $type, public array $transports, public string $attestationType, public TrustPath $trustPath, public Uuid $aaguid, public string $credentialPublicKey, public string $userHandle, public int $counter, public ?array $otherUI = null, public ?bool $backupEligible = null, public ?bool $backupStatus = null, public ?bool $uvInitialized = null) { } /** * @param string[] $transports * @param array|null $otherUI */ public static function create(string $publicKeyCredentialId, string $type, array $transports, string $attestationType, TrustPath $trustPath, Uuid $aaguid, string $credentialPublicKey, string $userHandle, int $counter, ?array $otherUI = null, ?bool $backupEligible = null, ?bool $backupStatus = null, ?bool $uvInitialized = null) : self { return new self($publicKeyCredentialId, $type, $transports, $attestationType, $trustPath, $aaguid, $credentialPublicKey, $userHandle, $counter, $otherUI, $backupEligible, $backupStatus, $uvInitialized); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getPublicKeyCredentialId() : string { return $this->publicKeyCredentialId; } public function getPublicKeyCredentialDescriptor() : PublicKeyCredentialDescriptor { return PublicKeyCredentialDescriptor::create($this->type, $this->publicKeyCredentialId, $this->transports); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttestationType() : string { return $this->attestationType; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTrustPath() : TrustPath { return $this->trustPath; } public function getAttestedCredentialData() : AttestedCredentialData { return AttestedCredentialData::create($this->aaguid, $this->publicKeyCredentialId, $this->credentialPublicKey); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getType() : string { return $this->type; } /** * @return string[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getTransports() : array { return $this->transports; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAaguid() : Uuid { return $this->aaguid; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCredentialPublicKey() : string { return $this->credentialPublicKey; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUserHandle() : string { return $this->userHandle; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCounter() : int { return $this->counter; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setCounter(int $counter) : void { $this->counter = $counter; } /** * @return array|null * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getOtherUI() : ?array { return $this->otherUI; } /** * @param array|null $otherUI * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function setOtherUI(?array $otherUI) : self { $this->otherUI = $otherUI; return $this; } /** * @param mixed[] $data * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $data) : self { $keys = \array_keys(\get_class_vars(self::class)); foreach ($keys as $key) { if (in_array($key, ['otherUI', 'backupEligible', 'backupStatus', 'uvInitialized'], \true)) { continue; } array_key_exists($key, $data) || throw InvalidDataException::create($data, sprintf('The parameter "%s" is missing', $key)); } \mb_strlen((string) $data['aaguid'], '8bit') === 36 || throw InvalidDataException::create($data, 'Invalid AAGUID'); $uuid = Uuid::fromString($data['aaguid']); try { return self::create(Base64UrlSafe::decodeNoPadding($data['publicKeyCredentialId']), $data['type'], $data['transports'], $data['attestationType'], TrustPathLoader::loadTrustPath($data['trustPath']), $uuid, Base64UrlSafe::decodeNoPadding($data['credentialPublicKey']), Base64UrlSafe::decodeNoPadding($data['userHandle']), $data['counter'], $data['otherUI'] ?? null, $data['backupEligible'] ?? null, $data['backupStatus'] ?? null); } catch (Throwable $throwable) { throw InvalidDataException::create($data, 'Unable to load the data', $throwable); } } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $result = ['publicKeyCredentialId' => Base64UrlSafe::encodeUnpadded($this->publicKeyCredentialId), 'type' => $this->type, 'transports' => $this->transports, 'attestationType' => $this->attestationType, 'trustPath' => $this->trustPath, 'aaguid' => $this->aaguid->__toString(), 'credentialPublicKey' => Base64UrlSafe::encodeUnpadded($this->credentialPublicKey), 'userHandle' => Base64UrlSafe::encodeUnpadded($this->userHandle), 'counter' => $this->counter, 'otherUI' => $this->otherUI, 'backupEligible' => $this->backupEligible, 'backupStatus' => $this->backupStatus, 'uvInitialized' => $this->uvInitialized]; return \array_filter($result, static fn($value): bool => $value !== null); } } pubKeyCredParams[] = $pubKeyCredParam; return $this; } /** * @deprecated since 4.7.0. No replacement. Please use the {self::create} instead. * @infection-ignore-all */ public function addPubKeyCredParams(PublicKeyCredentialParameters ...$pubKeyCredParams) : self { foreach ($pubKeyCredParams as $pubKeyCredParam) { $this->pubKeyCredParams[] = $pubKeyCredParam; } return $this; } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function excludeCredential(PublicKeyCredentialDescriptor $excludeCredential) : self { $this->excludeCredentials[] = $excludeCredential; return $this; } /** * @deprecated since 4.7.0. No replacement. Please use the {self::create} instead. * @infection-ignore-all */ public function excludeCredentials(PublicKeyCredentialDescriptor ...$excludeCredentials) : self { foreach ($excludeCredentials as $excludeCredential) { $this->excludeCredentials[] = $excludeCredential; } return $this; } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function setAuthenticatorSelection(?AuthenticatorSelectionCriteria $authenticatorSelection) : self { $this->authenticatorSelection = $authenticatorSelection; return $this; } /** * @deprecated since 4.7.0. Please use the {self::create} instead. * @infection-ignore-all */ public function setAttestation(string $attestation) : self { in_array($attestation, self::ATTESTATION_CONVEYANCE_PREFERENCES, \true) || throw InvalidDataException::create($attestation, 'Invalid attestation conveyance mode'); $this->attestation = $attestation; return $this; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRp() : PublicKeyCredentialRpEntity { return $this->rp; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getUser() : PublicKeyCredentialUserEntity { return $this->user; } /** * @return PublicKeyCredentialParameters[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getPubKeyCredParams() : array { return $this->pubKeyCredParams; } /** * @return PublicKeyCredentialDescriptor[] * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getExcludeCredentials() : array { return $this->excludeCredentials; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAuthenticatorSelection() : ?AuthenticatorSelectionCriteria { return $this->authenticatorSelection; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getAttestation() : ?string { return $this->attestation; } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromString(string $data) : static { $data = \json_decode($data, \true, flags: JSON_THROW_ON_ERROR); return self::createFromArray($data); } /** * @deprecated since 4.8.0. Please use {Webauthn\Denormalizer\WebauthnSerializerFactory} for converting the object. * @infection-ignore-all */ public static function createFromArray(array $json) : static { array_key_exists('rp', $json) || throw InvalidDataException::create($json, 'Invalid input. "rp" is missing.'); array_key_exists('pubKeyCredParams', $json) || throw InvalidDataException::create($json, 'Invalid input. "pubKeyCredParams" is missing.'); is_array($json['pubKeyCredParams']) || throw InvalidDataException::create($json, 'Invalid input. "pubKeyCredParams" is not an array.'); array_key_exists('challenge', $json) || throw InvalidDataException::create($json, 'Invalid input. "challenge" is missing.'); array_key_exists('attestation', $json) || throw InvalidDataException::create($json, 'Invalid input. "attestation" is missing.'); array_key_exists('user', $json) || throw InvalidDataException::create($json, 'Invalid input. "user" is missing.'); $pubKeyCredParams = []; foreach ($json['pubKeyCredParams'] as $pubKeyCredParam) { if (!is_array($pubKeyCredParam)) { continue; } $pubKeyCredParams[] = PublicKeyCredentialParameters::createFromArray($pubKeyCredParam); } $excludeCredentials = []; if (isset($json['excludeCredentials'])) { foreach ($json['excludeCredentials'] as $excludeCredential) { $excludeCredentials[] = PublicKeyCredentialDescriptor::createFromArray($excludeCredential); } } $challenge = Base64::decode($json['challenge']); $authenticatorSelection = isset($json['authenticatorSelection']) ? AuthenticatorSelectionCriteria::createFromArray($json['authenticatorSelection']) : null; $extensions = isset($json['extensions']) ? AuthenticationExtensionsClientInputs::createFromArray($json['extensions']) : AuthenticationExtensionsClientInputs::create(); return self::create(PublicKeyCredentialRpEntity::createFromArray($json['rp']), PublicKeyCredentialUserEntity::createFromArray($json['user']), $challenge, $pubKeyCredParams, $authenticatorSelection, $json['attestation'] ?? null, $excludeCredentials, $json['timeout'] ?? null, $extensions); } /** * @return mixed[] */ public function jsonSerialize() : array { \trigger_deprecation('web-auth/webauthn-bundle', '4.9.0', 'The "%s" method is deprecated and will be removed in 5.0. Please use the serializer instead.', __METHOD__); $json = ['rp' => $this->rp, 'user' => $this->user, 'challenge' => Base64UrlSafe::encodeUnpadded($this->challenge), 'pubKeyCredParams' => $this->pubKeyCredParams]; if ($this->timeout !== null) { $json['timeout'] = $this->timeout; } if (count($this->excludeCredentials) !== 0) { $json['excludeCredentials'] = $this->excludeCredentials; } if ($this->authenticatorSelection !== null) { $json['authenticatorSelection'] = $this->authenticatorSelection; } if ($this->attestation !== null) { $json['attestation'] = $this->attestation; } if ($this->extensions->count() !== 0) { $json['extensions'] = $this->extensions; } return $json; } } type = $type; $challenge = $data['challenge'] ?? ''; is_string($challenge) || throw InvalidDataException::create($data, 'Invalid parameter "challenge". Shall be a string.'); $challenge = Base64UrlSafe::decodeNoPadding($challenge); $challenge !== '' || throw InvalidDataException::create($data, 'Invalid parameter "challenge". Shall not be empty.'); $this->challenge = $challenge; $origin = $data['origin'] ?? ''; is_string($origin) && $origin !== '' || throw InvalidDataException::create($data, 'Invalid parameter "origin". Shall be a non-empty string.'); $this->origin = $origin; $this->topOrigin = $data['topOrigin'] ?? null; $this->crossOrigin = $data['crossOrigin'] ?? \false; $tokenBinding = $data['tokenBinding'] ?? null; $tokenBinding === null || is_array($tokenBinding) || throw InvalidDataException::create($data, 'Invalid parameter "tokenBinding". Shall be an object or .'); $this->tokenBinding = $tokenBinding; $this->data = $data; } /** * @param mixed[] $data */ public static function create(string $rawData, array $data) : self { return new self($rawData, $data); } public static function createFormJson(string $data) : self { $rawData = Base64UrlSafe::decodeNoPadding($data); $json = \json_decode($rawData, \true, flags: JSON_THROW_ON_ERROR); is_array($json) || throw InvalidDataException::create($data, 'Invalid JSON data.'); return self::create($rawData, $json); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getType() : string { return $this->type; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getChallenge() : string { return $this->challenge; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getOrigin() : string { return $this->origin; } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getCrossOrigin() : bool { return $this->crossOrigin; } /** * @deprecated Since 4.3.0 and will be removed in 5.0.0 * @infection-ignore-all */ public function getTokenBinding() : ?TokenBinding { return $this->tokenBinding === null ? null : TokenBinding::createFormArray($this->tokenBinding); } /** * @deprecated since 4.7.0. Please use the property directly. * @infection-ignore-all */ public function getRawData() : string { return $this->rawData; } /** * @return string[] */ public function all() : array { return \array_keys($this->data); } public function has(string $key) : bool { return array_key_exists($key, $this->data); } public function get(string $key) : mixed { if (!$this->has($key)) { throw InvalidDataException::create($this->data, sprintf('The key "%s" is missing', $key)); } return $this->data[$key]; } } MIT License Copyright (c) 2018 Spomky-Labs 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. COSE Support for PHP ==================== **CBOR Object Signing and Encryption (COSE) Support for PHP** is a **PHP library** that will help you to perform cypher operations using Cose Keys. ![Build Status](https://github.com/web-auth/cose-lib/workflows/Integrate/badge.svg) [![Latest Stable Version](https://poser.pugx.org/web-auth/cose-lib/v/stable.png)](https://packagist.org/packages/web-auth/cose-lib) [![Total Downloads](https://poser.pugx.org/web-auth/cose-lib/downloads.png)](https://packagist.org/packages/web-auth/cose-lib) [![Latest Unstable Version](https://poser.pugx.org/web-auth/cose-lib/v/unstable.png)](https://packagist.org/packages/web-auth/cose-lib) [![License](https://poser.pugx.org/web-auth/cose-lib/license.png)](https://packagist.org/packages/web-auth/cose-lib) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/web-auth/cose-lib/badge)](https://api.securityscorecards.dev/projects/github.com/web-auth/cose-lib) # Installation Install the library with Composer: `composer require web-auth/cose-lib`. # How to use *To be written* # Support I bring solutions to your problems and answer your questions. If you really love that project, and the work I have done or if you want I prioritize your issues, then you can help me out for a couple of :beers: or more! [Become a sponsor](https://github.com/sponsors/Spomky) Or [![Become a Patreon](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/FlorentMorselli) # Contributing Requests for new features, bug fixed and all other ideas to make this library useful are welcome. [Please follow these best practices](doc/Contributing.md). If you discover a security vulnerability within the project, please **don't use the bug tracker and don't publish it publicly**. Instead, all security issues must be sent to security [at] spomky-labs.com. # Licence This software is release under [MIT licence](LICENSE). { "name": "web-auth\/cose-lib", "type": "library", "license": "MIT", "description": "CBOR Object Signing and Encryption (COSE) For PHP", "keywords": [ "COSE", "RFC8152" ], "homepage": "https:\/\/github.com\/web-auth", "authors": [ { "name": "Florent Morselli", "homepage": "https:\/\/github.com\/Spomky" }, { "name": "All contributors", "homepage": "https:\/\/github.com\/web-auth\/cose\/contributors" } ], "require": { "php": ">=8.1", "ext-json": "*", "ext-openssl": "*", "brick\/math": "^0.9|^0.10|^0.11|^0.12", "spomky-labs\/pki-framework": "^1.0" }, "autoload": { "psr-4": { "_ContaoManager\\Cose\\": "src\/" } }, "require-dev": { "infection\/infection": "^0.29", "phpstan\/phpstan": "^1.7", "phpstan\/phpstan-deprecation-rules": "^1.0", "phpstan\/phpstan-phpunit": "^1.1", "phpstan\/phpstan-strict-rules": "^1.2", "phpunit\/phpunit": "^10.1|^11.0", "rector\/rector": "^1.0", "symplify\/easy-coding-standard": "^12.0", "symfony\/phpunit-bridge": "^6.4|^7.0", "ekino\/phpstan-banned-code": "^1.0", "php-parallel-lint\/php-parallel-lint": "^1.3", "qossmic\/deptrac": "^2.0", "phpstan\/extension-installer": "^1.3" }, "autoload-dev": { "psr-4": { "_ContaoManager\\Cose\\Tests\\": "tests\/" } }, "config": { "allow-plugins": { "infection\/extension-installer": true, "phpstan\/extension-installer": true } }, "suggest": { "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension" } }# Security Policy ## Supported Versions | Version | Supported | | ------- |----------------------------------------| | 4.0.x | :white_check_mark: | | 3.3.x | :white_check_mark: (security fix only) | | < 3.3.x | :x: | ## Reporting a Vulnerability If you think you have found a security issue, DO NOT open an issue. You MUST submit email security AT spomky-labs.com length; } /** * Compute the HMAC. */ public function hash(string $text) : string { return \hash($this->hash, $text, \true); } public function name() : string { return $this->hash; } public function t() : string { return $this->t; } } */ private readonly array $data; /** * @param array $data */ public function __construct(array $data) { if (!array_key_exists(self::TYPE, $data)) { throw new InvalidArgumentException('Invalid key: the type is not defined'); } $this->data = $data; } /** * @param array $data */ public static function create(array $data) : self { return new self($data); } /** * @param array $data */ public static function createFromData(array $data) : self { if (!array_key_exists(self::TYPE, $data)) { throw new InvalidArgumentException('Invalid key: the type is not defined'); } return match ($data[self::TYPE]) { '1' => new OkpKey($data), '2' => new Ec2Key($data), '3' => new RsaKey($data), '4' => new SymmetricKey($data), default => self::create($data), }; } public function type() : int|string { return $this->data[self::TYPE]; } public function alg() : int { return (int) $this->get(self::ALG); } /** * @return array */ public function getData() : array { return $this->data; } public function has(int|string $key) : bool { return array_key_exists($key, $this->data); } public function get(int|string $key) : mixed { if (!array_key_exists($key, $this->data)) { throw new InvalidArgumentException(\sprintf('The key has no data at index %d', $key)); } return $this->data[$key]; } } $data */ public function __construct(array $data) { foreach ([self::TYPE] as $key) { if (\is_numeric($data[$key])) { $data[$key] = (int) $data[$key]; } } parent::__construct($data); if ($data[self::TYPE] !== self::TYPE_RSA && $data[self::TYPE] !== self::TYPE_NAME_RSA) { throw new InvalidArgumentException('Invalid RSA key. The key type does not correspond to a RSA key'); } if (!isset($data[self::DATA_N], $data[self::DATA_E])) { throw new InvalidArgumentException('Invalid RSA key. The modulus or the exponent is missing'); } } /** * @param array $data */ public static function create(array $data) : self { return new self($data); } public function n() : string { return $this->get(self::DATA_N); } public function e() : string { return $this->get(self::DATA_E); } public function d() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_D); } public function p() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_P); } public function q() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_Q); } public function dP() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_DP); } public function dQ() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_DQ); } public function QInv() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_QI); } /** * @return array */ public function other() : array { $this->checkKeyIsPrivate(); return $this->get(self::DATA_OTHER); } public function rI() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_RI); } public function dI() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_DI); } public function tI() : string { $this->checkKeyIsPrivate(); return $this->get(self::DATA_TI); } public function hasPrimes() : bool { return $this->has(self::DATA_P) && $this->has(self::DATA_Q); } /** * @return string[] */ public function primes() : array { return [$this->p(), $this->q()]; } public function hasExponents() : bool { return $this->has(self::DATA_DP) && $this->has(self::DATA_DQ); } /** * @return string[] */ public function exponents() : array { return [$this->dP(), $this->dQ()]; } public function hasCoefficient() : bool { return $this->has(self::DATA_QI); } public function isPublic() : bool { return !$this->isPrivate(); } public function isPrivate() : bool { return array_key_exists(self::DATA_D, $this->getData()); } public function asPem() : string { if ($this->isPrivate()) { $privateKey = RSAPrivateKey::create($this->binaryToBigInteger($this->n()), $this->binaryToBigInteger($this->e()), $this->binaryToBigInteger($this->d()), $this->binaryToBigInteger($this->p()), $this->binaryToBigInteger($this->q()), $this->binaryToBigInteger($this->dP()), $this->binaryToBigInteger($this->dQ()), $this->binaryToBigInteger($this->QInv())); return $privateKey->toPEM()->string(); } $publicKey = RSAPublicKey::create($this->binaryToBigInteger($this->n()), $this->binaryToBigInteger($this->e())); $rsaKey = PublicKeyInfo::fromPublicKey($publicKey); return $rsaKey->toPEM()->string(); } public function toPublic() : static { $toBeRemoved = [self::DATA_D, self::DATA_P, self::DATA_Q, self::DATA_DP, self::DATA_DQ, self::DATA_QI, self::DATA_OTHER, self::DATA_RI, self::DATA_DI, self::DATA_TI]; $data = $this->getData(); foreach ($data as $k => $v) { if (in_array($k, $toBeRemoved, \true)) { unset($data[$k]); } } return new static($data); } private function checkKeyIsPrivate() : void { if (!$this->isPrivate()) { throw new InvalidArgumentException('The key is not private.'); } } private function binaryToBigInteger(string $data) : string { $res = \unpack('H*', $data); $res = \current($res); return BigInteger::fromBase($res, 16)->toBase(10); } } $data */ public function __construct(array $data) { parent::__construct($data); if (!isset($data[self::TYPE]) || (int) $data[self::TYPE] !== self::TYPE_OCT) { throw new InvalidArgumentException('Invalid symmetric key. The key type does not correspond to a symmetric key'); } if (!isset($data[self::DATA_K])) { throw new InvalidArgumentException('Invalid symmetric key. The parameter "k" is missing'); } } /** * @param array $data */ public static function create(array $data) : self { return new self($data); } public function k() : string { return $this->get(self::DATA_K); } } '1.2.840.10045.3.1.7', // NIST P-256 / secp256r1 self::CURVE_P256K => '1.3.132.0.10', // NIST P-256K / secp256k1 self::CURVE_P384 => '1.3.132.0.34', // NIST P-384 / secp384r1 self::CURVE_P521 => '1.3.132.0.35', ]; private const CURVE_KEY_LENGTH = [self::CURVE_P256 => 32, self::CURVE_P256K => 32, self::CURVE_P384 => 48, self::CURVE_P521 => 66, self::CURVE_NAME_P256 => 32, self::CURVE_NAME_P256K => 32, self::CURVE_NAME_P384 => 48, self::CURVE_NAME_P521 => 66]; /** * @param array $data */ public function __construct(array $data) { foreach ([self::DATA_CURVE, self::TYPE] as $key) { if (\is_numeric($data[$key])) { $data[$key] = (int) $data[$key]; } } parent::__construct($data); if ($data[self::TYPE] !== self::TYPE_EC2 && $data[self::TYPE] !== self::TYPE_NAME_EC2) { throw new InvalidArgumentException('Invalid EC2 key. The key type does not correspond to an EC2 key'); } if (!isset($data[self::DATA_CURVE], $data[self::DATA_X], $data[self::DATA_Y])) { throw new InvalidArgumentException('Invalid EC2 key. The curve or the "x/y" coordinates are missing'); } if (strlen((string) $data[self::DATA_X]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) { throw new InvalidArgumentException('Invalid length for x coordinate'); } if (strlen((string) $data[self::DATA_Y]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) { throw new InvalidArgumentException('Invalid length for y coordinate'); } if (is_int($data[self::DATA_CURVE])) { if (!in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_INT, \true)) { throw new InvalidArgumentException('The curve is not supported'); } } elseif (!in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_NAMES, \true)) { throw new InvalidArgumentException('The curve is not supported'); } } /** * @param array $data */ public static function create(array $data) : self { return new self($data); } public function toPublic() : self { $data = $this->getData(); unset($data[self::DATA_D]); return new self($data); } public function x() : string { return $this->get(self::DATA_X); } public function y() : string { return $this->get(self::DATA_Y); } public function isPrivate() : bool { return array_key_exists(self::DATA_D, $this->getData()); } public function d() : string { if (!$this->isPrivate()) { throw new InvalidArgumentException('The key is not private.'); } return $this->get(self::DATA_D); } public function curve() : int|string { return $this->get(self::DATA_CURVE); } public function asPEM() : string { if ($this->isPrivate()) { $der = Sequence::create(Integer::create(1), OctetString::create($this->d()), ExplicitlyTaggedType::create(0, ObjectIdentifier::create($this->getCurveOid())), ExplicitlyTaggedType::create(1, BitString::create($this->getUncompressedCoordinates()))); return $this->pem('EC PRIVATE KEY', $der->toDER()); } $der = Sequence::create(Sequence::create(ObjectIdentifier::create('1.2.840.10045.2.1'), ObjectIdentifier::create($this->getCurveOid())), BitString::create($this->getUncompressedCoordinates())); return $this->pem('PUBLIC KEY', $der->toDER()); } public function getUncompressedCoordinates() : string { return "\x04" . $this->x() . $this->y(); } private function getCurveOid() : string { return self::NAMED_CURVE_OID[$this->curve()]; } private function pem(string $type, string $der) : string { return \sprintf("-----BEGIN %s-----\n", \strtoupper($type)) . \chunk_split(\base64_encode($der), 64, "\n") . \sprintf("-----END %s-----\n", \strtoupper($type)); } } $data */ public function __construct(array $data) { foreach ([self::DATA_CURVE, self::TYPE] as $key) { if (\is_numeric($data[$key])) { $data[$key] = (int) $data[$key]; } } parent::__construct($data); if ($data[self::TYPE] !== self::TYPE_OKP && $data[self::TYPE] !== self::TYPE_NAME_OKP) { throw new InvalidArgumentException('Invalid OKP key. The key type does not correspond to an OKP key'); } if (!isset($data[self::DATA_CURVE], $data[self::DATA_X])) { throw new InvalidArgumentException('Invalid EC2 key. The curve or the "x" coordinate is missing'); } if (\is_numeric($data[self::DATA_CURVE])) { if (!in_array((int) $data[self::DATA_CURVE], self::SUPPORTED_CURVES_INT, \true)) { throw new InvalidArgumentException('The curve is not supported'); } } elseif (!in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_NAME, \true)) { throw new InvalidArgumentException('The curve is not supported'); } } /** * @param array $data */ public static function create(array $data) : self { return new self($data); } public function x() : string { return $this->get(self::DATA_X); } public function isPrivate() : bool { return array_key_exists(self::DATA_D, $this->getData()); } public function d() : string { if (!$this->isPrivate()) { throw new InvalidArgumentException('The key is not private.'); } return $this->get(self::DATA_D); } public function curve() : int|string { return $this->get(self::DATA_CURVE); } } */ private array $algorithms = []; public static function create() : self { return new self(); } public function add(string $alias, Algorithm $algorithm) : self { $this->algorithms[$alias] = $algorithm; return $this; } /** * @return string[] */ public function list() : iterable { yield from \array_keys($this->algorithms); } /** * @return Algorithm[] */ public function all() : iterable { yield from $this->algorithms; } public function generate(string ...$aliases) : Manager { $manager = Manager::create(); foreach ($aliases as $alias) { if (!array_key_exists($alias, $this->algorithms)) { throw new InvalidArgumentException(\sprintf('The algorithm with alias "%s" is not supported', $alias)); } $manager->add($this->algorithms[$alias]); } return $manager; } } handleKey($key); openssl_sign($data, $signature, $key->asPEM(), $this->getHashAlgorithm()); return ECSignature::fromAsn1($signature, $this->getSignaturePartLength()); } public function verify(string $data, Key $key, string $signature) : bool { $key = $this->handleKey($key); $publicKey = $key->toPublic(); $signature = ECSignature::toAsn1($signature, $this->getSignaturePartLength()); return openssl_verify($data, $signature, $publicKey->asPEM(), $this->getHashAlgorithm()) === 1; } protected abstract function getCurve() : int; protected abstract function getHashAlgorithm() : int; protected abstract function getSignaturePartLength() : int; private function handleKey(Key $key) : Ec2Key { $key = Ec2Key::create($key->getData()); if ($key->curve() !== $this->getCurve()) { throw new InvalidArgumentException('This key cannot be used with this algorithm'); } return $key; } } self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : ''; return hex2bin(self::ASN1_SEQUENCE . $lengthPrefix . dechex($totalLength) . self::ASN1_INTEGER . dechex($lengthR) . $pointR . self::ASN1_INTEGER . dechex($lengthS) . $pointS); } public static function fromAsn1(string $signature, int $length) : string { $message = bin2hex($signature); $position = 0; if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_SEQUENCE) { throw new InvalidArgumentException('Invalid data. Should start with a sequence.'); } // @phpstan-ignore-next-line if (self::readAsn1Content($message, $position, self::BYTE_SIZE) === self::ASN1_LENGTH_2BYTES) { $position += self::BYTE_SIZE; } $pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); $pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); return hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT) . str_pad($pointS, $length, '0', STR_PAD_LEFT)); } private static function octetLength(string $data) : int { return \intdiv(strlen($data), self::BYTE_SIZE); } private static function preparePositiveInteger(string $data) : string { if (substr($data, 0, self::BYTE_SIZE) > self::ASN1_BIG_INTEGER_LIMIT) { return self::ASN1_NEGATIVE_INTEGER . $data; } while (\str_starts_with($data, self::ASN1_NEGATIVE_INTEGER) && substr($data, 2, self::BYTE_SIZE) <= self::ASN1_BIG_INTEGER_LIMIT) { $data = substr($data, 2, null); } return $data; } private static function readAsn1Content(string $message, int &$position, int $length) : string { $content = substr($message, $position, $length); $position += $length; return $content; } private static function readAsn1Integer(string $message, int &$position) : string { if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_INTEGER) { throw new InvalidArgumentException('Invalid data. Should contain an integer.'); } $length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE)); return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE); } private static function retrievePositiveInteger(string $data) : string { while (\str_starts_with($data, self::ASN1_NEGATIVE_INTEGER) && substr($data, 2, self::BYTE_SIZE) > self::ASN1_BIG_INTEGER_LIMIT) { $data = substr($data, 2, null); } return $data; } } handleKey($key); if (!$key->isPrivate()) { throw new InvalidArgumentException('The key is not private.'); } try { openssl_sign($data, $signature, $key->asPem(), $this->getHashAlgorithm()); } catch (Throwable $e) { throw new InvalidArgumentException('Unable to sign the data', 0, $e); } return $signature; } public function verify(string $data, Key $key, string $signature) : bool { $key = $this->handleKey($key); return openssl_verify($data, $signature, $key->toPublic()->asPem(), $this->getHashAlgorithm()) === 1; } protected abstract function getHashAlgorithm() : int; private function handleKey(Key $key) : RsaKey { return RsaKey::create($key->getData()); } } handleKey($key); $modulusLength = strlen($key->n()); $em = $this->encodeEMSAPSS($data, 8 * $modulusLength - 1, $this->getHashAlgorithm()); $message = BigInteger::createFromBinaryString($em); $signature = $this->exponentiate($key, $message); return $this->convertIntegerToOctetString($signature, $modulusLength); } public function verify(string $data, Key $key, string $signature) : bool { $key = $this->handleKey($key); $modulusLength = strlen($key->n()); if (strlen($signature) !== $modulusLength) { throw new InvalidArgumentException('Invalid modulus length'); } $s2 = BigInteger::createFromBinaryString($signature); $m2 = $this->exponentiate($key, $s2); $em = $this->convertIntegerToOctetString($m2, $modulusLength); $modBits = 8 * $modulusLength; return $this->verifyEMSAPSS($data, $em, $modBits - 1, $this->getHashAlgorithm()); } /** * Exponentiate with or without Chinese Remainder Theorem. Operation with primes 'p' and 'q' is appox. 2x faster. */ public function exponentiate(RsaKey $key, BigInteger $c) : BigInteger { if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare(BigInteger::createFromBinaryString($key->n())) > 0) { throw new RuntimeException(); } if ($key->isPublic() || !$key->hasPrimes() || !$key->hasExponents() || !$key->hasCoefficient()) { return $c->modPow(BigInteger::createFromBinaryString($key->e()), BigInteger::createFromBinaryString($key->n())); } [$pS, $qS] = $key->primes(); [$dPS, $dQS] = $key->exponents(); $qInv = BigInteger::createFromBinaryString($key->QInv()); $p = BigInteger::createFromBinaryString($pS); $q = BigInteger::createFromBinaryString($qS); $dP = BigInteger::createFromBinaryString($dPS); $dQ = BigInteger::createFromBinaryString($dQS); $m1 = $c->modPow($dP, $p); $m2 = $c->modPow($dQ, $q); $h = $qInv->multiply($m1->subtract($m2)->add($p))->mod($p); return $m2->add($h->multiply($q)); } protected abstract function getHashAlgorithm() : Hash; private function handleKey(Key $key) : RsaKey { return RsaKey::create($key->getData()); } private function convertIntegerToOctetString(BigInteger $x, int $xLen) : string { $xB = $x->toBytes(); if (strlen($xB) > $xLen) { throw new RuntimeException('Unable to convert the integer'); } return str_pad($xB, $xLen, chr(0), STR_PAD_LEFT); } /** * MGF1. */ private function getMGF1(string $mgfSeed, int $maskLen, Hash $mgfHash) : string { $t = ''; $count = ceil($maskLen / $mgfHash->getLength()); for ($i = 0; $i < $count; ++$i) { $c = pack('N', $i); $t .= $mgfHash->hash($mgfSeed . $c); } return \substr($t, 0, $maskLen); } /** * EMSA-PSS-ENCODE. */ private function encodeEMSAPSS(string $message, int $modulusLength, Hash $hash) : string { $emLen = $modulusLength + 1 >> 3; $sLen = $hash->getLength(); $mHash = $hash->hash($message); if ($emLen <= $hash->getLength() + $sLen + 2) { throw new RuntimeException(); } $salt = random_bytes($sLen); $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt; $h = $hash->hash($m2); $ps = str_repeat(chr(0), $emLen - $sLen - $hash->getLength() - 2); $db = $ps . chr(1) . $salt; $dbMask = $this->getMGF1($h, $emLen - $hash->getLength() - 1, $hash); $maskedDB = $db ^ $dbMask; $maskedDB[0] = ~chr(0xff << ($modulusLength & 7)) & $maskedDB[0]; return $maskedDB . $h . chr(0xbc); } /** * EMSA-PSS-VERIFY. */ private function verifyEMSAPSS(string $m, string $em, int $emBits, Hash $hash) : bool { $emLen = $emBits + 1 >> 3; $sLen = $hash->getLength(); $mHash = $hash->hash($m); if ($emLen < $hash->getLength() + $sLen + 2) { throw new InvalidArgumentException(); } if ($em[strlen($em) - 1] !== chr(0xbc)) { throw new InvalidArgumentException(); } $maskedDB = \substr($em, 0, -$hash->getLength() - 1); $h = \substr($em, -$hash->getLength() - 1, $hash->getLength()); $temp = chr(0xff << ($emBits & 7)); if ((~$maskedDB[0] & $temp) !== $temp) { throw new InvalidArgumentException(); } $dbMask = $this->getMGF1($h, $emLen - $hash->getLength() - 1, $hash); $db = $maskedDB ^ $dbMask; $db[0] = ~chr(0xff << ($emBits & 7)) & $db[0]; $temp = $emLen - $hash->getLength() - $sLen - 2; if (!\str_starts_with($db, str_repeat(chr(0), $temp))) { throw new InvalidArgumentException(); } if (ord($db[$temp]) !== 1) { throw new InvalidArgumentException(); } $salt = \substr($db, $temp + 1, null); // should be $sLen long $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt; $h2 = $hash->hash($m2); return hash_equals($h, $h2); } } handleKey($key); if (!$key->isPrivate()) { throw new InvalidArgumentException('The key is not private.'); } $x = $key->x(); $d = $key->d(); $secret = $d . $x; return match ($key->curve()) { OkpKey::CURVE_ED25519 => sodium_crypto_sign_detached($data, $secret), OkpKey::CURVE_NAME_ED25519 => sodium_crypto_sign_detached($data, $secret), default => throw new InvalidArgumentException('Unsupported curve'), }; } public function verify(string $data, Key $key, string $signature) : bool { $key = $this->handleKey($key); if ($key->curve() !== OkpKey::CURVE_ED25519 && $key->curve() !== OkpKey::CURVE_NAME_ED25519) { throw new InvalidArgumentException('Unsupported curve'); } try { sodium_crypto_sign_verify_detached($signature, $data, $key->x()); } catch (Throwable) { return \false; } return \true; } public static function identifier() : int { return Algorithms::COSE_ALGORITHM_EDDSA; } private function handleKey(Key $key) : OkpKey { return OkpKey::create($key->getData()); } } checKey($key); $signature = \hash_hmac($this->getHashAlgorithm(), $data, (string) $key->get(SymmetricKey::DATA_K), \true); return \substr($signature, 0, \intdiv($this->getSignatureLength(), 8)); } public function verify(string $data, Key $key, string $signature) : bool { return \hash_equals($this->hash($data, $key), $signature); } protected abstract function getHashAlgorithm() : string; protected abstract function getSignatureLength() : int; private function checKey(Key $key) : void { if ($key->type() !== Key::TYPE_OCT && $key->type() !== Key::TYPE_NAME_OCT) { throw new InvalidArgumentException('Invalid key. Must be of type symmetric'); } if (!$key->has(SymmetricKey::DATA_K)) { throw new InvalidArgumentException('Invalid key. The value of the key is missing'); } } } */ private array $algorithms = []; public static function create() : self { return new self(); } public function add(Algorithm ...$algorithms) : self { foreach ($algorithms as $algorithm) { $identifier = $algorithm::identifier(); $this->algorithms[$identifier] = $algorithm; } return $this; } /** * @return iterable */ public function list() : iterable { yield from \array_keys($this->algorithms); } /** * @return iterable */ public function all() : iterable { yield from $this->algorithms; } public function has(int $identifier) : bool { return array_key_exists($identifier, $this->algorithms); } public function get(int $identifier) : Algorithm { if (!$this->has($identifier)) { throw new InvalidArgumentException('Unsupported algorithm'); } return $this->algorithms[$identifier]; } } value->isEqualTo(BrickBigInteger::zero())) { return ''; } $temp = $this->value->toBase(16); $temp = 0 !== (strlen($temp) & 1) ? '0' . $temp : $temp; $temp = hex2bin($temp); return \ltrim($temp, chr(0)); } /** * Adds two BigIntegers. */ public function add(self $y) : self { $value = $this->value->plus($y->value); return new self($value); } /** * Subtracts two BigIntegers. */ public function subtract(self $y) : self { $value = $this->value->minus($y->value); return new self($value); } /** * Multiplies two BigIntegers. */ public function multiply(self $x) : self { $value = $this->value->multipliedBy($x->value); return new self($value); } /** * Performs modular exponentiation. */ public function modPow(self $e, self $n) : self { $value = $this->value->modPow($e->value, $n->value); return new self($value); } /** * Performs modular exponentiation. */ public function mod(self $d) : self { $value = $this->value->mod($d->value); return new self($value); } /** * Compares two numbers. */ public function compare(self $y) : int { return $this->value->compareTo($y->value); } } OPENSSL_ALGO_SHA256, self::COSE_ALGORITHM_ES384 => OPENSSL_ALGO_SHA384, self::COSE_ALGORITHM_ES512 => OPENSSL_ALGO_SHA512, self::COSE_ALGORITHM_RS256 => OPENSSL_ALGO_SHA256, self::COSE_ALGORITHM_RS384 => OPENSSL_ALGO_SHA384, self::COSE_ALGORITHM_RS512 => OPENSSL_ALGO_SHA512, self::COSE_ALGORITHM_RS1 => OPENSSL_ALGO_SHA1]; public final const COSE_HASH_MAP = [self::COSE_ALGORITHM_ES256K => 'sha256', self::COSE_ALGORITHM_ES256 => 'sha256', self::COSE_ALGORITHM_ES384 => 'sha384', self::COSE_ALGORITHM_ES512 => 'sha512', self::COSE_ALGORITHM_RS256 => 'sha256', self::COSE_ALGORITHM_RS384 => 'sha384', self::COSE_ALGORITHM_RS512 => 'sha512', self::COSE_ALGORITHM_PS256 => 'sha256', self::COSE_ALGORITHM_PS384 => 'sha384', self::COSE_ALGORITHM_PS512 => 'sha512', self::COSE_ALGORITHM_RS1 => 'sha1']; public static function getOpensslAlgorithmFor(int $algorithmIdentifier) : int { if (!array_key_exists($algorithmIdentifier, self::COSE_ALGORITHM_MAP)) { throw new InvalidArgumentException('The specified algorithm identifier is not supported'); } return self::COSE_ALGORITHM_MAP[$algorithmIdentifier]; } public static function getHashAlgorithmFor(int $algorithmIdentifier) : string { if (!array_key_exists($algorithmIdentifier, self::COSE_HASH_MAP)) { throw new InvalidArgumentException('The specified algorithm identifier is not supported'); } return self::COSE_HASH_MAP[$algorithmIdentifier]; } } `Composer\XdebugHandler\XdebugHandler` [Unreleased]: https://github.com/composer/xdebug-handler/compare/3.0.5...HEAD [3.0.5]: https://github.com/composer/xdebug-handler/compare/3.0.4...3.0.5 [3.0.4]: https://github.com/composer/xdebug-handler/compare/3.0.3...3.0.4 [3.0.3]: https://github.com/composer/xdebug-handler/compare/3.0.2...3.0.3 [3.0.2]: https://github.com/composer/xdebug-handler/compare/3.0.1...3.0.2 [3.0.1]: https://github.com/composer/xdebug-handler/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/composer/xdebug-handler/compare/2.0.3...3.0.0 [2.0.3]: https://github.com/composer/xdebug-handler/compare/2.0.2...2.0.3 [2.0.2]: https://github.com/composer/xdebug-handler/compare/2.0.1...2.0.2 [2.0.1]: https://github.com/composer/xdebug-handler/compare/2.0.0...2.0.1 [2.0.0]: https://github.com/composer/xdebug-handler/compare/1.4.6...2.0.0 [1.4.6]: https://github.com/composer/xdebug-handler/compare/1.4.5...1.4.6 [1.4.5]: https://github.com/composer/xdebug-handler/compare/1.4.4...1.4.5 [1.4.4]: https://github.com/composer/xdebug-handler/compare/1.4.3...1.4.4 [1.4.3]: https://github.com/composer/xdebug-handler/compare/1.4.2...1.4.3 [1.4.2]: https://github.com/composer/xdebug-handler/compare/1.4.1...1.4.2 [1.4.1]: https://github.com/composer/xdebug-handler/compare/1.4.0...1.4.1 [1.4.0]: https://github.com/composer/xdebug-handler/compare/1.3.3...1.4.0 [1.3.3]: https://github.com/composer/xdebug-handler/compare/1.3.2...1.3.3 [1.3.2]: https://github.com/composer/xdebug-handler/compare/1.3.1...1.3.2 [1.3.1]: https://github.com/composer/xdebug-handler/compare/1.3.0...1.3.1 [1.3.0]: https://github.com/composer/xdebug-handler/compare/1.2.1...1.3.0 [1.2.1]: https://github.com/composer/xdebug-handler/compare/1.2.0...1.2.1 [1.2.0]: https://github.com/composer/xdebug-handler/compare/1.1.0...1.2.0 [1.1.0]: https://github.com/composer/xdebug-handler/compare/1.0.0...1.1.0 [1.0.0]: https://github.com/composer/xdebug-handler/compare/d66f0d15cb57...1.0.0 # composer/xdebug-handler [![packagist](https://img.shields.io/packagist/v/composer/xdebug-handler)](https://packagist.org/packages/composer/xdebug-handler) [![Continuous Integration](https://github.com/composer/xdebug-handler/actions/workflows/continuous-integration.yml/badge.svg?branch=main)](https://github.com/composer/xdebug-handler/actions?query=branch:main) ![license](https://img.shields.io/github/license/composer/xdebug-handler.svg) ![php](https://img.shields.io/packagist/php-v/composer/xdebug-handler?colorB=8892BF) Restart a CLI process without loading the Xdebug extension, unless `xdebug.mode=off`. Originally written as part of [composer/composer](https://github.com/composer/composer), now extracted and made available as a stand-alone library. ### Version 3 Removed support for legacy PHP versions and added type declarations. Long term support for version 2 (PHP 5.3.2 - 7.2.4) follows [Composer 2.2 LTS](https://blog.packagist.com/composer-2-2/) policy. ## Installation Install the latest version with: ```bash $ composer require composer/xdebug-handler ``` ## Requirements * PHP 7.2.5 minimum, although using the latest PHP version is highly recommended. ## Basic Usage ```php use Composer\XdebugHandler\XdebugHandler; $xdebug = new XdebugHandler('myapp'); $xdebug->check(); unset($xdebug); ``` The constructor takes a single parameter, `$envPrefix`, which is upper-cased and prepended to default base values to create two distinct environment variables. The above example enables the use of: - `MYAPP_ALLOW_XDEBUG=1` to override automatic restart and allow Xdebug - `MYAPP_ORIGINAL_INIS` to obtain ini file locations in a restarted process ## Advanced Usage * [How it works](#how-it-works) * [Limitations](#limitations) * [Helper methods](#helper-methods) * [Setter methods](#setter-methods) * [Process configuration](#process-configuration) * [Troubleshooting](#troubleshooting) * [Extending the library](#extending-the-library) * [Examples](#examples) ### How it works A temporary ini file is created from the loaded (and scanned) ini files, with any references to the Xdebug extension commented out. Current ini settings are merged, so that most ini settings made on the command-line or by the application are included (see [Limitations](#limitations)) * `MYAPP_ALLOW_XDEBUG` is set with internal data to flag and use in the restart. * The command-line and environment are [configured](#process-configuration) for the restart. * The application is restarted in a new process. * The restart settings are stored in the environment. * `MYAPP_ALLOW_XDEBUG` is unset. * The application runs and exits. * The main process exits with the exit code from the restarted process. See [Examples](#examples) for further information. #### Signal handling Asynchronous signal handling is automatically enabled if the pcntl extension is loaded. `SIGINT` is set to `SIG_IGN` in the parent process and restored to `SIG_DFL` in the restarted process (if no other handler has been set). From PHP 7.4 on Windows, `CTRL+C` and `CTRL+BREAK` handling is automatically enabled in the restarted process and ignored in the parent process. ### Limitations There are a few things to be aware of when running inside a restarted process. * Extensions set on the command-line will not be loaded. * Ini file locations will be reported as per the restart - see [getAllIniFiles()](#getallinifiles-array). * Php sub-processes may be loaded with Xdebug enabled - see [Process configuration](#process-configuration). ### Helper methods These static methods provide information from the current process, regardless of whether it has been restarted or not. #### _getAllIniFiles(): array_ Returns an array of the original ini file locations. Use this instead of calling `php_ini_loaded_file` and `php_ini_scanned_files`, which will report the wrong values in a restarted process. ```php use Composer\XdebugHandler\XdebugHandler; $files = XdebugHandler::getAllIniFiles(); # $files[0] always exists, it could be an empty string $loadedIni = array_shift($files); $scannedInis = $files; ``` These locations are also available in the `MYAPP_ORIGINAL_INIS` environment variable. This is a path-separated string comprising the location returned from `php_ini_loaded_file`, which could be empty, followed by locations parsed from calling `php_ini_scanned_files`. #### _getRestartSettings(): ?array_ Returns an array of settings that can be used with PHP [sub-processes](#sub-processes), or null if the process was not restarted. ```php use Composer\XdebugHandler\XdebugHandler; $settings = XdebugHandler::getRestartSettings(); /** * $settings: array (if the current process was restarted, * or called with the settings from a previous restart), or null * * 'tmpIni' => the temporary ini file used in the restart (string) * 'scannedInis' => if there were any scanned inis (bool) * 'scanDir' => the original PHP_INI_SCAN_DIR value (false|string) * 'phprc' => the original PHPRC value (false|string) * 'inis' => the original inis from getAllIniFiles (array) * 'skipped' => the skipped version from getSkippedVersion (string) */ ``` #### _getSkippedVersion(): string_ Returns the Xdebug version string that was skipped by the restart, or an empty string if there was no restart (or Xdebug is still loaded, perhaps by an extending class restarting for a reason other than removing Xdebug). ```php use Composer\XdebugHandler\XdebugHandler; $version = XdebugHandler::getSkippedVersion(); # $version: '3.1.1' (for example), or an empty string ``` #### _isXdebugActive(): bool_ Returns true if Xdebug is loaded and is running in an active mode (if it supports modes). Returns false if Xdebug is not loaded, or it is running with `xdebug.mode=off`. ### Setter methods These methods implement a fluent interface and must be called before the main `check()` method. #### _setLogger(LoggerInterface $logger): self_ Enables the output of status messages to an external PSR3 logger. All messages are reported with either `DEBUG` or `WARNING` log levels. For example (showing the level and message): ``` // No restart DEBUG Checking MYAPP_ALLOW_XDEBUG DEBUG The Xdebug extension is loaded (3.1.1) xdebug.mode=off DEBUG No restart (APP_ALLOW_XDEBUG=0) Allowed by xdebug.mode // Restart overridden DEBUG Checking MYAPP_ALLOW_XDEBUG DEBUG The Xdebug extension is loaded (3.1.1) xdebug.mode=coverage,debug,develop DEBUG No restart (MYAPP_ALLOW_XDEBUG=1) // Failed restart DEBUG Checking MYAPP_ALLOW_XDEBUG DEBUG The Xdebug extension is loaded (3.1.0) WARNING No restart (Unable to create temp ini file at: ...) ``` Status messages can also be output with `XDEBUG_HANDLER_DEBUG`. See [Troubleshooting](#troubleshooting). #### _setMainScript(string $script): self_ Sets the location of the main script to run in the restart. This is only needed in more esoteric use-cases, or if the `argv[0]` location is inaccessible. The script name `--` is supported for standard input. #### _setPersistent(): self_ Configures the restart using [persistent settings](#persistent-settings), so that Xdebug is not loaded in any sub-process. Use this method if your application invokes one or more PHP sub-process and the Xdebug extension is not needed. This avoids the overhead of implementing specific [sub-process](#sub-processes) strategies. Alternatively, this method can be used to set up a default _Xdebug-free_ environment which can be changed if a sub-process requires Xdebug, then restored afterwards: ```php function SubProcessWithXdebug() { $phpConfig = new Composer\XdebugHandler\PhpConfig(); # Set the environment to the original configuration $phpConfig->useOriginal(); # run the process with Xdebug loaded ... # Restore Xdebug-free environment $phpConfig->usePersistent(); } ``` ### Process configuration The library offers two strategies to invoke a new PHP process without loading Xdebug, using either _standard_ or _persistent_ settings. Note that this is only important if the application calls a PHP sub-process. #### Standard settings Uses command-line options to remove Xdebug from the new process only. * The -n option is added to the command-line. This tells PHP not to scan for additional inis. * The temporary ini is added to the command-line with the -c option. >_If the new process calls a PHP sub-process, Xdebug will be loaded in that sub-process (unless it implements xdebug-handler, in which case there will be another restart)._ This is the default strategy used in the restart. #### Persistent settings Uses environment variables to remove Xdebug from the new process and persist these settings to any sub-process. * `PHP_INI_SCAN_DIR` is set to an empty string. This tells PHP not to scan for additional inis. * `PHPRC` is set to the temporary ini. >_If the new process calls a PHP sub-process, Xdebug will not be loaded in that sub-process._ This strategy can be used in the restart by calling [setPersistent()](#setpersistent-self). #### Sub-processes The `PhpConfig` helper class makes it easy to invoke a PHP sub-process (with or without Xdebug loaded), regardless of whether there has been a restart. Each of its methods returns an array of PHP options (to add to the command-line) and sets up the environment for the required strategy. The [getRestartSettings()](#getrestartsettings-array) method is used internally. * `useOriginal()` - Xdebug will be loaded in the new process. * `useStandard()` - Xdebug will **not** be loaded in the new process - see [standard settings](#standard-settings). * `userPersistent()` - Xdebug will **not** be loaded in the new process - see [persistent settings](#persistent-settings) If there was no restart, an empty options array is returned and the environment is not changed. ```php use Composer\XdebugHandler\PhpConfig; $config = new PhpConfig; $options = $config->useOriginal(); # $options: empty array # environment: PHPRC and PHP_INI_SCAN_DIR set to original values $options = $config->useStandard(); # $options: [-n, -c, tmpIni] # environment: PHPRC and PHP_INI_SCAN_DIR set to original values $options = $config->usePersistent(); # $options: empty array # environment: PHPRC=tmpIni, PHP_INI_SCAN_DIR='' ``` ### Troubleshooting The following environment settings can be used to troubleshoot unexpected behavior: * `XDEBUG_HANDLER_DEBUG=1` Outputs status messages to `STDERR`, if it is defined, irrespective of any PSR3 logger. Each message is prefixed `xdebug-handler[pid]`, where pid is the process identifier. * `XDEBUG_HANDLER_DEBUG=2` As above, but additionally saves the temporary ini file and reports its location in a status message. ### Extending the library The API is defined by classes and their accessible elements that are not annotated as @internal. The main class has two protected methods that can be overridden to provide additional functionality: #### _requiresRestart(bool $default): bool_ By default the process will restart if Xdebug is loaded and not running with `xdebug.mode=off`. Extending this method allows an application to decide, by returning a boolean (or equivalent) value. It is only called if `MYAPP_ALLOW_XDEBUG` is empty, so it will not be called in the restarted process (where this variable contains internal data), or if the restart has been overridden. Note that the [setMainScript()](#setmainscriptstring-script-self) and [setPersistent()](#setpersistent-self) setters can be used here, if required. #### _restart(array $command): void_ An application can extend this to modify the temporary ini file, its location given in the `tmpIni` property. New settings can be safely appended to the end of the data, which is `PHP_EOL` terminated. The `$command` parameter is an array of unescaped command-line arguments that will be used for the new process. Remember to finish with `parent::restart($command)`. #### Example This example demonstrates two ways to extend basic functionality: * To avoid the overhead of spinning up a new process, the restart is skipped if a simple help command is requested. * The application needs write-access to phar files, so it will force a restart if `phar.readonly` is set (regardless of whether Xdebug is loaded) and change this value in the temporary ini file. ```php use Composer\XdebugHandler\XdebugHandler; use MyApp\Command; class MyRestarter extends XdebugHandler { private $required; protected function requiresRestart(bool $default): bool { if (Command::isHelp()) { # No need to disable Xdebug for this return false; } $this->required = (bool) ini_get('phar.readonly'); return $this->required || $default; } protected function restart(array $command): void { if ($this->required) { # Add required ini setting to tmpIni $content = file_get_contents($this->tmpIni); $content .= 'phar.readonly=0'.PHP_EOL; file_put_contents($this->tmpIni, $content); } parent::restart($command); } } ``` ### Examples The `tests\App` directory contains command-line scripts that demonstrate the internal workings in a variety of scenarios. See [Functional Test Scripts](./tests/App/README.md). ## License composer/xdebug-handler is licensed under the MIT License, see the LICENSE file for details. { "name": "composer\/xdebug-handler", "description": "Restarts a process without Xdebug.", "type": "library", "license": "MIT", "keywords": [ "xdebug", "performance" ], "authors": [ { "name": "John Stevenson", "email": "john-stevenson@blueyonder.co.uk" } ], "support": { "irc": "ircs:\/\/irc.libera.chat:6697\/composer", "issues": "https:\/\/github.com\/composer\/xdebug-handler\/issues" }, "require": { "php": "^7.2.5 || ^8.0", "psr\/log": "^1 || ^2 || ^3", "composer\/pcre": "^1 || ^2 || ^3" }, "require-dev": { "phpstan\/phpstan": "^1.0", "phpstan\/phpstan-strict-rules": "^1.1", "phpunit\/phpunit": "^8.5 || ^9.6 || ^10.5" }, "autoload": { "psr-4": { "Composer\\XdebugHandler\\": "src" } }, "autoload-dev": { "psr-4": { "Composer\\XdebugHandler\\Tests\\": "tests" } }, "scripts": { "test": "@php vendor\/bin\/phpunit", "phpstan": "@php vendor\/bin\/phpstan analyse" } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\XdebugHandler; /** * @author John Stevenson * * @phpstan-type restartData array{tmpIni: string, scannedInis: bool, scanDir: false|string, phprc: false|string, inis: string[], skipped: string} */ class PhpConfig { /** * Use the original PHP configuration * * @return string[] Empty array of PHP cli options */ public function useOriginal() : array { $this->getDataAndReset(); return []; } /** * Use standard restart settings * * @return string[] PHP cli options */ public function useStandard() : array { $data = $this->getDataAndReset(); if ($data !== null) { return ['-n', '-c', $data['tmpIni']]; } return []; } /** * Use environment variables to persist settings * * @return string[] Empty array of PHP cli options */ public function usePersistent() : array { $data = $this->getDataAndReset(); if ($data !== null) { $this->updateEnv('PHPRC', $data['tmpIni']); $this->updateEnv('PHP_INI_SCAN_DIR', ''); } return []; } /** * Returns restart data if available and resets the environment * * @phpstan-return restartData|null */ private function getDataAndReset() : ?array { $data = \Composer\XdebugHandler\XdebugHandler::getRestartSettings(); if ($data !== null) { $this->updateEnv('PHPRC', $data['phprc']); $this->updateEnv('PHP_INI_SCAN_DIR', $data['scanDir']); } return $data; } /** * Updates a restart settings value in the environment * * @param string $name * @param string|false $value */ private function updateEnv(string $name, $value) : void { \Composer\XdebugHandler\Process::setEnv($name, \false !== $value ? $value : null); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ declare (strict_types=1); namespace Composer\XdebugHandler; use _ContaoManager\Psr\Log\LoggerInterface; use _ContaoManager\Psr\Log\LogLevel; /** * @author John Stevenson * @internal */ class Status { const ENV_RESTART = 'XDEBUG_HANDLER_RESTART'; const CHECK = 'Check'; const ERROR = 'Error'; const INFO = 'Info'; const NORESTART = 'NoRestart'; const RESTART = 'Restart'; const RESTARTING = 'Restarting'; const RESTARTED = 'Restarted'; /** @var bool */ private $debug; /** @var string */ private $envAllowXdebug; /** @var string|null */ private $loaded; /** @var LoggerInterface|null */ private $logger; /** @var bool */ private $modeOff; /** @var float */ private $time; /** * @param string $envAllowXdebug Prefixed _ALLOW_XDEBUG name * @param bool $debug Whether debug output is required */ public function __construct(string $envAllowXdebug, bool $debug) { $start = \getenv(self::ENV_RESTART); \Composer\XdebugHandler\Process::setEnv(self::ENV_RESTART); $this->time = \is_numeric($start) ? \round((\microtime(\true) - $start) * 1000) : 0; $this->envAllowXdebug = $envAllowXdebug; $this->debug = $debug && \defined('STDERR'); $this->modeOff = \false; } /** * Activates status message output to a PSR3 logger * * @return void */ public function setLogger(LoggerInterface $logger) : void { $this->logger = $logger; } /** * Calls a handler method to report a message * * @throws \InvalidArgumentException If $op is not known */ public function report(string $op, ?string $data) : void { if ($this->logger !== null || $this->debug) { $param = (string) $data; switch ($op) { case self::CHECK: $this->reportCheck($param); break; case self::ERROR: $this->reportError($param); break; case self::INFO: $this->reportInfo($param); break; case self::NORESTART: $this->reportNoRestart(); break; case self::RESTART: $this->reportRestart(); break; case self::RESTARTED: $this->reportRestarted(); break; case self::RESTARTING: $this->reportRestarting($param); break; default: throw new \InvalidArgumentException('Unknown op handler: ' . $op); } } } /** * Outputs a status message */ private function output(string $text, ?string $level = null) : void { if ($this->logger !== null) { $this->logger->log($level !== null ? $level : LogLevel::DEBUG, $text); } if ($this->debug) { \fwrite(\STDERR, \sprintf('xdebug-handler[%d] %s', \getmypid(), $text . \PHP_EOL)); } } /** * Checking status message */ private function reportCheck(string $loaded) : void { list($version, $mode) = \explode('|', $loaded); if ($version !== '') { $this->loaded = '(' . $version . ')' . ($mode !== '' ? ' xdebug.mode=' . $mode : ''); } $this->modeOff = $mode === 'off'; $this->output('Checking ' . $this->envAllowXdebug); } /** * Error status message */ private function reportError(string $error) : void { $this->output(\sprintf('No restart (%s)', $error), LogLevel::WARNING); } /** * Info status message */ private function reportInfo(string $info) : void { $this->output($info); } /** * No restart status message */ private function reportNoRestart() : void { $this->output($this->getLoadedMessage()); if ($this->loaded !== null) { $text = \sprintf('No restart (%s)', $this->getEnvAllow()); if (!(bool) \getenv($this->envAllowXdebug)) { $text .= ' Allowed by ' . ($this->modeOff ? 'xdebug.mode' : 'application'); } $this->output($text); } } /** * Restart status message */ private function reportRestart() : void { $this->output($this->getLoadedMessage()); \Composer\XdebugHandler\Process::setEnv(self::ENV_RESTART, (string) \microtime(\true)); } /** * Restarted status message */ private function reportRestarted() : void { $loaded = $this->getLoadedMessage(); $text = \sprintf('Restarted (%d ms). %s', $this->time, $loaded); $level = $this->loaded !== null ? LogLevel::WARNING : null; $this->output($text, $level); } /** * Restarting status message */ private function reportRestarting(string $command) : void { $text = \sprintf('Process restarting (%s)', $this->getEnvAllow()); $this->output($text); $text = 'Running: ' . $command; $this->output($text); } /** * Returns the _ALLOW_XDEBUG environment variable as name=value */ private function getEnvAllow() : string { return $this->envAllowXdebug . '=' . \getenv($this->envAllowXdebug); } /** * Returns the Xdebug status and version */ private function getLoadedMessage() : string { $loaded = $this->loaded !== null ? \sprintf('loaded %s', $this->loaded) : 'not loaded'; return 'The Xdebug extension is ' . $loaded; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ declare (strict_types=1); namespace Composer\XdebugHandler; use Composer\Pcre\Preg; use _ContaoManager\Psr\Log\LoggerInterface; /** * @author John Stevenson * * @phpstan-import-type restartData from PhpConfig */ class XdebugHandler { const SUFFIX_ALLOW = '_ALLOW_XDEBUG'; const SUFFIX_INIS = '_ORIGINAL_INIS'; const RESTART_ID = 'internal'; const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS'; const DEBUG = 'XDEBUG_HANDLER_DEBUG'; /** @var string|null */ protected $tmpIni; /** @var bool */ private static $inRestart; /** @var string */ private static $name; /** @var string|null */ private static $skipped; /** @var bool */ private static $xdebugActive; /** @var string|null */ private static $xdebugMode; /** @var string|null */ private static $xdebugVersion; /** @var bool */ private $cli; /** @var string|null */ private $debug; /** @var string */ private $envAllowXdebug; /** @var string */ private $envOriginalInis; /** @var bool */ private $persistent; /** @var string|null */ private $script; /** @var Status */ private $statusWriter; /** * Constructor * * The $envPrefix is used to create distinct environment variables. It is * uppercased and prepended to the default base values. For example 'myapp' * would result in MYAPP_ALLOW_XDEBUG and MYAPP_ORIGINAL_INIS. * * @param string $envPrefix Value used in environment variables * @throws \RuntimeException If the parameter is invalid */ public function __construct(string $envPrefix) { if ($envPrefix === '') { throw new \RuntimeException('Invalid constructor parameter'); } self::$name = \strtoupper($envPrefix); $this->envAllowXdebug = self::$name . self::SUFFIX_ALLOW; $this->envOriginalInis = self::$name . self::SUFFIX_INIS; self::setXdebugDetails(); self::$inRestart = \false; if ($this->cli = \PHP_SAPI === 'cli') { $this->debug = (string) \getenv(self::DEBUG); } $this->statusWriter = new \Composer\XdebugHandler\Status($this->envAllowXdebug, (bool) $this->debug); } /** * Activates status message output to a PSR3 logger */ public function setLogger(LoggerInterface $logger) : self { $this->statusWriter->setLogger($logger); return $this; } /** * Sets the main script location if it cannot be called from argv */ public function setMainScript(string $script) : self { $this->script = $script; return $this; } /** * Persist the settings to keep Xdebug out of sub-processes */ public function setPersistent() : self { $this->persistent = \true; return $this; } /** * Checks if Xdebug is loaded and the process needs to be restarted * * This behaviour can be disabled by setting the MYAPP_ALLOW_XDEBUG * environment variable to 1. This variable is used internally so that * the restarted process is created only once. */ public function check() : void { $this->notify(\Composer\XdebugHandler\Status::CHECK, self::$xdebugVersion . '|' . self::$xdebugMode); $envArgs = \explode('|', (string) \getenv($this->envAllowXdebug)); if (!(bool) $envArgs[0] && $this->requiresRestart(self::$xdebugActive)) { // Restart required $this->notify(\Composer\XdebugHandler\Status::RESTART); $command = $this->prepareRestart(); if ($command !== null) { $this->restart($command); } return; } if (self::RESTART_ID === $envArgs[0] && \count($envArgs) === 5) { // Restarted, so unset environment variable and use saved values $this->notify(\Composer\XdebugHandler\Status::RESTARTED); \Composer\XdebugHandler\Process::setEnv($this->envAllowXdebug); self::$inRestart = \true; if (self::$xdebugVersion === null) { // Skipped version is only set if Xdebug is not loaded self::$skipped = $envArgs[1]; } $this->tryEnableSignals(); // Put restart settings in the environment $this->setEnvRestartSettings($envArgs); return; } $this->notify(\Composer\XdebugHandler\Status::NORESTART); $settings = self::getRestartSettings(); if ($settings !== null) { // Called with existing settings, so sync our settings $this->syncSettings($settings); } } /** * Returns an array of php.ini locations with at least one entry * * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files. * The loaded ini location is the first entry and may be an empty string. * * @return non-empty-list */ public static function getAllIniFiles() : array { if (self::$name !== null) { $env = \getenv(self::$name . self::SUFFIX_INIS); if (\false !== $env) { return \explode(\PATH_SEPARATOR, $env); } } $paths = [(string) \php_ini_loaded_file()]; $scanned = \php_ini_scanned_files(); if ($scanned !== \false) { $paths = \array_merge($paths, \array_map('trim', \explode(',', $scanned))); } return $paths; } /** * Returns an array of restart settings or null * * Settings will be available if the current process was restarted, or * called with the settings from an existing restart. * * @phpstan-return restartData|null */ public static function getRestartSettings() : ?array { $envArgs = \explode('|', (string) \getenv(self::RESTART_SETTINGS)); if (\count($envArgs) !== 6 || !self::$inRestart && \php_ini_loaded_file() !== $envArgs[0]) { return null; } return ['tmpIni' => $envArgs[0], 'scannedInis' => (bool) $envArgs[1], 'scanDir' => '*' === $envArgs[2] ? \false : $envArgs[2], 'phprc' => '*' === $envArgs[3] ? \false : $envArgs[3], 'inis' => \explode(\PATH_SEPARATOR, $envArgs[4]), 'skipped' => $envArgs[5]]; } /** * Returns the Xdebug version that triggered a successful restart */ public static function getSkippedVersion() : string { return (string) self::$skipped; } /** * Returns whether Xdebug is loaded and active * * true: if Xdebug is loaded and is running in an active mode. * false: if Xdebug is not loaded, or it is running with xdebug.mode=off. */ public static function isXdebugActive() : bool { self::setXdebugDetails(); return self::$xdebugActive; } /** * Allows an extending class to decide if there should be a restart * * The default is to restart if Xdebug is loaded and its mode is not "off". */ protected function requiresRestart(bool $default) : bool { return $default; } /** * Allows an extending class to access the tmpIni * * @param non-empty-list $command */ protected function restart(array $command) : void { $this->doRestart($command); } /** * Executes the restarted command then deletes the tmp ini * * @param non-empty-list $command * @phpstan-return never */ private function doRestart(array $command) : void { if (\PHP_VERSION_ID >= 70400) { $cmd = $command; $displayCmd = \sprintf('[%s]', \implode(', ', $cmd)); } else { $cmd = \Composer\XdebugHandler\Process::escapeShellCommand($command); if (\defined('PHP_WINDOWS_VERSION_BUILD')) { // Outer quotes required on cmd string below PHP 8 $cmd = '"' . $cmd . '"'; } $displayCmd = $cmd; } $this->tryEnableSignals(); $this->notify(\Composer\XdebugHandler\Status::RESTARTING, $displayCmd); $process = \proc_open($cmd, [], $pipes); if (\is_resource($process)) { $exitCode = \proc_close($process); } if (!isset($exitCode)) { // Unlikely that php or the default shell cannot be invoked $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unable to restart process'); $exitCode = -1; } else { $this->notify(\Composer\XdebugHandler\Status::INFO, 'Restarted process exited ' . $exitCode); } if ($this->debug === '2') { $this->notify(\Composer\XdebugHandler\Status::INFO, 'Temp ini saved: ' . $this->tmpIni); } else { @\unlink((string) $this->tmpIni); } exit($exitCode); } /** * Returns the command line array if everything was written for the restart * * If any of the following fails (however unlikely) we must return false to * stop potential recursion: * - tmp ini file creation * - environment variable creation * * @return non-empty-list|null */ private function prepareRestart() : ?array { if (!$this->cli) { $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unsupported SAPI: ' . \PHP_SAPI); return null; } if (($argv = $this->checkServerArgv()) === null) { $this->notify(\Composer\XdebugHandler\Status::ERROR, '$_SERVER[argv] is not as expected'); return null; } if (!$this->checkConfiguration($info)) { $this->notify(\Composer\XdebugHandler\Status::ERROR, $info); return null; } $mainScript = (string) $this->script; if (!$this->checkMainScript($mainScript, $argv)) { $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unable to access main script: ' . $mainScript); return null; } $tmpDir = \sys_get_temp_dir(); $iniError = 'Unable to create temp ini file at: ' . $tmpDir; if (($tmpfile = @\tempnam($tmpDir, '')) === \false) { $this->notify(\Composer\XdebugHandler\Status::ERROR, $iniError); return null; } $error = null; $iniFiles = self::getAllIniFiles(); $scannedInis = \count($iniFiles) > 1; if (!$this->writeTmpIni($tmpfile, $iniFiles, $error)) { $this->notify(\Composer\XdebugHandler\Status::ERROR, $error ?? $iniError); @\unlink($tmpfile); return null; } if (!$this->setEnvironment($scannedInis, $iniFiles, $tmpfile)) { $this->notify(\Composer\XdebugHandler\Status::ERROR, 'Unable to set environment variables'); @\unlink($tmpfile); return null; } $this->tmpIni = $tmpfile; return $this->getCommand($argv, $tmpfile, $mainScript); } /** * Returns true if the tmp ini file was written * * @param non-empty-list $iniFiles All ini files used in the current process */ private function writeTmpIni(string $tmpFile, array $iniFiles, ?string &$error) : bool { // $iniFiles has at least one item and it may be empty if ($iniFiles[0] === '') { \array_shift($iniFiles); } $content = ''; $sectionRegex = '/^\\s*\\[(?:PATH|HOST)\\s*=/mi'; $xdebugRegex = '/^\\s*(zend_extension\\s*=.*xdebug.*)$/mi'; foreach ($iniFiles as $file) { // Check for inaccessible ini files if (($data = @\file_get_contents($file)) === \false) { $error = 'Unable to read ini: ' . $file; return \false; } // Check and remove directives after HOST and PATH sections if (Preg::isMatchWithOffsets($sectionRegex, $data, $matches)) { $data = \substr($data, 0, $matches[0][1]); } $content .= Preg::replace($xdebugRegex, ';$1', $data) . \PHP_EOL; } // Merge loaded settings into our ini content, if it is valid $config = \parse_ini_string($content); $loaded = \ini_get_all(null, \false); if (\false === $config || \false === $loaded) { $error = 'Unable to parse ini data'; return \false; } $content .= $this->mergeLoadedConfig($loaded, $config); // Work-around for https://bugs.php.net/bug.php?id=75932 $content .= 'opcache.enable_cli=0' . \PHP_EOL; return (bool) @\file_put_contents($tmpFile, $content); } /** * Returns the command line arguments for the restart * * @param non-empty-list $argv * @return non-empty-list */ private function getCommand(array $argv, string $tmpIni, string $mainScript) : array { $php = [\PHP_BINARY]; $args = \array_slice($argv, 1); if (!$this->persistent) { // Use command-line options \array_push($php, '-n', '-c', $tmpIni); } return \array_merge($php, [$mainScript], $args); } /** * Returns true if the restart environment variables were set * * No need to update $_SERVER since this is set in the restarted process. * * @param non-empty-list $iniFiles All ini files used in the current process */ private function setEnvironment(bool $scannedInis, array $iniFiles, string $tmpIni) : bool { $scanDir = \getenv('PHP_INI_SCAN_DIR'); $phprc = \getenv('PHPRC'); // Make original inis available to restarted process if (!\putenv($this->envOriginalInis . '=' . \implode(\PATH_SEPARATOR, $iniFiles))) { return \false; } if ($this->persistent) { // Use the environment to persist the settings if (!\putenv('PHP_INI_SCAN_DIR=') || !\putenv('PHPRC=' . $tmpIni)) { return \false; } } // Flag restarted process and save values for it to use $envArgs = [self::RESTART_ID, self::$xdebugVersion, (int) $scannedInis, \false === $scanDir ? '*' : $scanDir, \false === $phprc ? '*' : $phprc]; return \putenv($this->envAllowXdebug . '=' . \implode('|', $envArgs)); } /** * Logs status messages */ private function notify(string $op, ?string $data = null) : void { $this->statusWriter->report($op, $data); } /** * Returns default, changed and command-line ini settings * * @param mixed[] $loadedConfig All current ini settings * @param mixed[] $iniConfig Settings from user ini files * */ private function mergeLoadedConfig(array $loadedConfig, array $iniConfig) : string { $content = ''; foreach ($loadedConfig as $name => $value) { // Value will either be null, string or array (HHVM only) if (!\is_string($value) || \strpos($name, 'xdebug') === 0 || $name === 'apc.mmap_file_mask') { continue; } if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) { // Double-quote escape each value $content .= $name . '="' . \addcslashes($value, '\\"') . '"' . \PHP_EOL; } } return $content; } /** * Returns true if the script name can be used * * @param non-empty-list $argv */ private function checkMainScript(string &$mainScript, array $argv) : bool { if ($mainScript !== '') { // Allow an application to set -- for standard input return \file_exists($mainScript) || '--' === $mainScript; } if (\file_exists($mainScript = $argv[0])) { return \true; } // Use a backtrace to resolve Phar and chdir issues. $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); $main = \end($trace); if ($main !== \false && isset($main['file'])) { return \file_exists($mainScript = $main['file']); } return \false; } /** * Adds restart settings to the environment * * @param non-empty-list $envArgs */ private function setEnvRestartSettings(array $envArgs) : void { $settings = [\php_ini_loaded_file(), $envArgs[2], $envArgs[3], $envArgs[4], \getenv($this->envOriginalInis), self::$skipped]; \Composer\XdebugHandler\Process::setEnv(self::RESTART_SETTINGS, \implode('|', $settings)); } /** * Syncs settings and the environment if called with existing settings * * @phpstan-param restartData $settings */ private function syncSettings(array $settings) : void { if (\false === \getenv($this->envOriginalInis)) { // Called by another app, so make original inis available \Composer\XdebugHandler\Process::setEnv($this->envOriginalInis, \implode(\PATH_SEPARATOR, $settings['inis'])); } self::$skipped = $settings['skipped']; $this->notify(\Composer\XdebugHandler\Status::INFO, 'Process called with existing restart settings'); } /** * Returns true if there are no known configuration issues */ private function checkConfiguration(?string &$info) : bool { if (!\function_exists('proc_open')) { $info = 'proc_open function is disabled'; return \false; } if (!\file_exists(\PHP_BINARY)) { $info = 'PHP_BINARY is not available'; return \false; } if (\extension_loaded('uopz') && !(bool) \ini_get('uopz.disable')) { // uopz works at opcode level and disables exit calls if (\function_exists('uopz_allow_exit')) { @\uopz_allow_exit(\true); } else { $info = 'uopz extension is not compatible'; return \false; } } // Check UNC paths when using cmd.exe if (\defined('PHP_WINDOWS_VERSION_BUILD') && \PHP_VERSION_ID < 70400) { $workingDir = \getcwd(); if ($workingDir === \false) { $info = 'unable to determine working directory'; return \false; } if (0 === \strpos($workingDir, '\\\\')) { $info = 'cmd.exe does not support UNC paths: ' . $workingDir; return \false; } } return \true; } /** * Enables async signals and control interrupts in the restarted process * * Available on Unix PHP 7.1+ with the pcntl extension and Windows PHP 7.4+. */ private function tryEnableSignals() : void { if (\function_exists('pcntl_async_signals') && \function_exists('pcntl_signal')) { \pcntl_async_signals(\true); $message = 'Async signals enabled'; if (!self::$inRestart) { // Restarting, so ignore SIGINT in parent \pcntl_signal(\SIGINT, \SIG_IGN); } elseif (\is_int(\pcntl_signal_get_handler(\SIGINT))) { // Restarted, no handler set so force default action \pcntl_signal(\SIGINT, \SIG_DFL); } } if (!self::$inRestart && \function_exists('sapi_windows_set_ctrl_handler')) { // Restarting, so set a handler to ignore CTRL events in the parent. // This ensures that CTRL+C events will be available in the child // process without having to enable them there, which is unreliable. \sapi_windows_set_ctrl_handler(function ($evt) { }); } } /** * Returns $_SERVER['argv'] if it is as expected * * @return non-empty-list|null */ private function checkServerArgv() : ?array { $result = []; if (isset($_SERVER['argv']) && \is_array($_SERVER['argv'])) { foreach ($_SERVER['argv'] as $value) { if (!\is_string($value)) { return null; } $result[] = $value; } } return \count($result) > 0 ? $result : null; } /** * Sets static properties $xdebugActive, $xdebugVersion and $xdebugMode */ private static function setXdebugDetails() : void { if (self::$xdebugActive !== null) { return; } self::$xdebugActive = \false; if (!\extension_loaded('xdebug')) { return; } $version = \phpversion('xdebug'); self::$xdebugVersion = $version !== \false ? $version : 'unknown'; if (\version_compare(self::$xdebugVersion, '3.1', '>=')) { $modes = \xdebug_info('mode'); self::$xdebugMode = \count($modes) === 0 ? 'off' : \implode(',', $modes); self::$xdebugActive = self::$xdebugMode !== 'off'; return; } // See if xdebug.mode is supported in this version $iniMode = \ini_get('xdebug.mode'); if ($iniMode === \false) { self::$xdebugActive = \true; return; } // Environment value wins but cannot be empty $envMode = (string) \getenv('XDEBUG_MODE'); if ($envMode !== '') { self::$xdebugMode = $envMode; } else { self::$xdebugMode = $iniMode !== '' ? $iniMode : 'off'; } // An empty comma-separated list is treated as mode 'off' if (Preg::isMatch('/^,+$/', \str_replace(' ', '', self::$xdebugMode))) { self::$xdebugMode = 'off'; } self::$xdebugActive = self::$xdebugMode !== 'off'; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ declare (strict_types=1); namespace Composer\XdebugHandler; use Composer\Pcre\Preg; /** * Process utility functions * * @author John Stevenson */ class Process { /** * Escapes a string to be used as a shell argument. * * From https://github.com/johnstevenson/winbox-args * MIT Licensed (c) John Stevenson * * @param string $arg The argument to be escaped * @param bool $meta Additionally escape cmd.exe meta characters * @param bool $module The argument is the module to invoke */ public static function escape(string $arg, bool $meta = \true, bool $module = \false) : string { if (!\defined('PHP_WINDOWS_VERSION_BUILD')) { return "'" . \str_replace("'", "'\\''", $arg) . "'"; } $quote = \strpbrk($arg, " \t") !== \false || $arg === ''; $arg = Preg::replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes); $dquotes = (bool) $dquotes; if ($meta) { $meta = $dquotes || Preg::isMatch('/%[^%]+%/', $arg); if (!$meta) { $quote = $quote || \strpbrk($arg, '^&|<>()') !== \false; } elseif ($module && !$dquotes && $quote) { $meta = \false; } } if ($quote) { $arg = '"' . Preg::replace('/(\\\\*)$/', '$1$1', $arg) . '"'; } if ($meta) { $arg = Preg::replace('/(["^&|<>()%])/', '^$1', $arg); } return $arg; } /** * Escapes an array of arguments that make up a shell command * * @param string[] $args Argument list, with the module name first */ public static function escapeShellCommand(array $args) : string { $command = ''; $module = \array_shift($args); if ($module !== null) { $command = self::escape($module, \true, \true); foreach ($args as $arg) { $command .= ' ' . self::escape($arg); } } return $command; } /** * Makes putenv environment changes available in $_SERVER and $_ENV * * @param string $name * @param ?string $value A null value unsets the variable */ public static function setEnv(string $name, ?string $value = null) : bool { $unset = null === $value; if (!\putenv($unset ? $name : $name . '=' . $value)) { return \false; } if ($unset) { unset($_SERVER[$name]); } else { $_SERVER[$name] = $value; } // Update $_ENV if it is being used if (\false !== \stripos((string) \ini_get('variables_order'), 'E')) { if ($unset) { unset($_ENV[$name]); } else { $_ENV[$name] = $value; } } return \true; } } Copyright (C) 2022 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. composer/class-map-generator ============================ Utilities to generate class maps and scan PHP code. [![Continuous Integration](https://github.com/composer/class-map-generator/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/composer/class-map-generator/actions) Installation ------------ Install the latest version with: ```bash composer require composer/class-map-generator ``` Requirements ------------ * PHP 7.2 is required. Basic usage ----------- If all you want is to scan a directory and extract a classmap with all classes/interfaces/traits/enums mapped to their paths, you can simply use: ```php use Composer\ClassMapGenerator\ClassMapGenerator; $map = ClassMapGenerator::createMap('path/to/scan'); foreach ($map as $symbol => $path) { // do your thing } ``` For more advanced usage, you can instantiate a generator object and call scanPaths one or more time then call getClassMap to get a ClassMap object containing the resulting map + eventual warnings. ```php use Composer\ClassMapGenerator\ClassMapGenerator; $generator = new ClassMapGenerator; $generator->scanPaths('path/to/scan'); $generator->scanPaths('path/to/scan2'); $classMap = $generator->getClassMap(); $classMap->sort(); // optionally sort classes alphabetically foreach ($classMap->getMap() as $symbol => $path) { // do your thing } foreach ($classMap->getAmbiguousClasses() as $symbol => $paths) { // warn user about ambiguous class resolution } ``` License ------- composer/class-map-generator is licensed under the MIT License, see the LICENSE file for details. { "name": "composer\/class-map-generator", "description": "Utilities to scan PHP code and generate class maps.", "type": "library", "license": "MIT", "keywords": [ "classmap" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "https:\/\/seld.be" } ], "require": { "php": "^7.2 || ^8.0", "symfony\/finder": "^4.4 || ^5.3 || ^6 || ^7", "composer\/pcre": "^2.1 || ^3.1" }, "require-dev": { "phpunit\/phpunit": "^8", "phpstan\/phpstan": "^1.12 || ^2", "phpstan\/phpstan-deprecation-rules": "^1 || ^2", "phpstan\/phpstan-strict-rules": "^1.1 || ^2", "phpstan\/phpstan-phpunit": "^1 || ^2", "symfony\/filesystem": "^5.4 || ^6" }, "autoload": { "psr-4": { "Composer\\ClassMapGenerator\\": "src" } }, "autoload-dev": { "psr-4": { "Composer\\ClassMapGenerator\\": "tests" } }, "extra": { "branch-alias": { "dev-main": "1.x-dev" } }, "scripts": { "test": "@php phpunit", "phpstan": "@php phpstan analyse" } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * This file was initially based on a version from the Symfony package. * * (c) Fabien Potencier */ namespace Composer\ClassMapGenerator; use Composer\Pcre\Preg; use _ContaoManager\Symfony\Component\Finder\Finder; use Composer\IO\IOInterface; /** * ClassMapGenerator * * @author Gyula Sallai * @author Jordi Boggiano */ class ClassMapGenerator { /** * @var list */ private $extensions; /** * @var FileList|null */ private $scannedFiles = null; /** * @var ClassMap */ private $classMap; /** * @var non-empty-string */ private $streamWrappersRegex; /** * @param list $extensions File extensions to scan for classes in the given paths */ public function __construct(array $extensions = ['php', 'inc']) { $this->extensions = $extensions; $this->classMap = new \Composer\ClassMapGenerator\ClassMap(); $this->streamWrappersRegex = \sprintf('{^(?:%s)://}', \implode('|', \array_map('preg_quote', \stream_get_wrappers()))); } /** * When calling scanPaths repeatedly with paths that may overlap, calling this will ensure that the same class is never scanned twice * * You can provide your own FileList instance or use the default one if you pass no argument * * @return $this */ public function avoidDuplicateScans(?\Composer\ClassMapGenerator\FileList $scannedFiles = null) : self { $this->scannedFiles = $scannedFiles ?? new \Composer\ClassMapGenerator\FileList(); return $this; } /** * Iterate over all files in the given directory searching for classes * * @param string|\Traversable<\SplFileInfo>|array<\SplFileInfo> $path The path to search in or an array/traversable of SplFileInfo (e.g. symfony/finder instance) * @return array A class map array * * @throws \RuntimeException When the path is neither an existing file nor directory */ public static function createMap($path) : array { $generator = new self(); $generator->scanPaths($path); return $generator->getClassMap()->getMap(); } public function getClassMap() : \Composer\ClassMapGenerator\ClassMap { return $this->classMap; } /** * Iterate over all files in the given directory searching for classes * * @param string|\Traversable<\SplFileInfo>|array<\SplFileInfo> $path The path to search in or an array/traversable of SplFileInfo (e.g. symfony/finder instance) * @param non-empty-string|null $excluded Regex that matches file paths to be excluded from the classmap * @param 'classmap'|'psr-0'|'psr-4' $autoloadType Optional autoload standard to use mapping rules with the namespace instead of purely doing a classmap * @param string|null $namespace Optional namespace prefix to filter by, only for psr-0/psr-4 autoloading * @param array $excludedDirs Optional dirs to exclude from search relative to $path * * @throws \RuntimeException When the path is neither an existing file nor directory */ public function scanPaths($path, ?string $excluded = null, string $autoloadType = 'classmap', ?string $namespace = null, array $excludedDirs = []) : void { if (!\in_array($autoloadType, ['psr-0', 'psr-4', 'classmap'], \true)) { throw new \InvalidArgumentException('$autoloadType must be one of: "psr-0", "psr-4" or "classmap"'); } if ('classmap' !== $autoloadType) { if (!\is_string($path)) { throw new \InvalidArgumentException('$path must be a string when specifying a psr-0 or psr-4 autoload type'); } if (!\is_string($namespace)) { throw new \InvalidArgumentException('$namespace must be given (even if it is an empty string if you do not want to filter) when specifying a psr-0 or psr-4 autoload type'); } $basePath = $path; } if (\is_string($path)) { if (\is_file($path)) { $path = [new \SplFileInfo($path)]; } elseif (\is_dir($path) || \strpos($path, '*') !== \false) { $path = Finder::create()->files()->followLinks()->name('/\\.(?:' . \implode('|', \array_map('preg_quote', $this->extensions)) . ')$/')->in($path)->exclude($excludedDirs); } else { throw new \RuntimeException('Could not scan for classes inside "' . $path . '" which does not appear to be a file nor a folder'); } } $cwd = \realpath(self::getCwd()); foreach ($path as $file) { $filePath = $file->getPathname(); if (!\in_array(\pathinfo($filePath, \PATHINFO_EXTENSION), $this->extensions, \true)) { continue; } $isStreamWrapperPath = Preg::isMatch($this->streamWrappersRegex, $filePath); if (!self::isAbsolutePath($filePath) && !$isStreamWrapperPath) { $filePath = $cwd . '/' . $filePath; $filePath = self::normalizePath($filePath); } else { $filePath = Preg::replace('{(?getPathname()); } $realPath = $isStreamWrapperPath ? $filePath : \realpath($filePath); // fallback just in case but this really should not happen if (\false === $realPath) { throw new \RuntimeException('realpath of ' . $filePath . ' failed to resolve, got false'); } // if a list of scanned files is given, avoid scanning twice the same file to save cycles and avoid generating warnings // in case a PSR-0/4 declaration follows another more specific one, or a classmap declaration, which covered this file already if ($this->scannedFiles !== null && $this->scannedFiles->contains($realPath)) { continue; } // check the realpath of the file against the excluded paths as the path might be a symlink and the excluded path is realpath'd so symlink are resolved if (null !== $excluded && Preg::isMatch($excluded, \strtr($realPath, '\\', '/'))) { continue; } // check non-realpath of file for directories symlink in project dir if (null !== $excluded && Preg::isMatch($excluded, \strtr($filePath, '\\', '/'))) { continue; } $classes = \Composer\ClassMapGenerator\PhpFileParser::findClasses($filePath); if ('classmap' !== $autoloadType && isset($namespace)) { $classes = $this->filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath); // if no valid class was found in the file then we do not mark it as scanned as it might still be matched by another rule later if (\count($classes) > 0 && $this->scannedFiles !== null) { $this->scannedFiles->add($realPath); } } elseif ($this->scannedFiles !== null) { // classmap autoload rules always collect all classes so for these we definitely do not want to scan again $this->scannedFiles->add($realPath); } foreach ($classes as $class) { if (!$this->classMap->hasClass($class)) { $this->classMap->addClass($class, $filePath); } elseif ($filePath !== $this->classMap->getClassPath($class)) { $this->classMap->addAmbiguousClass($class, $filePath); } } } } /** * Remove classes which could not have been loaded by namespace autoloaders * * @param array $classes found classes in given file * @param string $filePath current file * @param string $baseNamespace prefix of given autoload mapping * @param 'psr-0'|'psr-4' $namespaceType * @param string $basePath root directory of given autoload mapping * @return array valid classes * * @throws \InvalidArgumentException When namespaceType is neither psr-0 nor psr-4 */ private function filterByNamespace(array $classes, string $filePath, string $baseNamespace, string $namespaceType, string $basePath) : array { $validClasses = []; $rejectedClasses = []; $realSubPath = \substr($filePath, \strlen($basePath) + 1); $dotPosition = \strrpos($realSubPath, '.'); $realSubPath = \substr($realSubPath, 0, $dotPosition === \false ? \PHP_INT_MAX : $dotPosition); foreach ($classes as $class) { // transform class name to file path and validate if ('psr-0' === $namespaceType) { $namespaceLength = \strrpos($class, '\\'); if (\false !== $namespaceLength) { $namespace = \substr($class, 0, $namespaceLength + 1); $className = \substr($class, $namespaceLength + 1); $subPath = \str_replace('\\', \DIRECTORY_SEPARATOR, $namespace) . \str_replace('_', \DIRECTORY_SEPARATOR, $className); } else { $subPath = \str_replace('_', \DIRECTORY_SEPARATOR, $class); } } elseif ('psr-4' === $namespaceType) { $subNamespace = '' !== $baseNamespace ? \substr($class, \strlen($baseNamespace)) : $class; $subPath = \str_replace('\\', \DIRECTORY_SEPARATOR, $subNamespace); } else { throw new \InvalidArgumentException('$namespaceType must be "psr-0" or "psr-4"'); } if ($subPath === $realSubPath) { $validClasses[] = $class; } else { $rejectedClasses[] = $class; } } // warn only if no valid classes, else silently skip invalid if (\count($validClasses) === 0) { $cwd = \realpath(self::getCwd()); if ($cwd === \false) { $cwd = self::getCwd(); } $cwd = self::normalizePath($cwd); $shortPath = Preg::replace('{^' . \preg_quote($cwd) . '}', '.', self::normalizePath($filePath), 1); $shortBasePath = Preg::replace('{^' . \preg_quote($cwd) . '}', '.', self::normalizePath($basePath), 1); foreach ($rejectedClasses as $class) { $this->classMap->addPsrViolation("Class {$class} located in {$shortPath} does not comply with {$namespaceType} autoloading standard (rule: {$baseNamespace} => {$shortBasePath}). Skipping.", $class, $filePath); } return []; } return $validClasses; } /** * Checks if the given path is absolute * * @see Composer\Util\Filesystem::isAbsolutePath * * @param string $path * @return bool */ private static function isAbsolutePath(string $path) { return \strpos($path, '/') === 0 || \substr($path, 1, 1) === ':' || \strpos($path, '\\\\') === 0; } /** * Normalize a path. This replaces backslashes with slashes, removes ending * slash and collapses redundant separators and up-level references. * * @see Composer\Util\Filesystem::normalizePath * * @param string $path Path to the file or directory * @return string */ private static function normalizePath(string $path) { $parts = []; $path = \strtr($path, '\\', '/'); $prefix = ''; $absolute = ''; // extract windows UNC paths e.g. \\foo\bar if (\strpos($path, '//') === 0 && \strlen($path) > 2) { $absolute = '//'; $path = \substr($path, 2); } // extract a prefix being a protocol://, protocol:, protocol://drive: or simply drive: if (Preg::isMatchStrictGroups('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) { $prefix = $match[1]; $path = \substr($path, \strlen($prefix)); } if (\strpos($path, '/') === 0) { $absolute = '/'; $path = \substr($path, 1); } $up = \false; foreach (\explode('/', $path) as $chunk) { if ('..' === $chunk && (\strlen($absolute) > 0 || $up)) { \array_pop($parts); $up = !(\count($parts) === 0 || '..' === \end($parts)); } elseif ('.' !== $chunk && '' !== $chunk) { $parts[] = $chunk; $up = '..' !== $chunk; } } // ensure c: is normalized to C: $prefix = Preg::replaceCallback('{(?:^|://)[a-z]:$}i', function (array $m) { return \strtoupper((string) $m[0]); }, $prefix); return $prefix . $absolute . \implode('/', $parts); } /** * @see Composer\Util\Platform::getCwd */ private static function getCwd() : string { $cwd = \getcwd(); if (\false === $cwd) { throw new \RuntimeException('Could not determine the current working directory'); } return $cwd; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\ClassMapGenerator; use Composer\Pcre\Preg; /** * @author Jordi Boggiano * @internal */ class PhpFileCleaner { /** @var array */ private static $typeConfig; /** @var non-empty-string */ private static $restPattern; /** * @readonly * @var string */ private $contents; /** * @readonly * @var int */ private $len; /** * @readonly * @var int */ private $maxMatches; /** @var int */ private $index = 0; /** * @param string[] $types */ public static function setTypeConfig(array $types) : void { foreach ($types as $type) { self::$typeConfig[$type[0]] = array('name' => $type, 'length' => \strlen($type), 'pattern' => '{.\\b(?])' . $type . '\\s++[a-zA-Z_\\x7f-\\xff:][a-zA-Z0-9_\\x7f-\\xff:\\-]*+}Ais'); } self::$restPattern = '{[^?"\'contents = $contents; $this->len = \strlen($this->contents); $this->maxMatches = $maxMatches; } public function clean() : string { $clean = ''; while ($this->index < $this->len) { $this->skipToPhp(); $clean .= 'index < $this->len) { $char = $this->contents[$this->index]; if ($char === '?' && $this->peek('>')) { $clean .= '?>'; $this->index += 2; continue 2; } if ($char === '"') { $this->skipString('"'); $clean .= 'null'; continue; } if ($char === "'") { $this->skipString("'"); $clean .= 'null'; continue; } if ($char === "<" && $this->peek('<') && $this->match('{<<<[ \\t]*+([\'"]?)([a-zA-Z_\\x80-\\xff][a-zA-Z0-9_\\x80-\\xff]*+)\\1(?:\\r\\n|\\n|\\r)}A', $match)) { $this->index += \strlen($match[0]); $this->skipHeredoc($match[2]); $clean .= 'null'; continue; } if ($char === '/') { if ($this->peek('/')) { $this->skipToNewline(); continue; } if ($this->peek('*')) { $this->skipComment(); continue; } } if ($this->maxMatches === 1 && isset(self::$typeConfig[$char])) { $type = self::$typeConfig[$char]; if (\substr($this->contents, $this->index, $type['length']) === $type['name'] && Preg::isMatch($type['pattern'], $this->contents, $match, 0, $this->index - 1)) { $clean .= $match[0]; return $clean; } } $this->index += 1; if ($this->match(self::$restPattern, $match)) { $clean .= $char . $match[0]; $this->index += \strlen($match[0]); } else { $clean .= $char; } } } return $clean; } private function skipToPhp() : void { while ($this->index < $this->len) { if ($this->contents[$this->index] === '<' && $this->peek('?')) { $this->index += 2; break; } $this->index += 1; } } private function skipString(string $delimiter) : void { $this->index += 1; while ($this->index < $this->len) { if ($this->contents[$this->index] === '\\' && ($this->peek('\\') || $this->peek($delimiter))) { $this->index += 2; continue; } if ($this->contents[$this->index] === $delimiter) { $this->index += 1; break; } $this->index += 1; } } private function skipComment() : void { $this->index += 2; while ($this->index < $this->len) { if ($this->contents[$this->index] === '*' && $this->peek('/')) { $this->index += 2; break; } $this->index += 1; } } private function skipToNewline() : void { while ($this->index < $this->len) { if ($this->contents[$this->index] === "\r" || $this->contents[$this->index] === "\n") { return; } $this->index += 1; } } private function skipHeredoc(string $delimiter) : void { $firstDelimiterChar = $delimiter[0]; $delimiterLength = \strlen($delimiter); $delimiterPattern = '{' . \preg_quote($delimiter) . '(?![a-zA-Z0-9_\\x80-\\xff])}A'; while ($this->index < $this->len) { // check if we find the delimiter after some spaces/tabs switch ($this->contents[$this->index]) { case "\t": case " ": $this->index += 1; continue 2; case $firstDelimiterChar: if (\substr($this->contents, $this->index, $delimiterLength) === $delimiter && $this->match($delimiterPattern)) { $this->index += $delimiterLength; return; } break; } // skip the rest of the line while ($this->index < $this->len) { $this->skipToNewline(); // skip newlines while ($this->index < $this->len && ($this->contents[$this->index] === "\r" || $this->contents[$this->index] === "\n")) { $this->index += 1; } break; } } } private function peek(string $char) : bool { return $this->index + 1 < $this->len && $this->contents[$this->index + 1] === $char; } /** * @param non-empty-string $regex * @param null|array $match * @param-out array $match */ private function match(string $regex, ?array &$match = null) : bool { return Preg::isMatchStrictGroups($regex, $this->contents, $match, 0, $this->index); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\ClassMapGenerator; /** * Contains a list of files which were scanned to generate a classmap * * @author Jordi Boggiano */ class FileList { /** * @var array */ public $files = []; /** * @param non-empty-string $path */ public function add(string $path) : void { $this->files[$path] = \true; } /** * @param non-empty-string $path */ public function contains(string $path) : bool { return isset($this->files[$path]); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\ClassMapGenerator; use Composer\Pcre\Preg; /** * @author Jordi Boggiano */ class PhpFileParser { /** * Extract the classes in the given file * * @param string $path The file to check * @throws \RuntimeException * @return list The found classes */ public static function findClasses(string $path) : array { $extraTypes = self::getExtraTypes(); // Use @ here instead of Silencer to actively suppress 'unhelpful' output // @link https://github.com/composer/composer/pull/4886 $contents = @\php_strip_whitespace($path); if ('' === $contents) { if (!\file_exists($path)) { $message = 'File at "%s" does not exist, check your classmap definitions'; } elseif (!self::isReadable($path)) { $message = 'File at "%s" is not readable, check its permissions'; } elseif ('' === \trim((string) \file_get_contents($path))) { // The input file was really empty and thus contains no classes return array(); } else { $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted'; } $error = \error_get_last(); if (isset($error['message'])) { $message .= \PHP_EOL . 'The following message may be helpful:' . \PHP_EOL . $error['message']; } throw new \RuntimeException(\sprintf($message, $path)); } // return early if there is no chance of matching anything in this file Preg::matchAllStrictGroups('{\\b(?:class|interface|trait' . $extraTypes . ')\\s}i', $contents, $matches); if (0 === \count($matches)) { return array(); } $p = new \Composer\ClassMapGenerator\PhpFileCleaner($contents, \count($matches[0])); $contents = $p->clean(); unset($p); Preg::matchAll('{ (?: \\b(?])(?Pclass|interface|trait' . $extraTypes . ') \\s++ (?P[a-zA-Z_\\x7f-\\xff:][a-zA-Z0-9_\\x7f-\\xff:\\-]*+) | \\b(?])(?Pnamespace) (?P\\s++[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+(?:\\s*+\\\\\\s*+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+)*+)? \\s*+ [\\{;] ) }ix', $contents, $matches); $classes = array(); $namespace = ''; for ($i = 0, $len = \count($matches['type']); $i < $len; $i++) { if (isset($matches['ns'][$i]) && $matches['ns'][$i] !== '') { $namespace = \str_replace(array(' ', "\t", "\r", "\n"), '', (string) $matches['nsname'][$i]) . '\\'; } else { $name = $matches['name'][$i]; \assert(\is_string($name)); // skip anon classes extending/implementing if ($name === 'extends' || $name === 'implements') { continue; } if ($name[0] === ':') { // This is an XHP class, https://github.com/facebook/xhp $name = 'xhp' . \substr(\str_replace(array('-', ':'), array('_', '__'), $name), 1); } elseif (\strtolower((string) $matches['type'][$i]) === 'enum') { // something like: // enum Foo: int { HERP = '123'; } // The regex above captures the colon, which isn't part of // the class name. // or: // enum Foo:int { HERP = '123'; } // The regex above captures the colon and type, which isn't part of // the class name. $colonPos = \strrpos($name, ':'); if (\false !== $colonPos) { $name = \substr($name, 0, $colonPos); } } /** @var class-string */ $className = \ltrim($namespace . $name, '\\'); $classes[] = $className; } } return $classes; } /** * @return string */ private static function getExtraTypes() : string { static $extraTypes = null; if (null === $extraTypes) { $extraTypes = ''; if (\PHP_VERSION_ID >= 80100 || \defined('_ContaoManager\\HHVM_VERSION') && \version_compare(HHVM_VERSION, '3.3', '>=')) { $extraTypes .= '|enum'; } $extraTypesArray = \array_filter(\explode('|', $extraTypes), function (string $type) { return $type !== ''; }); \Composer\ClassMapGenerator\PhpFileCleaner::setTypeConfig(\array_merge(['class', 'interface', 'trait'], $extraTypesArray)); } return $extraTypes; } /** * Cross-platform safe version of is_readable() * * This will also check for readability by reading the file as is_readable can not be trusted on network-mounts * and \\wsl$ paths. See https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926 * * @see Composer\Util\Filesystem::isReadable * * @param string $path * @return bool */ private static function isReadable(string $path) { if (\is_readable($path)) { return \true; } if (\is_file($path)) { return \false !== @\file_get_contents($path, \false, null, 0, 1); } // assume false otherwise return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\ClassMapGenerator; use Composer\Pcre\Preg; /** * @author Jordi Boggiano */ class ClassMap implements \Countable { /** * @var array */ public $map = []; /** * @var array> */ private $ambiguousClasses = []; /** * @var array> */ private $psrViolations = []; /** * Returns the class map, which is a list of paths indexed by class name * * @return array */ public function getMap() : array { return $this->map; } /** * Returns warning strings containing details about PSR-0/4 violations that were detected * * Violations are for ex a class which is in the wrong file/directory and thus should not be * found using psr-0/psr-4 autoloading but was found by the ClassMapGenerator as it scans all files. * * This is only happening when scanning paths using psr-0/psr-4 autoload type. Classmap type * always accepts every class as it finds it. * * @return string[] */ public function getPsrViolations() : array { if (\count($this->psrViolations) === 0) { return []; } return \array_map(static function (array $violation) : string { return $violation['warning']; }, \array_merge(...\array_values($this->psrViolations))); } /** * A map of class names to their list of ambiguous paths * * This occurs when the same class can be found in several files * * To get the path the class is being mapped to, call getClassPath * * By default, paths that contain test(s), fixture(s), example(s) or stub(s) are ignored * as those are typically not problematic when they're dummy classes in the tests folder. * If you want to get these back as well you can pass false to $duplicatesFilter. Or * you can pass your own pattern to exclude if you need to change the default. * * @param non-empty-string|false $duplicatesFilter * * @return array> */ public function getAmbiguousClasses($duplicatesFilter = '{/(test|fixture|example|stub)s?/}i') : array { if (\false === $duplicatesFilter) { return $this->ambiguousClasses; } if (\true === $duplicatesFilter) { throw new \InvalidArgumentException('$duplicatesFilter should be false or a string with a valid regex, got true.'); } $ambiguousClasses = []; foreach ($this->ambiguousClasses as $class => $paths) { $paths = \array_filter($paths, function ($path) use($duplicatesFilter) { return !Preg::isMatch($duplicatesFilter, \strtr($path, '\\', '/')); }); if (\count($paths) > 0) { $ambiguousClasses[$class] = \array_values($paths); } } return $ambiguousClasses; } /** * Sorts the class map alphabetically by class names */ public function sort() : void { \ksort($this->map); } /** * @param class-string $className * @param non-empty-string $path */ public function addClass(string $className, string $path) : void { unset($this->psrViolations[\strtr($path, '\\', '/')]); $this->map[$className] = $path; } /** * @param class-string $className * @return non-empty-string */ public function getClassPath(string $className) : string { if (!isset($this->map[$className])) { throw new \OutOfBoundsException('Class ' . $className . ' is not present in the map'); } return $this->map[$className]; } /** * @param class-string $className */ public function hasClass(string $className) : bool { return isset($this->map[$className]); } public function addPsrViolation(string $warning, string $className, string $path) : void { $path = \rtrim(\strtr($path, '\\', '/'), '/'); $this->psrViolations[$path][] = ['warning' => $warning, 'className' => $className]; } public function clearPsrViolationsByPath(string $pathPrefix) : void { $pathPrefix = \rtrim(\strtr($pathPrefix, '\\', '/'), '/'); foreach ($this->psrViolations as $path => $violations) { if ($path === $pathPrefix || 0 === \strpos($path, $pathPrefix . '/')) { unset($this->psrViolations[$path]); } } } /** * @param class-string $className * @param non-empty-string $path */ public function addAmbiguousClass(string $className, string $path) : void { $this->ambiguousClasses[$className][] = $path; } public function count() : int { return \count($this->map); } /** * Get the raw psr violations * * This is a map of filepath to an associative array of the warning string * and the offending class name. * @return array> */ public function getRawPsrViolations() : array { return $this->psrViolations; } } 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. * 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 \Closure(string):void */ private static $includeFile; /** @var string|null */ private $vendorDir; // PSR-4 /** * @var array> */ private $prefixLengthsPsr4 = array(); /** * @var array> */ private $prefixDirsPsr4 = array(); /** * @var list */ private $fallbackDirsPsr4 = array(); // PSR-0 /** * List of PSR-0 prefixes * * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) * * @var array>> */ private $prefixesPsr0 = array(); /** * @var list */ private $fallbackDirsPsr0 = array(); /** @var bool */ private $useIncludePath = false; /** * @var array */ private $classMap = array(); /** @var bool */ private $classMapAuthoritative = false; /** * @var array */ private $missingClasses = array(); /** @var string|null */ private $apcuPrefix; /** * @var array */ private static $registeredLoaders = array(); /** * @param string|null $vendorDir */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; self::initializeIncludeClosure(); } /** * @return array> */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); } /** * @return array> */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } /** * @return list */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } /** * @return list */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } /** * @return array Array of classname => path */ public function getClassMap() { return $this->classMap; } /** * @param array $classMap Class to filename map * * @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 list|string $paths The PSR-0 root directories * @param bool $prepend Whether to prepend the directories * * @return void */ public function add($prefix, $paths, $prepend = false) { $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, $paths ); } return; } $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], $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 list|string $paths The PSR-4 base directories * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException * * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, $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] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], $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 list|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 list|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 = self::$includeFile; $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 keyed by their corresponding vendor directories. * * @return array */ public static function getRegisteredLoaders() { return self::$registeredLoaders; } /** * @param string $class * @param string $ext * @return string|false */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup $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; } /** * @return void */ private static function initializeIncludeClosure() { if (self::$includeFile !== null) { return; } /** * Scope isolated include. * * Prevents access to $this/self from included files. * * @param string $file * @return void */ self::$includeFile = \Closure::bind(static function($file) { include $file; }, null, null); } } # Composer-specific PHPStan extensions # # These can be reused by third party packages by including 'vendor/composer/composer/phpstan/rules.neon' # in your phpstan config services: - class: Composer\PHPStan\ConfigReturnTypeExtension tags: - phpstan.broker.dynamicMethodReturnTypeExtension - class: Composer\PHPStan\RuleReasonDataReturnTypeExtension tags: - phpstan.broker.dynamicMethodReturnTypeExtension { "$schema": "https://json-schema.org/draft-04/schema#", "title": "Composer Package", "type": "object", "properties": { "name": { "type": "string", "description": "Package name, including 'vendor-name/' prefix.", "pattern": "^[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$" }, "description": { "type": "string", "description": "Short package description." }, "license": { "type": ["string", "array"], "description": "License name. Or an array of license names." }, "type": { "description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.", "type": "string", "pattern": "^[a-z0-9-]+$" }, "abandoned": { "type": ["boolean", "string"], "description": "Indicates whether this package has been abandoned, it can be boolean or a package name/URL pointing to a recommended alternative. Defaults to false." }, "version": { "type": "string", "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.", "pattern": "^v?\\d+(\\.\\d+){0,3}|^dev-" }, "default-branch": { "type": ["boolean"], "description": "Internal use only, do not specify this in composer.json. Indicates whether this version is the default branch of the linked VCS repository. Defaults to false." }, "non-feature-branches": { "type": ["array"], "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.", "items": { "type": "string" } }, "keywords": { "type": "array", "items": { "type": "string", "description": "A tag/keyword that this package relates to." } }, "readme": { "type": "string", "description": "Relative path to the readme document." }, "time": { "type": "string", "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format." }, "authors": { "$ref": "#/definitions/authors" }, "homepage": { "type": "string", "description": "Homepage URL for the project.", "format": "uri" }, "support": { "type": "object", "properties": { "email": { "type": "string", "description": "Email address for support.", "format": "email" }, "issues": { "type": "string", "description": "URL to the issue tracker.", "format": "uri" }, "forum": { "type": "string", "description": "URL to the forum.", "format": "uri" }, "wiki": { "type": "string", "description": "URL to the wiki.", "format": "uri" }, "irc": { "type": "string", "description": "IRC channel for support, as irc://server/channel.", "format": "uri" }, "chat": { "type": "string", "description": "URL to the support chat.", "format": "uri" }, "source": { "type": "string", "description": "URL to browse or download the sources.", "format": "uri" }, "docs": { "type": "string", "description": "URL to the documentation.", "format": "uri" }, "rss": { "type": "string", "description": "URL to the RSS feed.", "format": "uri" }, "security": { "type": "string", "description": "URL to the vulnerability disclosure policy (VDP).", "format": "uri" } } }, "funding": { "type": "array", "description": "A list of options to fund the development and maintenance of the package.", "items": { "type": "object", "properties": { "type": { "type": "string", "description": "Type of funding or platform through which funding is possible." }, "url": { "type": "string", "description": "URL to a website with details on funding and a way to fund the package.", "format": "uri" } } } }, "source": { "$ref": "#/definitions/source" }, "dist": { "$ref": "#/definitions/dist" }, "_comment": { "type": ["array", "string"], "description": "A key to store comments in" }, "require": { "type": "object", "description": "This is an object of package name (keys) and version constraints (values) that are required to run this package.", "additionalProperties": { "type": "string" } }, "require-dev": { "type": "object", "description": "This is an object of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).", "additionalProperties": { "type": "string" } }, "replace": { "type": "object", "description": "This is an object of package name (keys) and version constraints (values) that can be replaced by this package.", "additionalProperties": { "type": "string" } }, "conflict": { "type": "object", "description": "This is an object of package name (keys) and version constraints (values) that conflict with this package.", "additionalProperties": { "type": "string" } }, "provide": { "type": "object", "description": "This is an object of package name (keys) and version constraints (values) that this package provides in addition to this package's name.", "additionalProperties": { "type": "string" } }, "suggest": { "type": "object", "description": "This is an object of package name (keys) and descriptions (values) that this package suggests work well with it (this will be suggested to the user during installation).", "additionalProperties": { "type": "string" } }, "repositories": { "type": ["object", "array"], "description": "A set of additional repositories where packages can be found.", "additionalProperties": { "anyOf": [ { "$ref": "#/definitions/repository" }, { "type": "boolean", "enum": [false] } ] }, "items": { "anyOf": [ { "$ref": "#/definitions/repository" }, { "type": "object", "additionalProperties": { "type": "boolean", "enum": [false] }, "minProperties": 1, "maxProperties": 1 } ] } }, "minimum-stability": { "type": ["string"], "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.", "enum": ["dev", "alpha", "beta", "rc", "RC", "stable"] }, "prefer-stable": { "type": ["boolean"], "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages." }, "autoload": { "$ref": "#/definitions/autoload" }, "autoload-dev": { "type": "object", "description": "Description of additional autoload rules for development purpose (eg. a test suite).", "properties": { "psr-0": { "type": "object", "description": "This is an object of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.", "additionalProperties": { "type": ["string", "array"], "items": { "type": "string" } } }, "psr-4": { "type": "object", "description": "This is an object of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", "additionalProperties": { "type": ["string", "array"], "items": { "type": "string" } } }, "classmap": { "type": "array", "description": "This is an array of paths that contain classes to be included in the class-map generation process." }, "files": { "type": "array", "description": "This is an array of files that are always required on every request." } } }, "target-dir": { "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.", "type": "string" }, "include-path": { "type": ["array"], "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.", "items": { "type": "string" } }, "bin": { "type": ["string", "array"], "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).", "items": { "type": "string" } }, "archive": { "type": ["object"], "description": "Options for creating package archives for distribution.", "properties": { "name": { "type": "string", "description": "A base name for archive." }, "exclude": { "type": "array", "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark." } } }, "php-ext": { "type": "object", "description": "Settings for PHP extension packages.", "properties": { "extension-name": { "type": "string", "description": "If specified, this will be used as the name of the extension, where needed by tooling. If this is not specified, the extension name will be derived from the Composer package name (e.g. `vendor/name` would become `ext-name`). The extension name may be specified with or without the `ext-` prefix, and tools that use this must normalise this appropriately.", "example": "ext-xdebug" }, "priority": { "type": "integer", "description": "This is used to add a prefix to the INI file, e.g. `90-xdebug.ini` which affects the loading order. The priority is a number in the range 10-99 inclusive, with 10 being the highest priority (i.e. will be processed first), and 99 being the lowest priority (i.e. will be processed last). There are two digits so that the files sort correctly on any platform, whether the sorting is natural or not.", "minimum": 10, "maximum": 99, "example": 80, "default": 80 }, "support-zts": { "type": "boolean", "description": "Does this package support Zend Thread Safety", "example": false, "default": true }, "support-nts": { "type": "boolean", "description": "Does this package support non-Thread Safe mode", "example": false, "default": true }, "build-path": { "type": ["string", "null"], "description": "If specified, this is the subdirectory that will be used to build the extension instead of the root of the project.", "example": "my-extension-source", "default": null }, "os-families": { "type": "array", "minItems": 1, "description": "An array of OS families to mark as compatible with the extension. Specifying this property will mean this package is not installable with PIE on any OS family not listed here. Must not be specified alongside os-families-exclude.", "items": { "type": "string", "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"], "description": "The name of the OS family to mark as compatible." } }, "os-families-exclude": { "type": "array", "minItems": 1, "description": "An array of OS families to mark as incompatible with the extension. Specifying this property will mean this package is installable on any OS family except those listed here. Must not be specified alongside os-families.", "items": { "type": "string", "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"], "description": "The name of the OS family to exclude." } }, "configure-options": { "type": "array", "description": "These configure options make up the flags that can be passed to ./configure when installing the extension.", "items": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "description": "The name of the flag, this would typically be prefixed with `--`, for example, the value 'the-flag' would be passed as `./configure --the-flag`.", "example": "without-xdebug-compression", "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]*$" }, "needs-value": { "type": "boolean", "description": "If this is set to true, the flag needs a value (e.g. --with-somelib=), otherwise it is a flag without a value (e.g. --enable-some-feature).", "example": false, "default": false }, "description": { "type": "string", "description": "The description of what the flag does or means.", "example": "Disable compression through zlib" } } } } }, "allOf": [ { "not": { "required": ["os-families", "os-families-exclude"] } } ] }, "config": { "type": "object", "description": "Composer options.", "properties": { "platform": { "type": "object", "description": "This is an object of package name (keys) and version (values) that will be used to mock the platform packages on this machine, the version can be set to false to make it appear like the package is not present.", "additionalProperties": { "type": ["string", "boolean"] } }, "allow-plugins": { "type": ["object", "boolean"], "description": "This is an object of {\"pattern\": true|false} with packages which are allowed to be loaded as plugins, or true to allow all, false to allow none. Defaults to {} which prompts when an unknown plugin is added.", "additionalProperties": { "type": ["boolean"] } }, "process-timeout": { "type": "integer", "description": "The timeout in seconds for process executions, defaults to 300 (5mins)." }, "use-include-path": { "type": "boolean", "description": "If true, the Composer autoloader will also look for classes in the PHP include path." }, "use-parent-dir": { "type": ["string", "boolean"], "description": "When running Composer in a directory where there is no composer.json, if there is one present in a directory above Composer will by default ask you whether you want to use that directory's composer.json instead. One of: true (always use parent if needed), false (never ask or use it) or \"prompt\" (ask every time), defaults to prompt." }, "preferred-install": { "type": ["string", "object"], "description": "The install method Composer will prefer to use, defaults to auto and can be any of source, dist, auto, or an object of {\"pattern\": \"preference\"}.", "additionalProperties": { "type": ["string"] } }, "audit": { "type": "object", "description": "Security audit configuration options", "properties": { "ignore": { "anyOf": [ { "type": "object", "description": "A list of advisory ids, remote ids or CVE ids (keys) and the explanations (values) for why they're being ignored. The listed items are reported but let the audit command pass.", "additionalProperties": { "type": ["string", "string"] } }, { "type": "array", "description": "A set of advisory ids, remote ids or CVE ids that are reported but let the audit command pass.", "items": { "type": "string" } } ] }, "abandoned": { "enum": ["ignore", "report", "fail"], "description": "Whether abandoned packages should be ignored, reported as problems or cause an audit failure." } } }, "notify-on-install": { "type": "boolean", "description": "Composer allows repositories to define a notification URL, so that they get notified whenever a package from that repository is installed. This option allows you to disable that behaviour, defaults to true." }, "github-protocols": { "type": "array", "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"https\", \"ssh\", \"git\"].", "items": { "type": "string" } }, "github-oauth": { "type": "object", "description": "An object of domain name => github API oauth tokens, typically {\"github.com\":\"\"}.", "additionalProperties": { "type": "string" } }, "gitlab-oauth": { "type": "object", "description": "An object of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":{\"expires-at\":\"\", \"refresh-token\":\"\", \"token\":\"\"}}.", "additionalProperties": { "type": ["string", "object"], "required": [ "token"], "properties": { "expires-at": { "type": "integer", "description": "The expiration date for this GitLab token" }, "refresh-token": { "type": "string", "description": "The refresh token used for GitLab authentication" }, "token": { "type": "string", "description": "The token used for GitLab authentication" } } } }, "gitlab-token": { "type": "object", "description": "An object of domain name => gitlab private tokens, typically {\"gitlab.com\":\"\"}, or an object with username and token keys.", "additionalProperties": { "type": ["string", "object"], "required": ["username", "token"], "properties": { "username": { "type": "string", "description": "The username used for GitLab authentication" }, "token": { "type": "string", "description": "The token used for GitLab authentication" } } } }, "gitlab-protocol": { "enum": ["git", "http", "https"], "description": "A protocol to force use of when creating a repository URL for the `source` value of the package metadata. One of `git` or `http`. By default, Composer will generate a git URL for private repositories and http one for public repos." }, "bearer": { "type": "object", "description": "An object of domain name => bearer authentication token, for example {\"example.com\":\"\"}.", "additionalProperties": { "type": "string" } }, "disable-tls": { "type": "boolean", "description": "Defaults to `false`. If set to true all HTTPS URLs will be tried with HTTP instead and no network level encryption is performed. Enabling this is a security risk and is NOT recommended. The better way is to enable the php_openssl extension in php.ini." }, "secure-http": { "type": "boolean", "description": "Defaults to `true`. If set to true only HTTPS URLs are allowed to be downloaded via Composer. If you really absolutely need HTTP access to something then you can disable it, but using \"Let's Encrypt\" to get a free SSL certificate is generally a better alternative." }, "secure-svn-domains": { "type": "array", "description": "A list of domains which should be trusted/marked as using a secure Subversion/SVN transport. By default svn:// protocol is seen as insecure and will throw. This is a better/safer alternative to disabling `secure-http` altogether.", "items": { "type": "string" } }, "cafile": { "type": "string", "description": "A way to set the path to the openssl CA file. In PHP 5.6+ you should rather set this via openssl.cafile in php.ini, although PHP 5.6+ should be able to detect your system CA file automatically." }, "capath": { "type": "string", "description": "If cafile is not specified or if the certificate is not found there, the directory pointed to by capath is searched for a suitable certificate. capath must be a correctly hashed certificate directory." }, "http-basic": { "type": "object", "description": "An object of domain name => {\"username\": \"...\", \"password\": \"...\"}.", "additionalProperties": { "type": "object", "required": ["username", "password"], "properties": { "username": { "type": "string", "description": "The username used for HTTP Basic authentication" }, "password": { "type": "string", "description": "The password used for HTTP Basic authentication" } } } }, "store-auths": { "type": ["string", "boolean"], "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt." }, "vendor-dir": { "type": "string", "description": "The location where all packages are installed, defaults to \"vendor\"." }, "bin-dir": { "type": "string", "description": "The location where all binaries are linked, defaults to \"vendor/bin\"." }, "data-dir": { "type": "string", "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes." }, "cache-dir": { "type": "string", "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows." }, "cache-files-dir": { "type": "string", "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"." }, "cache-repo-dir": { "type": "string", "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"." }, "cache-vcs-dir": { "type": "string", "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"." }, "cache-ttl": { "type": "integer", "description": "The default cache time-to-live, defaults to 15552000 (6 months)." }, "cache-files-ttl": { "type": "integer", "description": "The cache time-to-live for files, defaults to the value of cache-ttl." }, "cache-files-maxsize": { "type": ["string", "integer"], "description": "The cache max size for the files cache, defaults to \"300MiB\"." }, "cache-read-only": { "type": ["boolean"], "description": "Whether to use the Composer cache in read-only mode." }, "bin-compat": { "enum": ["auto", "full", "proxy", "symlink"], "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed), can be \"full\" (compatible with both Windows and Unix-based systems) and \"proxy\" (only bash-style proxy)." }, "discard-changes": { "type": ["string", "boolean"], "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"." }, "autoloader-suffix": { "type": "string", "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated." }, "optimize-autoloader": { "type": "boolean", "description": "Always optimize when dumping the autoloader." }, "prepend-autoloader": { "type": "boolean", "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true." }, "classmap-authoritative": { "type": "boolean", "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false." }, "apcu-autoloader": { "type": "boolean", "description": "If true, the Composer autoloader will check for APCu and use it to cache found/not-found classes when the extension is enabled, defaults to false." }, "github-domains": { "type": "array", "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].", "items": { "type": "string" } }, "github-expose-hostname": { "type": "boolean", "description": "Defaults to true. If set to false, the OAuth tokens created to access the github API will have a date instead of the machine hostname." }, "gitlab-domains": { "type": "array", "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].", "items": { "type": "string" } }, "bitbucket-oauth": { "type": "object", "description": "An object of domain name => {\"consumer-key\": \"...\", \"consumer-secret\": \"...\"}.", "additionalProperties": { "type": "object", "required": ["consumer-key", "consumer-secret"], "properties": { "consumer-key": { "type": "string", "description": "The consumer-key used for OAuth authentication" }, "consumer-secret": { "type": "string", "description": "The consumer-secret used for OAuth authentication" }, "access-token": { "type": "string", "description": "The OAuth token retrieved from Bitbucket's API, this is written by Composer and you should not set it nor modify it." }, "access-token-expiration": { "type": "integer", "description": "The generated token's expiration timestamp, this is written by Composer and you should not set it nor modify it." } } } }, "use-github-api": { "type": "boolean", "description": "Defaults to true. If set to false, globally disables the use of the GitHub API for all GitHub repositories and clones the repository as it would for any other repository." }, "archive-format": { "type": "string", "description": "The default archiving format when not provided on cli, defaults to \"tar\"." }, "archive-dir": { "type": "string", "description": "The default archive path when not provided on cli, defaults to \".\"." }, "htaccess-protect": { "type": "boolean", "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories." }, "sort-packages": { "type": "boolean", "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency." }, "lock": { "type": "boolean", "description": "Defaults to true. If set to false, Composer will not create a composer.lock file." }, "platform-check": { "type": ["boolean", "string"], "description": "Defaults to \"php-only\" which checks only the PHP version. Setting to true will also check the presence of required PHP extensions. If set to false, Composer will not create and require a platform_check.php file as part of the autoloader bootstrap." }, "bump-after-update": { "type": ["string", "boolean"], "description": "Defaults to false and can be any of true, false, \"dev\"` or \"no-dev\"`. If set to true, Composer will run the bump command after running the update command. If set to \"dev\" or \"no-dev\" then only the corresponding dependencies will be bumped." }, "allow-missing-requirements": { "type": ["boolean"], "description": "Defaults to false. If set to true, Composer will allow install when lock file is not up to date with the latest changes in composer.json." } } }, "extra": { "type": ["object", "array"], "description": "Arbitrary extra data that can be used by plugins, for example, package of type composer-plugin may have a 'class' key defining an installer class name.", "additionalProperties": true }, "scripts": { "type": ["object"], "description": "Script listeners that will be executed before/after some events.", "properties": { "pre-install-cmd": { "type": ["array", "string"], "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands." }, "post-install-cmd": { "type": ["array", "string"], "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands." }, "pre-update-cmd": { "type": ["array", "string"], "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands." }, "post-update-cmd": { "type": ["array", "string"], "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands." }, "pre-status-cmd": { "type": ["array", "string"], "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands." }, "post-status-cmd": { "type": ["array", "string"], "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands." }, "pre-package-install": { "type": ["array", "string"], "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands." }, "post-package-install": { "type": ["array", "string"], "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands." }, "pre-package-update": { "type": ["array", "string"], "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands." }, "post-package-update": { "type": ["array", "string"], "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands." }, "pre-package-uninstall": { "type": ["array", "string"], "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands." }, "post-package-uninstall": { "type": ["array", "string"], "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands." }, "pre-autoload-dump": { "type": ["array", "string"], "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands." }, "post-autoload-dump": { "type": ["array", "string"], "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands." }, "post-root-package-install": { "type": ["array", "string"], "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands." }, "post-create-project-cmd": { "type": ["array", "string"], "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands." } } }, "scripts-descriptions": { "type": ["object"], "description": "Descriptions for custom commands, shown in console help.", "additionalProperties": { "type": "string" } }, "scripts-aliases": { "type": ["object"], "description": "Aliases for custom commands.", "additionalProperties": { "type": "array" } } }, "definitions": { "authors": { "type": "array", "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.", "items": { "type": "object", "additionalProperties": false, "required": [ "name"], "properties": { "name": { "type": "string", "description": "Full name of the author." }, "email": { "type": "string", "description": "Email address of the author.", "format": "email" }, "homepage": { "type": "string", "description": "Homepage URL for the author.", "format": "uri" }, "role": { "type": "string", "description": "Author's role in the project." } } } }, "autoload": { "type": "object", "description": "Description of how the package can be autoloaded.", "properties": { "psr-0": { "type": "object", "description": "This is an object of namespaces (keys) and the directories they can be found in (values, can be arrays of paths) by the autoloader.", "additionalProperties": { "type": ["string", "array"], "items": { "type": "string" } } }, "psr-4": { "type": "object", "description": "This is an object of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", "additionalProperties": { "type": ["string", "array"], "items": { "type": "string" } } }, "classmap": { "type": "array", "description": "This is an array of paths that contain classes to be included in the class-map generation process." }, "files": { "type": "array", "description": "This is an array of files that are always required on every request." }, "exclude-from-classmap": { "type": "array", "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]" } } }, "repository": { "type": "object", "anyOf": [ { "$ref": "#/definitions/composer-repository" }, { "$ref": "#/definitions/vcs-repository" }, { "$ref": "#/definitions/path-repository" }, { "$ref": "#/definitions/artifact-repository" }, { "$ref": "#/definitions/pear-repository" }, { "$ref": "#/definitions/package-repository" } ] }, "composer-repository": { "type": "object", "required": ["type", "url"], "properties": { "type": { "type": "string", "enum": ["composer"] }, "url": { "type": "string" }, "canonical": { "type": "boolean" }, "only": { "type": "array", "items": { "type": "string" } }, "exclude": { "type": "array", "items": { "type": "string" } }, "options": { "type": "object", "additionalProperties": true }, "allow_ssl_downgrade": { "type": "boolean" }, "force-lazy-providers": { "type": "boolean" } } }, "vcs-repository": { "type": "object", "required": ["type", "url"], "properties": { "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "bitbucket", "git-bitbucket", "hg", "fossil", "perforce", "svn"] }, "url": { "type": "string" }, "canonical": { "type": "boolean" }, "only": { "type": "array", "items": { "type": "string" } }, "exclude": { "type": "array", "items": { "type": "string" } }, "no-api": { "type": "boolean" }, "secure-http": { "type": "boolean" }, "svn-cache-credentials": { "type": "boolean" }, "trunk-path": { "type": ["string", "boolean"] }, "branches-path": { "type": ["string", "boolean"] }, "tags-path": { "type": ["string", "boolean"] }, "package-path": { "type": "string" }, "depot": { "type": "string" }, "branch": { "type": "string" }, "unique_perforce_client_name": { "type": "string" }, "p4user": { "type": "string" }, "p4password": { "type": "string" } } }, "path-repository": { "type": "object", "required": ["type", "url"], "properties": { "type": { "type": "string", "enum": ["path"] }, "url": { "type": "string" }, "canonical": { "type": "boolean" }, "only": { "type": "array", "items": { "type": "string" } }, "exclude": { "type": "array", "items": { "type": "string" } }, "options": { "type": "object", "properties": { "symlink": { "type": ["boolean", "null"] } }, "additionalProperties": true } } }, "artifact-repository": { "type": "object", "required": ["type", "url"], "properties": { "type": { "type": "string", "enum": ["artifact"] }, "url": { "type": "string" }, "canonical": { "type": "boolean" }, "only": { "type": "array", "items": { "type": "string" } }, "exclude": { "type": "array", "items": { "type": "string" } } } }, "pear-repository": { "type": "object", "required": ["type", "url"], "properties": { "type": { "type": "string", "enum": ["pear"] }, "url": { "type": "string" }, "canonical": { "type": "boolean" }, "only": { "type": "array", "items": { "type": "string" } }, "exclude": { "type": "array", "items": { "type": "string" } }, "vendor-alias": { "type": "string" } } }, "package-repository": { "type": "object", "required": ["type", "package"], "properties": { "type": { "type": "string", "enum": ["package"] }, "canonical": { "type": "boolean" }, "only": { "type": "array", "items": { "type": "string" } }, "exclude": { "type": "array", "items": { "type": "string" } }, "package": { "oneOf": [ { "$ref": "#/definitions/inline-package" }, { "type": "array", "items": { "$ref": "#/definitions/inline-package" } } ] } } }, "inline-package": { "type": "object", "required": ["name", "version"], "properties": { "name": { "type": "string", "description": "Package name, including 'vendor-name/' prefix." }, "type": { "type": "string" }, "target-dir": { "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.", "type": "string" }, "description": { "type": "string" }, "keywords": { "type": "array", "items": { "type": "string" } }, "homepage": { "type": "string", "format": "uri" }, "version": { "type": "string" }, "time": { "type": "string" }, "license": { "type": [ "string", "array" ] }, "authors": { "$ref": "#/definitions/authors" }, "require": { "type": "object", "additionalProperties": { "type": "string" } }, "replace": { "type": "object", "additionalProperties": { "type": "string" } }, "conflict": { "type": "object", "additionalProperties": { "type": "string" } }, "provide": { "type": "object", "additionalProperties": { "type": "string" } }, "require-dev": { "type": "object", "additionalProperties": { "type": "string" } }, "suggest": { "type": "object", "additionalProperties": { "type": "string" } }, "extra": { "type": ["object", "array"], "additionalProperties": true }, "autoload": { "$ref": "#/definitions/autoload" }, "archive": { "type": ["object"], "properties": { "exclude": { "type": "array" } } }, "bin": { "type": ["string", "array"], "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).", "items": { "type": "string" } }, "include-path": { "type": ["array"], "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.", "items": { "type": "string" } }, "source": { "$ref": "#/definitions/source" }, "dist": { "$ref": "#/definitions/dist" } }, "additionalProperties": true }, "source": { "type": "object", "required": ["type", "url", "reference"], "properties": { "type": { "type": "string" }, "url": { "type": "string" }, "reference": { "type": "string" }, "mirrors": { "type": "array" } } }, "dist": { "type": "object", "required": ["type", "url"], "properties": { "type": { "type": "string" }, "url": { "type": "string" }, "reference": { "type": "string" }, "shasum": { "type": "string" }, "mirrors": { "type": "array" } } } } } { "$schema": "https://json-schema.org/draft-04/schema#", "title": "Composer Lock File", "type": "object", "required": [ "content-hash", "packages", "packages-dev" ], "additionalProperties": true, "properties": { "_readme": { "type": "array", "items": { "type": "string" }, "description": "Informational text for humans reading the file" }, "content-hash": { "type": "string", "description": "Hash of all relevant properties of the composer.json that was used to create this lock file." }, "packages": { "type": "array", "description": "An array of packages that are required.", "items": { "$ref": "./composer-schema.json", "required": ["name", "version"] } }, "packages-dev": { "type": "array", "description": "An array of packages that are required in require-dev.", "items": { "$ref": "./composer-schema.json" } }, "aliases": { "type": "array", "description": "Inline aliases defined in the root package.", "items": { "type": "object", "required": [ "package", "version", "alias", "alias_normalized" ], "properties": { "package": { "type": "string" }, "version": { "type": "string" }, "alias": { "type": "string" }, "alias_normalized": { "type": "string" } } } }, "minimum-stability": { "type": "string", "description": "The minimum-stability used to generate this lock file." }, "stability-flags": { "type": "object", "description": "Root package stability flags changing the minimum-stability for specific packages.", "additionalProperties": { "type": "integer" } }, "prefer-stable": { "type": "boolean", "description": "Whether the --prefer-stable flag was used when building this lock file." }, "prefer-lowest": { "type": "boolean", "description": "Whether the --prefer-lowest flag was used when building this lock file." }, "platform": { "type": "object", "description": "Platform requirements of the root package.", "additionalProperties": { "type": "string" } }, "platform-dev": { "type": "object", "description": "Platform dev-requirements of the root package.", "additionalProperties": { "type": "string" } }, "platform-overrides": { "type": "object", "description": "Platform config overrides of the root package.", "additionalProperties": { "type": "string" } }, "plugin-api-version": { "type": "string", "description": "The composer-plugin-api version that was used to generate this lock file." } } } { "$schema": "https://json-schema.org/draft-04/schema#", "title": "Composer Package Repository", "type": "object", "oneOf": [ { "required": [ "packages" ] }, { "required": [ "providers" ] }, { "required": [ "provider-includes", "providers-url" ] }, { "required": [ "metadata-url" ] } ], "properties": { "packages": { "type": ["object", "array"], "description": "A hashmap of package names in the form of /.", "additionalProperties": { "$ref": "#/definitions/versions" } }, "metadata-url": { "type": "string", "description": "Endpoint to retrieve package metadata data from, in Composer v2 format, e.g. '/p2/%package%.json'." }, "available-packages": { "type": "array", "items": { "type": "string" }, "description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify all the package names that your repository contains here." }, "available-package-patterns": { "type": "array", "items": { "type": "string" }, "description": "If your repository only has a small number of packages, and you want to avoid serving many 404s, specify package name patterns containing wildcards (*) that your repository contains here." }, "security-advisories": { "type": "array", "items": { "type": "object", "required": ["metadata", "api-url"], "properties": { "metadata": { "type": "boolean", "description": "Whether metadata files contain security advisory data or whether it should always be queried using the API URL." }, "api-url": { "type": "string", "description": "Endpoint to call to retrieve security advisories data." } } } }, "metadata-changes-url": { "type": "string", "description": "Endpoint to retrieve package metadata updates from. This should receive a timestamp since last call to be able to return new changes. e.g. '/metadata/changes.json'." }, "providers-api": { "type": "string", "description": "Endpoint to retrieve package names providing a given name from, e.g. '/providers/%package%.json'." }, "notify-batch": { "type": "string", "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'." }, "search": { "type": "string", "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'." }, "list": { "type": "string", "description": "Endpoint that provides a full list of packages present in the repository. It should accept an optional `?filter=xx` query param, which can contain `*` as wildcards matching any substring. e.g. '/list.json'." }, "warnings": { "type": "array", "items": { "type": "object", "required": ["message", "versions"], "properties": { "message": { "type": "string", "description": "A message that will be output by Composer as a warning when this source is consulted." }, "versions": { "type": "string", "description": "A version constraint to limit to which Composer versions the warning should be shown." } } } }, "infos": { "type": "array", "items": { "type": "object", "required": ["message", "versions"], "properties": { "message": { "type": "string", "description": "A message that will be output by Composer as info when this source is consulted." }, "versions": { "type": "string", "description": "A version constraint to limit to which Composer versions the info should be shown." } } } }, "providers-url": { "type": "string", "description": "DEPRECATED: Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'." }, "provider-includes": { "type": "object", "description": "DEPRECATED: A hashmap of provider listings.", "additionalProperties": { "$ref": "#/definitions/provider" } }, "providers": { "type": "object", "description": "DEPRECATED: A hashmap of package names in the form of /.", "additionalProperties": { "$ref": "#/definitions/provider" } }, "warning": { "type": "string", "description": "DEPRECATED: A message that will be output by Composer as a warning when this source is consulted." }, "warning-versions": { "type": "string", "description": "DEPRECATED: A version constraint to limit to which Composer versions the warning should be shown." }, "info": { "type": "string", "description": "DEPRECATED: A message that will be output by Composer as a info when this source is consulted." }, "info-versions": { "type": "string", "description": "DEPRECATED: A version constraint to limit to which Composer versions the info should be shown." } }, "definitions": { "versions": { "type": "object", "description": "A hashmap of versions and their metadata.", "additionalProperties": { "$ref": "#/definitions/version" } }, "version": { "type": "object", "oneOf": [ { "$ref": "#/definitions/package" }, { "$ref": "#/definitions/metapackage" } ] }, "package-base": { "properties": { "name": { "type": "string" }, "type": { "type": "string" }, "version": { "type": "string" }, "version_normalized": { "type": "string", "description": "Normalized version, optional but can save computational time on client side." }, "autoload": { "type": "object" }, "require": { "type": "object" }, "replace": { "type": "object" }, "conflict": { "type": "object" }, "provide": { "type": "object" }, "time": { "type": "string" } }, "additionalProperties": true }, "package": { "allOf": [ { "$ref": "#/definitions/package-base" }, { "properties": { "dist": { "type": "object" }, "source": { "type": "object" } } }, { "oneOf": [ { "required": [ "name", "version", "source" ] }, { "required": [ "name", "version", "dist" ] } ] } ] }, "metapackage": { "allOf": [ { "$ref": "#/definitions/package-base" }, { "properties": { "type": { "type": "string", "enum": [ "metapackage" ] } }, "required": [ "name", "version", "type" ] } ] }, "provider": { "type": "object", "properties": { "sha256": { "type": "string", "description": "Hash value that can be used to validate the resource." } } } } } { "_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": "d6c1c91b79d7140594e249343184ce6f", "packages": [ { "name": "composer/ca-bundle", "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/ca-bundle/zipball/08c50d5ec4c6ced7d0271d2862dec8c1033283e6", "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6", "shasum": "" }, "require": { "ext-openssl": "*", "ext-pcre": "*", "php": "^7.2 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^8 || ^9", "psr/log": "^1.0 || ^2.0 || ^3.0", "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.x-dev" } }, "autoload": { "psr-4": { "Composer\\CaBundle\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" } ], "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", "keywords": [ "cabundle", "cacert", "certificate", "ssl", "tls" ], "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", "source": "https://github.com/composer/ca-bundle/tree/1.5.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": "2025-01-08T16:17:16+00:00" }, { "name": "composer/class-map-generator", "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", "reference": "4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/class-map-generator/zipball/4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915", "reference": "4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915", "shasum": "" }, "require": { "composer/pcre": "^2.1 || ^3.1", "php": "^7.2 || ^8.0", "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" }, "require-dev": { "phpstan/phpstan": "^1.12 || ^2", "phpstan/phpstan-deprecation-rules": "^1 || ^2", "phpstan/phpstan-phpunit": "^1 || ^2", "phpstan/phpstan-strict-rules": "^1.1 || ^2", "phpunit/phpunit": "^8", "symfony/filesystem": "^5.4 || ^6" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.x-dev" } }, "autoload": { "psr-4": { "Composer\\ClassMapGenerator\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "https://seld.be" } ], "description": "Utilities to scan PHP code and generate class maps.", "keywords": [ "classmap" ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", "source": "https://github.com/composer/class-map-generator/tree/1.5.0" }, "funding": [ { "url": "https://packagist.com", "type": "custom" }, { "url": "https://github.com/composer", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], "time": "2024-11-25T16:11:06+00:00" }, { "name": "composer/metadata-minifier", "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/composer/metadata-minifier.git", "reference": "c549d23829536f0d0e984aaabbf02af91f443207" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", "reference": "c549d23829536f0d0e984aaabbf02af91f443207", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { "composer/composer": "^2", "phpstan/phpstan": "^0.12.55", "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.x-dev" } }, "autoload": { "psr-4": { "Composer\\MetadataMinifier\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" } ], "description": "Small utility library that handles metadata minification and expansion.", "keywords": [ "composer", "compression" ], "support": { "issues": "https://github.com/composer/metadata-minifier/issues", "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" }, "funding": [ { "url": "https://packagist.com", "type": "custom" }, { "url": "https://github.com/composer", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], "time": "2021-04-07T13:37:33+00:00" }, { "name": "composer/pcre", "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", "reference": "ebb81df8f52b40172d14062ae96a06939d80a069" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/pcre/zipball/ebb81df8f52b40172d14062ae96a06939d80a069", "reference": "ebb81df8f52b40172d14062ae96a06939d80a069", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "conflict": { "phpstan/phpstan": "<1.11.10" }, "require-dev": { "phpstan/phpstan": "^1.12 || ^2", "phpstan/phpstan-strict-rules": "^1 || ^2", "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "phpstan": { "includes": [ "extension.neon" ] }, "branch-alias": { "dev-main": "2.x-dev" } }, "autoload": { "psr-4": { "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" } ], "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "keywords": [ "PCRE", "preg", "regex", "regular expression" ], "support": { "issues": "https://github.com/composer/pcre/issues", "source": "https://github.com/composer/pcre/tree/2.3.2" }, "funding": [ { "url": "https://packagist.com", "type": "custom" }, { "url": "https://github.com/composer", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], "time": "2024-11-12T16:24:47+00:00" }, { "name": "composer/semver", "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/composer/semver.git", "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^1.11", "symfony/phpunit-bridge": "^3 || ^7" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.x-dev" } }, "autoload": { "psr-4": { "Composer\\Semver\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nils Adermann", "email": "naderman@naderman.de", "homepage": "http://www.naderman.de" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" }, { "name": "Rob Bast", "email": "rob.bast@gmail.com", "homepage": "http://robbast.nl" } ], "description": "Semver library that offers utilities, version constraint parsing and validation.", "keywords": [ "semantic", "semver", "validation", "versioning" ], "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", "source": "https://github.com/composer/semver/tree/3.4.3" }, "funding": [ { "url": "https://packagist.com", "type": "custom" }, { "url": "https://github.com/composer", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], "time": "2024-09-19T14:15:21+00:00" }, { "name": "composer/spdx-licenses", "version": "1.5.8", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a", "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^0.12.55", "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.x-dev" } }, "autoload": { "psr-4": { "Composer\\Spdx\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nils Adermann", "email": "naderman@naderman.de", "homepage": "http://www.naderman.de" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" }, { "name": "Rob Bast", "email": "rob.bast@gmail.com", "homepage": "http://robbast.nl" } ], "description": "SPDX licenses list and validation library.", "keywords": [ "license", "spdx", "validator" ], "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/spdx-licenses/issues", "source": "https://github.com/composer/spdx-licenses/tree/1.5.8" }, "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-11-20T07:44:33+00:00" }, { "name": "composer/xdebug-handler", "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { "composer/pcre": "^1 || ^2 || ^3", "php": "^7.2.5 || ^8.0", "psr/log": "^1 || ^2 || ^3" }, "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, "type": "library", "autoload": { "psr-4": { "Composer\\XdebugHandler\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "John Stevenson", "email": "john-stevenson@blueyonder.co.uk" } ], "description": "Restarts a process without Xdebug.", "keywords": [ "Xdebug", "performance" ], "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/xdebug-handler/issues", "source": "https://github.com/composer/xdebug-handler/tree/3.0.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": "2024-05-06T16:37:16+00:00" }, { "name": "justinrainbow/json-schema", "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", "shasum": "" }, "require": { "php": ">=7.1" }, "require-dev": { "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", "json-schema/json-schema-test-suite": "1.2.0", "phpunit/phpunit": "^4.8.35" }, "bin": [ "bin/validate-json" ], "type": "library", "autoload": { "psr-4": { "JsonSchema\\": "src/JsonSchema/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Bruno Prieto Reis", "email": "bruno.p.reis@gmail.com" }, { "name": "Justin Rainbow", "email": "justin.rainbow@gmail.com" }, { "name": "Igor Wiedler", "email": "igor@wiedler.ch" }, { "name": "Robert Schönthal", "email": "seroscho@googlemail.com" } ], "description": "A library to validate a json schema.", "homepage": "https://github.com/justinrainbow/json-schema", "keywords": [ "json", "schema" ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" }, "time": "2024-07-06T21:00:26+00:00" }, { "name": "psr/container", "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", "shasum": "" }, "require": { "php": ">=7.2.0" }, "type": "library", "autoload": { "psr-4": { "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "Common Container Interface (PHP FIG PSR-11)", "homepage": "https://github.com/php-fig/container", "keywords": [ "PSR-11", "container", "container-interface", "container-interop", "psr" ], "support": { "issues": "https://github.com/php-fig/container/issues", "source": "https://github.com/php-fig/container/tree/1.1.1" }, "time": "2021-03-05T17:36:06+00:00" }, { "name": "psr/log", "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.1.x-dev" } }, "autoload": { "psr-4": { "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", "homepage": "https://github.com/php-fig/log", "keywords": [ "log", "psr", "psr-3" ], "support": { "source": "https://github.com/php-fig/log/tree/1.1.4" }, "time": "2021-05-03T11:20:27+00:00" }, { "name": "react/promise", "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", "reference": "8a164643313c71354582dc850b42b33fa12a4b63" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", "reference": "8a164643313c71354582dc850b42b33fa12a4b63", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { "phpstan/phpstan": "1.10.39 || 1.4.10", "phpunit/phpunit": "^9.6 || ^7.5" }, "type": "library", "autoload": { "files": [ "src/functions_include.php" ], "psr-4": { "React\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jan Sorgalla", "email": "jsorgalla@gmail.com", "homepage": "https://sorgalla.com/" }, { "name": "Christian Lück", "email": "christian@clue.engineering", "homepage": "https://clue.engineering/" }, { "name": "Cees-Jan Kiewiet", "email": "reactphp@ceesjankiewiet.nl", "homepage": "https://wyrihaximus.net/" }, { "name": "Chris Boden", "email": "cboden@gmail.com", "homepage": "https://cboden.dev/" } ], "description": "A lightweight implementation of CommonJS Promises/A for PHP", "keywords": [ "promise", "promises" ], "support": { "issues": "https://github.com/reactphp/promise/issues", "source": "https://github.com/reactphp/promise/tree/v3.2.0" }, "funding": [ { "url": "https://opencollective.com/reactphp", "type": "open_collective" } ], "time": "2024-05-24T10:39:05+00:00" }, { "name": "seld/jsonlint", "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2", "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2", "shasum": "" }, "require": { "php": "^5.3 || ^7.0 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^1.11", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" }, "bin": [ "bin/jsonlint" ], "type": "library", "autoload": { "psr-4": { "Seld\\JsonLint\\": "src/Seld/JsonLint/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "https://seld.be" } ], "description": "JSON Linter", "keywords": [ "json", "linter", "parser", "validator" ], "support": { "issues": "https://github.com/Seldaek/jsonlint/issues", "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0" }, "funding": [ { "url": "https://github.com/Seldaek", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", "type": "tidelift" } ], "time": "2024-07-11T14:55:45+00:00" }, { "name": "seld/phar-utils", "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/Seldaek/phar-utils.git", "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/ea2f4014f163c1be4c601b9b7bd6af81ba8d701c", "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c", "shasum": "" }, "require": { "php": ">=5.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { "Seld\\PharUtils\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be" } ], "description": "PHAR file format utilities, for when PHP phars you up", "keywords": [ "phar" ], "support": { "issues": "https://github.com/Seldaek/phar-utils/issues", "source": "https://github.com/Seldaek/phar-utils/tree/1.2.1" }, "time": "2022-08-31T10:31:18+00:00" }, { "name": "seld/signal-handler", "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/Seldaek/signal-handler.git", "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", "shasum": "" }, "require": { "php": ">=7.2.0" }, "require-dev": { "phpstan/phpstan": "^1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1", "phpstan/phpstan-strict-rules": "^1.3", "phpunit/phpunit": "^7.5.20 || ^8.5.23", "psr/log": "^1 || ^2 || ^3" }, "type": "library", "extra": { "branch-alias": { "dev-main": "2.x-dev" } }, "autoload": { "psr-4": { "Seld\\Signal\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" } ], "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development", "keywords": [ "posix", "sigint", "signal", "sigterm", "unix" ], "support": { "issues": "https://github.com/Seldaek/signal-handler/issues", "source": "https://github.com/Seldaek/signal-handler/tree/2.0.2" }, "time": "2023-09-03T09:24:00+00:00" }, { "name": "symfony/console", "version": "v5.4.47", "source": { "type": "git", "url": "https://github.com/symfony/console.git", "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.1|^2|^3", "symfony/string": "^5.1|^6.0" }, "conflict": { "psr/log": ">=3", "symfony/dependency-injection": "<4.4", "symfony/dotenv": "<5.1", "symfony/event-dispatcher": "<4.4", "symfony/lock": "<4.4", "symfony/process": "<4.4" }, "provide": { "psr/log-implementation": "1.0|2.0" }, "require-dev": { "psr/log": "^1|^2", "symfony/config": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^4.4|^5.0|^6.0", "symfony/event-dispatcher": "^4.4|^5.0|^6.0", "symfony/lock": "^4.4|^5.0|^6.0", "symfony/process": "^4.4|^5.0|^6.0", "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "suggest": { "psr/log": "For using the console logger", "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", "keywords": [ "cli", "command-line", "console", "terminal" ], "support": { "source": "https://github.com/symfony/console/tree/v5.4.47" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-11-06T11:30:55+00:00" }, { "name": "symfony/deprecation-contracts", "version": "v2.5.4", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", "shasum": "" }, "require": { "php": ">=7.1" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/contracts", "name": "symfony/contracts" }, "branch-alias": { "dev-main": "2.5-dev" } }, "autoload": { "files": [ "function.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-25T14:11:13+00:00" }, { "name": "symfony/filesystem", "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", "reference": "57c8294ed37d4a055b77057827c67f9558c95c54" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/filesystem/zipball/57c8294ed37d4a055b77057827c67f9558c95c54", "reference": "57c8294ed37d4a055b77057827c67f9558c95c54", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8", "symfony/polyfill-php80": "^1.16" }, "require-dev": { "symfony/process": "^5.4|^6.4" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { "source": "https://github.com/symfony/filesystem/tree/v5.4.45" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-10-22T13:05:35+00:00" }, { "name": "symfony/finder", "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", "reference": "63741784cd7b9967975eec610b256eed3ede022b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b", "reference": "63741784cd7b9967975eec610b256eed3ede022b", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { "source": "https://github.com/symfony/finder/tree/v5.4.45" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-28T13:32:08+00:00" }, { "name": "symfony/polyfill-ctype", "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { "php": ">=7.2" }, "provide": { "ext-ctype": "*" }, "suggest": { "ext-ctype": "For best performance" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Gert de Pagter", "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "ctype", "polyfill", "portable" ], "support": { "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "grapheme", "intl", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, "classmap": [ "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "intl", "normalizer", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { "php": ">=7.2" }, "provide": { "ext-mbstring": "*" }, "suggest": { "ext-mbstring": "For best performance" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", "mbstring", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php73", "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "shasum": "" }, "require": { "php": ">=7.2" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, "classmap": [ "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { "php": ">=7.2" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, "classmap": [ "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Ion Bazan", "email": "ion.bazan@gmail.com" }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php81", "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { "php": ">=7.2" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Polyfill\\Php81\\": "" }, "classmap": [ "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", "version": "v5.4.47", "source": { "type": "git", "url": "https://github.com/symfony/process.git", "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/process/zipball/5d1662fb32ebc94f17ddb8d635454a776066733d", "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { "source": "https://github.com/symfony/process/tree/v5.4.47" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-11-06T11:36:42+00:00" }, { "name": "symfony/service-contracts", "version": "v2.5.4", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", "shasum": "" }, "require": { "php": ">=7.2.5", "psr/container": "^1.1", "symfony/deprecation-contracts": "^2.1|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, "suggest": { "symfony/service-implementation": "" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/contracts", "name": "symfony/contracts" }, "branch-alias": { "dev-main": "2.5-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Generic abstractions related to writing services", "homepage": "https://symfony.com", "keywords": [ "abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards" ], "support": { "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-09-25T14:11:13+00:00" }, { "name": "symfony/string", "version": "v5.4.47", "source": { "type": "git", "url": "https://github.com/symfony/string.git", "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "~1.15" }, "conflict": { "symfony/translation-contracts": ">=3.0" }, "require-dev": { "symfony/error-handler": "^4.4|^5.0|^6.0", "symfony/http-client": "^4.4|^5.0|^6.0", "symfony/translation-contracts": "^1.1|^2", "symfony/var-exporter": "^4.4|^5.0|^6.0" }, "type": "library", "autoload": { "files": [ "Resources/functions.php" ], "psr-4": { "Symfony\\Component\\String\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", "keywords": [ "grapheme", "i18n", "string", "unicode", "utf-8", "utf8" ], "support": { "source": "https://github.com/symfony/string/tree/v5.4.47" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-11-10T20:33:58+00:00" } ], "packages-dev": [ { "name": "phpstan/phpstan", "version": "1.12.15", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", "reference": "c91d4e8bc056f46cf653656e6f71004b254574d1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c91d4e8bc056f46cf653656e6f71004b254574d1", "reference": "c91d4e8bc056f46cf653656e6f71004b254574d1", "shasum": "" }, "require": { "php": "^7.2|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" }, "bin": [ "phpstan", "phpstan.phar" ], "type": "library", "autoload": { "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ "dev", "static analysis" ], "support": { "docs": "https://phpstan.org/user-guide/getting-started", "forum": "https://github.com/phpstan/phpstan/discussions", "issues": "https://github.com/phpstan/phpstan/issues", "security": "https://github.com/phpstan/phpstan/security/policy", "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { "url": "https://github.com/ondrejmirtes", "type": "github" }, { "url": "https://github.com/phpstan", "type": "github" } ], "time": "2025-01-05T16:40:22+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/f94d246cc143ec5a23da868f8f7e1393b50eaa82", "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", "phpstan/phpstan": "^1.12" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", "extra": { "phpstan": { "includes": [ "rules.neon" ] } }, "autoload": { "psr-4": { "PHPStan\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.1" }, "time": "2024-09-11T15:52:35+00:00" }, { "name": "phpstan/phpstan-phpunit", "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", "reference": "72a6721c9b64b3e4c9db55abbc38f790b318267e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/72a6721c9b64b3e4c9db55abbc38f790b318267e", "reference": "72a6721c9b64b3e4c9db55abbc38f790b318267e", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", "phpstan/phpstan": "^1.12" }, "conflict": { "phpunit/phpunit": "<7.0" }, "require-dev": { "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/phpstan-strict-rules": "^1.5.1", "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", "extra": { "phpstan": { "includes": [ "extension.neon", "rules.neon" ] } }, "autoload": { "psr-4": { "PHPStan\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.2" }, "time": "2024-12-17T17:20:49+00:00" }, { "name": "phpstan/phpstan-strict-rules", "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", "reference": "b564ca479e7e735f750aaac4935af965572a7845" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b564ca479e7e735f750aaac4935af965572a7845", "reference": "b564ca479e7e735f750aaac4935af965572a7845", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", "phpstan/phpstan": "^1.12.4" }, "require-dev": { "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", "extra": { "phpstan": { "includes": [ "rules.neon" ] } }, "autoload": { "psr-4": { "PHPStan\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.2" }, "time": "2025-01-19T13:02:24+00:00" }, { "name": "phpstan/phpstan-symfony", "version": "1.4.13", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-symfony.git", "reference": "dd1aaa7f85f9916222a2ce7e4d21072fe03958f4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/dd1aaa7f85f9916222a2ce7e4d21072fe03958f4", "reference": "dd1aaa7f85f9916222a2ce7e4d21072fe03958f4", "shasum": "" }, "require": { "ext-simplexml": "*", "php": "^7.2 || ^8.0", "phpstan/phpstan": "^1.12" }, "conflict": { "symfony/framework-bundle": "<3.0" }, "require-dev": { "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/phpstan-phpunit": "^1.3.11", "phpstan/phpstan-strict-rules": "^1.5.1", "phpunit/phpunit": "^8.5.29 || ^9.5", "psr/container": "1.0 || 1.1.1", "symfony/config": "^5.4 || ^6.1", "symfony/console": "^5.4 || ^6.1", "symfony/dependency-injection": "^5.4 || ^6.1", "symfony/form": "^5.4 || ^6.1", "symfony/framework-bundle": "^5.4 || ^6.1", "symfony/http-foundation": "^5.4 || ^6.1", "symfony/messenger": "^5.4", "symfony/polyfill-php80": "^1.24", "symfony/serializer": "^5.4", "symfony/service-contracts": "^2.2.0" }, "type": "phpstan-extension", "extra": { "phpstan": { "includes": [ "extension.neon", "rules.neon" ] } }, "autoload": { "psr-4": { "PHPStan\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Lukáš Unger", "email": "looky.msc@gmail.com", "homepage": "https://lookyman.net" } ], "description": "Symfony Framework extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-symfony/issues", "source": "https://github.com/phpstan/phpstan-symfony/tree/1.4.13" }, "time": "2025-01-04T13:55:31+00:00" }, { "name": "symfony/phpunit-bridge", "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", "reference": "2bbde92ab25a0e2c88160857af7be9db5da0d145" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2bbde92ab25a0e2c88160857af7be9db5da0d145", "reference": "2bbde92ab25a0e2c88160857af7be9db5da0d145", "shasum": "" }, "require": { "php": ">=7.2.5" }, "conflict": { "phpunit/phpunit": "<7.5|9.1.2" }, "require-dev": { "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/error-handler": "^5.4|^6.4|^7.0", "symfony/polyfill-php81": "^1.27" }, "bin": [ "bin/simple-phpunit" ], "type": "symfony-bridge", "extra": { "thanks": { "url": "https://github.com/sebastianbergmann/phpunit", "name": "phpunit/phpunit" } }, "autoload": { "files": [ "bootstrap.php" ], "psr-4": { "Symfony\\Bridge\\PhpUnit\\": "" }, "exclude-from-classmap": [ "/Tests/", "/bin/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { "source": "https://github.com/symfony/phpunit-bridge/tree/v7.2.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2024-11-13T16:15:23+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "^7.2.5 || ^8.0" }, "platform-dev": {}, "platform-overrides": { "php": "7.2.5" }, "plugin-api-version": "2.6.0" } 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. #!/usr/bin/env php check(); unset($xdebug); if (\defined('_ContaoManager\\HHVM_VERSION') && \version_compare(\_ContaoManager\HHVM_VERSION, '4.0', '>=')) { echo 'HHVM 4.0 has dropped support for Composer, please use PHP instead. Aborting.' . \PHP_EOL; exit(1); } if (!\extension_loaded('iconv') && !\extension_loaded('mbstring')) { echo 'The iconv OR mbstring extension is required and both are missing.' . \PHP_EOL . 'Install either of them or recompile php without --disable-iconv.' . \PHP_EOL . 'Aborting.' . \PHP_EOL; exit(1); } if (\function_exists('ini_set')) { // check if error logging is on, but to an empty destination - for the CLI SAPI, that means stderr $logsToSapiDefault = '' === \ini_get('error_log') && (bool) \ini_get('log_errors'); // on the CLI SAPI, ensure errors are displayed on stderr, either via display_errors or via error_log if (\PHP_SAPI === 'cli') { @\ini_set('display_errors', $logsToSapiDefault ? '0' : 'stderr'); } // Set user defined memory limit if ($memoryLimit = \getenv('COMPOSER_MEMORY_LIMIT')) { @\ini_set('memory_limit', $memoryLimit); } else { $memoryInBytes = function ($value) { $unit = \strtolower(\substr($value, -1, 1)); $value = (int) $value; switch ($unit) { case 'g': $value *= 1024; // no break (cumulative multiplier) case 'm': $value *= 1024; // no break (cumulative multiplier) case 'k': $value *= 1024; } return $value; }; $memoryLimit = \trim(\ini_get('memory_limit')); // Increase memory_limit if it is lower than 1.5GB if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) { @\ini_set('memory_limit', '1536M'); } unset($memoryInBytes); } unset($memoryLimit); } // Workaround PHP bug on Windows where env vars containing Unicode chars are mangled in $_SERVER // see https://github.com/php/php-src/issues/7896 if (\PHP_VERSION_ID >= 70113 && (\PHP_VERSION_ID < 80016 || \PHP_VERSION_ID >= 80100 && \PHP_VERSION_ID < 80103) && Platform::isWindows()) { foreach ($_SERVER as $serverVar => $serverVal) { if (($serverVal = \getenv($serverVar)) !== \false) { $_SERVER[$serverVar] = $serverVal; } } } Platform::putEnv('COMPOSER_BINARY', \realpath($_SERVER['argv'][0])); ErrorHandler::register(); // run the command application $application = new Application(); $application->run(); #!/usr/bin/env php compile(); } catch (\Exception $e) { echo 'Failed to compile phar: [' . \get_class($e) . '] ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . \PHP_EOL; exit(1); } { "name": "composer\/composer", "type": "library", "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", "keywords": [ "package", "dependency", "autoload" ], "homepage": "https:\/\/getcomposer.org\/", "license": "MIT", "authors": [ { "name": "Nils Adermann", "email": "naderman@naderman.de", "homepage": "https:\/\/www.naderman.de" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "https:\/\/seld.be" } ], "require": { "php": "^7.2.5 || ^8.0", "composer\/ca-bundle": "^1.5", "composer\/class-map-generator": "^1.4.0", "composer\/metadata-minifier": "^1.0", "composer\/semver": "^3.3", "composer\/spdx-licenses": "^1.5.7", "composer\/xdebug-handler": "^2.0.2 || ^3.0.3", "justinrainbow\/json-schema": "^5.3", "psr\/log": "^1.0 || ^2.0 || ^3.0", "seld\/jsonlint": "^1.4", "seld\/phar-utils": "^1.2", "symfony\/console": "^5.4.35 || ^6.3.12 || ^7.0.3", "symfony\/filesystem": "^5.4.35 || ^6.3.12 || ^7.0.3", "symfony\/finder": "^5.4.35 || ^6.3.12 || ^7.0.3", "symfony\/process": "^5.4.35 || ^6.3.12 || ^7.0.3", "react\/promise": "^2.11 || ^3.2", "composer\/pcre": "^2.2 || ^3.2", "symfony\/polyfill-php73": "^1.24", "symfony\/polyfill-php80": "^1.24", "symfony\/polyfill-php81": "^1.24", "seld\/signal-handler": "^2.0" }, "require-dev": { "symfony\/phpunit-bridge": "^6.4.3 || ^7.0.1", "phpstan\/phpstan": "^1.11.8", "phpstan\/phpstan-phpunit": "^1.4.0", "phpstan\/phpstan-deprecation-rules": "^1.2.0", "phpstan\/phpstan-strict-rules": "^1.6.0", "phpstan\/phpstan-symfony": "^1.4.0" }, "suggest": { "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", "ext-zip": "Enabling the zip extension allows you to unzip archives", "ext-zlib": "Allow gzip compression of HTTP requests" }, "config": { "platform": { "php": "7.2.5" }, "platform-check": false }, "extra": { "branch-alias": { "dev-main": "2.8-dev" }, "phpstan": { "includes": [ "phpstan\/rules.neon" ] } }, "autoload": { "psr-4": { "Composer\\": "src\/Composer\/" } }, "autoload-dev": { "psr-4": { "Composer\\Test\\": "tests\/Composer\/Test\/" }, "exclude-from-classmap": [ "tests\/Composer\/Test\/Fixtures\/", "tests\/Composer\/Test\/Autoload\/Fixtures", "tests\/Composer\/Test\/Autoload\/MinimumVersionSupport", "tests\/Composer\/Test\/Plugin\/Fixtures" ] }, "bin": [ "bin\/composer" ], "scripts": { "compile": "@php -dphar.readonly=0 bin\/compile", "test": "@php simple-phpunit", "phpstan": "@php vendor\/bin\/phpstan analyse --configuration=phpstan\/config.neon" }, "scripts-descriptions": { "compile": "Compile composer.phar", "test": "Run all tests", "phpstan": "Runs PHPStan" }, "support": { "issues": "https:\/\/github.com\/composer\/composer\/issues", "irc": "ircs:\/\/irc.libera.chat:6697\/composer", "security": "https:\/\/github.com\/composer\/composer\/security\/policy" } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\PHPStan; use Composer\DependencyResolver\Rule; use Composer\Package\BasePackage; use Composer\Package\Link; use Composer\Semver\Constraint\ConstraintInterface; use _ContaoManager\PhpParser\Node\Expr\MethodCall; use _ContaoManager\PHPStan\Analyser\Scope; use _ContaoManager\PHPStan\Reflection\MethodReflection; use _ContaoManager\PHPStan\Type\Accessory\AccessoryNonEmptyStringType; use _ContaoManager\PHPStan\Type\Constant\ConstantArrayType; use _ContaoManager\PHPStan\Type\Constant\ConstantStringType; use _ContaoManager\PHPStan\Type\Constant\ConstantIntegerType; use _ContaoManager\PHPStan\Type\DynamicMethodReturnTypeExtension; use _ContaoManager\PHPStan\Type\IntegerType; use _ContaoManager\PHPStan\Type\StringType; use _ContaoManager\PHPStan\Type\Type; use _ContaoManager\PHPStan\Type\ObjectType; use _ContaoManager\PHPStan\Type\TypeCombinator; use _ContaoManager\PhpParser\Node\Identifier; final class RuleReasonDataReturnTypeExtension implements DynamicMethodReturnTypeExtension { public function getClass() : string { return Rule::class; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return \strtolower($methodReflection->getName()) === 'getreasondata'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : Type { $reasonType = $scope->getType(new MethodCall($methodCall->var, new Identifier('getReason'))); $types = [Rule::RULE_ROOT_REQUIRE => new ConstantArrayType([new ConstantStringType('packageName'), new ConstantStringType('constraint')], [new StringType(), new ObjectType(ConstraintInterface::class)]), Rule::RULE_FIXED => new ConstantArrayType([new ConstantStringType('package')], [new ObjectType(BasePackage::class)]), Rule::RULE_PACKAGE_CONFLICT => new ObjectType(Link::class), Rule::RULE_PACKAGE_REQUIRES => new ObjectType(Link::class), Rule::RULE_PACKAGE_SAME_NAME => TypeCombinator::intersect(new StringType(), new AccessoryNonEmptyStringType()), Rule::RULE_LEARNED => new IntegerType(), Rule::RULE_PACKAGE_ALIAS => new ObjectType(BasePackage::class), Rule::RULE_PACKAGE_INVERSE_ALIAS => new ObjectType(BasePackage::class)]; foreach ($types as $const => $type) { if ((new ConstantIntegerType($const))->isSuperTypeOf($reasonType)->yes()) { return $type; } } return TypeCombinator::union(...$types); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\PHPStan; use Composer\Config; use Composer\Json\JsonFile; use _ContaoManager\PhpParser\Node\Expr\MethodCall; use _ContaoManager\PHPStan\Analyser\Scope; use _ContaoManager\PHPStan\Reflection\MethodReflection; use _ContaoManager\PHPStan\Reflection\ParametersAcceptorSelector; use _ContaoManager\PHPStan\Type\ArrayType; use _ContaoManager\PHPStan\Type\BooleanType; use _ContaoManager\PHPStan\Type\Constant\ConstantArrayType; use _ContaoManager\PHPStan\Type\Constant\ConstantBooleanType; use _ContaoManager\PHPStan\Type\Constant\ConstantStringType; use _ContaoManager\PHPStan\Type\DynamicMethodReturnTypeExtension; use _ContaoManager\PHPStan\Type\IntegerRangeType; use _ContaoManager\PHPStan\Type\IntegerType; use _ContaoManager\PHPStan\Type\MixedType; use _ContaoManager\PHPStan\Type\StringType; use _ContaoManager\PHPStan\Type\Type; use _ContaoManager\PHPStan\Type\TypeCombinator; use _ContaoManager\PHPStan\Type\TypeUtils; use _ContaoManager\PHPStan\Type\UnionType; final class ConfigReturnTypeExtension implements DynamicMethodReturnTypeExtension { /** @var array */ private $properties = []; public function __construct() { $schema = JsonFile::parseJson((string) \file_get_contents(JsonFile::COMPOSER_SCHEMA_PATH)); /** * @var string $prop */ foreach ($schema['properties']['config']['properties'] as $prop => $conf) { $type = $this->parseType($conf, $prop); $this->properties[$prop] = $type; } } public function getClass() : string { return Config::class; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return \strtolower($methodReflection->getName()) === 'get'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { $args = $methodCall->getArgs(); if (\count($args) < 1) { return null; } $keyType = $scope->getType($args[0]->value); if (\method_exists($keyType, 'getConstantStrings')) { // @phpstan-ignore function.alreadyNarrowedType (- depending on PHPStan version, this method will always exist, or not.) $strings = $keyType->getConstantStrings(); } else { // for compat with old phpstan versions, we use a deprecated phpstan method. $strings = TypeUtils::getConstantStrings($keyType); // @phpstan-ignore staticMethod.deprecated (ignore deprecation) } if ($strings !== []) { $types = []; foreach ($strings as $string) { if (!isset($this->properties[$string->getValue()])) { return null; } $types[] = $this->properties[$string->getValue()]; } return TypeCombinator::union(...$types); } return null; } /** * @param array $def */ private function parseType(array $def, string $path) : Type { if (isset($def['type'])) { $types = []; foreach ((array) $def['type'] as $type) { switch ($type) { case 'integer': if (\in_array($path, ['process-timeout', 'cache-ttl', 'cache-files-ttl', 'cache-files-maxsize'], \true)) { $types[] = IntegerRangeType::createAllGreaterThanOrEqualTo(0); } else { $types[] = new IntegerType(); } break; case 'string': if ($path === 'cache-files-maxsize') { // passthru, skip as it is always converted to int } elseif ($path === 'discard-changes') { $types[] = new ConstantStringType('stash'); } elseif ($path === 'use-parent-dir') { $types[] = new ConstantStringType('prompt'); } elseif ($path === 'store-auths') { $types[] = new ConstantStringType('prompt'); } elseif ($path === 'platform-check') { $types[] = new ConstantStringType('php-only'); } elseif ($path === 'github-protocols') { $types[] = new UnionType([new ConstantStringType('git'), new ConstantStringType('https'), new ConstantStringType('ssh'), new ConstantStringType('http')]); } elseif (\str_starts_with($path, 'preferred-install')) { $types[] = new UnionType([new ConstantStringType('source'), new ConstantStringType('dist'), new ConstantStringType('auto')]); } else { $types[] = new StringType(); } break; case 'boolean': if ($path === 'platform.additionalProperties') { $types[] = new ConstantBooleanType(\false); } else { $types[] = new BooleanType(); } break; case 'object': $addlPropType = null; if (isset($def['additionalProperties'])) { $addlPropType = $this->parseType($def['additionalProperties'], $path . '.additionalProperties'); } if (isset($def['properties'])) { $keyNames = []; $valTypes = []; $optionalKeys = []; $propIndex = 0; foreach ($def['properties'] as $propName => $propdef) { $keyNames[] = new ConstantStringType($propName); $valType = $this->parseType($propdef, $path . '.' . $propName); if (!isset($def['required']) || !\in_array($propName, $def['required'], \true)) { $valType = TypeCombinator::addNull($valType); $optionalKeys[] = $propIndex; } $valTypes[] = $valType; $propIndex++; } if ($addlPropType !== null) { $types[] = new ArrayType(TypeCombinator::union(new StringType(), ...$keyNames), TypeCombinator::union($addlPropType, ...$valTypes)); } else { $types[] = new ConstantArrayType($keyNames, $valTypes, [0], $optionalKeys); } } else { $types[] = new ArrayType(new StringType(), $addlPropType ?? new MixedType()); } break; case 'array': if (isset($def['items'])) { $valType = $this->parseType($def['items'], $path . '.items'); } else { $valType = new MixedType(); } $types[] = new ArrayType(new IntegerType(), $valType); break; default: $types[] = new MixedType(); } } $type = TypeCombinator::union(...$types); } elseif (isset($def['enum'])) { $type = TypeCombinator::union(...\array_map(static function (string $value) : ConstantStringType { return new ConstantStringType($value); }, $def['enum'])); } else { $type = new MixedType(); } // allow-plugins defaults to null until July 1st 2022 for some BC hackery, but after that it is not nullable anymore if ($path === 'allow-plugins' && \time() < \strtotime('2022-07-01')) { $type = TypeCombinator::addNull($type); } // default null props if (\in_array($path, ['autoloader-suffix', 'gitlab-protocol'], \true)) { $type = TypeCombinator::addNull($type); } return $type; } } * 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\Config\JsonConfigSource; use Composer\Json\JsonFile; use Composer\IO\IOInterface; use Composer\Package\Archiver; use Composer\Package\Version\VersionGuesser; use Composer\Package\RootPackageInterface; use Composer\Repository\FilesystemRepository; use Composer\Repository\RepositoryManager; use Composer\Repository\RepositoryFactory; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Util\HttpDownloader; use Composer\Util\Loop; use Composer\Util\Silencer; use Composer\Plugin\PluginEvents; use Composer\EventDispatcher\Event; use Phar; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle; use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput; use Composer\EventDispatcher\EventDispatcher; use Composer\Autoload\AutoloadGenerator; use Composer\Package\Version\VersionParser; use Composer\Downloader\TransportException; use Composer\Json\JsonValidationException; use Composer\Repository\InstalledRepositoryInterface; use UnexpectedValueException; use ZipArchive; /** * Creates a configured instance of composer. * * @author Ryan Weaver * @author Jordi Boggiano * @author Igor Wiedler * @author Nils Adermann */ class Factory { /** * @throws \RuntimeException */ protected static function getHomeDir() : string { $home = Platform::getEnv('COMPOSER_HOME'); if ($home) { return $home; } if (Platform::isWindows()) { if (!Platform::getEnv('APPDATA')) { throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly'); } return \rtrim(\strtr(Platform::getEnv('APPDATA'), '\\', '/'), '/') . '/Composer'; } $userDir = self::getUserDir(); $dirs = []; if (self::useXdg()) { // XDG Base Directory Specifications $xdgConfig = Platform::getEnv('XDG_CONFIG_HOME'); if (!$xdgConfig) { $xdgConfig = $userDir . '/.config'; } $dirs[] = $xdgConfig . '/composer'; } $dirs[] = $userDir . '/.composer'; // select first dir which exists of: $XDG_CONFIG_HOME/composer or ~/.composer foreach ($dirs as $dir) { if (Silencer::call('is_dir', $dir)) { return $dir; } } // if none exists, we default to first defined one (XDG one if system uses it, or ~/.composer otherwise) return $dirs[0]; } protected static function getCacheDir(string $home) : string { $cacheDir = Platform::getEnv('COMPOSER_CACHE_DIR'); if ($cacheDir) { return $cacheDir; } $homeEnv = Platform::getEnv('COMPOSER_HOME'); if ($homeEnv) { return $homeEnv . '/cache'; } if (Platform::isWindows()) { if ($cacheDir = Platform::getEnv('LOCALAPPDATA')) { $cacheDir .= '/Composer'; } else { $cacheDir = $home . '/cache'; } return \rtrim(\strtr($cacheDir, '\\', '/'), '/'); } $userDir = self::getUserDir(); if (\PHP_OS === 'Darwin') { // Migrate existing cache dir in old location if present if (\is_dir($home . '/cache') && !\is_dir($userDir . '/Library/Caches/composer')) { Silencer::call('rename', $home . '/cache', $userDir . '/Library/Caches/composer'); } return $userDir . '/Library/Caches/composer'; } if ($home === $userDir . '/.composer' && \is_dir($home . '/cache')) { return $home . '/cache'; } if (self::useXdg()) { $xdgCache = Platform::getEnv('XDG_CACHE_HOME') ?: $userDir . '/.cache'; return $xdgCache . '/composer'; } return $home . '/cache'; } protected static function getDataDir(string $home) : string { $homeEnv = Platform::getEnv('COMPOSER_HOME'); if ($homeEnv) { return $homeEnv; } if (Platform::isWindows()) { return \strtr($home, '\\', '/'); } $userDir = self::getUserDir(); if ($home !== $userDir . '/.composer' && self::useXdg()) { $xdgData = Platform::getEnv('XDG_DATA_HOME') ?: $userDir . '/.local/share'; return $xdgData . '/composer'; } return $home; } public static function createConfig(?IOInterface $io = null, ?string $cwd = null) : \Composer\Config { $cwd = $cwd ?? Platform::getCwd(\true); $config = new \Composer\Config(\true, $cwd); // determine and add main dirs to the config $home = self::getHomeDir(); $config->merge(['config' => ['home' => $home, 'cache-dir' => self::getCacheDir($home), 'data-dir' => self::getDataDir($home)]], \Composer\Config::SOURCE_DEFAULT); // load global config $file = new JsonFile($config->get('home') . '/config.json'); if ($file->exists()) { if ($io instanceof IOInterface) { $io->writeError('Loading config file ' . $file->getPath(), \true, IOInterface::DEBUG); } self::validateJsonSchema($io, $file); $config->merge($file->read(), $file->getPath()); } $config->setConfigSource(new JsonConfigSource($file)); $htaccessProtect = $config->get('htaccess-protect'); if ($htaccessProtect) { // Protect directory against web access. Since HOME could be // the www-data's user home and be web-accessible it is a // potential security risk $dirs = [$config->get('home'), $config->get('cache-dir'), $config->get('data-dir')]; foreach ($dirs as $dir) { if (!\file_exists($dir . '/.htaccess')) { if (!\is_dir($dir)) { Silencer::call('mkdir', $dir, 0777, \true); } Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all'); } } } // load global auth file $file = new JsonFile($config->get('home') . '/auth.json'); if ($file->exists()) { if ($io instanceof IOInterface) { $io->writeError('Loading config file ' . $file->getPath(), \true, IOInterface::DEBUG); } self::validateJsonSchema($io, $file, JsonFile::AUTH_SCHEMA); $config->merge(['config' => $file->read()], $file->getPath()); } $config->setAuthConfigSource(new JsonConfigSource($file, \true)); self::loadComposerAuthEnv($config, $io); return $config; } public static function getComposerFile() : string { $env = Platform::getEnv('COMPOSER'); if (\is_string($env)) { $env = \trim($env); if ('' !== $env) { if (\is_dir($env)) { throw new \RuntimeException('The COMPOSER environment variable is set to ' . $env . ' which is a directory, this variable should point to a composer.json or be left unset.'); } return $env; } } return './composer.json'; } public static function getLockFile(string $composerFile) : string { return "json" === \pathinfo($composerFile, \PATHINFO_EXTENSION) ? \substr($composerFile, 0, -4) . 'lock' : $composerFile . '.lock'; } /** * @return array{highlight: OutputFormatterStyle, warning: OutputFormatterStyle} */ public static function createAdditionalStyles() : array { return ['highlight' => new OutputFormatterStyle('red'), 'warning' => new OutputFormatterStyle('black', 'yellow')]; } public static function createOutput() : ConsoleOutput { $styles = self::createAdditionalStyles(); $formatter = new OutputFormatter(\false, $styles); return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter); } /** * Creates a Composer instance * * @param IOInterface $io IO instance * @param array|string|null $localConfig either a configuration array or a filename to read from, if null it will * read from the default filename * @param bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins * @param bool $disableScripts Whether scripts should not be run * @param bool $fullLoad Whether to initialize everything or only main project stuff (used when loading the global composer) * @throws \InvalidArgumentException * @throws \UnexpectedValueException * @return Composer|PartialComposer Composer if $fullLoad is true, otherwise PartialComposer * @phpstan-return ($fullLoad is true ? Composer : PartialComposer) */ public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = \false, ?string $cwd = null, bool $fullLoad = \true, bool $disableScripts = \false) { // if a custom composer.json path is given, we change the default cwd to be that file's directory if (\is_string($localConfig) && \is_file($localConfig) && null === $cwd) { $cwd = \dirname($localConfig); } $cwd = $cwd ?? Platform::getCwd(\true); // load Composer configuration if (null === $localConfig) { $localConfig = static::getComposerFile(); } $localConfigSource = \Composer\Config::SOURCE_UNKNOWN; if (\is_string($localConfig)) { $composerFile = $localConfig; $file = new JsonFile($localConfig, null, $io); if (!$file->exists()) { if ($localConfig === './composer.json' || $localConfig === 'composer.json') { $message = 'Composer could not find a composer.json file in ' . $cwd; } else { $message = 'Composer could not find the config file: ' . $localConfig; } $instructions = $fullLoad ? 'To initialize a project, please create a composer.json file. See https://getcomposer.org/basic-usage' : ''; throw new \InvalidArgumentException($message . \PHP_EOL . $instructions); } if (!Platform::isInputCompletionProcess()) { try { $file->validateSchema(JsonFile::LAX_SCHEMA); } catch (JsonValidationException $e) { $errors = ' - ' . \implode(\PHP_EOL . ' - ', $e->getErrors()); $message = $e->getMessage() . ':' . \PHP_EOL . $errors; throw new JsonValidationException($message); } } $localConfig = $file->read(); $localConfigSource = $file->getPath(); } // Load config and override with local config/auth config $config = static::createConfig($io, $cwd); $isGlobal = $localConfigSource !== \Composer\Config::SOURCE_UNKNOWN && \realpath($config->get('home')) === \realpath(\dirname($localConfigSource)); $config->merge($localConfig, $localConfigSource); if (isset($composerFile)) { $io->writeError('Loading config file ' . $composerFile . ' (' . \realpath($composerFile) . ')', \true, IOInterface::DEBUG); $config->setConfigSource(new JsonConfigSource(new JsonFile(\realpath($composerFile), null, $io))); $localAuthFile = new JsonFile(\dirname(\realpath($composerFile)) . '/auth.json', null, $io); if ($localAuthFile->exists()) { $io->writeError('Loading config file ' . $localAuthFile->getPath(), \true, IOInterface::DEBUG); self::validateJsonSchema($io, $localAuthFile, JsonFile::AUTH_SCHEMA); $config->merge(['config' => $localAuthFile->read()], $localAuthFile->getPath()); $config->setLocalAuthConfigSource(new JsonConfigSource($localAuthFile, \true)); } } // make sure we load the auth env again over the local auth.json + composer.json config self::loadComposerAuthEnv($config, $io); $vendorDir = $config->get('vendor-dir'); // initialize composer $composer = $fullLoad ? new \Composer\Composer() : new \Composer\PartialComposer(); $composer->setConfig($config); if ($isGlobal) { $composer->setGlobal(); } if ($fullLoad) { // load auth configs into the IO instance $io->loadConfiguration($config); // load existing Composer\InstalledVersions instance if available and scripts/plugins are allowed, as they might need it // we only load if the InstalledVersions class wasn't defined yet so that this is only loaded once if (\false === $disablePlugins && \false === $disableScripts && !\class_exists('Composer\\InstalledVersions', \false) && \file_exists($installedVersionsPath = $config->get('vendor-dir') . '/composer/installed.php')) { // force loading the class at this point so it is loaded from the composer phar and not from the vendor dir // as we cannot guarantee integrity of that file if (\class_exists('Composer\\InstalledVersions')) { FilesystemRepository::safelyLoadInstalledVersions($installedVersionsPath); } } } $httpDownloader = self::createHttpDownloader($io, $config); $process = new ProcessExecutor($io); $loop = new Loop($httpDownloader, $process); $composer->setLoop($loop); // initialize event dispatcher $dispatcher = new EventDispatcher($composer, $io, $process); $dispatcher->setRunScripts(!$disableScripts); $composer->setEventDispatcher($dispatcher); // initialize repository manager $rm = RepositoryFactory::manager($io, $config, $httpDownloader, $dispatcher, $process); $composer->setRepositoryManager($rm); // force-set the version of the global package if not defined as // guessing it adds no value and only takes time if (!$fullLoad && !isset($localConfig['version'])) { $localConfig['version'] = '1.0.0'; } // load package $parser = new VersionParser(); $guesser = new VersionGuesser($config, $process, $parser, $io); $loader = $this->loadRootPackage($rm, $config, $parser, $guesser, $io); $package = $loader->load($localConfig, 'Composer\\Package\\RootPackage', $cwd); $composer->setPackage($package); // load local repository $this->addLocalRepository($io, $rm, $vendorDir, $package, $process); // initialize installation manager $im = $this->createInstallationManager($loop, $io, $dispatcher); $composer->setInstallationManager($im); if ($composer instanceof \Composer\Composer) { // initialize download manager $dm = $this->createDownloadManager($io, $config, $httpDownloader, $process, $dispatcher); $composer->setDownloadManager($dm); // initialize autoload generator $generator = new AutoloadGenerator($dispatcher, $io); $composer->setAutoloadGenerator($generator); // initialize archive manager $am = $this->createArchiveManager($config, $dm, $loop); $composer->setArchiveManager($am); } // add installers to the manager (must happen after download manager is created since they read it out of $composer) $this->createDefaultInstallers($im, $composer, $io, $process); // init locker if possible if ($composer instanceof \Composer\Composer && isset($composerFile)) { $lockFile = self::getLockFile($composerFile); if (!$config->get('lock') && \file_exists($lockFile)) { $io->writeError('' . $lockFile . ' is present but ignored as the "lock" config option is disabled.'); } $locker = new \Composer\Package\Locker($io, new JsonFile($config->get('lock') ? $lockFile : Platform::getDevNull(), null, $io), $im, \file_get_contents($composerFile), $process); $composer->setLocker($locker); } elseif ($composer instanceof \Composer\Composer) { $locker = new \Composer\Package\Locker($io, new JsonFile(Platform::getDevNull(), null, $io), $im, JsonFile::encode($localConfig), $process); $composer->setLocker($locker); } if ($composer instanceof \Composer\Composer) { $globalComposer = null; if (!$composer->isGlobal()) { $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins, $disableScripts); } $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins); $composer->setPluginManager($pm); if ($composer->isGlobal()) { $pm->setRunningInGlobalDir(\true); } $pm->loadInstalledPlugins(); } if ($fullLoad) { $initEvent = new Event(PluginEvents::INIT); $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent); // once everything is initialized we can // purge packages from local repos if they have been deleted on the filesystem $this->purgePackages($rm->getLocalRepository(), $im); } return $composer; } /** * @param bool $disablePlugins Whether plugins should not be loaded * @param bool $disableScripts Whether scripts should not be executed */ public static function createGlobal(IOInterface $io, bool $disablePlugins = \false, bool $disableScripts = \false) : ?\Composer\Composer { $factory = new static(); return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, $disableScripts, \true); } /** * @param Repository\RepositoryManager $rm */ protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, string $vendorDir, RootPackageInterface $rootPackage, ?ProcessExecutor $process = null) : void { $fs = null; if ($process) { $fs = new Filesystem($process); } $rm->setLocalRepository(new \Composer\Repository\InstalledFilesystemRepository(new JsonFile($vendorDir . '/composer/installed.json', null, $io), \true, $rootPackage, $fs)); } /** * @param bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins * @return PartialComposer|Composer|null By default PartialComposer, but Composer if $fullLoad is set to true * @phpstan-return ($fullLoad is true ? Composer|null : PartialComposer|null) */ protected function createGlobalComposer(IOInterface $io, \Composer\Config $config, $disablePlugins, bool $disableScripts, bool $fullLoad = \false) : ?\Composer\PartialComposer { // make sure if disable plugins was 'local' it is now turned off $disablePlugins = $disablePlugins === 'global' || $disablePlugins === \true; $composer = null; try { $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad, $disableScripts); } catch (\Exception $e) { $io->writeError('Failed to initialize global composer: ' . $e->getMessage(), \true, IOInterface::DEBUG); } return $composer; } /** * @param IO\IOInterface $io * @param EventDispatcher $eventDispatcher */ public function createDownloadManager(IOInterface $io, \Composer\Config $config, HttpDownloader $httpDownloader, ProcessExecutor $process, ?EventDispatcher $eventDispatcher = null) : \Composer\Downloader\DownloadManager { $cache = null; if ($config->get('cache-files-ttl') > 0) { $cache = new \Composer\Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./'); $cache->setReadOnly($config->get('cache-read-only')); } $fs = new Filesystem($process); $dm = new \Composer\Downloader\DownloadManager($io, \false, $fs); switch ($preferred = $config->get('preferred-install')) { case 'dist': $dm->setPreferDist(\true); break; case 'source': $dm->setPreferSource(\true); break; case 'auto': default: // noop break; } if (\is_array($preferred)) { $dm->setPreferences($preferred); } $dm->setDownloader('git', new \Composer\Downloader\GitDownloader($io, $config, $process, $fs)); $dm->setDownloader('svn', new \Composer\Downloader\SvnDownloader($io, $config, $process, $fs)); $dm->setDownloader('fossil', new \Composer\Downloader\FossilDownloader($io, $config, $process, $fs)); $dm->setDownloader('hg', new \Composer\Downloader\HgDownloader($io, $config, $process, $fs)); $dm->setDownloader('perforce', new \Composer\Downloader\PerforceDownloader($io, $config, $process, $fs)); $dm->setDownloader('zip', new \Composer\Downloader\ZipDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); $dm->setDownloader('rar', new \Composer\Downloader\RarDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); $dm->setDownloader('tar', new \Composer\Downloader\TarDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); $dm->setDownloader('gzip', new \Composer\Downloader\GzipDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); $dm->setDownloader('xz', new \Composer\Downloader\XzDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); $dm->setDownloader('phar', new \Composer\Downloader\PharDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); $dm->setDownloader('file', new \Composer\Downloader\FileDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); $dm->setDownloader('path', new \Composer\Downloader\PathDownloader($io, $config, $httpDownloader, $eventDispatcher, $cache, $fs, $process)); return $dm; } /** * @param Config $config The configuration * @param Downloader\DownloadManager $dm Manager use to download sources * @return Archiver\ArchiveManager */ public function createArchiveManager(\Composer\Config $config, \Composer\Downloader\DownloadManager $dm, Loop $loop) { $am = new Archiver\ArchiveManager($dm, $loop); if (\class_exists(ZipArchive::class)) { $am->addArchiver(new Archiver\ZipArchiver()); } if (\class_exists(Phar::class)) { $am->addArchiver(new Archiver\PharArchiver()); } return $am; } /** * @param bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins */ protected function createPluginManager(IOInterface $io, \Composer\Composer $composer, ?\Composer\PartialComposer $globalComposer = null, $disablePlugins = \false) : \Composer\Plugin\PluginManager { return new \Composer\Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins); } public function createInstallationManager(Loop $loop, IOInterface $io, ?EventDispatcher $eventDispatcher = null) : \Composer\Installer\InstallationManager { return new \Composer\Installer\InstallationManager($loop, $io, $eventDispatcher); } protected function createDefaultInstallers(\Composer\Installer\InstallationManager $im, \Composer\PartialComposer $composer, IOInterface $io, ?ProcessExecutor $process = null) : void { $fs = new Filesystem($process); $binaryInstaller = new \Composer\Installer\BinaryInstaller($io, \rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $fs, \rtrim($composer->getConfig()->get('vendor-dir'), '/')); $im->addInstaller(new \Composer\Installer\LibraryInstaller($io, $composer, null, $fs, $binaryInstaller)); $im->addInstaller(new \Composer\Installer\PluginInstaller($io, $composer, $fs, $binaryInstaller)); $im->addInstaller(new \Composer\Installer\MetapackageInstaller($io)); } /** * @param InstalledRepositoryInterface $repo repository to purge packages from * @param Installer\InstallationManager $im manager to check whether packages are still installed */ protected function purgePackages(InstalledRepositoryInterface $repo, \Composer\Installer\InstallationManager $im) : void { foreach ($repo->getPackages() as $package) { if (!$im->isPackageInstalled($repo, $package)) { $repo->removePackage($package); } } } protected function loadRootPackage(RepositoryManager $rm, \Composer\Config $config, VersionParser $parser, VersionGuesser $guesser, IOInterface $io) : \Composer\Package\Loader\RootPackageLoader { return new \Composer\Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io); } /** * @param IOInterface $io IO instance * @param mixed $config either a configuration array or a filename to read from, if null it will read from * the default filename * @param bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins * @param bool $disableScripts Whether scripts should not be run */ public static function create(IOInterface $io, $config = null, $disablePlugins = \false, bool $disableScripts = \false) : \Composer\Composer { $factory = new static(); // for BC reasons, if a config is passed in either as array or a path that is not the default composer.json path // we disable local plugins as they really should not be loaded from CWD // If you want to avoid this behavior, you should be calling createComposer directly with a $cwd arg set correctly // to the path where the composer.json being loaded resides if ($config !== null && $config !== self::getComposerFile() && $disablePlugins === \false) { $disablePlugins = 'local'; } return $factory->createComposer($io, $config, $disablePlugins, null, \true, $disableScripts); } /** * If you are calling this in a plugin, you probably should instead use $composer->getLoop()->getHttpDownloader() * * @param IOInterface $io IO instance * @param Config $config Config instance * @param mixed[] $options Array of options passed directly to HttpDownloader constructor */ public static function createHttpDownloader(IOInterface $io, \Composer\Config $config, array $options = []) : HttpDownloader { static $warned = \false; $disableTls = \false; // allow running the config command if disable-tls is in the arg list, even if openssl is missing, to allow disabling it via the config command if (isset($_SERVER['argv']) && \in_array('disable-tls', $_SERVER['argv']) && (\in_array('conf', $_SERVER['argv']) || \in_array('config', $_SERVER['argv']))) { $warned = \true; $disableTls = !\extension_loaded('openssl'); } elseif ($config->get('disable-tls') === \true) { if (!$warned) { $io->writeError('You are running Composer with SSL/TLS protection disabled.'); } $warned = \true; $disableTls = \true; } elseif (!\extension_loaded('openssl')) { throw new \Composer\Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. ' . 'If you can not enable the openssl extension, you can disable this error, at your own risk, by setting the \'disable-tls\' option to true.'); } $httpDownloaderOptions = []; if ($disableTls === \false) { if ('' !== $config->get('cafile')) { $httpDownloaderOptions['ssl']['cafile'] = $config->get('cafile'); } if ('' !== $config->get('capath')) { $httpDownloaderOptions['ssl']['capath'] = $config->get('capath'); } $httpDownloaderOptions = \array_replace_recursive($httpDownloaderOptions, $options); } try { $httpDownloader = new HttpDownloader($io, $config, $httpDownloaderOptions, $disableTls); } catch (TransportException $e) { if (\false !== \strpos($e->getMessage(), 'cafile')) { $io->write('Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.'); $io->write('A valid CA certificate file is required for SSL/TLS protection.'); $io->write('You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.'); } throw $e; } return $httpDownloader; } private static function loadComposerAuthEnv(\Composer\Config $config, ?IOInterface $io) : void { $composerAuthEnv = Platform::getEnv('COMPOSER_AUTH'); if (\false === $composerAuthEnv || '' === $composerAuthEnv) { return; } $authData = \json_decode($composerAuthEnv); if (null === $authData) { throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object'); } if ($io instanceof IOInterface) { $io->writeError('Loading auth config from COMPOSER_AUTH', \true, IOInterface::DEBUG); } self::validateJsonSchema($io, $authData, JsonFile::AUTH_SCHEMA, 'COMPOSER_AUTH'); $authData = \json_decode($composerAuthEnv, \true); if (null !== $authData) { $config->merge(['config' => $authData], 'COMPOSER_AUTH'); } } private static function useXdg() : bool { foreach (\array_keys($_SERVER) as $key) { if (\strpos((string) $key, 'XDG_') === 0) { return \true; } } if (Silencer::call('is_dir', '/etc/xdg')) { return \true; } return \false; } /** * @throws \RuntimeException */ private static function getUserDir() : string { $home = Platform::getEnv('HOME'); if (!$home) { throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly'); } return \rtrim(\strtr($home, '\\', '/'), '/'); } /** * @param mixed $fileOrData * @param JsonFile::*_SCHEMA $schema */ private static function validateJsonSchema(?IOInterface $io, $fileOrData, int $schema = JsonFile::LAX_SCHEMA, ?string $source = null) : void { if (Platform::isInputCompletionProcess()) { return; } try { if ($fileOrData instanceof JsonFile) { $fileOrData->validateSchema($schema); } else { if (null === $source) { throw new \InvalidArgumentException('$source is required to be provided if $fileOrData is arbitrary data'); } JsonFile::validateJsonSchema($source, $fileOrData, $schema); } } catch (JsonValidationException $e) { $msg = $e->getMessage() . ', this may result in errors and should be resolved:' . \PHP_EOL . ' - ' . \implode(\PHP_EOL . ' - ', $e->getErrors()); if ($io instanceof IOInterface) { $io->writeError('' . $msg . ''); } else { throw new UnexpectedValueException($msg); } } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\PackageInterface; use Composer\Package\BasePackage; use Composer\Semver\Constraint\ConstraintInterface; /** * Repository interface. * * @author Nils Adermann * @author Konstantin Kudryashov * @author Jordi Boggiano */ interface RepositoryInterface extends \Countable { public const SEARCH_FULLTEXT = 0; public const SEARCH_NAME = 1; public const SEARCH_VENDOR = 2; /** * Checks if specified package registered (installed). * * @param PackageInterface $package package instance * * @return bool */ public function hasPackage(PackageInterface $package); /** * Searches for the first match of a package by name and version. * * @param string $name package name * @param string|ConstraintInterface $constraint package version or version constraint to match against * * @return BasePackage|null */ public function findPackage(string $name, $constraint); /** * Searches for all packages matching a name and optionally a version. * * @param string $name package name * @param string|ConstraintInterface $constraint package version or version constraint to match against * * @return BasePackage[] */ public function findPackages(string $name, $constraint = null); /** * Returns list of registered packages. * * @return BasePackage[] */ public function getPackages(); /** * Returns list of registered packages with the supplied name * * - The packages returned are the packages found which match the constraints, acceptable stability and stability flags provided * - The namesFound returned are names which should be considered as canonically found in this repository, that should not be looked up in any further lower priority repositories * * @param ConstraintInterface[] $packageNameMap package names pointing to constraints * @param array $acceptableStabilities array of stability => BasePackage::STABILITY_* value * @param array $stabilityFlags an array of package name => BasePackage::STABILITY_* value * @param array> $alreadyLoaded an array of package name => package version => package * * @return array * * @phpstan-param array, BasePackage::STABILITY_*> $acceptableStabilities * @phpstan-param array $packageNameMap * @phpstan-return array{namesFound: array, packages: array} */ public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []); /** * Searches the repository for packages containing the query * * @param string $query search query, for SEARCH_NAME and SEARCH_VENDOR regular expressions metacharacters are supported by implementations, and user input should be escaped through preg_quote by callers * @param int $mode a set of SEARCH_* constants to search on, implementations should do a best effort only, default is SEARCH_FULLTEXT * @param ?string $type The type of package to search for. Defaults to all types of packages * * @return array[] an array of array('name' => '...', 'description' => '...'|null, 'abandoned' => 'string'|true|unset) For SEARCH_VENDOR the name will be in "vendor" form * @phpstan-return list */ public function search(string $query, int $mode = 0, ?string $type = null); /** * Returns a list of packages providing a given package name * * Packages which have the same name as $packageName should not be returned, only those that have a "provide" on it. * * @param string $packageName package name which must be provided * * @return array[] an array with the provider name as key and value of array('name' => '...', 'description' => '...', 'type' => '...') * @phpstan-return array */ public function getProviders(string $packageName); /** * Returns a name representing this repository to the user * * This is best effort and definitely can not always be very precise * * @return string */ public function getRepoName(); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Installed filesystem repository. * * @author Jordi Boggiano */ class InstalledFilesystemRepository extends \Composer\Repository\FilesystemRepository implements \Composer\Repository\InstalledRepositoryInterface { public function getRepoName() { return 'installed ' . parent::getRepoName(); } /** * @inheritDoc */ public function isFresh() { return !$this->file->exists(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Pcre\Preg; /** * Package repository. * * @author Jordi Boggiano */ class PackageRepository extends \Composer\Repository\ArrayRepository { /** @var mixed[] */ private $config; /** * Initializes filesystem repository. * * @param array{package: mixed[]} $config package definition */ public function __construct(array $config) { parent::__construct(); $this->config = $config['package']; // make sure we have an array of package definitions if (!\is_numeric(\key($this->config))) { $this->config = [$this->config]; } } /** * Initializes repository (reads file, or remote address). */ protected function initialize() : void { parent::initialize(); $loader = new ValidatingArrayLoader(new ArrayLoader(null, \true), \true); foreach ($this->config as $package) { try { $package = $loader->load($package); } catch (\Exception $e) { throw new \Composer\Repository\InvalidRepositoryException('A repository of type "package" contains an invalid package definition: ' . $e->getMessage() . "\n\nInvalid package definition:\n" . \json_encode($package)); } $this->addPackage($package); } } public function getRepoName() : string { return Preg::replace('{^array }', 'package ', parent::getRepoName()); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Lock array repository. * * Regular array repository, only uses a different type to identify the lock file as the source of info * * @author Nils Adermann */ class LockArrayRepository extends \Composer\Repository\ArrayRepository { use \Composer\Repository\CanonicalPackagesTrait; public function getRepoName() : string { return 'lock repo'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Composer; use Composer\Package\CompletePackage; use Composer\Package\CompletePackageInterface; use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Pcre\Preg; use Composer\Platform\HhvmDetector; use Composer\Platform\Runtime; use Composer\Platform\Version; use Composer\Plugin\PluginInterface; use Composer\Semver\Constraint\Constraint; use Composer\Util\Silencer; use Composer\XdebugHandler\XdebugHandler; /** * @author Jordi Boggiano */ class PlatformRepository extends \Composer\Repository\ArrayRepository { /** * @deprecated use PlatformRepository::isPlatformPackage(string $name) instead * @private */ public const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer(?:-(?:plugin|runtime)-api)?)$}iD'; /** * @var ?string */ private static $lastSeenPlatformPhp = null; /** * @var VersionParser */ private $versionParser; /** * Defines overrides so that the platform can be mocked * * Keyed by package name (lowercased) * * @var array */ private $overrides = []; /** * Stores which packages have been disabled and their actual version * * @var array */ private $disabledPackages = []; /** @var Runtime */ private $runtime; /** @var HhvmDetector */ private $hhvmDetector; /** * @param array $overrides */ public function __construct(array $packages = [], array $overrides = [], ?Runtime $runtime = null, ?HhvmDetector $hhvmDetector = null) { $this->runtime = $runtime ?: new Runtime(); $this->hhvmDetector = $hhvmDetector ?: new HhvmDetector(); foreach ($overrides as $name => $version) { if (!\is_string($version) && \false !== $version) { // @phpstan-ignore-line throw new \UnexpectedValueException('config.platform.' . $name . ' should be a string or false, but got ' . \gettype($version) . ' ' . \var_export($version, \true)); } if ($name === 'php' && $version === \false) { throw new \UnexpectedValueException('config.platform.' . $name . ' cannot be set to false as you cannot disable php entirely.'); } $this->overrides[\strtolower($name)] = ['name' => $name, 'version' => $version]; } parent::__construct($packages); } public function getRepoName() : string { return 'platform repo'; } public function isPlatformPackageDisabled(string $name) : bool { return isset($this->disabledPackages[$name]); } /** * @return array */ public function getDisabledPackages() : array { return $this->disabledPackages; } protected function initialize() : void { parent::initialize(); $libraries = []; $this->versionParser = new VersionParser(); // Add each of the override versions as options. // Later we might even replace the extensions instead. foreach ($this->overrides as $override) { // Check that it's a platform package. if (!self::isPlatformPackage($override['name'])) { throw new \InvalidArgumentException('Invalid platform package name in config.platform: ' . $override['name']); } if ($override['version'] !== \false) { $this->addOverriddenPackage($override); } } $prettyVersion = Composer::getVersion(); $version = $this->versionParser->normalize($prettyVersion); $composer = new CompletePackage('composer', $version, $prettyVersion); $composer->setDescription('Composer package'); $this->addPackage($composer); $prettyVersion = PluginInterface::PLUGIN_API_VERSION; $version = $this->versionParser->normalize($prettyVersion); $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion); $composerPluginApi->setDescription('The Composer Plugin API'); $this->addPackage($composerPluginApi); $prettyVersion = Composer::RUNTIME_API_VERSION; $version = $this->versionParser->normalize($prettyVersion); $composerRuntimeApi = new CompletePackage('composer-runtime-api', $version, $prettyVersion); $composerRuntimeApi->setDescription('The Composer Runtime API'); $this->addPackage($composerRuntimeApi); try { $prettyVersion = $this->runtime->getConstant('PHP_VERSION'); $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { $prettyVersion = Preg::replace('#^([^~+-]+).*$#', '$1', $this->runtime->getConstant('PHP_VERSION')); $version = $this->versionParser->normalize($prettyVersion); } $php = new CompletePackage('php', $version, $prettyVersion); $php->setDescription('The PHP interpreter'); $this->addPackage($php); if ($this->runtime->getConstant('PHP_DEBUG')) { $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion); $phpdebug->setDescription('The PHP interpreter, with debugging symbols'); $this->addPackage($phpdebug); } if ($this->runtime->hasConstant('PHP_ZTS') && $this->runtime->getConstant('PHP_ZTS')) { $phpzts = new CompletePackage('php-zts', $version, $prettyVersion); $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety'); $this->addPackage($phpzts); } if ($this->runtime->getConstant('PHP_INT_SIZE') === 8) { $php64 = new CompletePackage('php-64bit', $version, $prettyVersion); $php64->setDescription('The PHP interpreter, 64bit'); $this->addPackage($php64); } // The AF_INET6 constant is only defined if ext-sockets is available but // IPv6 support might still be available. if ($this->runtime->hasConstant('AF_INET6') || Silencer::call([$this->runtime, 'invoke'], 'inet_pton', ['::']) !== \false) { $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion); $phpIpv6->setDescription('The PHP interpreter, with IPv6 support'); $this->addPackage($phpIpv6); } $loadedExtensions = $this->runtime->getExtensions(); // Extensions scanning foreach ($loadedExtensions as $name) { if (\in_array($name, ['standard', 'Core'])) { continue; } $this->addExtension($name, $this->runtime->getExtensionVersion($name)); } // Check for Xdebug in a restarted process if (!\in_array('xdebug', $loadedExtensions, \true) && ($prettyVersion = XdebugHandler::getSkippedVersion())) { $this->addExtension('xdebug', $prettyVersion); } // Another quick loop, just for possible libraries // Doing it this way to know that functions or constants exist before // relying on them. foreach ($loadedExtensions as $name) { switch ($name) { case 'amqp': $info = $this->runtime->getExtensionInfo($name); // librabbitmq version => 0.9.0 if (Preg::isMatch('/^librabbitmq version => (?.+)$/im', $info, $librabbitmqMatches)) { $this->addLibrary($libraries, $name . '-librabbitmq', $librabbitmqMatches['version'], 'AMQP librabbitmq version'); } // AMQP protocol version => 0-9-1 if (Preg::isMatchStrictGroups('/^AMQP protocol version => (?.+)$/im', $info, $protocolMatches)) { $this->addLibrary($libraries, $name . '-protocol', \str_replace('-', '.', $protocolMatches['version']), 'AMQP protocol version'); } break; case 'bz2': $info = $this->runtime->getExtensionInfo($name); // BZip2 Version => 1.0.6, 6-Sept-2010 if (Preg::isMatch('/^BZip2 Version => (?.*),/im', $info, $matches)) { $this->addLibrary($libraries, $name, $matches['version']); } break; case 'curl': $curlVersion = $this->runtime->invoke('curl_version'); $this->addLibrary($libraries, $name, $curlVersion['version']); $info = $this->runtime->getExtensionInfo($name); // SSL Version => OpenSSL/1.0.1t if (Preg::isMatchStrictGroups('{^SSL Version => (?[^/]+)/(?.+)$}im', $info, $sslMatches)) { $library = \strtolower($sslMatches['library']); if ($library === 'openssl') { $parsedVersion = Version::parseOpenssl($sslMatches['version'], $isFips); $this->addLibrary($libraries, $name . '-openssl' . ($isFips ? '-fips' : ''), $parsedVersion, 'curl OpenSSL version (' . $parsedVersion . ')', [], $isFips ? ['curl-openssl'] : []); } else { if ($library === '(securetransport) openssl') { $shortlib = 'securetransport'; } else { $shortlib = $library; } $this->addLibrary($libraries, $name . '-' . $shortlib, $sslMatches['version'], 'curl ' . $library . ' version (' . $sslMatches['version'] . ')', ['curl-openssl']); } } // libSSH Version => libssh2/1.4.3 if (Preg::isMatchStrictGroups('{^libSSH Version => (?[^/]+)/(?.+?)(?:/.*)?$}im', $info, $sshMatches)) { $this->addLibrary($libraries, $name . '-' . \strtolower($sshMatches['library']), $sshMatches['version'], 'curl ' . $sshMatches['library'] . ' version'); } // ZLib Version => 1.2.8 if (Preg::isMatchStrictGroups('{^ZLib Version => (?.+)$}im', $info, $zlibMatches)) { $this->addLibrary($libraries, $name . '-zlib', $zlibMatches['version'], 'curl zlib version'); } break; case 'date': $info = $this->runtime->getExtensionInfo($name); // timelib version => 2018.03 if (Preg::isMatchStrictGroups('/^timelib version => (?.+)$/im', $info, $timelibMatches)) { $this->addLibrary($libraries, $name . '-timelib', $timelibMatches['version'], 'date timelib version'); } // Timezone Database => internal if (Preg::isMatchStrictGroups('/^Timezone Database => (?internal|external)$/im', $info, $zoneinfoSourceMatches)) { $external = $zoneinfoSourceMatches['source'] === 'external'; if (Preg::isMatchStrictGroups('/^"Olson" Timezone Database Version => (?.+?)(?:\\.system)?$/im', $info, $zoneinfoMatches)) { // If the timezonedb is provided by ext/timezonedb, register that version as a replacement if ($external && \in_array('timezonedb', $loadedExtensions, \true)) { $this->addLibrary($libraries, 'timezonedb-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date (replaced by timezonedb)', [$name . '-zoneinfo']); } else { $this->addLibrary($libraries, $name . '-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date'); } } } break; case 'fileinfo': $info = $this->runtime->getExtensionInfo($name); // libmagic => 537 if (Preg::isMatch('/^libmagic => (?.+)$/im', $info, $magicMatches)) { $this->addLibrary($libraries, $name . '-libmagic', $magicMatches['version'], 'fileinfo libmagic version'); } break; case 'gd': $this->addLibrary($libraries, $name, $this->runtime->getConstant('GD_VERSION')); $info = $this->runtime->getExtensionInfo($name); if (Preg::isMatchStrictGroups('/^libJPEG Version => (?.+?)(?: compatible)?$/im', $info, $libjpegMatches)) { $this->addLibrary($libraries, $name . '-libjpeg', Version::parseLibjpeg($libjpegMatches['version']), 'libjpeg version for gd'); } if (Preg::isMatchStrictGroups('/^libPNG Version => (?.+)$/im', $info, $libpngMatches)) { $this->addLibrary($libraries, $name . '-libpng', $libpngMatches['version'], 'libpng version for gd'); } if (Preg::isMatchStrictGroups('/^FreeType Version => (?.+)$/im', $info, $freetypeMatches)) { $this->addLibrary($libraries, $name . '-freetype', $freetypeMatches['version'], 'freetype version for gd'); } if (Preg::isMatchStrictGroups('/^libXpm Version => (?\\d+)$/im', $info, $libxpmMatches)) { $this->addLibrary($libraries, $name . '-libxpm', Version::convertLibxpmVersionId((int) $libxpmMatches['versionId']), 'libxpm version for gd'); } break; case 'gmp': $this->addLibrary($libraries, $name, $this->runtime->getConstant('GMP_VERSION')); break; case 'iconv': $this->addLibrary($libraries, $name, $this->runtime->getConstant('ICONV_VERSION')); break; case 'intl': $info = $this->runtime->getExtensionInfo($name); $description = 'The ICU unicode and globalization support library'; // Truthy check is for testing only so we can make the condition fail if ($this->runtime->hasConstant('INTL_ICU_VERSION')) { $this->addLibrary($libraries, 'icu', $this->runtime->getConstant('INTL_ICU_VERSION'), $description); } elseif (Preg::isMatch('/^ICU version => (?.+)$/im', $info, $matches)) { $this->addLibrary($libraries, 'icu', $matches['version'], $description); } // ICU TZData version => 2019c if (Preg::isMatchStrictGroups('/^ICU TZData version => (?.*)$/im', $info, $zoneinfoMatches) && null !== ($version = Version::parseZoneinfoVersion($zoneinfoMatches['version']))) { $this->addLibrary($libraries, 'icu-zoneinfo', $version, 'zoneinfo ("Olson") database for icu'); } // Add a separate version for the CLDR library version if ($this->runtime->hasClass('ResourceBundle')) { $resourceBundle = $this->runtime->invoke(['ResourceBundle', 'create'], ['root', 'ICUDATA', \false]); if ($resourceBundle !== null) { $this->addLibrary($libraries, 'icu-cldr', $resourceBundle->get('Version'), 'ICU CLDR project version'); } } if ($this->runtime->hasClass('IntlChar')) { $this->addLibrary($libraries, 'icu-unicode', \implode('.', \array_slice($this->runtime->invoke(['IntlChar', 'getUnicodeVersion']), 0, 3)), 'ICU unicode version'); } break; case 'imagick': // @phpstan-ignore staticMethod.dynamicCall (called like this for mockability) $imageMagickVersion = $this->runtime->construct('Imagick')->getVersion(); // 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org // 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org if (Preg::isMatch('/^ImageMagick (?[\\d.]+)(?:-(?\\d+))?/', $imageMagickVersion['versionString'], $matches)) { $version = $matches['version']; if (isset($matches['patch'])) { $version .= '.' . $matches['patch']; } $this->addLibrary($libraries, $name . '-imagemagick', $version, null, ['imagick']); } break; case 'ldap': $info = $this->runtime->getExtensionInfo($name); if (Preg::isMatchStrictGroups('/^Vendor Version => (?\\d+)$/im', $info, $matches) && Preg::isMatchStrictGroups('/^Vendor Name => (?.+)$/im', $info, $vendorMatches)) { $this->addLibrary($libraries, $name . '-' . \strtolower($vendorMatches['vendor']), Version::convertOpenldapVersionId((int) $matches['versionId']), $vendorMatches['vendor'] . ' version of ldap'); } break; case 'libxml': // ext/dom, ext/simplexml, ext/xmlreader and ext/xmlwriter use the same libxml as the ext/libxml $libxmlProvides = \array_map(static function ($extension) : string { return $extension . '-libxml'; }, \array_intersect($loadedExtensions, ['dom', 'simplexml', 'xml', 'xmlreader', 'xmlwriter'])); $this->addLibrary($libraries, $name, $this->runtime->getConstant('LIBXML_DOTTED_VERSION'), 'libxml library version', [], $libxmlProvides); break; case 'mbstring': $info = $this->runtime->getExtensionInfo($name); // libmbfl version => 1.3.2 if (Preg::isMatch('/^libmbfl version => (?.+)$/im', $info, $libmbflMatches)) { $this->addLibrary($libraries, $name . '-libmbfl', $libmbflMatches['version'], 'mbstring libmbfl version'); } if ($this->runtime->hasConstant('MB_ONIGURUMA_VERSION')) { $this->addLibrary($libraries, $name . '-oniguruma', $this->runtime->getConstant('MB_ONIGURUMA_VERSION'), 'mbstring oniguruma version'); // Multibyte regex (oniguruma) version => 5.9.5 // oniguruma version => 6.9.0 } elseif (Preg::isMatch('/^(?:oniguruma|Multibyte regex \\(oniguruma\\)) version => (?.+)$/im', $info, $onigurumaMatches)) { $this->addLibrary($libraries, $name . '-oniguruma', $onigurumaMatches['version'], 'mbstring oniguruma version'); } break; case 'memcached': $info = $this->runtime->getExtensionInfo($name); // libmemcached version => 1.0.18 if (Preg::isMatch('/^libmemcached version => (?.+)$/im', $info, $matches)) { $this->addLibrary($libraries, $name . '-libmemcached', $matches['version'], 'libmemcached version'); } break; case 'openssl': // OpenSSL 1.1.1g 21 Apr 2020 if (Preg::isMatchStrictGroups('{^(?:OpenSSL|LibreSSL)?\\s*(?\\S+)}i', $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), $matches)) { $parsedVersion = Version::parseOpenssl($matches['version'], $isFips); $this->addLibrary($libraries, $name . ($isFips ? '-fips' : ''), $parsedVersion, $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), [], $isFips ? [$name] : []); } break; case 'pcre': $this->addLibrary($libraries, $name, Preg::replace('{^(\\S+).*}', '$1', $this->runtime->getConstant('PCRE_VERSION'))); $info = $this->runtime->getExtensionInfo($name); // PCRE Unicode Version => 12.1.0 if (Preg::isMatchStrictGroups('/^PCRE Unicode Version => (?.+)$/im', $info, $pcreUnicodeMatches)) { $this->addLibrary($libraries, $name . '-unicode', $pcreUnicodeMatches['version'], 'PCRE Unicode version support'); } break; case 'mysqlnd': case 'pdo_mysql': $info = $this->runtime->getExtensionInfo($name); if (Preg::isMatchStrictGroups('/^(?:Client API version|Version) => mysqlnd (?.+?) /mi', $info, $matches)) { $this->addLibrary($libraries, $name . '-mysqlnd', $matches['version'], 'mysqlnd library version for ' . $name); } break; case 'mongodb': $info = $this->runtime->getExtensionInfo($name); if (Preg::isMatchStrictGroups('/^libmongoc bundled version => (?.+)$/im', $info, $libmongocMatches)) { $this->addLibrary($libraries, $name . '-libmongoc', $libmongocMatches['version'], 'libmongoc version of mongodb'); } if (Preg::isMatchStrictGroups('/^libbson bundled version => (?.+)$/im', $info, $libbsonMatches)) { $this->addLibrary($libraries, $name . '-libbson', $libbsonMatches['version'], 'libbson version of mongodb'); } break; case 'pgsql': if ($this->runtime->hasConstant('PGSQL_LIBPQ_VERSION')) { $this->addLibrary($libraries, 'pgsql-libpq', $this->runtime->getConstant('PGSQL_LIBPQ_VERSION'), 'libpq for pgsql'); break; } // intentional fall-through to next case... case 'pdo_pgsql': $info = $this->runtime->getExtensionInfo($name); if (Preg::isMatch('/^PostgreSQL\\(libpq\\) Version => (?.*)$/im', $info, $matches)) { $this->addLibrary($libraries, $name . '-libpq', $matches['version'], 'libpq for ' . $name); } break; case 'pq': $info = $this->runtime->getExtensionInfo($name); // Used Library => Compiled => Linked // libpq => 14.3 (Ubuntu 14.3-1.pgdg22.04+1) => 15.0.2 if (Preg::isMatch('/^libpq => (?.+) => (?.+)$/im', $info, $matches)) { $this->addLibrary($libraries, $name . '-libpq', $matches['linked'], 'libpq for ' . $name); } break; case 'rdkafka': if ($this->runtime->hasConstant('RD_KAFKA_VERSION')) { /** * Interpreted as hex \c MM.mm.rr.xx: * - MM = Major * - mm = minor * - rr = revision * - xx = pre-release id (0xff is the final release) * * pre-release ID in practice is always 0xff even for RCs etc, so we ignore it */ $libRdKafkaVersionInt = $this->runtime->getConstant('RD_KAFKA_VERSION'); $this->addLibrary($libraries, $name . '-librdkafka', \sprintf('%d.%d.%d', ($libRdKafkaVersionInt & 0xff000000) >> 24, ($libRdKafkaVersionInt & 0xff0000) >> 16, ($libRdKafkaVersionInt & 0xff00) >> 8), 'librdkafka for ' . $name); } break; case 'libsodium': case 'sodium': if ($this->runtime->hasConstant('SODIUM_LIBRARY_VERSION')) { $this->addLibrary($libraries, 'libsodium', $this->runtime->getConstant('SODIUM_LIBRARY_VERSION')); $this->addLibrary($libraries, 'libsodium', $this->runtime->getConstant('SODIUM_LIBRARY_VERSION')); } break; case 'sqlite3': case 'pdo_sqlite': $info = $this->runtime->getExtensionInfo($name); if (Preg::isMatch('/^SQLite Library => (?.+)$/im', $info, $matches)) { $this->addLibrary($libraries, $name . '-sqlite', $matches['version']); } break; case 'ssh2': $info = $this->runtime->getExtensionInfo($name); if (Preg::isMatch('/^libssh2 version => (?.+)$/im', $info, $matches)) { $this->addLibrary($libraries, $name . '-libssh2', $matches['version']); } break; case 'xsl': $this->addLibrary($libraries, 'libxslt', $this->runtime->getConstant('LIBXSLT_DOTTED_VERSION'), null, ['xsl']); $info = $this->runtime->getExtensionInfo('xsl'); if (Preg::isMatch('/^libxslt compiled against libxml Version => (?.+)$/im', $info, $matches)) { $this->addLibrary($libraries, 'libxslt-libxml', $matches['version'], 'libxml version libxslt is compiled against'); } break; case 'yaml': $info = $this->runtime->getExtensionInfo('yaml'); if (Preg::isMatch('/^LibYAML Version => (?.+)$/im', $info, $matches)) { $this->addLibrary($libraries, $name . '-libyaml', $matches['version'], 'libyaml version of yaml'); } break; case 'zip': if ($this->runtime->hasConstant('LIBZIP_VERSION', 'ZipArchive')) { $this->addLibrary($libraries, $name . '-libzip', $this->runtime->getConstant('LIBZIP_VERSION', 'ZipArchive'), null, ['zip']); } break; case 'zlib': if ($this->runtime->hasConstant('ZLIB_VERSION')) { $this->addLibrary($libraries, $name, $this->runtime->getConstant('ZLIB_VERSION')); // Linked Version => 1.2.8 } elseif (Preg::isMatch('/^Linked Version => (?.+)$/im', $this->runtime->getExtensionInfo($name), $matches)) { $this->addLibrary($libraries, $name, $matches['version']); } break; default: break; } } $hhvmVersion = $this->hhvmDetector->getVersion(); if ($hhvmVersion) { try { $prettyVersion = $hhvmVersion; $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { $prettyVersion = Preg::replace('#^([^~+-]+).*$#', '$1', $hhvmVersion); $version = $this->versionParser->normalize($prettyVersion); } $hhvm = new CompletePackage('hhvm', $version, $prettyVersion); $hhvm->setDescription('The HHVM Runtime (64bit)'); $this->addPackage($hhvm); } } /** * @inheritDoc */ public function addPackage(PackageInterface $package) : void { if (!$package instanceof CompletePackage) { throw new \UnexpectedValueException('Expected CompletePackage but got ' . \get_class($package)); } // Skip if overridden if (isset($this->overrides[$package->getName()])) { if ($this->overrides[$package->getName()]['version'] === \false) { $this->addDisabledPackage($package); return; } $overrider = $this->findPackage($package->getName(), '*'); if ($package->getVersion() === $overrider->getVersion()) { $actualText = 'same as actual'; } else { $actualText = 'actual: ' . $package->getPrettyVersion(); } if ($overrider instanceof CompletePackageInterface) { $overrider->setDescription($overrider->getDescription() . ', ' . $actualText); } return; } // Skip if PHP is overridden and we are adding a php-* package if (isset($this->overrides['php']) && 0 === \strpos($package->getName(), 'php-')) { $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName()); if ($package->getVersion() === $overrider->getVersion()) { $actualText = 'same as actual'; } else { $actualText = 'actual: ' . $package->getPrettyVersion(); } $overrider->setDescription($overrider->getDescription() . ', ' . $actualText); return; } parent::addPackage($package); } /** * @param array{version: string, name: string} $override */ private function addOverriddenPackage(array $override, ?string $name = null) : CompletePackage { $version = $this->versionParser->normalize($override['version']); $package = new CompletePackage($name ?: $override['name'], $version, $override['version']); $package->setDescription('Package overridden via config.platform'); $package->setExtra(['config.platform' => \true]); parent::addPackage($package); if ($package->getName() === 'php') { self::$lastSeenPlatformPhp = \implode('.', \array_slice(\explode('.', $package->getVersion()), 0, 3)); } return $package; } private function addDisabledPackage(CompletePackage $package) : void { $package->setDescription($package->getDescription() . '. Package disabled via config.platform'); $package->setExtra(['config.platform' => \true]); $this->disabledPackages[$package->getName()] = $package; } /** * Parses the version and adds a new package to the repository */ private function addExtension(string $name, string $prettyVersion) : void { $extraDescription = null; try { $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { $extraDescription = ' (actual version: ' . $prettyVersion . ')'; if (Preg::isMatchStrictGroups('{^(\\d+\\.\\d+\\.\\d+(?:\\.\\d+)?)}', $prettyVersion, $match)) { $prettyVersion = $match[1]; } else { $prettyVersion = '0'; } $version = $this->versionParser->normalize($prettyVersion); } $packageName = $this->buildPackageName($name); $ext = new CompletePackage($packageName, $version, $prettyVersion); $ext->setDescription('The ' . $name . ' PHP extension' . $extraDescription); $ext->setType('php-ext'); if ($name === 'uuid') { $ext->setReplaces(['lib-uuid' => new Link('ext-uuid', 'lib-uuid', new Constraint('=', $version), Link::TYPE_REPLACE, $ext->getPrettyVersion())]); } $this->addPackage($ext); } private function buildPackageName(string $name) : string { return 'ext-' . \str_replace(' ', '-', \strtolower($name)); } /** * @param array $libraries * @param array $replaces * @param array $provides */ private function addLibrary(array &$libraries, string $name, ?string $prettyVersion, ?string $description = null, array $replaces = [], array $provides = []) : void { if (null === $prettyVersion) { return; } try { $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { return; } // avoid adding the same lib twice even if two conflicting extensions provide the same lib // see https://github.com/composer/composer/issues/12082 if (isset($libraries['lib-' . $name])) { return; } $libraries['lib-' . $name] = \true; if ($description === null) { $description = 'The ' . $name . ' library'; } $lib = new CompletePackage('lib-' . $name, $version, $prettyVersion); $lib->setDescription($description); $replaceLinks = []; foreach ($replaces as $replace) { $replace = \strtolower($replace); $replaceLinks[$replace] = new Link('lib-' . $name, 'lib-' . $replace, new Constraint('=', $version), Link::TYPE_REPLACE, $lib->getPrettyVersion()); } $provideLinks = []; foreach ($provides as $provide) { $provide = \strtolower($provide); $provideLinks[$provide] = new Link('lib-' . $name, 'lib-' . $provide, new Constraint('=', $version), Link::TYPE_PROVIDE, $lib->getPrettyVersion()); } $lib->setReplaces($replaceLinks); $lib->setProvides($provideLinks); $this->addPackage($lib); } /** * Check if a package name is a platform package. */ public static function isPlatformPackage(string $name) : bool { static $cache = []; if (isset($cache[$name])) { return $cache[$name]; } return $cache[$name] = Preg::isMatch(\Composer\Repository\PlatformRepository::PLATFORM_PACKAGE_REGEX, $name); } /** * Returns the last seen config.platform.php version if defined * * This is a best effort attempt for internal purposes, retrieve the real * packages from a PlatformRepository instance if you need a version guaranteed to * be correct. * * @internal */ public static function getPlatformPhpVersion() : ?string { return self::$lastSeenPlatformPhp; } public function search(string $query, int $mode = 0, ?string $type = null) : array { // suppress vendor search as there are no vendors to match in platform packages if ($mode === self::SEARCH_VENDOR) { return []; } return parent::search($query, $mode, $type); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Factory; use Composer\IO\IOInterface; use Composer\Config; use Composer\EventDispatcher\EventDispatcher; use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; use Composer\Util\ProcessExecutor; use Composer\Json\JsonFile; /** * @author Jordi Boggiano */ class RepositoryFactory { /** * @return array|mixed */ public static function configFromString(IOInterface $io, Config $config, string $repository, bool $allowFilesystem = \false) { if (0 === \strpos($repository, 'http')) { $repoConfig = ['type' => 'composer', 'url' => $repository]; } elseif ("json" === \pathinfo($repository, \PATHINFO_EXTENSION)) { $json = new JsonFile($repository, Factory::createHttpDownloader($io, $config)); $data = $json->read(); if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) { $repoConfig = ['type' => 'composer', 'url' => 'file://' . \strtr(\realpath($repository), '\\', '/')]; } elseif ($allowFilesystem) { $repoConfig = ['type' => 'filesystem', 'json' => $json]; } else { throw new \InvalidArgumentException("Invalid repository URL ({$repository}) given. This file does not contain a valid composer repository."); } } elseif (\strpos($repository, '{') === 0) { // assume it is a json object that makes a repo config $repoConfig = JsonFile::parseJson($repository); } else { throw new \InvalidArgumentException("Invalid repository url ({$repository}) given. Has to be a .json file, an http url or a JSON object."); } return $repoConfig; } public static function fromString(IOInterface $io, Config $config, string $repository, bool $allowFilesystem = \false, ?\Composer\Repository\RepositoryManager $rm = null) : \Composer\Repository\RepositoryInterface { $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem); return static::createRepo($io, $config, $repoConfig, $rm); } /** * @param array $repoConfig */ public static function createRepo(IOInterface $io, Config $config, array $repoConfig, ?\Composer\Repository\RepositoryManager $rm = null) : \Composer\Repository\RepositoryInterface { if (!$rm) { @\trigger_error('Not passing a repository manager when calling createRepo is deprecated since Composer 2.3.6', \E_USER_DEPRECATED); $rm = static::manager($io, $config); } $repos = self::createRepos($rm, [$repoConfig]); return \reset($repos); } /** * @return RepositoryInterface[] */ public static function defaultRepos(?IOInterface $io = null, ?Config $config = null, ?\Composer\Repository\RepositoryManager $rm = null) : array { if (null === $rm) { @\trigger_error('Not passing a repository manager when calling defaultRepos is deprecated since Composer 2.3.6, use defaultReposWithDefaultManager() instead if you cannot get a manager.', \E_USER_DEPRECATED); } if (null === $config) { $config = Factory::createConfig($io); } if (null !== $io) { $io->loadConfiguration($config); } if (null === $rm) { if (null === $io) { throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager'); } $rm = static::manager($io, $config, Factory::createHttpDownloader($io, $config)); } return self::createRepos($rm, $config->getRepositories()); } /** * @param EventDispatcher $eventDispatcher * @param HttpDownloader $httpDownloader */ public static function manager(IOInterface $io, Config $config, ?HttpDownloader $httpDownloader = null, ?EventDispatcher $eventDispatcher = null, ?ProcessExecutor $process = null) : \Composer\Repository\RepositoryManager { if ($httpDownloader === null) { $httpDownloader = Factory::createHttpDownloader($io, $config); } if ($process === null) { $process = new ProcessExecutor($io); $process->enableAsync(); } $rm = new \Composer\Repository\RepositoryManager($io, $config, $httpDownloader, $eventDispatcher, $process); $rm->setRepositoryClass('composer', 'Composer\\Repository\\ComposerRepository'); $rm->setRepositoryClass('vcs', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('package', 'Composer\\Repository\\PackageRepository'); $rm->setRepositoryClass('pear', 'Composer\\Repository\\PearRepository'); $rm->setRepositoryClass('git', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('bitbucket', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('git-bitbucket', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('github', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('gitlab', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('svn', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('fossil', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('perforce', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('hg', 'Composer\\Repository\\VcsRepository'); $rm->setRepositoryClass('artifact', 'Composer\\Repository\\ArtifactRepository'); $rm->setRepositoryClass('path', 'Composer\\Repository\\PathRepository'); return $rm; } /** * @return RepositoryInterface[] */ public static function defaultReposWithDefaultManager(IOInterface $io) : array { $manager = \Composer\Repository\RepositoryFactory::manager($io, $config = Factory::createConfig($io)); $io->loadConfiguration($config); return \Composer\Repository\RepositoryFactory::defaultRepos($io, $config, $manager); } /** * @param array $repoConfigs * * @return RepositoryInterface[] */ private static function createRepos(\Composer\Repository\RepositoryManager $rm, array $repoConfigs) : array { $repos = []; foreach ($repoConfigs as $index => $repo) { if (\is_string($repo)) { throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given'); } if (!\is_array($repo)) { throw new \UnexpectedValueException('Repository "' . $index . '" (' . \json_encode($repo) . ') should be an array, ' . \gettype($repo) . ' given'); } if (!isset($repo['type'])) { throw new \UnexpectedValueException('Repository "' . $index . '" (' . \json_encode($repo) . ') must have a type defined'); } $name = self::generateRepositoryName($index, $repo, $repos); if ($repo['type'] === 'filesystem') { $repos[$name] = new \Composer\Repository\FilesystemRepository($repo['json']); } else { $repos[$name] = $rm->createRepository($repo['type'], $repo, (string) $index); } } return $repos; } /** * @param int|string $index * @param array{url?: string} $repo * @param array $existingRepos */ public static function generateRepositoryName($index, array $repo, array $existingRepos) : string { $name = \is_int($index) && isset($repo['url']) ? Preg::replace('{^https?://}i', '', $repo['url']) : (string) $index; while (isset($existingRepos[$name])) { $name .= '2'; } return $name; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Installable repository interface. * * Just used to tag installed repositories so the base classes can act differently on Alias packages * * @author Jordi Boggiano */ interface InstalledRepositoryInterface extends \Composer\Repository\WritableRepositoryInterface { /** * @return bool|null true if dev requirements were installed, false if --no-dev was used, null if yet unknown */ public function getDevMode(); /** * @return bool true if packages were never installed in this repository */ public function isFresh(); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\PackageInterface; use Composer\Installer\InstallationManager; /** * Writable repository interface. * * @author Konstantin Kudryashov */ interface WritableRepositoryInterface extends \Composer\Repository\RepositoryInterface { /** * Writes repository (f.e. to the disc). * * @param bool $devMode Whether dev requirements were included or not in this installation * @return void */ public function write(bool $devMode, InstallationManager $installationManager); /** * Adds package to the repository. * * @param PackageInterface $package package instance * @return void */ public function addPackage(PackageInterface $package); /** * Removes package from the repository. * * @param PackageInterface $package package instance * @return void */ public function removePackage(PackageInterface $package); /** * Get unique packages (at most one package of each name), with aliases resolved and removed. * * @return PackageInterface[] */ public function getCanonicalPackages(); /** * Forces a reload of all packages. * * @return void */ public function reload(); /** * @param string[] $devPackageNames * @return void */ public function setDevPackageNames(array $devPackageNames); /** * @return string[] Names of dependencies installed through require-dev */ public function getDevPackageNames(); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\PackageInterface; /** * @author Jordi Boggiano * * @see RepositorySet for ways to work with sets of repos */ class RepositoryUtils { /** * Find all of $packages which are required by $requirer, either directly or transitively * * Require-dev is ignored by default, you can enable the require-dev of the initial $requirer * packages by passing $includeRequireDev=true, but require-dev of transitive dependencies * are always ignored. * * @template T of PackageInterface * @param array $packages * @param list $bucket Do not pass this in, only used to avoid recursion with circular deps * @return list */ public static function filterRequiredPackages(array $packages, PackageInterface $requirer, bool $includeRequireDev = \false, array $bucket = []) : array { $requires = $requirer->getRequires(); if ($includeRequireDev) { $requires = \array_merge($requires, $requirer->getDevRequires()); } foreach ($packages as $candidate) { foreach ($candidate->getNames() as $name) { if (isset($requires[$name])) { if (!\in_array($candidate, $bucket, \true)) { $bucket[] = $candidate; $bucket = self::filterRequiredPackages($packages, $candidate, \false, $bucket); } break; } } } return $bucket; } /** * Unwraps CompositeRepository, InstalledRepository and optionally FilterRepository to get a flat array of pure repository instances * * @return RepositoryInterface[] */ public static function flattenRepositories(\Composer\Repository\RepositoryInterface $repo, bool $unwrapFilterRepos = \true) : array { // unwrap filter repos if ($unwrapFilterRepos && $repo instanceof \Composer\Repository\FilterRepository) { $repo = $repo->getRepository(); } if (!$repo instanceof \Composer\Repository\CompositeRepository) { return [$repo]; } $repos = []; foreach ($repo->getRepositories() as $r) { foreach (self::flattenRepositories($r, $unwrapFilterRepos) as $r2) { $repos[] = $r2; } } return $repos; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Thrown when a security problem, like a broken or missing signature * * @author Eric Daspet */ class RepositorySecurityException extends \Exception { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\BasePackage; use Composer\Package\PackageInterface; /** * Composite repository. * * @author Beau Simensen */ class CompositeRepository implements \Composer\Repository\RepositoryInterface { /** * List of repositories * @var RepositoryInterface[] */ private $repositories; /** * Constructor * @param RepositoryInterface[] $repositories */ public function __construct(array $repositories) { $this->repositories = []; foreach ($repositories as $repo) { $this->addRepository($repo); } } public function getRepoName() : string { return 'composite repo (' . \implode(', ', \array_map(static function ($repo) : string { return $repo->getRepoName(); }, $this->repositories)) . ')'; } /** * Returns all the wrapped repositories * * @return RepositoryInterface[] */ public function getRepositories() : array { return $this->repositories; } /** * @inheritDoc */ public function hasPackage(PackageInterface $package) : bool { foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ if ($repository->hasPackage($package)) { return \true; } } return \false; } /** * @inheritDoc */ public function findPackage($name, $constraint) : ?BasePackage { foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ $package = $repository->findPackage($name, $constraint); if (null !== $package) { return $package; } } return null; } /** * @inheritDoc */ public function findPackages($name, $constraint = null) : array { $packages = []; foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ $packages[] = $repository->findPackages($name, $constraint); } return $packages ? \array_merge(...$packages) : []; } /** * @inheritDoc */ public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []) : array { $packages = []; $namesFound = []; foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ $result = $repository->loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded); $packages[] = $result['packages']; $namesFound[] = $result['namesFound']; } return ['packages' => $packages ? \array_merge(...$packages) : [], 'namesFound' => $namesFound ? \array_unique(\array_merge(...$namesFound)) : []]; } /** * @inheritDoc */ public function search(string $query, int $mode = 0, ?string $type = null) : array { $matches = []; foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ $matches[] = $repository->search($query, $mode, $type); } return \count($matches) > 0 ? \array_merge(...$matches) : []; } /** * @inheritDoc */ public function getPackages() : array { $packages = []; foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ $packages[] = $repository->getPackages(); } return $packages ? \array_merge(...$packages) : []; } /** * @inheritDoc */ public function getProviders($packageName) : array { $results = []; foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ $results[] = $repository->getProviders($packageName); } return $results ? \array_merge(...$results) : []; } public function removePackage(PackageInterface $package) : void { foreach ($this->repositories as $repository) { if ($repository instanceof \Composer\Repository\WritableRepositoryInterface) { $repository->removePackage($package); } } } /** * @inheritDoc */ public function count() : int { $total = 0; foreach ($this->repositories as $repository) { /* @var $repository RepositoryInterface */ $total += $repository->count(); } return $total; } /** * Add a repository. */ public function addRepository(\Composer\Repository\RepositoryInterface $repository) : void { if ($repository instanceof self) { foreach ($repository->getRepositories() as $repo) { $this->addRepository($repo); } } else { $this->repositories[] = $repository; } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\CompletePackage; use Composer\Package\PackageInterface; use Composer\Package\CompletePackageInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Version\StabilityFilter; use Composer\Pcre\Preg; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\Constraint; /** * A repository implementation that simply stores packages in an array * * @author Nils Adermann */ class ArrayRepository implements \Composer\Repository\RepositoryInterface { /** @var ?array */ protected $packages = null; /** * @var ?array indexed by package unique name and used to cache hasPackage calls */ protected $packageMap = null; /** * @param array $packages */ public function __construct(array $packages = []) { foreach ($packages as $package) { $this->addPackage($package); } } public function getRepoName() { return 'array repo (defining ' . $this->count() . ' package' . ($this->count() > 1 ? 's' : '') . ')'; } /** * @inheritDoc */ public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []) { $packages = $this->getPackages(); $result = []; $namesFound = []; foreach ($packages as $package) { if (\array_key_exists($package->getName(), $packageNameMap)) { if ((!$packageNameMap[$package->getName()] || $packageNameMap[$package->getName()]->matches(new Constraint('==', $package->getVersion()))) && StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, $package->getNames(), $package->getStability()) && !isset($alreadyLoaded[$package->getName()][$package->getVersion()])) { // add selected packages which match stability requirements $result[\spl_object_hash($package)] = $package; // add the aliased package for packages where the alias matches if ($package instanceof AliasPackage && !isset($result[\spl_object_hash($package->getAliasOf())])) { $result[\spl_object_hash($package->getAliasOf())] = $package->getAliasOf(); } } $namesFound[$package->getName()] = \true; } } // add aliases of packages that were selected, even if the aliases did not match foreach ($packages as $package) { if ($package instanceof AliasPackage) { if (isset($result[\spl_object_hash($package->getAliasOf())])) { $result[\spl_object_hash($package)] = $package; } } } return ['namesFound' => \array_keys($namesFound), 'packages' => $result]; } /** * @inheritDoc */ public function findPackage(string $name, $constraint) { $name = \strtolower($name); if (!$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } foreach ($this->getPackages() as $package) { if ($name === $package->getName()) { $pkgConstraint = new Constraint('==', $package->getVersion()); if ($constraint->matches($pkgConstraint)) { return $package; } } } return null; } /** * @inheritDoc */ public function findPackages(string $name, $constraint = null) { // normalize name $name = \strtolower($name); $packages = []; if (null !== $constraint && !$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } foreach ($this->getPackages() as $package) { if ($name === $package->getName()) { if (null === $constraint || $constraint->matches(new Constraint('==', $package->getVersion()))) { $packages[] = $package; } } } return $packages; } /** * @inheritDoc */ public function search(string $query, int $mode = 0, ?string $type = null) { if ($mode === self::SEARCH_FULLTEXT) { $regex = '{(?:' . \implode('|', Preg::split('{\\s+}', \preg_quote($query))) . ')}i'; } else { // vendor/name searches expect the caller to have preg_quoted the query $regex = '{(?:' . \implode('|', Preg::split('{\\s+}', $query)) . ')}i'; } $matches = []; foreach ($this->getPackages() as $package) { $name = $package->getName(); if ($mode === self::SEARCH_VENDOR) { [$name] = \explode('/', $name); } if (isset($matches[$name])) { continue; } if (null !== $type && $package->getType() !== $type) { continue; } if (Preg::isMatch($regex, $name) || $mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && Preg::isMatch($regex, \implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription())) { if ($mode === self::SEARCH_VENDOR) { $matches[$name] = ['name' => $name, 'description' => null]; } else { $matches[$name] = ['name' => $package->getPrettyName(), 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null]; if ($package instanceof CompletePackageInterface && $package->isAbandoned()) { $matches[$name]['abandoned'] = $package->getReplacementPackage() ?: \true; } } } } return \array_values($matches); } /** * @inheritDoc */ public function hasPackage(PackageInterface $package) { if ($this->packageMap === null) { $this->packageMap = []; foreach ($this->getPackages() as $repoPackage) { $this->packageMap[$repoPackage->getUniqueName()] = $repoPackage; } } return isset($this->packageMap[$package->getUniqueName()]); } /** * Adds a new package to the repository * * @return void */ public function addPackage(PackageInterface $package) { if (!$package instanceof BasePackage) { throw new \InvalidArgumentException('Only subclasses of BasePackage are supported'); } if (null === $this->packages) { $this->initialize(); } $package->setRepository($this); $this->packages[] = $package; if ($package instanceof AliasPackage) { $aliasedPackage = $package->getAliasOf(); if (null === $aliasedPackage->getRepository()) { $this->addPackage($aliasedPackage); } } // invalidate package map cache $this->packageMap = null; } /** * @inheritDoc */ public function getProviders(string $packageName) { $result = []; foreach ($this->getPackages() as $candidate) { if (isset($result[$candidate->getName()])) { continue; } foreach ($candidate->getProvides() as $link) { if ($packageName === $link->getTarget()) { $result[$candidate->getName()] = ['name' => $candidate->getName(), 'description' => $candidate instanceof CompletePackageInterface ? $candidate->getDescription() : null, 'type' => $candidate->getType()]; continue 2; } } } return $result; } /** * @return AliasPackage|CompleteAliasPackage */ protected function createAliasPackage(BasePackage $package, string $alias, string $prettyAlias) { while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } if ($package instanceof CompletePackage) { return new CompleteAliasPackage($package, $alias, $prettyAlias); } return new AliasPackage($package, $alias, $prettyAlias); } /** * Removes package from repository. * * @param PackageInterface $package package instance * * @return void */ public function removePackage(PackageInterface $package) { $packageId = $package->getUniqueName(); foreach ($this->getPackages() as $key => $repoPackage) { if ($packageId === $repoPackage->getUniqueName()) { \array_splice($this->packages, $key, 1); // invalidate package map cache $this->packageMap = null; return; } } } /** * @inheritDoc */ public function getPackages() { if (null === $this->packages) { $this->initialize(); } if (null === $this->packages) { throw new \LogicException('initialize failed to initialize the packages array'); } return $this->packages; } /** * Returns the number of packages in this repository * * @return 0|positive-int Number of packages */ public function count() : int { if (null === $this->packages) { $this->initialize(); } return \count($this->packages); } /** * Initializes the packages array. Mostly meant as an extension point. * * @return void */ protected function initialize() { $this->packages = []; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Installer\InstallationManager; /** * Writable array repository. * * @author Jordi Boggiano */ class WritableArrayRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\WritableRepositoryInterface { use \Composer\Repository\CanonicalPackagesTrait; /** * @var string[] */ protected $devPackageNames = []; /** @var bool|null */ private $devMode = null; /** * @return bool|null true if dev requirements were installed, false if --no-dev was used, null if yet unknown */ public function getDevMode() { return $this->devMode; } /** * @inheritDoc */ public function setDevPackageNames(array $devPackageNames) { $this->devPackageNames = $devPackageNames; } /** * @inheritDoc */ public function getDevPackageNames() { return $this->devPackageNames; } /** * @inheritDoc */ public function write(bool $devMode, InstallationManager $installationManager) { $this->devMode = $devMode; } /** * @inheritDoc */ public function reload() { $this->devMode = null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; use Composer\Repository\Vcs\VcsDriverInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Package\Loader\InvalidPackageException; use Composer\Package\Loader\LoaderInterface; use Composer\EventDispatcher\EventDispatcher; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Util\HttpDownloader; use Composer\Util\Url; use Composer\Semver\Constraint\Constraint; use Composer\IO\IOInterface; use Composer\Config; /** * @author Jordi Boggiano */ class VcsRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface { /** @var string */ protected $url; /** @var ?string */ protected $packageName; /** @var bool */ protected $isVerbose; /** @var bool */ protected $isVeryVerbose; /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var VersionParser */ protected $versionParser; /** @var string */ protected $type; /** @var ?LoaderInterface */ protected $loader; /** @var array */ protected $repoConfig; /** @var HttpDownloader */ protected $httpDownloader; /** @var ProcessExecutor */ protected $processExecutor; /** @var bool */ protected $branchErrorOccurred = \false; /** @var array> */ private $drivers; /** @var ?VcsDriverInterface */ private $driver; /** @var ?VersionCacheInterface */ private $versionCache; /** @var list */ private $emptyReferences = []; /** @var array<'tags'|'branches', array> */ private $versionTransportExceptions = []; /** * @param array{url: string, type?: string}&array $repoConfig * @param array>|null $drivers */ public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $dispatcher = null, ?ProcessExecutor $process = null, ?array $drivers = null, ?\Composer\Repository\VersionCacheInterface $versionCache = null) { parent::__construct(); $this->drivers = $drivers ?: [ 'github' => 'Composer\\Repository\\Vcs\\GitHubDriver', 'gitlab' => 'Composer\\Repository\\Vcs\\GitLabDriver', 'bitbucket' => 'Composer\\Repository\\Vcs\\GitBitbucketDriver', 'git-bitbucket' => 'Composer\\Repository\\Vcs\\GitBitbucketDriver', 'git' => 'Composer\\Repository\\Vcs\\GitDriver', 'hg' => 'Composer\\Repository\\Vcs\\HgDriver', 'perforce' => 'Composer\\Repository\\Vcs\\PerforceDriver', 'fossil' => 'Composer\\Repository\\Vcs\\FossilDriver', // svn must be last because identifying a subversion server for sure is practically impossible 'svn' => 'Composer\\Repository\\Vcs\\SvnDriver', ]; $this->url = $repoConfig['url'] = Platform::expandPath($repoConfig['url']); $this->io = $io; $this->type = $repoConfig['type'] ?? 'vcs'; $this->isVerbose = $io->isVerbose(); $this->isVeryVerbose = $io->isVeryVerbose(); $this->config = $config; $this->repoConfig = $repoConfig; $this->versionCache = $versionCache; $this->httpDownloader = $httpDownloader; $this->processExecutor = $process ?? new ProcessExecutor($io); } public function getRepoName() { $driverClass = \get_class($this->getDriver()); $driverType = \array_search($driverClass, $this->drivers); if (!$driverType) { $driverType = $driverClass; } return 'vcs repo (' . $driverType . ' ' . Url::sanitize($this->url) . ')'; } public function getRepoConfig() { return $this->repoConfig; } public function setLoader(LoaderInterface $loader) : void { $this->loader = $loader; } public function getDriver() : ?VcsDriverInterface { if ($this->driver) { return $this->driver; } if (isset($this->drivers[$this->type])) { $class = $this->drivers[$this->type]; $this->driver = new $class($this->repoConfig, $this->io, $this->config, $this->httpDownloader, $this->processExecutor); $this->driver->initialize(); return $this->driver; } foreach ($this->drivers as $driver) { if ($driver::supports($this->io, $this->config, $this->url)) { $this->driver = new $driver($this->repoConfig, $this->io, $this->config, $this->httpDownloader, $this->processExecutor); $this->driver->initialize(); return $this->driver; } } foreach ($this->drivers as $driver) { if ($driver::supports($this->io, $this->config, $this->url, \true)) { $this->driver = new $driver($this->repoConfig, $this->io, $this->config, $this->httpDownloader, $this->processExecutor); $this->driver->initialize(); return $this->driver; } } return null; } public function hadInvalidBranches() : bool { return $this->branchErrorOccurred; } /** * @return list */ public function getEmptyReferences() : array { return $this->emptyReferences; } /** * @return array<'tags'|'branches', array> */ public function getVersionTransportExceptions() : array { return $this->versionTransportExceptions; } protected function initialize() { parent::initialize(); $isVerbose = $this->isVerbose; $isVeryVerbose = $this->isVeryVerbose; $driver = $this->getDriver(); if (!$driver) { throw new \InvalidArgumentException('No driver found to handle VCS repository ' . $this->url); } $this->versionParser = new VersionParser(); if (!$this->loader) { $this->loader = new ArrayLoader($this->versionParser); } $hasRootIdentifierComposerJson = \false; try { $hasRootIdentifierComposerJson = $driver->hasComposerFile($driver->getRootIdentifier()); if ($hasRootIdentifierComposerJson) { $data = $driver->getComposerInformation($driver->getRootIdentifier()); $this->packageName = !empty($data['name']) ? $data['name'] : null; } } catch (\Exception $e) { if ($e instanceof TransportException && $this->shouldRethrowTransportException($e)) { throw $e; } if ($isVeryVerbose) { $this->io->writeError('Skipped parsing ' . $driver->getRootIdentifier() . ', ' . $e->getMessage() . ''); } } foreach ($driver->getTags() as $tag => $identifier) { $tag = (string) $tag; $msg = 'Reading composer.json of ' . ($this->packageName ?: $this->url) . ' (' . $tag . ')'; // strip the release- prefix from tags if present $tag = \str_replace('release-', '', $tag); $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose); if ($cachedPackage) { $this->addPackage($cachedPackage); continue; } if ($cachedPackage === \false) { $this->emptyReferences[] = $identifier; continue; } if (!($parsedTag = $this->validateTag($tag))) { if ($isVeryVerbose) { $this->io->writeError('Skipped tag ' . $tag . ', invalid tag name'); } continue; } if ($isVeryVerbose) { $this->io->writeError($msg); } elseif ($isVerbose) { $this->io->overwriteError($msg, \false); } try { $data = $driver->getComposerInformation($identifier); if (null === $data) { if ($isVeryVerbose) { $this->io->writeError('Skipped tag ' . $tag . ', no composer file'); } $this->emptyReferences[] = $identifier; continue; } // manually versioned package if (isset($data['version'])) { $data['version_normalized'] = $this->versionParser->normalize($data['version']); } else { // auto-versioned package, read value from tag $data['version'] = $tag; $data['version_normalized'] = $parsedTag; } // make sure tag packages have no -dev flag $data['version'] = Preg::replace('{[.-]?dev$}i', '', $data['version']); $data['version_normalized'] = Preg::replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']); // make sure tag do not contain the default-branch marker unset($data['default-branch']); // broken package, version doesn't match tag if ($data['version_normalized'] !== $parsedTag) { if ($isVeryVerbose) { if (Preg::isMatch('{(^dev-|[.-]?dev$)}i', $parsedTag)) { $this->io->writeError('Skipped tag ' . $tag . ', invalid tag name, tags can not use dev prefixes or suffixes'); } else { $this->io->writeError('Skipped tag ' . $tag . ', tag (' . $parsedTag . ') does not match version (' . $data['version_normalized'] . ') in composer.json'); } } continue; } $tagPackageName = $this->packageName ?: $data['name'] ?? ''; if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) { if ($isVeryVerbose) { $this->io->writeError('Skipped tag ' . $tag . ', it conflicts with an another tag (' . $existingPackage->getPrettyVersion() . ') as both resolve to ' . $data['version_normalized'] . ' internally'); } continue; } if ($isVeryVerbose) { $this->io->writeError('Importing tag ' . $tag . ' (' . $data['version_normalized'] . ')'); } $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier))); } catch (\Exception $e) { if ($e instanceof TransportException) { $this->versionTransportExceptions['tags'][$tag] = $e; if ($e->getCode() === 404) { $this->emptyReferences[] = $identifier; } if ($this->shouldRethrowTransportException($e)) { throw $e; } } if ($isVeryVerbose) { $this->io->writeError('Skipped tag ' . $tag . ', ' . ($e instanceof TransportException ? 'no composer file was found (' . $e->getCode() . ' HTTP status code)' : $e->getMessage()) . ''); } continue; } } if (!$isVeryVerbose) { $this->io->overwriteError('', \false); } $branches = $driver->getBranches(); // make sure the root identifier branch gets loaded first if ($hasRootIdentifierComposerJson && isset($branches[$driver->getRootIdentifier()])) { $branches = [$driver->getRootIdentifier() => $branches[$driver->getRootIdentifier()]] + $branches; } foreach ($branches as $branch => $identifier) { $branch = (string) $branch; $msg = 'Reading composer.json of ' . ($this->packageName ?: $this->url) . ' (' . $branch . ')'; if ($isVeryVerbose) { $this->io->writeError($msg); } elseif ($isVerbose) { $this->io->overwriteError($msg, \false); } if (!($parsedBranch = $this->validateBranch($branch))) { if ($isVeryVerbose) { $this->io->writeError('Skipped branch ' . $branch . ', invalid name'); } continue; } // make sure branch packages have a dev flag if (\strpos($parsedBranch, 'dev-') === 0 || VersionParser::DEFAULT_BRANCH_ALIAS === $parsedBranch) { $version = 'dev-' . \str_replace('#', '+', $branch); $parsedBranch = \str_replace('#', '+', $parsedBranch); } else { $prefix = \strpos($branch, 'v') === 0 ? 'v' : ''; $version = $prefix . Preg::replace('{(\\.9{7})+}', '.x', $parsedBranch); } $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose, $driver->getRootIdentifier() === $branch); if ($cachedPackage) { $this->addPackage($cachedPackage); continue; } if ($cachedPackage === \false) { $this->emptyReferences[] = $identifier; continue; } try { $data = $driver->getComposerInformation($identifier); if (null === $data) { if ($isVeryVerbose) { $this->io->writeError('Skipped branch ' . $branch . ', no composer file'); } $this->emptyReferences[] = $identifier; continue; } // branches are always auto-versioned, read value from branch name $data['version'] = $version; $data['version_normalized'] = $parsedBranch; unset($data['default-branch']); if ($driver->getRootIdentifier() === $branch) { $data['default-branch'] = \true; } if ($isVeryVerbose) { $this->io->writeError('Importing branch ' . $branch . ' (' . $data['version'] . ')'); } $packageData = $this->preProcess($driver, $data, $identifier); $package = $this->loader->load($packageData); if ($this->loader instanceof ValidatingArrayLoader && \count($this->loader->getWarnings()) > 0) { throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData); } $this->addPackage($package); } catch (TransportException $e) { $this->versionTransportExceptions['branches'][$branch] = $e; if ($e->getCode() === 404) { $this->emptyReferences[] = $identifier; } if ($this->shouldRethrowTransportException($e)) { throw $e; } if ($isVeryVerbose) { $this->io->writeError('Skipped branch ' . $branch . ', no composer file was found (' . $e->getCode() . ' HTTP status code)'); } continue; } catch (\Exception $e) { if (!$isVeryVerbose) { $this->io->writeError(''); } $this->branchErrorOccurred = \true; $this->io->writeError('Skipped branch ' . $branch . ', ' . $e->getMessage() . ''); $this->io->writeError(''); continue; } } $driver->cleanup(); if (!$isVeryVerbose) { $this->io->overwriteError('', \false); } if (!$this->getPackages()) { throw new \Composer\Repository\InvalidRepositoryException('No valid composer.json was found in any branch or tag of ' . $this->url . ', could not load a package from it.'); } } /** * @param array{name?: string, dist?: array{type: string, url: string, reference: string, shasum: string}, source?: array{type: string, url: string, reference: string}} $data * * @return array{name: string|null, dist: array{type: string, url: string, reference: string, shasum: string}|null, source: array{type: string, url: string, reference: string}} */ protected function preProcess(VcsDriverInterface $driver, array $data, string $identifier) : array { // keep the name of the main identifier for all packages // this ensures that a package can be renamed in one place and that all old tags // will still be installable using that new name without requiring re-tagging $dataPackageName = $data['name'] ?? null; $data['name'] = $this->packageName ?: $dataPackageName; if (!isset($data['dist'])) { $data['dist'] = $driver->getDist($identifier); } if (!isset($data['source'])) { $data['source'] = $driver->getSource($identifier); } // if custom dist info is provided but does not provide a reference, copy the source reference to it if (\is_array($data['dist']) && !isset($data['dist']['reference']) && isset($data['source']['reference'])) { $data['dist']['reference'] = $data['source']['reference']; } return $data; } /** * @return string|false */ private function validateBranch(string $branch) { try { $normalizedBranch = $this->versionParser->normalizeBranch($branch); // validate that the branch name has no weird characters conflicting with constraints $this->versionParser->parseConstraints($normalizedBranch); return $normalizedBranch; } catch (\Exception $e) { } return \false; } /** * @return string|false */ private function validateTag(string $version) { try { return $this->versionParser->normalize($version); } catch (\Exception $e) { } return \false; } /** * @return \Composer\Package\CompletePackage|\Composer\Package\CompleteAliasPackage|null|false null if no cache present, false if the absence of a version was cached */ private function getCachedPackageVersion(string $version, string $identifier, bool $isVerbose, bool $isVeryVerbose, bool $isDefaultBranch = \false) { if (!$this->versionCache) { return null; } $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier); if ($cachedPackage === \false) { if ($isVeryVerbose) { $this->io->writeError('Skipped ' . $version . ', no composer file (cached from ref ' . $identifier . ')'); } return \false; } if ($cachedPackage) { $msg = 'Found cached composer.json of ' . ($this->packageName ?: $this->url) . ' (' . $version . ')'; if ($isVeryVerbose) { $this->io->writeError($msg); } elseif ($isVerbose) { $this->io->overwriteError($msg, \false); } unset($cachedPackage['default-branch']); if ($isDefaultBranch) { $cachedPackage['default-branch'] = \true; } if ($existingPackage = $this->findPackage($cachedPackage['name'], new Constraint('=', $cachedPackage['version_normalized']))) { if ($isVeryVerbose) { $this->io->writeError('Skipped cached version ' . $version . ', it conflicts with an another tag (' . $existingPackage->getPrettyVersion() . ') as both resolve to ' . $cachedPackage['version_normalized'] . ' internally'); } $cachedPackage = null; } } if ($cachedPackage) { return $this->loader->load($cachedPackage); } return null; } private function shouldRethrowTransportException(TransportException $e) : bool { return \in_array($e->getCode(), [401, 403, 429], \true) || $e->getCode() >= 500; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Advisory\PartialSecurityAdvisory; use Composer\Advisory\SecurityAdvisory; use Composer\Package\BasePackage; use Composer\Package\Loader\ArrayLoader; use Composer\Package\PackageInterface; use Composer\Package\AliasPackage; use Composer\Package\CompletePackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\Version\VersionParser; use Composer\Package\Version\StabilityFilter; use Composer\Json\JsonFile; use Composer\Cache; use Composer\Config; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Plugin\PostFileDownloadEvent; use Composer\Semver\CompilingMatcher; use Composer\Util\HttpDownloader; use Composer\Util\Loop; use Composer\Plugin\PluginEvents; use Composer\Plugin\PreFileDownloadEvent; use Composer\EventDispatcher\EventDispatcher; use Composer\Downloader\TransportException; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Util\Http\Response; use Composer\MetadataMinifier\MetadataMinifier; use Composer\Util\Url; use React\Promise\PromiseInterface; /** * @author Jordi Boggiano */ class ComposerRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface, \Composer\Repository\AdvisoryProviderInterface { /** * @var mixed[] * @phpstan-var array{url: string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool} */ private $repoConfig; /** @var mixed[] */ private $options; /** @var non-empty-string */ private $url; /** @var non-empty-string */ private $baseUrl; /** @var IOInterface */ private $io; /** @var HttpDownloader */ private $httpDownloader; /** @var Loop */ private $loop; /** @var Cache */ protected $cache; /** @var ?non-empty-string */ protected $notifyUrl = null; /** @var ?non-empty-string */ protected $searchUrl = null; /** @var ?non-empty-string a URL containing %package% which can be queried to get providers of a given name */ protected $providersApiUrl = null; /** @var bool */ protected $hasProviders = \false; /** @var ?non-empty-string */ protected $providersUrl = null; /** @var ?non-empty-string */ protected $listUrl = null; /** @var bool Indicates whether a comprehensive list of packages this repository might provide is expressed in the repository root. **/ protected $hasAvailablePackageList = \false; /** @var ?array */ protected $availablePackages = null; /** @var ?array */ protected $availablePackagePatterns = null; /** @var ?non-empty-string */ protected $lazyProvidersUrl = null; /** @var ?array */ protected $providerListing; /** @var ArrayLoader */ protected $loader; /** @var bool */ private $allowSslDowngrade = \false; /** @var ?EventDispatcher */ private $eventDispatcher; /** @var ?array> */ private $sourceMirrors; /** @var ?list */ private $distMirrors; /** @var bool */ private $degradedMode = \false; /** @var mixed[]|true */ private $rootData; /** @var bool */ private $hasPartialPackages = \false; /** @var ?array */ private $partialPackagesByName = null; /** @var bool */ private $displayedWarningAboutNonMatchingPackageIndex = \false; /** @var array{metadata: bool, api-url: string|null}|null */ private $securityAdvisoryConfig = null; /** * @var array list of package names which are fresh and can be loaded from the cache directly in case loadPackage is called several times * useful for v2 metadata repositories with lazy providers * @phpstan-var array */ private $freshMetadataUrls = []; /** * @var array list of package names which returned a 404 and should not be re-fetched in case loadPackage is called several times * useful for v2 metadata repositories with lazy providers * @phpstan-var array */ private $packagesNotFoundCache = []; /** * @var VersionParser */ private $versionParser; /** * @param array $repoConfig * @phpstan-param array{url: non-empty-string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool} $repoConfig */ public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $eventDispatcher = null) { parent::__construct(); if (!Preg::isMatch('{^[\\w.]+\\??://}', $repoConfig['url'])) { if (($localFilePath = \realpath($repoConfig['url'])) !== \false) { // it is a local path, add file scheme $repoConfig['url'] = 'file://' . $localFilePath; } else { // otherwise, assume http as the default protocol $repoConfig['url'] = 'http://' . $repoConfig['url']; } } $repoConfig['url'] = \rtrim($repoConfig['url'], '/'); if ($repoConfig['url'] === '') { throw new \InvalidArgumentException('The repository url must not be an empty string'); } if (\str_starts_with($repoConfig['url'], 'https?')) { $repoConfig['url'] = (\extension_loaded('openssl') ? 'https' : 'http') . \substr($repoConfig['url'], 6); } $urlBits = \parse_url(\strtr($repoConfig['url'], '\\', '/')); if ($urlBits === \false || empty($urlBits['scheme'])) { throw new \UnexpectedValueException('Invalid url given for Composer repository: ' . $repoConfig['url']); } if (!isset($repoConfig['options'])) { $repoConfig['options'] = []; } if (isset($repoConfig['allow_ssl_downgrade']) && \true === $repoConfig['allow_ssl_downgrade']) { $this->allowSslDowngrade = \true; } $this->options = $repoConfig['options']; $this->url = $repoConfig['url']; // force url for packagist.org to repo.packagist.org if (Preg::isMatch('{^(?Phttps?)://packagist\\.org/?$}i', $this->url, $match)) { $this->url = $match['proto'] . '://repo.packagist.org'; } $baseUrl = \rtrim(Preg::replace('{(?:/[^/\\\\]+\\.json)?(?:[?#].*)?$}', '', $this->url), '/'); \assert($baseUrl !== ''); $this->baseUrl = $baseUrl; $this->io = $io; $this->cache = new Cache($io, $config->get('cache-repo-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->url)), 'a-z0-9.$~_'); $this->cache->setReadOnly($config->get('cache-read-only')); $this->versionParser = new VersionParser(); $this->loader = new ArrayLoader($this->versionParser); $this->httpDownloader = $httpDownloader; $this->eventDispatcher = $eventDispatcher; $this->repoConfig = $repoConfig; $this->loop = new Loop($this->httpDownloader); } public function getRepoName() { return 'composer repo (' . Url::sanitize($this->url) . ')'; } public function getRepoConfig() { return $this->repoConfig; } /** * @inheritDoc */ public function findPackage(string $name, $constraint) { // this call initializes loadRootServerFile which is needed for the rest below to work $hasProviders = $this->hasProviders(); $name = \strtolower($name); if (!$constraint instanceof ConstraintInterface) { $constraint = $this->versionParser->parseConstraints($constraint); } if ($this->lazyProvidersUrl) { if ($this->hasPartialPackages() && isset($this->partialPackagesByName[$name])) { return $this->filterPackages($this->whatProvides($name), $constraint, \true); } if ($this->hasAvailablePackageList && !$this->lazyProvidersRepoContains($name)) { return null; } $packages = $this->loadAsyncPackages([$name => $constraint]); if (\count($packages['packages']) > 0) { return \reset($packages['packages']); } return null; } if ($hasProviders) { foreach ($this->getProviderNames() as $providerName) { if ($name === $providerName) { return $this->filterPackages($this->whatProvides($providerName), $constraint, \true); } } return null; } return parent::findPackage($name, $constraint); } /** * @inheritDoc */ public function findPackages(string $name, $constraint = null) { // this call initializes loadRootServerFile which is needed for the rest below to work $hasProviders = $this->hasProviders(); $name = \strtolower($name); if (null !== $constraint && !$constraint instanceof ConstraintInterface) { $constraint = $this->versionParser->parseConstraints($constraint); } if ($this->lazyProvidersUrl) { if ($this->hasPartialPackages() && isset($this->partialPackagesByName[$name])) { return $this->filterPackages($this->whatProvides($name), $constraint); } if ($this->hasAvailablePackageList && !$this->lazyProvidersRepoContains($name)) { return []; } $result = $this->loadAsyncPackages([$name => $constraint]); return $result['packages']; } if ($hasProviders) { foreach ($this->getProviderNames() as $providerName) { if ($name === $providerName) { return $this->filterPackages($this->whatProvides($providerName), $constraint); } } return []; } return parent::findPackages($name, $constraint); } /** * @param array $packages * * @return BasePackage|array|null */ private function filterPackages(array $packages, ?ConstraintInterface $constraint = null, bool $returnFirstMatch = \false) { if (null === $constraint) { if ($returnFirstMatch) { return \reset($packages); } return $packages; } $filteredPackages = []; foreach ($packages as $package) { $pkgConstraint = new Constraint('==', $package->getVersion()); if ($constraint->matches($pkgConstraint)) { if ($returnFirstMatch) { return $package; } $filteredPackages[] = $package; } } if ($returnFirstMatch) { return null; } return $filteredPackages; } public function getPackages() { $hasProviders = $this->hasProviders(); if ($this->lazyProvidersUrl) { if (\is_array($this->availablePackages) && !$this->availablePackagePatterns) { $packageMap = []; foreach ($this->availablePackages as $name) { $packageMap[$name] = new MatchAllConstraint(); } $result = $this->loadAsyncPackages($packageMap); return \array_values($result['packages']); } if ($this->hasPartialPackages()) { if (!\is_array($this->partialPackagesByName)) { throw new \LogicException('hasPartialPackages failed to initialize $this->partialPackagesByName'); } return $this->createPackages($this->partialPackagesByName, 'packages.json inline packages'); } throw new \LogicException('Composer repositories that have lazy providers and no available-packages list can not load the complete list of packages, use getPackageNames instead.'); } if ($hasProviders) { throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getPackageNames instead.'); } return parent::getPackages(); } /** * @param string|null $packageFilter Package pattern filter which can include "*" as a wildcard * * @return string[] */ public function getPackageNames(?string $packageFilter = null) { $hasProviders = $this->hasProviders(); $filterResults = static function (array $results) : array { return $results; }; if (null !== $packageFilter && '' !== $packageFilter) { $packageFilterRegex = BasePackage::packageNameToRegexp($packageFilter); $filterResults = static function (array $results) use($packageFilterRegex) : array { /** @var list $results */ return Preg::grep($packageFilterRegex, $results); }; } if ($this->lazyProvidersUrl) { if (\is_array($this->availablePackages)) { return $filterResults(\array_keys($this->availablePackages)); } if ($this->listUrl) { // no need to call $filterResults here as the $packageFilter is applied in the function itself return $this->loadPackageList($packageFilter); } if ($this->hasPartialPackages() && $this->partialPackagesByName !== null) { return $filterResults(\array_keys($this->partialPackagesByName)); } return []; } if ($hasProviders) { return $filterResults($this->getProviderNames()); } $names = []; foreach ($this->getPackages() as $package) { $names[] = $package->getPrettyName(); } return $filterResults($names); } /** * @return list */ private function getVendorNames() : array { $cacheKey = 'vendor-list.txt'; $cacheAge = $this->cache->getAge($cacheKey); if (\false !== $cacheAge && $cacheAge < 600 && ($cachedData = $this->cache->read($cacheKey)) !== \false) { $cachedData = \explode("\n", $cachedData); return $cachedData; } $names = $this->getPackageNames(); $uniques = []; foreach ($names as $name) { $uniques[\explode('/', $name, 2)[0]] = \true; } $vendors = \array_keys($uniques); if (!$this->cache->isReadOnly()) { $this->cache->write($cacheKey, \implode("\n", $vendors)); } return $vendors; } /** * @return list */ private function loadPackageList(?string $packageFilter = null) : array { if (null === $this->listUrl) { throw new \LogicException('Make sure to call loadRootServerFile before loadPackageList'); } $url = $this->listUrl; if (\is_string($packageFilter) && $packageFilter !== '') { $url .= '?filter=' . \urlencode($packageFilter); $result = $this->httpDownloader->get($url, $this->options)->decodeJson(); return $result['packageNames']; } $cacheKey = 'package-list.txt'; $cacheAge = $this->cache->getAge($cacheKey); if (\false !== $cacheAge && $cacheAge < 600 && ($cachedData = $this->cache->read($cacheKey)) !== \false) { $cachedData = \explode("\n", $cachedData); return $cachedData; } $result = $this->httpDownloader->get($url, $this->options)->decodeJson(); if (!$this->cache->isReadOnly()) { $this->cache->write($cacheKey, \implode("\n", $result['packageNames'])); } return $result['packageNames']; } public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []) { // this call initializes loadRootServerFile which is needed for the rest below to work $hasProviders = $this->hasProviders(); if (!$hasProviders && !$this->hasPartialPackages() && null === $this->lazyProvidersUrl) { return parent::loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded); } $packages = []; $namesFound = []; if ($hasProviders || $this->hasPartialPackages()) { foreach ($packageNameMap as $name => $constraint) { $matches = []; // if a repo has no providers but only partial packages and the partial packages are missing // then we don't want to call whatProvides as it would try to load from the providers and fail if (!$hasProviders && !isset($this->partialPackagesByName[$name])) { continue; } $candidates = $this->whatProvides($name, $acceptableStabilities, $stabilityFlags, $alreadyLoaded); foreach ($candidates as $candidate) { if ($candidate->getName() !== $name) { throw new \LogicException('whatProvides should never return a package with a different name than the requested one'); } $namesFound[$name] = \true; if (!$constraint || $constraint->matches(new Constraint('==', $candidate->getVersion()))) { $matches[\spl_object_hash($candidate)] = $candidate; if ($candidate instanceof AliasPackage && !isset($matches[\spl_object_hash($candidate->getAliasOf())])) { $matches[\spl_object_hash($candidate->getAliasOf())] = $candidate->getAliasOf(); } } } // add aliases of matched packages even if they did not match the constraint foreach ($candidates as $candidate) { if ($candidate instanceof AliasPackage) { if (isset($matches[\spl_object_hash($candidate->getAliasOf())])) { $matches[\spl_object_hash($candidate)] = $candidate; } } } $packages = \array_merge($packages, $matches); unset($packageNameMap[$name]); } } if ($this->lazyProvidersUrl && \count($packageNameMap)) { if ($this->hasAvailablePackageList) { foreach ($packageNameMap as $name => $constraint) { if (!$this->lazyProvidersRepoContains(\strtolower($name))) { unset($packageNameMap[$name]); } } } $result = $this->loadAsyncPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded); $packages = \array_merge($packages, $result['packages']); $namesFound = \array_merge($namesFound, $result['namesFound']); } return ['namesFound' => \array_keys($namesFound), 'packages' => $packages]; } /** * @inheritDoc */ public function search(string $query, int $mode = 0, ?string $type = null) { $this->loadRootServerFile(600); if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) { $url = \str_replace(['%query%', '%type%'], [\urlencode($query), $type], $this->searchUrl); $search = $this->httpDownloader->get($url, $this->options)->decodeJson(); if (empty($search['results'])) { return []; } $results = []; foreach ($search['results'] as $result) { // do not show virtual packages in results as they are not directly useful from a composer perspective if (!empty($result['virtual'])) { continue; } $results[] = $result; } return $results; } if ($mode === self::SEARCH_VENDOR) { $results = []; $regex = '{(?:' . \implode('|', Preg::split('{\\s+}', $query)) . ')}i'; $vendorNames = $this->getVendorNames(); foreach (Preg::grep($regex, $vendorNames) as $name) { $results[] = ['name' => $name, 'description' => '']; } return $results; } if ($this->hasProviders() || $this->lazyProvidersUrl) { // optimize search for "^foo/bar" where at least "^foo/" is present by loading this directly from the listUrl if present if (Preg::isMatchStrictGroups('{^\\^(?P(?P[a-z0-9_.-]+)/[a-z0-9_.-]*)\\*?$}i', $query, $match) && $this->listUrl !== null) { $url = $this->listUrl . '?vendor=' . \urlencode($match['vendor']) . '&filter=' . \urlencode($match['query'] . '*'); $result = $this->httpDownloader->get($url, $this->options)->decodeJson(); $results = []; foreach ($result['packageNames'] as $name) { $results[] = ['name' => $name, 'description' => '']; } return $results; } $results = []; $regex = '{(?:' . \implode('|', Preg::split('{\\s+}', $query)) . ')}i'; $packageNames = $this->getPackageNames(); foreach (Preg::grep($regex, $packageNames) as $name) { $results[] = ['name' => $name, 'description' => '']; } return $results; } return parent::search($query, $mode); } public function hasSecurityAdvisories() : bool { $this->loadRootServerFile(600); return $this->securityAdvisoryConfig !== null && ($this->securityAdvisoryConfig['metadata'] || $this->securityAdvisoryConfig['api-url'] !== null); } /** * @inheritDoc */ public function getSecurityAdvisories(array $packageConstraintMap, bool $allowPartialAdvisories = \false) : array { $this->loadRootServerFile(600); if (null === $this->securityAdvisoryConfig) { return ['namesFound' => [], 'advisories' => []]; } $advisories = []; $namesFound = []; $apiUrl = $this->securityAdvisoryConfig['api-url']; // respect available-package-patterns / available-packages directives from the repo if ($this->hasAvailablePackageList) { foreach ($packageConstraintMap as $name => $constraint) { if (!$this->lazyProvidersRepoContains(\strtolower($name))) { unset($packageConstraintMap[$name]); } } } $parser = new VersionParser(); /** * @param array $data * @param string $name * @return ($allowPartialAdvisories is false ? SecurityAdvisory|null : PartialSecurityAdvisory|SecurityAdvisory|null) */ $create = function (array $data, string $name) use($parser, $allowPartialAdvisories, &$packageConstraintMap) : ?PartialSecurityAdvisory { $advisory = PartialSecurityAdvisory::create($name, $data, $parser); if (!$allowPartialAdvisories && !$advisory instanceof SecurityAdvisory) { throw new \RuntimeException('Advisory for ' . $name . ' could not be loaded as a full advisory from ' . $this->getRepoName() . \PHP_EOL . \var_export($data, \true)); } if (!$advisory->affectedVersions->matches($packageConstraintMap[$name])) { return null; } return $advisory; }; if ($this->securityAdvisoryConfig['metadata'] && ($allowPartialAdvisories || $apiUrl === null)) { $promises = []; foreach ($packageConstraintMap as $name => $constraint) { $name = \strtolower($name); // skip platform packages, root package and composer-plugin-api if (\Composer\Repository\PlatformRepository::isPlatformPackage($name) || '__root__' === $name) { continue; } $promises[] = $this->startCachedAsyncDownload($name, $name)->then(static function (array $spec) use(&$advisories, &$namesFound, &$packageConstraintMap, $name, $create) : void { [$response] = $spec; if (!isset($response['security-advisories']) || !\is_array($response['security-advisories'])) { return; } $namesFound[$name] = \true; if (\count($response['security-advisories']) > 0) { $advisories[$name] = \array_filter(\array_map(static function ($data) use($name, $create) { return $create($data, $name); }, $response['security-advisories'])); } unset($packageConstraintMap[$name]); }); } $this->loop->wait($promises); } if ($apiUrl !== null && \count($packageConstraintMap) > 0) { $options = $this->options; $options['http']['method'] = 'POST'; if (isset($options['http']['header'])) { $options['http']['header'] = (array) $options['http']['header']; } $options['http']['header'][] = 'Content-type: application/x-www-form-urlencoded'; $options['http']['timeout'] = 10; $options['http']['content'] = \http_build_query(['packages' => \array_keys($packageConstraintMap)]); $response = $this->httpDownloader->get($apiUrl, $options); $warned = \false; /** @var string $name */ foreach ($response->decodeJson()['advisories'] as $name => $list) { if (!isset($packageConstraintMap[$name])) { if (!$warned) { $this->io->writeError('' . $this->getRepoName() . ' returned names which were not requested in response to the security-advisories API. ' . $name . ' was not requested but is present in the response. Requested names were: ' . \implode(', ', \array_keys($packageConstraintMap)) . ''); $warned = \true; } continue; } if (\count($list) > 0) { $advisories[$name] = \array_filter(\array_map(static function ($data) use($name, $create) { return $create($data, $name); }, $list)); } $namesFound[$name] = \true; } } return ['namesFound' => \array_keys($namesFound), 'advisories' => \array_filter($advisories)]; } public function getProviders(string $packageName) { $this->loadRootServerFile(); $result = []; if ($this->providersApiUrl) { try { $apiResult = $this->httpDownloader->get(\str_replace('%package%', $packageName, $this->providersApiUrl), $this->options)->decodeJson(); } catch (TransportException $e) { if ($e->getStatusCode() === 404) { return $result; } throw $e; } foreach ($apiResult['providers'] as $provider) { $result[$provider['name']] = $provider; } return $result; } if ($this->hasPartialPackages()) { if (!\is_array($this->partialPackagesByName)) { throw new \LogicException('hasPartialPackages failed to initialize $this->partialPackagesByName'); } foreach ($this->partialPackagesByName as $versions) { foreach ($versions as $candidate) { if (isset($result[$candidate['name']]) || !isset($candidate['provide'][$packageName])) { continue; } $result[$candidate['name']] = ['name' => $candidate['name'], 'description' => $candidate['description'] ?? '', 'type' => $candidate['type'] ?? '']; } } } if ($this->packages) { $result = \array_merge($result, parent::getProviders($packageName)); } return $result; } /** * @return string[] */ private function getProviderNames() : array { $this->loadRootServerFile(); if (null === $this->providerListing) { $data = $this->loadRootServerFile(); if (\is_array($data)) { $this->loadProviderListings($data); } } if ($this->lazyProvidersUrl) { // Can not determine list of provided packages for lazy repositories return []; } if (null !== $this->providersUrl && null !== $this->providerListing) { return \array_keys($this->providerListing); } return []; } protected function configurePackageTransportOptions(PackageInterface $package) : void { foreach ($package->getDistUrls() as $url) { if (\strpos($url, $this->baseUrl) === 0) { $package->setTransportOptions($this->options); return; } } } private function hasProviders() : bool { $this->loadRootServerFile(); return $this->hasProviders; } /** * @param string $name package name * @param array|null $acceptableStabilities * @phpstan-param array, BasePackage::STABILITY_*>|null $acceptableStabilities * @param array|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value * @phpstan-param array|null $stabilityFlags * @param array> $alreadyLoaded * * @return array */ private function whatProvides(string $name, ?array $acceptableStabilities = null, ?array $stabilityFlags = null, array $alreadyLoaded = []) : array { $packagesSource = null; if (!$this->hasPartialPackages() || !isset($this->partialPackagesByName[$name])) { // skip platform packages, root package and composer-plugin-api if (\Composer\Repository\PlatformRepository::isPlatformPackage($name) || '__root__' === $name) { return []; } if (null === $this->providerListing) { $data = $this->loadRootServerFile(); if (\is_array($data)) { $this->loadProviderListings($data); } } $useLastModifiedCheck = \false; if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) { $hash = null; $url = \str_replace('%package%', $name, $this->lazyProvidersUrl); $cacheKey = 'provider-' . \strtr($name, '/', '$') . '.json'; $useLastModifiedCheck = \true; } elseif ($this->providersUrl) { // package does not exist in this repo if (!isset($this->providerListing[$name])) { return []; } $hash = $this->providerListing[$name]['sha256']; $url = \str_replace(['%package%', '%hash%'], [$name, $hash], $this->providersUrl); $cacheKey = 'provider-' . \strtr($name, '/', '$') . '.json'; } else { return []; } $packages = null; if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) { $packages = \json_decode($this->cache->read($cacheKey), \true); $packagesSource = 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')'; } elseif ($useLastModifiedCheck) { if ($contents = $this->cache->read($cacheKey)) { $contents = \json_decode($contents, \true); // we already loaded some packages from this file, so assume it is fresh and avoid fetching it again if (isset($alreadyLoaded[$name])) { $packages = $contents; $packagesSource = 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')'; } elseif (isset($contents['last-modified'])) { $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']); $packages = \true === $response ? $contents : $response; $packagesSource = \true === $response ? 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')' : 'downloaded file (' . Url::sanitize($url) . ')'; } } } if (!$packages) { try { $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck); $packagesSource = 'downloaded file (' . Url::sanitize($url) . ')'; } catch (TransportException $e) { // 404s are acceptable for lazy provider repos if ($this->lazyProvidersUrl && \in_array($e->getStatusCode(), [404, 499], \true)) { $packages = ['packages' => []]; $packagesSource = 'not-found file (' . Url::sanitize($url) . ')'; if ($e->getStatusCode() === 499) { $this->io->error('' . $e->getMessage() . ''); } } else { throw $e; } } } $loadingPartialPackage = \false; } else { $packages = ['packages' => ['versions' => $this->partialPackagesByName[$name]]]; $packagesSource = 'root file (' . Url::sanitize($this->getPackagesJsonUrl()) . ')'; $loadingPartialPackage = \true; } $result = []; $versionsToLoad = []; foreach ($packages['packages'] as $versions) { foreach ($versions as $version) { $normalizedName = \strtolower($version['name']); // only load the actual named package, not other packages that might find themselves in the same file if ($normalizedName !== $name) { continue; } if (!$loadingPartialPackage && $this->hasPartialPackages() && isset($this->partialPackagesByName[$normalizedName])) { continue; } if (!isset($versionsToLoad[$version['uid']])) { if (!isset($version['version_normalized'])) { $version['version_normalized'] = $this->versionParser->normalize($version['version']); } elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) { // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it $version['version_normalized'] = $this->versionParser->normalize($version['version']); } // avoid loading packages which have already been loaded if (isset($alreadyLoaded[$name][$version['version_normalized']])) { continue; } if ($this->isVersionAcceptable(null, $normalizedName, $version, $acceptableStabilities, $stabilityFlags)) { $versionsToLoad[$version['uid']] = $version; } } } } // load acceptable packages in the providers $loadedPackages = $this->createPackages($versionsToLoad, $packagesSource); $uids = \array_keys($versionsToLoad); foreach ($loadedPackages as $index => $package) { $package->setRepository($this); $uid = $uids[$index]; if ($package instanceof AliasPackage) { $aliased = $package->getAliasOf(); $aliased->setRepository($this); $result[$uid] = $aliased; $result[$uid . '-alias'] = $package; } else { $result[$uid] = $package; } } return $result; } /** * @inheritDoc */ protected function initialize() { parent::initialize(); $repoData = $this->loadDataFromServer(); foreach ($this->createPackages($repoData, 'root file (' . Url::sanitize($this->getPackagesJsonUrl()) . ')') as $package) { $this->addPackage($package); } } /** * Adds a new package to the repository */ public function addPackage(PackageInterface $package) { parent::addPackage($package); $this->configurePackageTransportOptions($package); } /** * @param array $packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only * packages matching it will be loaded * @param array|null $acceptableStabilities * @phpstan-param array, BasePackage::STABILITY_*>|null $acceptableStabilities * @param array|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value * @phpstan-param array|null $stabilityFlags * @param array> $alreadyLoaded * * @return array{namesFound: array, packages: array} */ private function loadAsyncPackages(array $packageNames, ?array $acceptableStabilities = null, ?array $stabilityFlags = null, array $alreadyLoaded = []) : array { $this->loadRootServerFile(); $packages = []; $namesFound = []; $promises = []; if (null === $this->lazyProvidersUrl) { throw new \LogicException('loadAsyncPackages only supports v2 protocol composer repos with a metadata-url'); } // load ~dev versions of the packages as well if needed foreach ($packageNames as $name => $constraint) { if ($acceptableStabilities === null || $stabilityFlags === null || StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, [$name], 'dev')) { $packageNames[$name . '~dev'] = $constraint; } // if only dev stability is requested, we skip loading the non dev file if (isset($acceptableStabilities['dev']) && \count($acceptableStabilities) === 1 && \count($stabilityFlags) === 0) { unset($packageNames[$name]); } } foreach ($packageNames as $name => $constraint) { $name = \strtolower($name); $realName = Preg::replace('{~dev$}', '', $name); // skip platform packages, root package and composer-plugin-api if (\Composer\Repository\PlatformRepository::isPlatformPackage($realName) || '__root__' === $realName) { continue; } $promises[] = $this->startCachedAsyncDownload($name, $realName)->then(function (array $spec) use(&$packages, &$namesFound, $realName, $constraint, $acceptableStabilities, $stabilityFlags, $alreadyLoaded) : void { [$response, $packagesSource] = $spec; if (null === $response || !isset($response['packages'][$realName])) { return; } $versions = $response['packages'][$realName]; if (isset($response['minified']) && $response['minified'] === 'composer/2.0') { $versions = MetadataMinifier::expand($versions); } $namesFound[$realName] = \true; $versionsToLoad = []; foreach ($versions as $version) { if (!isset($version['version_normalized'])) { $version['version_normalized'] = $this->versionParser->normalize($version['version']); } elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) { // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it $version['version_normalized'] = $this->versionParser->normalize($version['version']); } // avoid loading packages which have already been loaded if (isset($alreadyLoaded[$realName][$version['version_normalized']])) { continue; } if ($this->isVersionAcceptable($constraint, $realName, $version, $acceptableStabilities, $stabilityFlags)) { $versionsToLoad[] = $version; } } $loadedPackages = $this->createPackages($versionsToLoad, $packagesSource); foreach ($loadedPackages as $package) { $package->setRepository($this); $packages[\spl_object_hash($package)] = $package; if ($package instanceof AliasPackage && !isset($packages[\spl_object_hash($package->getAliasOf())])) { $package->getAliasOf()->setRepository($this); $packages[\spl_object_hash($package->getAliasOf())] = $package->getAliasOf(); } } }); } $this->loop->wait($promises); return ['namesFound' => $namesFound, 'packages' => $packages]; } /** * @phpstan-return PromiseInterface */ private function startCachedAsyncDownload(string $fileName, ?string $packageName = null) : PromiseInterface { if (null === $this->lazyProvidersUrl) { throw new \LogicException('startCachedAsyncDownload only supports v2 protocol composer repos with a metadata-url'); } $name = \strtolower($fileName); $packageName = $packageName ?? $name; $url = \str_replace('%package%', $name, $this->lazyProvidersUrl); $cacheKey = 'provider-' . \strtr($name, '/', '~') . '.json'; $lastModified = null; if ($contents = $this->cache->read($cacheKey)) { $contents = \json_decode($contents, \true); $lastModified = $contents['last-modified'] ?? null; } return $this->asyncFetchFile($url, $cacheKey, $lastModified)->then(static function ($response) use($url, $cacheKey, $contents, $packageName) : array { $packagesSource = 'downloaded file (' . Url::sanitize($url) . ')'; if (\true === $response) { $packagesSource = 'cached file (' . $cacheKey . ' originating from ' . Url::sanitize($url) . ')'; $response = $contents; } if (!isset($response['packages'][$packageName]) && !isset($response['security-advisories'])) { return [null, $packagesSource]; } return [$response, $packagesSource]; }); } /** * @param string $name package name (must be lowercased already) * @param array $versionData * @param array|null $acceptableStabilities * @phpstan-param array, BasePackage::STABILITY_*>|null $acceptableStabilities * @param array|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value * @phpstan-param array|null $stabilityFlags */ private function isVersionAcceptable(?ConstraintInterface $constraint, string $name, array $versionData, ?array $acceptableStabilities = null, ?array $stabilityFlags = null) : bool { $versions = [$versionData['version_normalized']]; if ($alias = $this->loader->getBranchAlias($versionData)) { $versions[] = $alias; } foreach ($versions as $version) { if (null !== $acceptableStabilities && null !== $stabilityFlags && !StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, [$name], VersionParser::parseStability($version))) { continue; } if ($constraint && !CompilingMatcher::match($constraint, Constraint::OP_EQ, $version)) { continue; } return \true; } return \false; } private function getPackagesJsonUrl() : string { $jsonUrlParts = \parse_url(\strtr($this->url, '\\', '/')); if (isset($jsonUrlParts['path']) && \false !== \strpos($jsonUrlParts['path'], '.json')) { return $this->url; } return $this->url . '/packages.json'; } /** * @return array<'providers'|'provider-includes'|'packages'|'providers-url'|'notify-batch'|'search'|'mirrors'|'providers-lazy-url'|'metadata-url'|'available-packages'|'available-package-patterns', mixed>|true */ protected function loadRootServerFile(?int $rootMaxAge = null) { if (null !== $this->rootData) { return $this->rootData; } if (!\extension_loaded('openssl') && \strpos($this->url, 'https') === 0) { throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from ' . $this->url); } if ($cachedData = $this->cache->read('packages.json')) { $cachedData = \json_decode($cachedData, \true); if ($rootMaxAge !== null && ($age = $this->cache->getAge('packages.json')) !== \false && $age <= $rootMaxAge) { $data = $cachedData; } elseif (isset($cachedData['last-modified'])) { $response = $this->fetchFileIfLastModified($this->getPackagesJsonUrl(), 'packages.json', $cachedData['last-modified']); $data = \true === $response ? $cachedData : $response; } } if (!isset($data)) { $data = $this->fetchFile($this->getPackagesJsonUrl(), 'packages.json', null, \true); } if (!empty($data['notify-batch'])) { $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']); } elseif (!empty($data['notify'])) { $this->notifyUrl = $this->canonicalizeUrl($data['notify']); } if (!empty($data['search'])) { $this->searchUrl = $this->canonicalizeUrl($data['search']); } if (!empty($data['mirrors'])) { foreach ($data['mirrors'] as $mirror) { if (!empty($mirror['git-url'])) { $this->sourceMirrors['git'][] = ['url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred'])]; } if (!empty($mirror['hg-url'])) { $this->sourceMirrors['hg'][] = ['url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred'])]; } if (!empty($mirror['dist-url'])) { $this->distMirrors[] = ['url' => $this->canonicalizeUrl($mirror['dist-url']), 'preferred' => !empty($mirror['preferred'])]; } } } if (!empty($data['providers-lazy-url'])) { $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']); $this->hasProviders = \true; $this->hasPartialPackages = !empty($data['packages']) && \is_array($data['packages']); } // metadata-url indicates V2 repo protocol so it takes over from all the V1 types // V2 only has lazyProviders and possibly partial packages, but no ability to process anything else, // V2 also supports async loading if (!empty($data['metadata-url'])) { $this->lazyProvidersUrl = $this->canonicalizeUrl($data['metadata-url']); $this->providersUrl = null; $this->hasProviders = \false; $this->hasPartialPackages = !empty($data['packages']) && \is_array($data['packages']); $this->allowSslDowngrade = \false; // provides a list of package names that are available in this repo // this disables lazy-provider behavior in the sense that if a list is available we assume it is finite and won't search for other packages in that repo // while if no list is there lazyProvidersUrl is used when looking for any package name to see if the repo knows it if (!empty($data['available-packages'])) { $availPackages = \array_map('strtolower', $data['available-packages']); $this->availablePackages = \array_combine($availPackages, $availPackages); $this->hasAvailablePackageList = \true; } // Provides a list of package name patterns (using * wildcards to match any substring, e.g. "vendor/*") that are available in this repo // Disables lazy-provider behavior as with available-packages, but may allow much more compact expression of packages covered by this repository. // Over-specifying covered packages is safe, but may result in increased traffic to your repository. if (!empty($data['available-package-patterns'])) { $this->availablePackagePatterns = \array_map(static function ($pattern) : string { return BasePackage::packageNameToRegexp($pattern); }, $data['available-package-patterns']); $this->hasAvailablePackageList = \true; } // Remove legacy keys as most repos need to be compatible with Composer v1 // as well but we are not interested in the old format anymore at this point unset($data['providers-url'], $data['providers'], $data['providers-includes']); if (isset($data['security-advisories']) && \is_array($data['security-advisories'])) { $this->securityAdvisoryConfig = ['metadata' => $data['security-advisories']['metadata'] ?? \false, 'api-url' => isset($data['security-advisories']['api-url']) && \is_string($data['security-advisories']['api-url']) ? $this->canonicalizeUrl($data['security-advisories']['api-url']) : null]; if ($this->securityAdvisoryConfig['api-url'] === null && !$this->hasAvailablePackageList) { throw new \UnexpectedValueException('Invalid security advisory configuration on ' . $this->getRepoName() . ': If the repository does not provide a security-advisories.api-url then available-packages or available-package-patterns are required to be provided for performance reason.'); } } } if ($this->allowSslDowngrade) { $this->url = \str_replace('https://', 'http://', $this->url); $this->baseUrl = \str_replace('https://', 'http://', $this->baseUrl); } if (!empty($data['providers-url'])) { $this->providersUrl = $this->canonicalizeUrl($data['providers-url']); $this->hasProviders = \true; } if (!empty($data['list'])) { $this->listUrl = $this->canonicalizeUrl($data['list']); } if (!empty($data['providers']) || !empty($data['providers-includes'])) { $this->hasProviders = \true; } if (!empty($data['providers-api'])) { $this->providersApiUrl = $this->canonicalizeUrl($data['providers-api']); } return $this->rootData = $data; } /** * @param string $url * @return non-empty-string */ private function canonicalizeUrl(string $url) : string { if (\strlen($url) === 0) { throw new \InvalidArgumentException('Expected a string with a value and not an empty string'); } if (\str_starts_with($url, '/')) { if (Preg::isMatch('{^[^:]++://[^/]*+}', $this->url, $matches)) { return $matches[0] . $url; } return $this->url; } return $url; } /** * @return mixed[] */ private function loadDataFromServer() : array { $data = $this->loadRootServerFile(); if (\true === $data) { throw new \LogicException('loadRootServerFile should not return true during initialization'); } return $this->loadIncludes($data); } private function hasPartialPackages() : bool { if ($this->hasPartialPackages && null === $this->partialPackagesByName) { $this->initializePartialPackages(); } return $this->hasPartialPackages; } /** * @param array{providers?: mixed[], provider-includes?: mixed[]} $data */ private function loadProviderListings($data) : void { if (isset($data['providers'])) { if (!\is_array($this->providerListing)) { $this->providerListing = []; } $this->providerListing = \array_merge($this->providerListing, $data['providers']); } if ($this->providersUrl && isset($data['provider-includes'])) { $includes = $data['provider-includes']; foreach ($includes as $include => $metadata) { $url = $this->baseUrl . '/' . \str_replace('%hash%', $metadata['sha256'], $include); $cacheKey = \str_replace(['%hash%', '$'], '', $include); if ($this->cache->sha256($cacheKey) === $metadata['sha256']) { $includedData = \json_decode($this->cache->read($cacheKey), \true); } else { $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']); } $this->loadProviderListings($includedData); } } } /** * @param mixed[] $data * * @return mixed[] */ private function loadIncludes(array $data) : array { $packages = []; // legacy repo handling if (!isset($data['packages']) && !isset($data['includes'])) { foreach ($data as $pkg) { if (isset($pkg['versions']) && \is_array($pkg['versions'])) { foreach ($pkg['versions'] as $metadata) { $packages[] = $metadata; } } } return $packages; } if (isset($data['packages'])) { foreach ($data['packages'] as $package => $versions) { $packageName = \strtolower((string) $package); foreach ($versions as $version => $metadata) { $packages[] = $metadata; if (!$this->displayedWarningAboutNonMatchingPackageIndex && $packageName !== \strtolower((string) ($metadata['name'] ?? ''))) { $this->displayedWarningAboutNonMatchingPackageIndex = \true; $this->io->writeError(\sprintf("Warning: the packages key '%s' doesn't match the name defined in the package metadata '%s' in repository %s", $package, $metadata['name'] ?? '', $this->baseUrl)); } } } } if (isset($data['includes'])) { foreach ($data['includes'] as $include => $metadata) { if (isset($metadata['sha1']) && $this->cache->sha1((string) $include) === $metadata['sha1']) { $includedData = \json_decode($this->cache->read((string) $include), \true); } else { $includedData = $this->fetchFile($include); } $packages = \array_merge($packages, $this->loadIncludes($includedData)); } } return $packages; } /** * @param mixed[] $packages * * @return list */ private function createPackages(array $packages, ?string $source = null) : array { if (!$packages) { return []; } try { foreach ($packages as &$data) { if (!isset($data['notification-url'])) { $data['notification-url'] = $this->notifyUrl; } } $packageInstances = $this->loader->loadPackages($packages); foreach ($packageInstances as $package) { if (isset($this->sourceMirrors[$package->getSourceType()])) { $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]); } $package->setDistMirrors($this->distMirrors); $this->configurePackageTransportOptions($package); } return $packageInstances; } catch (\Exception $e) { throw new \RuntimeException('Could not load packages ' . ($packages[0]['name'] ?? \json_encode($packages)) . ' in ' . $this->getRepoName() . ($source ? ' from ' . $source : '') . ': [' . \get_class($e) . '] ' . $e->getMessage(), 0, $e); } } /** * @return array */ protected function fetchFile(string $filename, ?string $cacheKey = null, ?string $sha256 = null, bool $storeLastModifiedTime = \false) { if ('' === $filename) { throw new \InvalidArgumentException('$filename should not be an empty string'); } if (null === $cacheKey) { $cacheKey = $filename; $filename = $this->baseUrl . '/' . $filename; } // url-encode $ signs in URLs as bad proxies choke on them if (($pos = \strpos($filename, '$')) && Preg::isMatch('{^https?://}i', $filename)) { $filename = \substr($filename, 0, $pos) . '%24' . \substr($filename, $pos + 1); } $retries = 3; while ($retries--) { try { $options = $this->options; if ($this->eventDispatcher) { $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename, 'metadata', ['repository' => $this]); $preFileDownloadEvent->setTransportOptions($this->options); $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); $filename = $preFileDownloadEvent->getProcessedUrl(); $options = $preFileDownloadEvent->getTransportOptions(); } $response = $this->httpDownloader->get($filename, $options); $json = (string) $response->getBody(); if ($sha256 && $sha256 !== \hash('sha256', $json)) { // undo downgrade before trying again if http seems to be hijacked or modifying content somehow if ($this->allowSslDowngrade) { $this->url = \str_replace('http://', 'https://', $this->url); $this->baseUrl = \str_replace('http://', 'https://', $this->baseUrl); $filename = \str_replace('http://', 'https://', $filename); } if ($retries > 0) { \usleep(100000); continue; } // TODO use scarier wording once we know for sure it doesn't do false positives anymore throw new \Composer\Repository\RepositorySecurityException('The contents of ' . $filename . ' do not match its signature. This could indicate a man-in-the-middle attack or e.g. antivirus software corrupting files. Try running composer again and report this if you think it is a mistake.'); } if ($this->eventDispatcher) { $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, $sha256, $filename, 'metadata', ['response' => $response, 'repository' => $this]); $this->eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent); } $data = $response->decodeJson(); HttpDownloader::outputWarnings($this->io, $this->url, $data); if ($cacheKey && !$this->cache->isReadOnly()) { if ($storeLastModifiedTime) { $lastModifiedDate = $response->getHeader('last-modified'); if ($lastModifiedDate) { $data['last-modified'] = $lastModifiedDate; $json = JsonFile::encode($data, 0); } } $this->cache->write($cacheKey, $json); } $response->collect(); break; } catch (\Exception $e) { if ($e instanceof \LogicException) { throw $e; } if ($e instanceof TransportException && $e->getStatusCode() === 404) { throw $e; } if ($e instanceof \Composer\Repository\RepositorySecurityException) { throw $e; } if ($cacheKey && ($contents = $this->cache->read($cacheKey))) { if (!$this->degradedMode) { $this->io->writeError('' . $this->url . ' could not be fully loaded (' . $e->getMessage() . '), package information was loaded from the local cache and may be out of date'); } $this->degradedMode = \true; $data = JsonFile::parseJson($contents, $this->cache->getRoot() . $cacheKey); break; } throw $e; } } if (!isset($data)) { throw new \LogicException("ComposerRepository: Undefined \$data. Please report at https://github.com/composer/composer/issues/new."); } return $data; } /** * @return array|true */ private function fetchFileIfLastModified(string $filename, string $cacheKey, string $lastModifiedTime) { if ('' === $filename) { throw new \InvalidArgumentException('$filename should not be an empty string'); } try { $options = $this->options; if ($this->eventDispatcher) { $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename, 'metadata', ['repository' => $this]); $preFileDownloadEvent->setTransportOptions($this->options); $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); $filename = $preFileDownloadEvent->getProcessedUrl(); $options = $preFileDownloadEvent->getTransportOptions(); } if (isset($options['http']['header'])) { $options['http']['header'] = (array) $options['http']['header']; } $options['http']['header'][] = 'If-Modified-Since: ' . $lastModifiedTime; $response = $this->httpDownloader->get($filename, $options); $json = (string) $response->getBody(); if ($json === '' && $response->getStatusCode() === 304) { return \true; } if ($this->eventDispatcher) { $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, null, $filename, 'metadata', ['response' => $response, 'repository' => $this]); $this->eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent); } $data = $response->decodeJson(); HttpDownloader::outputWarnings($this->io, $this->url, $data); $lastModifiedDate = $response->getHeader('last-modified'); $response->collect(); if ($lastModifiedDate) { $data['last-modified'] = $lastModifiedDate; $json = JsonFile::encode($data, 0); } if (!$this->cache->isReadOnly()) { $this->cache->write($cacheKey, $json); } return $data; } catch (\Exception $e) { if ($e instanceof \LogicException) { throw $e; } if ($e instanceof TransportException && $e->getStatusCode() === 404) { throw $e; } if (!$this->degradedMode) { $this->io->writeError('' . $this->url . ' could not be fully loaded (' . $e->getMessage() . '), package information was loaded from the local cache and may be out of date'); } $this->degradedMode = \true; return \true; } } /** * @phpstan-return PromiseInterface|true> true if the response was a 304 and the cache is fresh, otherwise it returns the decoded json */ private function asyncFetchFile(string $filename, string $cacheKey, ?string $lastModifiedTime = null) : PromiseInterface { if ('' === $filename) { throw new \InvalidArgumentException('$filename should not be an empty string'); } if (isset($this->packagesNotFoundCache[$filename])) { return \React\Promise\resolve(['packages' => []]); } if (isset($this->freshMetadataUrls[$filename]) && $lastModifiedTime) { // make it look like we got a 304 response /** @var PromiseInterface $promise */ $promise = \React\Promise\resolve(\true); return $promise; } $httpDownloader = $this->httpDownloader; $options = $this->options; if ($this->eventDispatcher) { $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename, 'metadata', ['repository' => $this]); $preFileDownloadEvent->setTransportOptions($this->options); $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); $filename = $preFileDownloadEvent->getProcessedUrl(); $options = $preFileDownloadEvent->getTransportOptions(); } if ($lastModifiedTime) { if (isset($options['http']['header'])) { $options['http']['header'] = (array) $options['http']['header']; } $options['http']['header'][] = 'If-Modified-Since: ' . $lastModifiedTime; } $io = $this->io; $url = $this->url; $cache = $this->cache; $degradedMode =& $this->degradedMode; $eventDispatcher = $this->eventDispatcher; /** * @return array|true true if the response was a 304 and the cache is fresh */ $accept = function ($response) use($io, $url, $filename, $cache, $cacheKey, $eventDispatcher) { // package not found is acceptable for a v2 protocol repository if ($response->getStatusCode() === 404) { $this->packagesNotFoundCache[$filename] = \true; return ['packages' => []]; } $json = (string) $response->getBody(); if ($json === '' && $response->getStatusCode() === 304) { $this->freshMetadataUrls[$filename] = \true; return \true; } if ($eventDispatcher) { $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, null, $filename, 'metadata', ['response' => $response, 'repository' => $this]); $eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent); } $data = $response->decodeJson(); HttpDownloader::outputWarnings($io, $url, $data); $lastModifiedDate = $response->getHeader('last-modified'); $response->collect(); if ($lastModifiedDate) { $data['last-modified'] = $lastModifiedDate; $json = JsonFile::encode($data, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); } if (!$cache->isReadOnly()) { $cache->write($cacheKey, $json); } $this->freshMetadataUrls[$filename] = \true; return $data; }; $reject = function ($e) use($filename, $accept, $io, $url, &$degradedMode, $lastModifiedTime) { if ($e instanceof TransportException && $e->getStatusCode() === 404) { $this->packagesNotFoundCache[$filename] = \true; return \false; } if (!$degradedMode) { $io->writeError('' . $url . ' could not be fully loaded (' . $e->getMessage() . '), package information was loaded from the local cache and may be out of date'); } $degradedMode = \true; // if the file is in the cache, we fake a 304 Not Modified to allow the process to continue if ($lastModifiedTime) { return $accept(new Response(['url' => $url], 304, [], '')); } // special error code returned when network is being artificially disabled if ($e instanceof TransportException && $e->getStatusCode() === 499) { return $accept(new Response(['url' => $url], 404, [], '')); } throw $e; }; return $httpDownloader->add($filename, $options)->then($accept, $reject); } /** * This initializes the packages key of a partial packages.json that contain some packages inlined + a providers-lazy-url * * This should only be called once */ private function initializePartialPackages() : void { $rootData = $this->loadRootServerFile(); if ($rootData === \true) { return; } $this->partialPackagesByName = []; foreach ($rootData['packages'] as $package => $versions) { foreach ($versions as $version) { $versionPackageName = \strtolower((string) ($version['name'] ?? '')); $this->partialPackagesByName[$versionPackageName][] = $version; if (!$this->displayedWarningAboutNonMatchingPackageIndex && $versionPackageName !== \strtolower($package)) { $this->io->writeError(\sprintf("Warning: the packages key '%s' doesn't match the name defined in the package metadata '%s' in repository %s", $package, $version['name'] ?? '', $this->baseUrl)); $this->displayedWarningAboutNonMatchingPackageIndex = \true; } } } // wipe rootData as it is fully consumed at this point and this saves some memory $this->rootData = \true; } /** * Checks if the package name is present in this lazy providers repo * * @return bool true if the package name is present in availablePackages or matched by availablePackagePatterns */ protected function lazyProvidersRepoContains(string $name) { if (!$this->hasAvailablePackageList) { throw new \LogicException('lazyProvidersRepoContains should not be called unless hasAvailablePackageList is true'); } if (\is_array($this->availablePackages) && isset($this->availablePackages[$name])) { return \true; } if (\is_array($this->availablePackagePatterns)) { foreach ($this->availablePackagePatterns as $providerRegex) { if (Preg::isMatch($providerRegex, $name)) { return \true; } } } return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Builds list of package from PEAR channel. * * Packages read from channel are named as 'pear-{channelName}/{packageName}' * and has aliased as 'pear-{channelAlias}/{packageName}' * * @author Benjamin Eberlei * @author Jordi Boggiano * @deprecated * @private */ class PearRepository extends \Composer\Repository\ArrayRepository { public function __construct() { throw new \InvalidArgumentException('The PEAR repository has been removed from Composer 2.x'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\DependencyResolver\PoolOptimizer; use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\PoolBuilder; use Composer\DependencyResolver\Request; use Composer\EventDispatcher\EventDispatcher; use Composer\Advisory\SecurityAdvisory; use Composer\Advisory\PartialSecurityAdvisory; use Composer\IO\IOInterface; use Composer\IO\NullIO; use Composer\Package\BasePackage; use Composer\Package\AliasPackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\CompletePackage; use Composer\Package\PackageInterface; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Package\Version\StabilityFilter; use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Semver\Constraint\MultiConstraint; /** * @author Nils Adermann * * @see RepositoryUtils for ways to work with single repos */ class RepositorySet { /** * Packages are returned even though their stability does not match the required stability */ public const ALLOW_UNACCEPTABLE_STABILITIES = 1; /** * Packages will be looked up in all repositories, even after they have been found in a higher prio one */ public const ALLOW_SHADOWED_REPOSITORIES = 2; /** * @var array[] * @phpstan-var array> */ private $rootAliases; /** * @var string[] * @phpstan-var array */ private $rootReferences; /** @var RepositoryInterface[] */ private $repositories = []; /** * @var int[] array of stability => BasePackage::STABILITY_* value * @phpstan-var array, BasePackage::STABILITY_*> */ private $acceptableStabilities; /** * @var int[] array of package name => BasePackage::STABILITY_* value * @phpstan-var array */ private $stabilityFlags; /** * @var ConstraintInterface[] * @phpstan-var array */ private $rootRequires; /** * @var array */ private $temporaryConstraints; /** @var bool */ private $locked = \false; /** @var bool */ private $allowInstalledRepositories = \false; /** * In most cases if you are looking to use this class as a way to find packages from repositories * passing minimumStability is all you need to worry about. The rest is for advanced pool creation including * aliases, pinned references and other special cases. * * @param key-of $minimumStability * @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value * @phpstan-param array $stabilityFlags * @param array[] $rootAliases * @phpstan-param list $rootAliases * @param string[] $rootReferences an array of package name => source reference * @phpstan-param array $rootReferences * @param ConstraintInterface[] $rootRequires an array of package name => constraint from the root package * @phpstan-param array $rootRequires * @param array $temporaryConstraints Runtime temporary constraints that will be used to filter packages */ public function __construct(string $minimumStability = 'stable', array $stabilityFlags = [], array $rootAliases = [], array $rootReferences = [], array $rootRequires = [], array $temporaryConstraints = []) { $this->rootAliases = self::getRootAliasesPerPackage($rootAliases); $this->rootReferences = $rootReferences; $this->acceptableStabilities = []; foreach (BasePackage::STABILITIES as $stability => $value) { if ($value <= BasePackage::STABILITIES[$minimumStability]) { $this->acceptableStabilities[$stability] = $value; } } $this->stabilityFlags = $stabilityFlags; $this->rootRequires = $rootRequires; foreach ($rootRequires as $name => $constraint) { if (\Composer\Repository\PlatformRepository::isPlatformPackage($name)) { unset($this->rootRequires[$name]); } } $this->temporaryConstraints = $temporaryConstraints; } public function allowInstalledRepositories(bool $allow = \true) : void { $this->allowInstalledRepositories = $allow; } /** * @return ConstraintInterface[] an array of package name => constraint from the root package, platform requirements excluded * @phpstan-return array */ public function getRootRequires() : array { return $this->rootRequires; } /** * @return array Runtime temporary constraints that will be used to filter packages */ public function getTemporaryConstraints() : array { return $this->temporaryConstraints; } /** * Adds a repository to this repository set * * The first repos added have a higher priority. As soon as a package is found in any * repository the search for that package ends, and following repos will not be consulted. * * @param RepositoryInterface $repo A package repository */ public function addRepository(\Composer\Repository\RepositoryInterface $repo) : void { if ($this->locked) { throw new \RuntimeException("Pool has already been created from this repository set, it cannot be modified anymore."); } if ($repo instanceof \Composer\Repository\CompositeRepository) { $repos = $repo->getRepositories(); } else { $repos = [$repo]; } foreach ($repos as $repo) { $this->repositories[] = $repo; } } /** * Find packages providing or matching a name and optionally meeting a constraint in all repositories * * Returned in the order of repositories, matching priority * * @param int $flags any of the ALLOW_* constants from this class to tweak what is returned * @return BasePackage[] */ public function findPackages(string $name, ?ConstraintInterface $constraint = null, int $flags = 0) : array { $ignoreStability = ($flags & self::ALLOW_UNACCEPTABLE_STABILITIES) !== 0; $loadFromAllRepos = ($flags & self::ALLOW_SHADOWED_REPOSITORIES) !== 0; $packages = []; if ($loadFromAllRepos) { foreach ($this->repositories as $repository) { $packages[] = $repository->findPackages($name, $constraint) ?: []; } } else { foreach ($this->repositories as $repository) { $result = $repository->loadPackages([$name => $constraint], $ignoreStability ? BasePackage::STABILITIES : $this->acceptableStabilities, $ignoreStability ? [] : $this->stabilityFlags); $packages[] = $result['packages']; foreach ($result['namesFound'] as $nameFound) { // avoid loading the same package again from other repositories once it has been found if ($name === $nameFound) { break 2; } } } } $candidates = $packages ? \array_merge(...$packages) : []; // when using loadPackages above (!$loadFromAllRepos) the repos already filter for stability so no need to do it again if ($ignoreStability || !$loadFromAllRepos) { return $candidates; } $result = []; foreach ($candidates as $candidate) { if ($this->isPackageAcceptable($candidate->getNames(), $candidate->getStability())) { $result[] = $candidate; } } return $result; } /** * @param string[] $packageNames * @return ($allowPartialAdvisories is true ? array> : array>) */ public function getSecurityAdvisories(array $packageNames, bool $allowPartialAdvisories = \false) : array { $map = []; foreach ($packageNames as $name) { $map[$name] = new MatchAllConstraint(); } return $this->getSecurityAdvisoriesForConstraints($map, $allowPartialAdvisories); } /** * @param PackageInterface[] $packages * @return ($allowPartialAdvisories is true ? array> : array>) */ public function getMatchingSecurityAdvisories(array $packages, bool $allowPartialAdvisories = \false) : array { $map = []; foreach ($packages as $package) { // ignore root alias versions as they are not actual package versions and should not matter when it comes to vulnerabilities if ($package instanceof AliasPackage && $package->isRootPackageAlias()) { continue; } if (isset($map[$package->getName()])) { $map[$package->getName()] = new MultiConstraint([new Constraint('=', $package->getVersion()), $map[$package->getName()]], \false); } else { $map[$package->getName()] = new Constraint('=', $package->getVersion()); } } return $this->getSecurityAdvisoriesForConstraints($map, $allowPartialAdvisories); } /** * @param array $packageConstraintMap * @return ($allowPartialAdvisories is true ? array> : array>) */ private function getSecurityAdvisoriesForConstraints(array $packageConstraintMap, bool $allowPartialAdvisories) : array { $repoAdvisories = []; foreach ($this->repositories as $repository) { if (!$repository instanceof \Composer\Repository\AdvisoryProviderInterface || !$repository->hasSecurityAdvisories()) { continue; } $repoAdvisories[] = $repository->getSecurityAdvisories($packageConstraintMap, $allowPartialAdvisories)['advisories']; } $advisories = \array_merge_recursive([], ...$repoAdvisories); \ksort($advisories); return $advisories; } /** * @return array[] an array with the provider name as key and value of array('name' => '...', 'description' => '...', 'type' => '...') * @phpstan-return array */ public function getProviders(string $packageName) : array { $providers = []; foreach ($this->repositories as $repository) { if ($repoProviders = $repository->getProviders($packageName)) { $providers = \array_merge($providers, $repoProviders); } } return $providers; } /** * Check for each given package name whether it would be accepted by this RepositorySet in the given $stability * * @param string[] $names * @param key-of $stability one of 'stable', 'RC', 'beta', 'alpha' or 'dev' */ public function isPackageAcceptable(array $names, string $stability) : bool { return StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $names, $stability); } /** * Create a pool for dependency resolution from the packages in this repository set. * * @param list $ignoredTypes Packages of those types are ignored * @param list|null $allowedTypes Only packages of those types are allowed if set to non-null */ public function createPool(Request $request, IOInterface $io, ?EventDispatcher $eventDispatcher = null, ?PoolOptimizer $poolOptimizer = null, array $ignoredTypes = [], ?array $allowedTypes = null) : Pool { $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $io, $eventDispatcher, $poolOptimizer, $this->temporaryConstraints); $poolBuilder->setIgnoredTypes($ignoredTypes); $poolBuilder->setAllowedTypes($allowedTypes); foreach ($this->repositories as $repo) { if (($repo instanceof \Composer\Repository\InstalledRepositoryInterface || $repo instanceof \Composer\Repository\InstalledRepository) && !$this->allowInstalledRepositories) { throw new \LogicException('The pool can not accept packages from an installed repository'); } } $this->locked = \true; return $poolBuilder->buildPool($this->repositories, $request); } /** * Create a pool for dependency resolution from the packages in this repository set. */ public function createPoolWithAllPackages() : Pool { foreach ($this->repositories as $repo) { if (($repo instanceof \Composer\Repository\InstalledRepositoryInterface || $repo instanceof \Composer\Repository\InstalledRepository) && !$this->allowInstalledRepositories) { throw new \LogicException('The pool can not accept packages from an installed repository'); } } $this->locked = \true; $packages = []; foreach ($this->repositories as $repository) { foreach ($repository->getPackages() as $package) { $packages[] = $package; if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) { $alias = $this->rootAliases[$package->getName()][$package->getVersion()]; while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } if ($package instanceof CompletePackage) { $aliasPackage = new CompleteAliasPackage($package, $alias['alias_normalized'], $alias['alias']); } else { $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']); } $aliasPackage->setRootPackageAlias(\true); $packages[] = $aliasPackage; } } } return new Pool($packages); } public function createPoolForPackage(string $packageName, ?\Composer\Repository\LockArrayRepository $lockedRepo = null) : Pool { // TODO unify this with above in some simpler version without "request"? return $this->createPoolForPackages([$packageName], $lockedRepo); } /** * @param string[] $packageNames */ public function createPoolForPackages(array $packageNames, ?\Composer\Repository\LockArrayRepository $lockedRepo = null) : Pool { $request = new Request($lockedRepo); $allowedPackages = []; foreach ($packageNames as $packageName) { if (\Composer\Repository\PlatformRepository::isPlatformPackage($packageName)) { throw new \LogicException('createPoolForPackage(s) can not be used for platform packages, as they are never loaded by the PoolBuilder which expects them to be fixed. Use createPoolWithAllPackages or pass in a proper request with the platform packages you need fixed in it.'); } $request->requireName($packageName); $allowedPackages[] = \strtolower($packageName); } if (\count($allowedPackages) > 0) { $request->restrictPackages($allowedPackages); } return $this->createPool($request, new NullIO()); } /** * @param array[] $aliases * @phpstan-param list $aliases * * @return array> */ private static function getRootAliasesPerPackage(array $aliases) : array { $normalizedAliases = []; foreach ($aliases as $alias) { $normalizedAliases[$alias['package']][$alias['version']] = ['alias' => $alias['alias'], 'alias_normalized' => $alias['alias_normalized']]; } return $normalizedAliases; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\BasePackage; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\LoaderInterface; use Composer\Util\Platform; use Composer\Util\Tar; use Composer\Util\Zip; /** * @author Serge Smertin */ class ArtifactRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface { /** @var LoaderInterface */ protected $loader; /** @var string */ protected $lookup; /** @var array{url: string} */ protected $repoConfig; /** @var IOInterface */ private $io; /** * @param array{url: string} $repoConfig */ public function __construct(array $repoConfig, IOInterface $io) { parent::__construct(); if (!\extension_loaded('zip')) { throw new \RuntimeException('The artifact repository requires PHP\'s zip extension'); } $this->loader = new ArrayLoader(); $this->lookup = Platform::expandPath($repoConfig['url']); $this->io = $io; $this->repoConfig = $repoConfig; } public function getRepoName() { return 'artifact repo (' . $this->lookup . ')'; } public function getRepoConfig() { return $this->repoConfig; } protected function initialize() { parent::initialize(); $this->scanDirectory($this->lookup); } private function scanDirectory(string $path) : void { $io = $this->io; $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS); $iterator = new \RecursiveIteratorIterator($directory); $regex = new \RegexIterator($iterator, '/^.+\\.(zip|tar|gz|tgz)$/i'); foreach ($regex as $file) { /* @var $file \SplFileInfo */ if (!$file->isFile()) { continue; } $package = $this->getComposerInformation($file); if (!$package) { $io->writeError("File {$file->getBasename()} doesn't seem to hold a package", \true, IOInterface::VERBOSE); continue; } $template = 'Found package %s (%s) in file %s'; $io->writeError(\sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), \true, IOInterface::VERBOSE); $this->addPackage($package); } } /** * @return ?BasePackage */ private function getComposerInformation(\SplFileInfo $file) : ?BasePackage { $json = null; $fileType = null; $fileExtension = \pathinfo($file->getPathname(), \PATHINFO_EXTENSION); if (\in_array($fileExtension, ['gz', 'tar', 'tgz'], \true)) { $fileType = 'tar'; } elseif ($fileExtension === 'zip') { $fileType = 'zip'; } else { throw new \RuntimeException('Files with "' . $fileExtension . '" extensions aren\'t supported. Only ZIP and TAR/TAR.GZ/TGZ archives are supported.'); } try { if ($fileType === 'tar') { $json = Tar::getComposerJson($file->getPathname()); } else { $json = Zip::getComposerJson($file->getPathname()); } } catch (\Exception $exception) { $this->io->write('Failed loading package ' . $file->getPathname() . ': ' . $exception->getMessage(), \false, IOInterface::VERBOSE); } if (null === $json) { return null; } $package = JsonFile::parseJson($json, $file->getPathname() . '#composer.json'); $package['dist'] = ['type' => $fileType, 'url' => \strtr($file->getPathname(), '\\', '/'), 'shasum' => \hash_file('sha1', $file->getRealPath())]; try { $package = $this->loader->load($package); } catch (\UnexpectedValueException $e) { throw new \UnexpectedValueException('Failed loading package in ' . $file . ': ' . $e->getMessage(), 0, $e); } return $package; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\RootPackageInterface; /** * Root package repository. * * This is used for serving the RootPackage inside an in-memory InstalledRepository * * @author Jordi Boggiano */ class RootPackageRepository extends \Composer\Repository\ArrayRepository { public function __construct(RootPackageInterface $package) { parent::__construct([$package]); } public function getRepoName() : string { return 'root package repo'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\IO\IOInterface; use Composer\Config; use Composer\EventDispatcher\EventDispatcher; use Composer\Package\PackageInterface; use Composer\Util\HttpDownloader; use Composer\Util\ProcessExecutor; /** * Repositories manager. * * @author Jordi Boggiano * @author Konstantin Kudryashov * @author François Pluchino */ class RepositoryManager { /** @var InstalledRepositoryInterface */ private $localRepository; /** @var list */ private $repositories = []; /** @var array> */ private $repositoryClasses = []; /** @var IOInterface */ private $io; /** @var Config */ private $config; /** @var HttpDownloader */ private $httpDownloader; /** @var ?EventDispatcher */ private $eventDispatcher; /** @var ProcessExecutor */ private $process; public function __construct(IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $eventDispatcher = null, ?ProcessExecutor $process = null) { $this->io = $io; $this->config = $config; $this->httpDownloader = $httpDownloader; $this->eventDispatcher = $eventDispatcher; $this->process = $process ?? new ProcessExecutor($io); } /** * Searches for a package by its name and version in managed repositories. * * @param string $name package name * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against */ public function findPackage(string $name, $constraint) : ?PackageInterface { foreach ($this->repositories as $repository) { /** @var RepositoryInterface $repository */ if ($package = $repository->findPackage($name, $constraint)) { return $package; } } return null; } /** * Searches for all packages matching a name and optionally a version in managed repositories. * * @param string $name package name * @param string|\Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against * * @return PackageInterface[] */ public function findPackages(string $name, $constraint) : array { $packages = []; foreach ($this->getRepositories() as $repository) { $packages = \array_merge($packages, $repository->findPackages($name, $constraint)); } return $packages; } /** * Adds repository * * @param RepositoryInterface $repository repository instance */ public function addRepository(\Composer\Repository\RepositoryInterface $repository) : void { $this->repositories[] = $repository; } /** * Adds a repository to the beginning of the chain * * This is useful when injecting additional repositories that should trump Packagist, e.g. from a plugin. * * @param RepositoryInterface $repository repository instance */ public function prependRepository(\Composer\Repository\RepositoryInterface $repository) : void { \array_unshift($this->repositories, $repository); } /** * Returns a new repository for a specific installation type. * * @param string $type repository type * @param array $config repository configuration * @param string $name repository name * @throws \InvalidArgumentException if repository for provided type is not registered */ public function createRepository(string $type, array $config, ?string $name = null) : \Composer\Repository\RepositoryInterface { if (!isset($this->repositoryClasses[$type])) { throw new \InvalidArgumentException('Repository type is not registered: ' . $type); } if (isset($config['packagist']) && \false === $config['packagist']) { $this->io->writeError('Repository "' . $name . '" (' . \json_encode($config) . ') has a packagist key which should be in its own repository definition'); } $class = $this->repositoryClasses[$type]; if (isset($config['only']) || isset($config['exclude']) || isset($config['canonical'])) { $filterConfig = $config; unset($config['only'], $config['exclude'], $config['canonical']); } $repository = new $class($config, $this->io, $this->config, $this->httpDownloader, $this->eventDispatcher, $this->process); if (isset($filterConfig)) { $repository = new \Composer\Repository\FilterRepository($repository, $filterConfig); } return $repository; } /** * Stores repository class for a specific installation type. * * @param string $type installation type * @param class-string $class class name of the repo implementation */ public function setRepositoryClass(string $type, $class) : void { $this->repositoryClasses[$type] = $class; } /** * Returns all repositories, except local one. * * @return RepositoryInterface[] */ public function getRepositories() : array { return $this->repositories; } /** * Sets local repository for the project. * * @param InstalledRepositoryInterface $repository repository instance */ public function setLocalRepository(\Composer\Repository\InstalledRepositoryInterface $repository) : void { $this->localRepository = $repository; } /** * Returns local repository for the project. */ public function getLocalRepository() : \Composer\Repository\InstalledRepositoryInterface { return $this->localRepository; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\Downloader\TransportException; use Composer\Json\JsonFile; use Composer\Cache; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Util\GitHub; use Composer\Util\Http\Response; /** * @author Jordi Boggiano */ class GitHubDriver extends \Composer\Repository\Vcs\VcsDriver { /** @var string */ protected $owner; /** @var string */ protected $repository; /** @var array Map of tag name to identifier */ protected $tags; /** @var array Map of branch name to identifier */ protected $branches; /** @var string */ protected $rootIdentifier; /** @var mixed[] */ protected $repoData; /** @var bool */ protected $hasIssues = \false; /** @var bool */ protected $isPrivate = \false; /** @var bool */ private $isArchived = \false; /** @var array|false|null */ private $fundingInfo; /** * Git Driver * * @var ?GitDriver */ protected $gitDriver = null; /** * @inheritDoc */ public function initialize() : void { if (!Preg::isMatch('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/([^/]+?)(?:\\.git|/)?$#', $this->url, $match)) { throw new \InvalidArgumentException(\sprintf('The GitHub repository URL %s is invalid.', $this->url)); } $this->owner = $match[3]; $this->repository = $match[4]; $this->originUrl = \strtolower($match[1] ?? (string) $match[2]); if ($this->originUrl === 'www.github.com') { $this->originUrl = 'github.com'; } $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . $this->originUrl . '/' . $this->owner . '/' . $this->repository); $this->cache->setReadOnly($this->config->get('cache-read-only')); if ($this->config->get('use-github-api') === \false || isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) { $this->setupGitDriver($this->url); return; } $this->fetchRootIdentifier(); } public function getRepositoryUrl() : string { return 'https://' . $this->originUrl . '/' . $this->owner . '/' . $this->repository; } /** * @inheritDoc */ public function getRootIdentifier() : string { if ($this->gitDriver) { return $this->gitDriver->getRootIdentifier(); } return $this->rootIdentifier; } /** * @inheritDoc */ public function getUrl() : string { if ($this->gitDriver) { return $this->gitDriver->getUrl(); } return 'https://' . $this->originUrl . '/' . $this->owner . '/' . $this->repository . '.git'; } protected function getApiUrl() : string { if ('github.com' === $this->originUrl) { $apiUrl = 'api.github.com'; } else { $apiUrl = $this->originUrl . '/api/v3'; } return 'https://' . $apiUrl; } /** * @inheritDoc */ public function getSource(string $identifier) : array { if ($this->gitDriver) { return $this->gitDriver->getSource($identifier); } if ($this->isPrivate) { // Private GitHub repositories should be accessed using the // SSH version of the URL. $url = $this->generateSshUrl(); } else { $url = $this->getUrl(); } return ['type' => 'git', 'url' => $url, 'reference' => $identifier]; } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { $url = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/zipball/' . $identifier; return ['type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '']; } /** * @inheritDoc */ public function getComposerInformation(string $identifier) : ?array { if ($this->gitDriver) { return $this->gitDriver->getComposerInformation($identifier); } if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && ($res = $this->cache->read($identifier))) { $composer = JsonFile::parseJson($res); } else { $composer = $this->getBaseComposerInformation($identifier); if ($this->shouldCache($identifier)) { $this->cache->write($identifier, \json_encode($composer)); } } if ($composer !== null) { // specials for github if (isset($composer['support']) && !\is_array($composer['support'])) { $composer['support'] = []; } if (!isset($composer['support']['source'])) { $label = (\array_search($identifier, $this->getTags()) ?: \array_search($identifier, $this->getBranches())) ?: $identifier; $composer['support']['source'] = \sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label); } if (!isset($composer['support']['issues']) && $this->hasIssues) { $composer['support']['issues'] = \sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); } if (!isset($composer['abandoned']) && $this->isArchived) { $composer['abandoned'] = \true; } if (!isset($composer['funding']) && ($funding = $this->getFundingInfo())) { $composer['funding'] = $funding; } } $this->infoCache[$identifier] = $composer; } return $this->infoCache[$identifier]; } /** * @return array|false */ private function getFundingInfo() { if (null !== $this->fundingInfo) { return $this->fundingInfo; } if ($this->originUrl !== 'github.com') { return $this->fundingInfo = \false; } foreach ([$this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/contents/.github/FUNDING.yml', $this->getApiUrl() . '/repos/' . $this->owner . '/.github/contents/FUNDING.yml'] as $file) { try { $response = $this->httpDownloader->get($file, ['retry-auth-failure' => \false])->decodeJson(); } catch (TransportException $e) { continue; } if (empty($response['content']) || $response['encoding'] !== 'base64' || !($funding = \base64_decode($response['content']))) { continue; } break; } if (empty($funding)) { return $this->fundingInfo = \false; } $result = []; $key = null; foreach (Preg::split('{\\r?\\n}', $funding) as $line) { $line = \trim($line); if (Preg::isMatchStrictGroups('{^(\\w+)\\s*:\\s*(.+)$}', $line, $match)) { if ($match[2] === '[') { $key = $match[1]; continue; } if (Preg::isMatchStrictGroups('{^\\[(.*?)\\](?:\\s*#.*)?$}', $match[2], $match2)) { foreach (\array_map('trim', Preg::split('{[\'"]?\\s*,\\s*[\'"]?}', $match2[1])) as $item) { $result[] = ['type' => $match[1], 'url' => \trim($item, '"\' ')]; } } elseif (Preg::isMatchStrictGroups('{^([^#].*?)(?:\\s+#.*)?$}', $match[2], $match2)) { $result[] = ['type' => $match[1], 'url' => \trim($match2[1], '"\' ')]; } $key = null; } elseif (Preg::isMatchStrictGroups('{^(\\w+)\\s*:\\s*#\\s*$}', $line, $match)) { $key = $match[1]; } elseif ($key !== null && (Preg::isMatchStrictGroups('{^-\\s*(.+)(?:\\s+#.*)?$}', $line, $match) || Preg::isMatchStrictGroups('{^(.+),(?:\\s*#.*)?$}', $line, $match))) { $result[] = ['type' => $key, 'url' => \trim($match[1], '"\' ')]; } elseif ($key !== null && $line === ']') { $key = null; } } foreach ($result as $key => $item) { switch ($item['type']) { case 'community_bridge': $result[$key]['url'] = 'https://funding.communitybridge.org/projects/' . \basename($item['url']); break; case 'github': $result[$key]['url'] = 'https://github.com/' . \basename($item['url']); break; case 'issuehunt': $result[$key]['url'] = 'https://issuehunt.io/r/' . $item['url']; break; case 'ko_fi': $result[$key]['url'] = 'https://ko-fi.com/' . \basename($item['url']); break; case 'liberapay': $result[$key]['url'] = 'https://liberapay.com/' . \basename($item['url']); break; case 'open_collective': $result[$key]['url'] = 'https://opencollective.com/' . \basename($item['url']); break; case 'patreon': $result[$key]['url'] = 'https://www.patreon.com/' . \basename($item['url']); break; case 'tidelift': $result[$key]['url'] = 'https://tidelift.com/funding/github/' . $item['url']; break; case 'polar': $result[$key]['url'] = 'https://polar.sh/' . \basename($item['url']); break; case 'buy_me_a_coffee': $result[$key]['url'] = 'https://www.buymeacoffee.com/' . \basename($item['url']); break; case 'thanks_dev': $result[$key]['url'] = 'https://thanks.dev/' . $item['url']; break; case 'otechie': $result[$key]['url'] = 'https://otechie.com/' . \basename($item['url']); break; case 'custom': $bits = \parse_url($item['url']); if ($bits === \false) { unset($result[$key]); break; } if (!\array_key_exists('scheme', $bits) && !\array_key_exists('host', $bits)) { if (Preg::isMatch('{^[a-z0-9-]++\\.[a-z]{2,3}$}', $item['url'])) { $result[$key]['url'] = 'https://' . $item['url']; break; } $this->io->writeError('Funding URL ' . $item['url'] . ' not in a supported format.'); unset($result[$key]); break; } break; } } return $this->fundingInfo = $result; } /** * @inheritDoc */ public function getFileContent(string $file, string $identifier) : ?string { if ($this->gitDriver) { return $this->gitDriver->getFileContent($file, $identifier); } $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/contents/' . $file . '?ref=' . \urlencode($identifier); $resource = $this->getContents($resource)->decodeJson(); // The GitHub contents API only returns files up to 1MB as base64 encoded files // larger files either need be fetched with a raw accept header or by using the git blob endpoint if ((!isset($resource['content']) || $resource['content'] === '') && $resource['encoding'] === 'none' && isset($resource['git_url'])) { $resource = $this->getContents($resource['git_url'])->decodeJson(); } if (!isset($resource['content']) || $resource['encoding'] !== 'base64' || \false === ($content = \base64_decode($resource['content']))) { throw new \RuntimeException('Could not retrieve ' . $file . ' for ' . $identifier); } return $content; } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { if ($this->gitDriver) { return $this->gitDriver->getChangeDate($identifier); } $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/commits/' . \urlencode($identifier); $commit = $this->getContents($resource)->decodeJson(); return new \DateTimeImmutable($commit['commit']['committer']['date']); } /** * @inheritDoc */ public function getTags() : array { if ($this->gitDriver) { return $this->gitDriver->getTags(); } if (null === $this->tags) { $tags = []; $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/tags?per_page=100'; do { $response = $this->getContents($resource); $tagsData = $response->decodeJson(); foreach ($tagsData as $tag) { $tags[$tag['name']] = $tag['commit']['sha']; } $resource = $this->getNextPage($response); } while ($resource); $this->tags = $tags; } return $this->tags; } /** * @inheritDoc */ public function getBranches() : array { if ($this->gitDriver) { return $this->gitDriver->getBranches(); } if (null === $this->branches) { $branches = []; $resource = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository . '/git/refs/heads?per_page=100'; do { $response = $this->getContents($resource); $branchData = $response->decodeJson(); foreach ($branchData as $branch) { $name = \substr($branch['ref'], 11); if ($name !== 'gh-pages') { $branches[$name] = $branch['object']['sha']; } } $resource = $this->getNextPage($response); } while ($resource); $this->branches = $branches; } return $this->branches; } /** * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { if (!Preg::isMatch('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/([^/]+?)(?:\\.git|/)?$#', $url, $matches)) { return \false; } $originUrl = $matches[2] ?? (string) $matches[3]; if (!\in_array(\strtolower(Preg::replace('{^www\\.}i', '', $originUrl)), $config->get('github-domains'))) { return \false; } if (!\extension_loaded('openssl')) { $io->writeError('Skipping GitHub driver for ' . $url . ' because the OpenSSL PHP extension is missing.', \true, IOInterface::VERBOSE); return \false; } return \true; } /** * Gives back the loaded /repos// result * * @return mixed[]|null */ public function getRepoData() : ?array { $this->fetchRootIdentifier(); return $this->repoData; } /** * Generate an SSH URL */ protected function generateSshUrl() : string { if (\false !== \strpos($this->originUrl, ':')) { return 'ssh://git@' . $this->originUrl . '/' . $this->owner . '/' . $this->repository . '.git'; } return 'git@' . $this->originUrl . ':' . $this->owner . '/' . $this->repository . '.git'; } /** * @inheritDoc */ protected function getContents(string $url, bool $fetchingRepoData = \false) : Response { try { return parent::getContents($url); } catch (TransportException $e) { $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->httpDownloader); switch ($e->getCode()) { case 401: case 404: // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404 if (!$fetchingRepoData) { throw $e; } if ($gitHubUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } if (!$this->io->isInteractive()) { $this->attemptCloneFallback(); return new Response(['url' => 'dummy'], 200, [], 'null'); } $scopesIssued = []; $scopesNeeded = []; if ($headers = $e->getHeaders()) { if ($scopes = Response::findHeaderValue($headers, 'X-OAuth-Scopes')) { $scopesIssued = \explode(' ', $scopes); } if ($scopes = Response::findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) { $scopesNeeded = \explode(' ', $scopes); } } $scopesFailed = \array_diff($scopesNeeded, $scopesIssued); // non-authenticated requests get no scopesNeeded, so ask for credentials // authenticated requests which failed some scopes should ask for new credentials too if (!$headers || !\count($scopesNeeded) || \count($scopesFailed)) { $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (' . $this->url . ')'); } return parent::getContents($url); case 403: if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } if (!$this->io->isInteractive() && $fetchingRepoData) { $this->attemptCloneFallback(); return new Response(['url' => 'dummy'], 200, [], 'null'); } $rateLimited = $gitHubUtil->isRateLimited((array) $e->getHeaders()); if (!$this->io->hasAuthentication($this->originUrl)) { if (!$this->io->isInteractive()) { $this->io->writeError('GitHub API limit exhausted. Failed to get metadata for the ' . $this->url . ' repository, try running in interactive mode so that you can enter your GitHub credentials to increase the API limit'); throw $e; } $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (' . $this->url . ')'); return parent::getContents($url); } if ($rateLimited) { $rateLimit = $gitHubUtil->getRateLimit($e->getHeaders()); $this->io->writeError(\sprintf('GitHub API limit (%d calls/hr) is exhausted. You are already authorized so you have to wait until %s before doing more requests', $rateLimit['limit'], $rateLimit['reset'])); } throw $e; default: throw $e; } } } /** * Fetch root identifier from GitHub * * @throws TransportException */ protected function fetchRootIdentifier() : void { if ($this->repoData) { return; } $repoDataUrl = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository; try { $this->repoData = $this->getContents($repoDataUrl, \true)->decodeJson(); } catch (TransportException $e) { if ($e->getCode() === 499) { $this->attemptCloneFallback(); } else { throw $e; } } if (null === $this->repoData && null !== $this->gitDriver) { return; } $this->owner = $this->repoData['owner']['login']; $this->repository = $this->repoData['name']; $this->isPrivate = !empty($this->repoData['private']); if (isset($this->repoData['default_branch'])) { $this->rootIdentifier = $this->repoData['default_branch']; } elseif (isset($this->repoData['master_branch'])) { $this->rootIdentifier = $this->repoData['master_branch']; } else { $this->rootIdentifier = 'master'; } $this->hasIssues = !empty($this->repoData['has_issues']); $this->isArchived = !empty($this->repoData['archived']); } /** * @phpstan-impure * * @return true * @throws \RuntimeException */ protected function attemptCloneFallback() : bool { $this->isPrivate = \true; try { // If this repository may be private (hard to say for sure, // GitHub returns 404 for private repositories) and we // cannot ask for authentication credentials (because we // are not interactive) then we fallback to GitDriver. $this->setupGitDriver($this->generateSshUrl()); return \true; } catch (\RuntimeException $e) { $this->gitDriver = null; $this->io->writeError('Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode so that you can enter your GitHub credentials'); throw $e; } } protected function setupGitDriver(string $url) : void { $this->gitDriver = new \Composer\Repository\Vcs\GitDriver(['url' => $url], $this->io, $this->config, $this->httpDownloader, $this->process); $this->gitDriver->initialize(); } protected function getNextPage(Response $response) : ?string { $header = $response->getHeader('link'); if (!$header) { return null; } $links = \explode(',', $header); foreach ($links as $link) { if (Preg::isMatch('{<(.+?)>; *rel="next"}', $link, $match)) { return $match[1]; } } return null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Cache; use Composer\Downloader\TransportException; use Composer\Config; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\HttpDownloader; use Composer\Util\Filesystem; use Composer\Util\Http\Response; /** * A driver implementation for driver with authentication interaction. * * @author François Pluchino */ abstract class VcsDriver implements \Composer\Repository\Vcs\VcsDriverInterface { /** @var string */ protected $url; /** @var string */ protected $originUrl; /** @var array */ protected $repoConfig; /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var ProcessExecutor */ protected $process; /** @var HttpDownloader */ protected $httpDownloader; /** @var array */ protected $infoCache = []; /** @var ?Cache */ protected $cache; /** * Constructor. * * @param array{url: string}&array $repoConfig The repository configuration * @param IOInterface $io The IO instance * @param Config $config The composer configuration * @param HttpDownloader $httpDownloader Remote Filesystem, injectable for mocking * @param ProcessExecutor $process Process instance, injectable for mocking */ public final function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, ProcessExecutor $process) { if (Filesystem::isLocalPath($repoConfig['url'])) { $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']); } $this->url = $repoConfig['url']; $this->originUrl = $repoConfig['url']; $this->repoConfig = $repoConfig; $this->io = $io; $this->config = $config; $this->httpDownloader = $httpDownloader; $this->process = $process; } /** * Returns whether or not the given $identifier should be cached or not. */ protected function shouldCache(string $identifier) : bool { return $this->cache && Preg::isMatch('{^[a-f0-9]{40}$}iD', $identifier); } /** * @inheritDoc */ public function getComposerInformation(string $identifier) : ?array { if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && ($res = $this->cache->read($identifier))) { return $this->infoCache[$identifier] = JsonFile::parseJson($res); } $composer = $this->getBaseComposerInformation($identifier); if ($this->shouldCache($identifier)) { $this->cache->write($identifier, JsonFile::encode($composer, 0)); } $this->infoCache[$identifier] = $composer; } return $this->infoCache[$identifier]; } /** * @return array|null */ protected function getBaseComposerInformation(string $identifier) : ?array { $composerFileContent = $this->getFileContent('composer.json', $identifier); if (!$composerFileContent) { return null; } $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json'); if ([] === $composer || !\is_array($composer)) { return null; } if (empty($composer['time']) && null !== ($changeDate = $this->getChangeDate($identifier))) { $composer['time'] = $changeDate->format(\DATE_RFC3339); } return $composer; } /** * @inheritDoc */ public function hasComposerFile(string $identifier) : bool { try { return null !== $this->getComposerInformation($identifier); } catch (TransportException $e) { } return \false; } /** * Get the https or http protocol depending on SSL support. * * Call this only if you know that the server supports both. * * @return string The correct type of protocol */ protected function getScheme() : string { if (\extension_loaded('openssl')) { return 'https'; } return 'http'; } /** * Get the remote content. * * @param string $url The URL of content * * @throws TransportException */ protected function getContents(string $url) : Response { $options = $this->repoConfig['options'] ?? []; return $this->httpDownloader->get($url, $options); } /** * @inheritDoc */ public function cleanup() : void { } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Cache; use Composer\Config; use Composer\Json\JsonFile; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\Util\Url; use Composer\Util\Svn as SvnUtil; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; /** * @author Jordi Boggiano * @author Till Klampaeckel */ class SvnDriver extends \Composer\Repository\Vcs\VcsDriver { /** @var string */ protected $baseUrl; /** @var array Map of tag name to identifier */ protected $tags; /** @var array Map of branch name to identifier */ protected $branches; /** @var ?string */ protected $rootIdentifier; /** @var string|false */ protected $trunkPath = 'trunk'; /** @var string */ protected $branchesPath = 'branches'; /** @var string */ protected $tagsPath = 'tags'; /** @var string */ protected $packagePath = ''; /** @var bool */ protected $cacheCredentials = \true; /** * @var \Composer\Util\Svn */ private $util; /** * @inheritDoc */ public function initialize() : void { $this->url = $this->baseUrl = \rtrim(self::normalizeUrl($this->url), '/'); SvnUtil::cleanEnv(); if (isset($this->repoConfig['trunk-path'])) { $this->trunkPath = $this->repoConfig['trunk-path']; } if (isset($this->repoConfig['branches-path'])) { $this->branchesPath = $this->repoConfig['branches-path']; } if (isset($this->repoConfig['tags-path'])) { $this->tagsPath = $this->repoConfig['tags-path']; } if (\array_key_exists('svn-cache-credentials', $this->repoConfig)) { $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials']; } if (isset($this->repoConfig['package-path'])) { $this->packagePath = '/' . \trim($this->repoConfig['package-path'], '/'); } if (\false !== ($pos = \strrpos($this->url, '/' . $this->trunkPath))) { $this->baseUrl = \substr($this->url, 0, $pos); } $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->baseUrl))); $this->cache->setReadOnly($this->config->get('cache-read-only')); $this->getBranches(); $this->getTags(); } /** * @inheritDoc */ public function getRootIdentifier() : string { return $this->rootIdentifier ?: $this->trunkPath; } /** * @inheritDoc */ public function getUrl() : string { return $this->url; } /** * @inheritDoc */ public function getSource(string $identifier) : array { return ['type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier]; } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { return null; } /** * @inheritDoc */ protected function shouldCache(string $identifier) : bool { return $this->cache && Preg::isMatch('{@\\d+$}', $identifier); } /** * @inheritDoc */ public function getComposerInformation(string $identifier) : ?array { if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && ($res = $this->cache->read($identifier . '.json'))) { // old cache files had '' stored instead of null due to af3783b5f40bae32a23e353eaf0a00c9b8ce82e2, so we make sure here that we always return null or array // and fix outdated invalid cache files if ($res === '""') { $res = 'null'; $this->cache->write($identifier . '.json', \json_encode(null)); } return $this->infoCache[$identifier] = JsonFile::parseJson($res); } try { $composer = $this->getBaseComposerInformation($identifier); } catch (TransportException $e) { $message = $e->getMessage(); if (\stripos($message, 'path not found') === \false && \stripos($message, 'svn: warning: W160013') === \false) { throw $e; } // remember a not-existent composer.json $composer = null; } if ($this->shouldCache($identifier)) { $this->cache->write($identifier . '.json', \json_encode($composer)); } $this->infoCache[$identifier] = $composer; } // old cache files had '' stored instead of null due to af3783b5f40bae32a23e353eaf0a00c9b8ce82e2, so we make sure here that we always return null or array if (!\is_array($this->infoCache[$identifier])) { return null; } return $this->infoCache[$identifier]; } public function getFileContent(string $file, string $identifier) : ?string { $identifier = '/' . \trim($identifier, '/') . '/'; if (Preg::isMatch('{^(.+?)(@\\d+)?/$}', $identifier, $match) && $match[2] !== null) { $path = $match[1]; $rev = $match[2]; } else { $path = $identifier; $rev = ''; } try { $resource = $path . $file; $output = $this->execute(['svn', 'cat'], $this->baseUrl . $resource . $rev); if ('' === \trim($output)) { return null; } } catch (\RuntimeException $e) { throw new TransportException($e->getMessage()); } return $output; } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { $identifier = '/' . \trim($identifier, '/') . '/'; if (Preg::isMatch('{^(.+?)(@\\d+)?/$}', $identifier, $match) && null !== $match[2]) { $path = $match[1]; $rev = $match[2]; } else { $path = $identifier; $rev = ''; } $output = $this->execute(['svn', 'info'], $this->baseUrl . $path . $rev); foreach ($this->process->splitLines($output) as $line) { if ($line !== '' && Preg::isMatchStrictGroups('{^Last Changed Date: ([^(]+)}', $line, $match)) { return new \DateTimeImmutable($match[1], new \DateTimeZone('UTC')); } } return null; } /** * @inheritDoc */ public function getTags() : array { if (null === $this->tags) { $tags = []; if ($this->tagsPath !== \false) { $output = $this->execute(['svn', 'ls', '--verbose'], $this->baseUrl . '/' . $this->tagsPath); if ($output !== '') { $lastRev = 0; foreach ($this->process->splitLines($output) as $line) { $line = \trim($line); if ($line !== '' && Preg::isMatch('{^\\s*(\\S+).*?(\\S+)\\s*$}', $line, $match)) { if ($match[2] === './') { $lastRev = (int) $match[1]; } else { $tags[\rtrim($match[2], '/')] = $this->buildIdentifier('/' . $this->tagsPath . '/' . $match[2], \max($lastRev, (int) $match[1])); } } } } } $this->tags = $tags; } return $this->tags; } /** * @inheritDoc */ public function getBranches() : array { if (null === $this->branches) { $branches = []; if (\false === $this->trunkPath) { $trunkParent = $this->baseUrl . '/'; } else { $trunkParent = $this->baseUrl . '/' . $this->trunkPath; } $output = $this->execute(['svn', 'ls', '--verbose'], $trunkParent); if ($output !== '') { foreach ($this->process->splitLines($output) as $line) { $line = \trim($line); if ($line !== '' && Preg::isMatch('{^\\s*(\\S+).*?(\\S+)\\s*$}', $line, $match)) { if ($match[2] === './') { $branches['trunk'] = $this->buildIdentifier('/' . $this->trunkPath, (int) $match[1]); $this->rootIdentifier = $branches['trunk']; break; } } } } unset($output); if ($this->branchesPath !== \false) { $output = $this->execute(['svn', 'ls', '--verbose'], $this->baseUrl . '/' . $this->branchesPath); if ($output !== '') { $lastRev = 0; foreach ($this->process->splitLines(\trim($output)) as $line) { $line = \trim($line); if ($line !== '' && Preg::isMatch('{^\\s*(\\S+).*?(\\S+)\\s*$}', $line, $match)) { if ($match[2] === './') { $lastRev = (int) $match[1]; } else { $branches[\rtrim($match[2], '/')] = $this->buildIdentifier('/' . $this->branchesPath . '/' . $match[2], \max($lastRev, (int) $match[1])); } } } } } $this->branches = $branches; } return $this->branches; } /** * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { $url = self::normalizeUrl($url); if (Preg::isMatch('#(^svn://|^svn\\+ssh://|svn\\.)#i', $url)) { return \true; } // proceed with deep check for local urls since they are fast to process if (!$deep && !Filesystem::isLocalPath($url)) { return \false; } $process = new ProcessExecutor($io); $exit = $process->execute(['svn', 'info', '--non-interactive', '--', $url], $ignoredOutput); if ($exit === 0) { // This is definitely a Subversion repository. return \true; } // Subversion client 1.7 and older if (\false !== \stripos($process->getErrorOutput(), 'authorization failed:')) { // This is likely a remote Subversion repository that requires // authentication. We will handle actual authentication later. return \true; } // Subversion client 1.8 and newer if (\false !== \stripos($process->getErrorOutput(), 'Authentication failed')) { // This is likely a remote Subversion or newer repository that requires // authentication. We will handle actual authentication later. return \true; } return \false; } /** * An absolute path (leading '/') is converted to a file:// url. */ protected static function normalizeUrl(string $url) : string { $fs = new Filesystem(); if ($fs->isAbsolutePath($url)) { return 'file://' . \strtr($url, '\\', '/'); } return $url; } /** * Execute an SVN command and try to fix up the process with credentials * if necessary. * * @param non-empty-list $command The svn command to run. * @param string $url The SVN URL. * @throws \RuntimeException */ protected function execute(array $command, string $url) : string { if (null === $this->util) { $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process); $this->util->setCacheCredentials($this->cacheCredentials); } try { return $this->util->execute($command, $url); } catch (\RuntimeException $e) { if (null === $this->util->binaryVersion()) { throw new \RuntimeException('Failed to load ' . $this->url . ', svn was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()); } throw new \RuntimeException('Repository ' . $this->url . ' could not be processed, ' . $e->getMessage()); } } /** * Build the identifier respecting "package-path" config option * * @param string $baseDir The path to trunk/branch/tag * @param int $revision The revision mark to add to identifier */ protected function buildIdentifier(string $baseDir, int $revision) : string { return \rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\Cache; use Composer\Pcre\Preg; use Composer\Util\Hg as HgUtils; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\IO\IOInterface; use Composer\Util\Url; /** * @author Per Bernhardt */ class HgDriver extends \Composer\Repository\Vcs\VcsDriver { /** @var array Map of tag name to identifier */ protected $tags; /** @var array Map of branch name to identifier */ protected $branches; /** @var string */ protected $rootIdentifier; /** @var string */ protected $repoDir; /** * @inheritDoc */ public function initialize() : void { if (Filesystem::isLocalPath($this->url)) { $this->repoDir = $this->url; } else { if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) { throw new \RuntimeException('HgDriver requires a usable cache directory, and it looks like you set it to be disabled'); } $cacheDir = $this->config->get('cache-vcs-dir'); $this->repoDir = $cacheDir . '/' . Preg::replace('{[^a-z0-9]}i', '-', Url::sanitize($this->url)) . '/'; $fs = new Filesystem(); $fs->ensureDirectoryExists($cacheDir); if (!\is_writable(\dirname($this->repoDir))) { throw new \RuntimeException('Can not clone ' . $this->url . ' to access package information. The "' . $cacheDir . '" directory is not writable by the current user.'); } // Ensure we are allowed to use this URL by config $this->config->prohibitUrlByConfig($this->url, $this->io); $hgUtils = new HgUtils($this->io, $this->config, $this->process); // update the repo if it is a valid hg repository if (\is_dir($this->repoDir) && 0 === $this->process->execute(['hg', 'summary'], $output, $this->repoDir)) { if (0 !== $this->process->execute(['hg', 'pull'], $output, $this->repoDir)) { $this->io->writeError('Failed to update ' . $this->url . ', package information from this repository may be outdated (' . $this->process->getErrorOutput() . ')'); } } else { // clean up directory and do a fresh clone into it $fs->removeDirectory($this->repoDir); $repoDir = $this->repoDir; $command = static function ($url) use($repoDir) : array { return ['hg', 'clone', '--noupdate', '--', $url, $repoDir]; }; $hgUtils->runCommand($command, $this->url, null); } } $this->getTags(); $this->getBranches(); } /** * @inheritDoc */ public function getRootIdentifier() : string { if (null === $this->rootIdentifier) { $this->process->execute(['hg', 'tip', '--template', '{node}'], $output, $this->repoDir); $output = $this->process->splitLines($output); $this->rootIdentifier = $output[0]; } return $this->rootIdentifier; } /** * @inheritDoc */ public function getUrl() : string { return $this->url; } /** * @inheritDoc */ public function getSource(string $identifier) : array { return ['type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier]; } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { return null; } /** * @inheritDoc */ public function getFileContent(string $file, string $identifier) : ?string { if (isset($identifier[0]) && $identifier[0] === '-') { throw new \RuntimeException('Invalid hg identifier detected. Identifier must not start with a -, given: ' . $identifier); } $resource = ['hg', 'cat', '-r', $identifier, '--', $file]; $this->process->execute($resource, $content, $this->repoDir); if (!\trim($content)) { return null; } return $content; } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { $this->process->execute(['hg', 'log', '--template', '{date|rfc3339date}', '-r', $identifier], $output, $this->repoDir); return new \DateTimeImmutable(\trim($output), new \DateTimeZone('UTC')); } /** * @inheritDoc */ public function getTags() : array { if (null === $this->tags) { $tags = []; $this->process->execute(['hg', 'tags'], $output, $this->repoDir); foreach ($this->process->splitLines($output) as $tag) { if ($tag && Preg::isMatchStrictGroups('(^([^\\s]+)\\s+\\d+:(.*)$)', $tag, $match)) { $tags[$match[1]] = $match[2]; } } unset($tags['tip']); $this->tags = $tags; } return $this->tags; } /** * @inheritDoc */ public function getBranches() : array { if (null === $this->branches) { $branches = []; $bookmarks = []; $this->process->execute(['hg', 'branches'], $output, $this->repoDir); foreach ($this->process->splitLines($output) as $branch) { if ($branch && Preg::isMatchStrictGroups('(^([^\\s]+)\\s+\\d+:([a-f0-9]+))', $branch, $match) && $match[1][0] !== '-') { $branches[$match[1]] = $match[2]; } } $this->process->execute(['hg', 'bookmarks'], $output, $this->repoDir); foreach ($this->process->splitLines($output) as $branch) { if ($branch && Preg::isMatchStrictGroups('(^(?:[\\s*]*)([^\\s]+)\\s+\\d+:(.*)$)', $branch, $match) && $match[1][0] !== '-') { $bookmarks[$match[1]] = $match[2]; } } // Branches will have preference over bookmarks $this->branches = \array_merge($bookmarks, $branches); } return $this->branches; } /** * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { if (Preg::isMatch('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\\.kilnhg.com)#i', $url)) { return \true; } // local filesystem if (Filesystem::isLocalPath($url)) { $url = Filesystem::getPlatformPath($url); if (!\is_dir($url)) { return \false; } $process = new ProcessExecutor($io); // check whether there is a hg repo in that path if ($process->execute(['hg', 'summary'], $output, $url) === 0) { return \true; } } if (!$deep) { return \false; } $process = new ProcessExecutor($io); $exit = $process->execute(['hg', 'identify', '--', $url], $ignored); return $exit === 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\Cache; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Perforce; use Composer\Util\Http\Response; /** * @author Matt Whittom */ class PerforceDriver extends \Composer\Repository\Vcs\VcsDriver { /** @var string */ protected $depot; /** @var string */ protected $branch; /** @var ?Perforce */ protected $perforce = null; /** * @inheritDoc */ public function initialize() : void { $this->depot = $this->repoConfig['depot']; $this->branch = ''; if (!empty($this->repoConfig['branch'])) { $this->branch = $this->repoConfig['branch']; } $this->initPerforce($this->repoConfig); $this->perforce->p4Login(); $this->perforce->checkStream(); $this->perforce->writeP4ClientSpec(); $this->perforce->connectClient(); } /** * @param array $repoConfig */ private function initPerforce(array $repoConfig) : void { if (!empty($this->perforce)) { return; } if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) { throw new \RuntimeException('PerforceDriver requires a usable cache directory, and it looks like you set it to be disabled'); } $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot; $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io); } /** * @inheritDoc */ public function getFileContent(string $file, string $identifier) : ?string { return $this->perforce->getFileContent($file, $identifier); } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { return null; } /** * @inheritDoc */ public function getRootIdentifier() : string { return $this->branch; } /** * @inheritDoc */ public function getBranches() : array { return $this->perforce->getBranches(); } /** * @inheritDoc */ public function getTags() : array { return $this->perforce->getTags(); } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { return null; } /** * @inheritDoc */ public function getSource(string $identifier) : array { return ['type' => 'perforce', 'url' => $this->repoConfig['url'], 'reference' => $identifier, 'p4user' => $this->perforce->getUser()]; } /** * @inheritDoc */ public function getUrl() : string { return $this->url; } /** * @inheritDoc */ public function hasComposerFile(string $identifier) : bool { $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier); return !empty($composerInfo); } /** * @inheritDoc */ public function getContents(string $url) : Response { throw new \BadMethodCallException('Not implemented/used in PerforceDriver'); } /** * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { if ($deep || Preg::isMatch('#\\b(perforce|p4)\\b#i', $url)) { return Perforce::checkServerExists($url, new ProcessExecutor($io)); } return \false; } /** * @inheritDoc */ public function cleanup() : void { $this->perforce->cleanupClientSpec(); $this->perforce = null; } public function getDepot() : string { return $this->depot; } public function getBranch() : string { return $this->branch; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\IO\IOInterface; use Composer\Cache; use Composer\Downloader\TransportException; use Composer\Json\JsonFile; use Composer\Pcre\Preg; use Composer\Util\Bitbucket; use Composer\Util\Http\Response; /** * @author Per Bernhardt */ class GitBitbucketDriver extends \Composer\Repository\Vcs\VcsDriver { /** @var string */ protected $owner; /** @var string */ protected $repository; /** @var bool */ private $hasIssues = \false; /** @var ?string */ private $rootIdentifier; /** @var array Map of tag name to identifier */ private $tags; /** @var array Map of branch name to identifier */ private $branches; /** @var string */ private $branchesUrl = ''; /** @var string */ private $tagsUrl = ''; /** @var string */ private $homeUrl = ''; /** @var string */ private $website = ''; /** @var string */ private $cloneHttpsUrl = ''; /** @var array */ private $repoData; /** * @var ?VcsDriver */ protected $fallbackDriver = null; /** @var string|null if set either git or hg */ private $vcsType; /** * @inheritDoc */ public function initialize() : void { if (!Preg::isMatchStrictGroups('#^https?://bitbucket\\.org/([^/]+)/([^/]+?)(?:\\.git|/?)?$#i', $this->url, $match)) { throw new \InvalidArgumentException(\sprintf('The Bitbucket repository URL %s is invalid. It must be the HTTPS URL of a Bitbucket repository.', $this->url)); } $this->owner = $match[1]; $this->repository = $match[2]; $this->originUrl = 'bitbucket.org'; $this->cache = new Cache($this->io, \implode('/', [$this->config->get('cache-repo-dir'), $this->originUrl, $this->owner, $this->repository])); $this->cache->setReadOnly($this->config->get('cache-read-only')); } /** * @inheritDoc */ public function getUrl() : string { if ($this->fallbackDriver) { return $this->fallbackDriver->getUrl(); } return $this->cloneHttpsUrl; } /** * Attempts to fetch the repository data via the BitBucket API and * sets some parameters which are used in other methods * * @phpstan-impure */ protected function getRepoData() : bool { $resource = \sprintf('https://api.bitbucket.org/2.0/repositories/%s/%s?%s', $this->owner, $this->repository, \http_build_query(['fields' => '-project,-owner'], '', '&')); $repoData = $this->fetchWithOAuthCredentials($resource, \true)->decodeJson(); if ($this->fallbackDriver) { return \false; } $this->parseCloneUrls($repoData['links']['clone']); $this->hasIssues = !empty($repoData['has_issues']); $this->branchesUrl = $repoData['links']['branches']['href']; $this->tagsUrl = $repoData['links']['tags']['href']; $this->homeUrl = $repoData['links']['html']['href']; $this->website = $repoData['website']; $this->vcsType = $repoData['scm']; $this->repoData = $repoData; return \true; } /** * @inheritDoc */ public function getComposerInformation(string $identifier) : ?array { if ($this->fallbackDriver) { return $this->fallbackDriver->getComposerInformation($identifier); } if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && ($res = $this->cache->read($identifier))) { $composer = JsonFile::parseJson($res); } else { $composer = $this->getBaseComposerInformation($identifier); if ($this->shouldCache($identifier)) { $this->cache->write($identifier, \json_encode($composer)); } } if ($composer !== null) { // specials for bitbucket if (isset($composer['support']) && !\is_array($composer['support'])) { $composer['support'] = []; } if (!isset($composer['support']['source'])) { $label = (\array_search($identifier, $this->getTags()) ?: \array_search($identifier, $this->getBranches())) ?: $identifier; if (\array_key_exists($label, $tags = $this->getTags())) { $hash = $tags[$label]; } elseif (\array_key_exists($label, $branches = $this->getBranches())) { $hash = $branches[$label]; } if (!isset($hash)) { $composer['support']['source'] = \sprintf('https://%s/%s/%s/src', $this->originUrl, $this->owner, $this->repository); } else { $composer['support']['source'] = \sprintf('https://%s/%s/%s/src/%s/?at=%s', $this->originUrl, $this->owner, $this->repository, $hash, $label); } } if (!isset($composer['support']['issues']) && $this->hasIssues) { $composer['support']['issues'] = \sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository); } if (!isset($composer['homepage'])) { $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website; } } $this->infoCache[$identifier] = $composer; } return $this->infoCache[$identifier]; } /** * @inheritDoc */ public function getFileContent(string $file, string $identifier) : ?string { if ($this->fallbackDriver) { return $this->fallbackDriver->getFileContent($file, $identifier); } if (\strpos($identifier, '/') !== \false) { $branches = $this->getBranches(); if (isset($branches[$identifier])) { $identifier = $branches[$identifier]; } } $resource = \sprintf('https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s', $this->owner, $this->repository, $identifier, $file); return $this->fetchWithOAuthCredentials($resource)->getBody(); } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { if ($this->fallbackDriver) { return $this->fallbackDriver->getChangeDate($identifier); } if (\strpos($identifier, '/') !== \false) { $branches = $this->getBranches(); if (isset($branches[$identifier])) { $identifier = $branches[$identifier]; } } $resource = \sprintf('https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date', $this->owner, $this->repository, $identifier); $commit = $this->fetchWithOAuthCredentials($resource)->decodeJson(); return new \DateTimeImmutable($commit['date']); } /** * @inheritDoc */ public function getSource(string $identifier) : array { if ($this->fallbackDriver) { return $this->fallbackDriver->getSource($identifier); } return ['type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier]; } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { if ($this->fallbackDriver) { return $this->fallbackDriver->getDist($identifier); } $url = \sprintf('https://bitbucket.org/%s/%s/get/%s.zip', $this->owner, $this->repository, $identifier); return ['type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '']; } /** * @inheritDoc */ public function getTags() : array { if ($this->fallbackDriver) { return $this->fallbackDriver->getTags(); } if (null === $this->tags) { $tags = []; $resource = \sprintf('%s?%s', $this->tagsUrl, \http_build_query(['pagelen' => 100, 'fields' => 'values.name,values.target.hash,next', 'sort' => '-target.date'], '', '&')); $hasNext = \true; while ($hasNext) { $tagsData = $this->fetchWithOAuthCredentials($resource)->decodeJson(); foreach ($tagsData['values'] as $data) { $tags[$data['name']] = $data['target']['hash']; } if (empty($tagsData['next'])) { $hasNext = \false; } else { $resource = $tagsData['next']; } } $this->tags = $tags; } return $this->tags; } /** * @inheritDoc */ public function getBranches() : array { if ($this->fallbackDriver) { return $this->fallbackDriver->getBranches(); } if (null === $this->branches) { $branches = []; $resource = \sprintf('%s?%s', $this->branchesUrl, \http_build_query(['pagelen' => 100, 'fields' => 'values.name,values.target.hash,values.heads,next', 'sort' => '-target.date'], '', '&')); $hasNext = \true; while ($hasNext) { $branchData = $this->fetchWithOAuthCredentials($resource)->decodeJson(); foreach ($branchData['values'] as $data) { $branches[$data['name']] = $data['target']['hash']; } if (empty($branchData['next'])) { $hasNext = \false; } else { $resource = $branchData['next']; } } $this->branches = $branches; } return $this->branches; } /** * Get the remote content. * * @param string $url The URL of content * * @return Response The result * * @phpstan-impure */ protected function fetchWithOAuthCredentials(string $url, bool $fetchingRepoData = \false) : Response { try { return parent::getContents($url); } catch (TransportException $e) { $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->httpDownloader); if (\in_array($e->getCode(), [403, 404], \true) || 401 === $e->getCode() && \strpos($e->getMessage(), 'Could not authenticate against') === 0) { if (!$this->io->hasAuthentication($this->originUrl) && $bitbucketUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } if (!$this->io->isInteractive() && $fetchingRepoData) { $this->attemptCloneFallback(); return new Response(['url' => 'dummy'], 200, [], 'null'); } } throw $e; } } /** * Generate an SSH URL */ protected function generateSshUrl() : string { return 'git@' . $this->originUrl . ':' . $this->owner . '/' . $this->repository . '.git'; } /** * @phpstan-impure * * @return true * @throws \RuntimeException */ protected function attemptCloneFallback() : bool { try { $this->setupFallbackDriver($this->generateSshUrl()); return \true; } catch (\RuntimeException $e) { $this->fallbackDriver = null; $this->io->writeError('Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode' . ' so that you can enter your Bitbucket OAuth consumer credentials'); throw $e; } } protected function setupFallbackDriver(string $url) : void { $this->fallbackDriver = new \Composer\Repository\Vcs\GitDriver(['url' => $url], $this->io, $this->config, $this->httpDownloader, $this->process); $this->fallbackDriver->initialize(); } /** * @param array $cloneLinks */ protected function parseCloneUrls(array $cloneLinks) : void { foreach ($cloneLinks as $cloneLink) { if ($cloneLink['name'] === 'https') { // Format: https://(user@)bitbucket.org/{user}/{repo} // Strip username from URL (only present in clone URL's for private repositories) $this->cloneHttpsUrl = Preg::replace('/https:\\/\\/([^@]+@)?/', 'https://', $cloneLink['href']); } } } /** * @inheritDoc */ public function getRootIdentifier() : string { if ($this->fallbackDriver) { return $this->fallbackDriver->getRootIdentifier(); } if (null === $this->rootIdentifier) { if (!$this->getRepoData()) { if (!$this->fallbackDriver) { throw new \LogicException('A fallback driver should be setup if getRepoData returns false'); } return $this->fallbackDriver->getRootIdentifier(); } if ($this->vcsType !== 'git') { throw new \RuntimeException($this->url . ' does not appear to be a git repository, use ' . $this->cloneHttpsUrl . ' but remember that Bitbucket no longer supports the mercurial repositories. ' . 'https://bitbucket.org/blog/sunsetting-mercurial-support-in-bitbucket'); } $this->rootIdentifier = $this->repoData['mainbranch']['name'] ?? 'master'; } return $this->rootIdentifier; } /** * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { if (!Preg::isMatch('#^https?://bitbucket\\.org/([^/]+)/([^/]+?)(\\.git|/?)?$#i', $url)) { return \false; } if (!\extension_loaded('openssl')) { $io->writeError('Skipping Bitbucket git driver for ' . $url . ' because the OpenSSL PHP extension is missing.', \true, IOInterface::VERBOSE); return \false; } return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\Util\Url; use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; use Composer\Cache; use Composer\Config; /** * @author Jordi Boggiano */ class GitDriver extends \Composer\Repository\Vcs\VcsDriver { /** @var array Map of tag name (can be turned to an int by php if it is a numeric name) to identifier */ protected $tags; /** @var array Map of branch name (can be turned to an int by php if it is a numeric name) to identifier */ protected $branches; /** @var string */ protected $rootIdentifier; /** @var string */ protected $repoDir; /** * @inheritDoc */ public function initialize() : void { if (Filesystem::isLocalPath($this->url)) { $this->url = Preg::replace('{[\\/]\\.git/?$}', '', $this->url); if (!\is_dir($this->url)) { throw new \RuntimeException('Failed to read package information from ' . $this->url . ' as the path does not exist'); } $this->repoDir = $this->url; $cacheUrl = \realpath($this->url); } else { if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) { throw new \RuntimeException('GitDriver requires a usable cache directory, and it looks like you set it to be disabled'); } $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->url)) . '/'; GitUtil::cleanEnv(); $fs = new Filesystem(); $fs->ensureDirectoryExists(\dirname($this->repoDir)); if (!\is_writable(\dirname($this->repoDir))) { throw new \RuntimeException('Can not clone ' . $this->url . ' to access package information. The "' . \dirname($this->repoDir) . '" directory is not writable by the current user.'); } if (Preg::isMatch('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) { throw new \InvalidArgumentException('The source URL ' . $this->url . ' is invalid, ssh URLs should have a port number after ":".' . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.'); } $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs); if (!$gitUtil->syncMirror($this->url, $this->repoDir)) { if (!\is_dir($this->repoDir)) { throw new \RuntimeException('Failed to clone ' . $this->url . ' to read package information from it'); } $this->io->writeError('Failed to update ' . $this->url . ', package information from this repository may be outdated'); } $cacheUrl = $this->url; } $this->getTags(); $this->getBranches(); $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($cacheUrl))); $this->cache->setReadOnly($this->config->get('cache-read-only')); } /** * @inheritDoc */ public function getRootIdentifier() : string { if (null === $this->rootIdentifier) { $this->rootIdentifier = 'master'; $gitUtil = new GitUtil($this->io, $this->config, $this->process, new Filesystem()); if (!Filesystem::isLocalPath($this->url)) { $defaultBranch = $gitUtil->getMirrorDefaultBranch($this->url, $this->repoDir, \false); if ($defaultBranch !== null) { return $this->rootIdentifier = $defaultBranch; } } // select currently checked out branch as default branch $this->process->execute(['git', 'branch', '--no-color'], $output, $this->repoDir); $branches = $this->process->splitLines($output); if (!\in_array('* master', $branches)) { foreach ($branches as $branch) { if ($branch && Preg::isMatchStrictGroups('{^\\* +(\\S+)}', $branch, $match)) { $this->rootIdentifier = $match[1]; break; } } } } return $this->rootIdentifier; } /** * @inheritDoc */ public function getUrl() : string { return $this->url; } /** * @inheritDoc */ public function getSource(string $identifier) : array { return ['type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier]; } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { return null; } /** * @inheritDoc */ public function getFileContent(string $file, string $identifier) : ?string { if (isset($identifier[0]) && $identifier[0] === '-') { throw new \RuntimeException('Invalid git identifier detected. Identifier must not start with a -, given: ' . $identifier); } $this->process->execute(['git', 'show', $identifier . ':' . $file], $content, $this->repoDir); if (\trim($content) === '') { return null; } return $content; } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { $this->process->execute(['git', '-c', 'log.showSignature=false', 'log', '-1', '--format=%at', $identifier], $output, $this->repoDir); return new \DateTimeImmutable('@' . \trim($output), new \DateTimeZone('UTC')); } /** * @inheritDoc */ public function getTags() : array { if (null === $this->tags) { $this->tags = []; $this->process->execute(['git', 'show-ref', '--tags', '--dereference'], $output, $this->repoDir); foreach ($this->process->splitLines($output) as $tag) { if ($tag !== '' && Preg::isMatch('{^([a-f0-9]{40}) refs/tags/(\\S+?)(\\^\\{\\})?$}', $tag, $match)) { $this->tags[$match[2]] = $match[1]; } } } return $this->tags; } /** * @inheritDoc */ public function getBranches() : array { if (null === $this->branches) { $branches = []; $this->process->execute(['git', 'branch', '--no-color', '--no-abbrev', '-v'], $output, $this->repoDir); foreach ($this->process->splitLines($output) as $branch) { if ($branch !== '' && !Preg::isMatch('{^ *[^/]+/HEAD }', $branch)) { if (Preg::isMatchStrictGroups('{^(?:\\* )? *(\\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match) && $match[1][0] !== '-') { $branches[$match[1]] = $match[2]; } } } $this->branches = $branches; } return $this->branches; } /** * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { if (Preg::isMatch('#(^git://|\\.git/?$|git(?:olite)?@|//git\\.|//github.com/)#i', $url)) { return \true; } // local filesystem if (Filesystem::isLocalPath($url)) { $url = Filesystem::getPlatformPath($url); if (!\is_dir($url)) { return \false; } $process = new ProcessExecutor($io); // check whether there is a git repo in that path if ($process->execute(['git', 'tag'], $output, $url) === 0) { return \true; } GitUtil::checkForRepoOwnershipError($process->getErrorOutput(), $url); } if (!$deep) { return \false; } $gitUtil = new GitUtil($io, $config, new ProcessExecutor($io), new Filesystem()); GitUtil::cleanEnv(); try { $gitUtil->runCommands([['git', 'ls-remote', '--heads', '--', '%url%']], $url, \sys_get_temp_dir()); } catch (\RuntimeException $e) { return \false; } return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\Cache; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; use Composer\Util\GitLab; use Composer\Util\Http\Response; /** * Driver for GitLab API, use the Git driver for local checkouts. * * @author Henrik Bjørnskov * @author Jérôme Tamarelle */ class GitLabDriver extends \Composer\Repository\Vcs\VcsDriver { /** * @var string * @phpstan-var 'https'|'http' */ private $scheme; /** @var string */ private $namespace; /** @var string */ private $repository; /** * @var mixed[] Project data returned by GitLab API */ private $project = null; /** * @var array Keeps commits returned by GitLab API as commit id => info */ private $commits = []; /** @var array Map of tag name to identifier */ private $tags; /** @var array Map of branch name to identifier */ private $branches; /** * Git Driver * * @var ?GitDriver */ protected $gitDriver = null; /** * Protocol to force use of for repository URLs. * * @var string One of ssh, http */ protected $protocol; /** * Defaults to true unless we can make sure it is public * * @var bool defines whether the repo is private or not */ private $isPrivate = \true; /** * @var bool true if the origin has a port number or a path component in it */ private $hasNonstandardOrigin = \false; public const URL_REGEX = '#^(?:(?Phttps?)://(?P.+?)(?::(?P[0-9]+))?/|git@(?P[^:]+):)(?P.+)/(?P[^/]+?)(?:\\.git|/)?$#'; /** * Extracts information from the repository url. * * SSH urls use https by default. Set "secure-http": false on the repository config to use http instead. * * @inheritDoc */ public function initialize() : void { if (!Preg::isMatch(self::URL_REGEX, $this->url, $match)) { throw new \InvalidArgumentException(\sprintf('The GitLab repository URL %s is invalid. It must be the HTTP URL of a GitLab project.', $this->url)); } $guessedDomain = $match['domain'] ?? (string) $match['domain2']; $configuredDomains = $this->config->get('gitlab-domains'); $urlParts = \explode('/', $match['parts']); $this->scheme = \in_array($match['scheme'], ['https', 'http'], \true) ? $match['scheme'] : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === \false ? 'http' : 'https'); $origin = self::determineOrigin($configuredDomains, $guessedDomain, $urlParts, $match['port']); if (\false === $origin) { throw new \LogicException('It should not be possible to create a gitlab driver with an unparsable origin URL (' . $this->url . ')'); } $this->originUrl = $origin; if (\is_string($protocol = $this->config->get('gitlab-protocol'))) { // https treated as a synonym for http. if (!\in_array($protocol, ['git', 'http', 'https'], \true)) { throw new \RuntimeException('gitlab-protocol must be one of git, http.'); } $this->protocol = $protocol === 'git' ? 'ssh' : 'http'; } if (\false !== \strpos($this->originUrl, ':') || \false !== \strpos($this->originUrl, '/')) { $this->hasNonstandardOrigin = \true; } $this->namespace = \implode('/', $urlParts); $this->repository = Preg::replace('#(\\.git)$#', '', $match['repo']); $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir') . '/' . $this->originUrl . '/' . $this->namespace . '/' . $this->repository); $this->cache->setReadOnly($this->config->get('cache-read-only')); $this->fetchProject(); } /** * Updates the HttpDownloader instance. * Mainly useful for tests. * * @internal */ public function setHttpDownloader(HttpDownloader $httpDownloader) : void { $this->httpDownloader = $httpDownloader; } /** * @inheritDoc */ public function getComposerInformation(string $identifier) : ?array { if ($this->gitDriver) { return $this->gitDriver->getComposerInformation($identifier); } if (!isset($this->infoCache[$identifier])) { if ($this->shouldCache($identifier) && ($res = $this->cache->read($identifier))) { $composer = JsonFile::parseJson($res); } else { $composer = $this->getBaseComposerInformation($identifier); if ($this->shouldCache($identifier)) { $this->cache->write($identifier, \json_encode($composer)); } } if (null !== $composer) { // specials for gitlab (this data is only available if authentication is provided) if (isset($composer['support']) && !\is_array($composer['support'])) { $composer['support'] = []; } if (!isset($composer['support']['source']) && isset($this->project['web_url'])) { $label = (\array_search($identifier, $this->getTags(), \true) ?: \array_search($identifier, $this->getBranches(), \true)) ?: $identifier; $composer['support']['source'] = \sprintf('%s/-/tree/%s', $this->project['web_url'], $label); } if (!isset($composer['support']['issues']) && !empty($this->project['issues_enabled']) && isset($this->project['web_url'])) { $composer['support']['issues'] = \sprintf('%s/-/issues', $this->project['web_url']); } if (!isset($composer['abandoned']) && !empty($this->project['archived'])) { $composer['abandoned'] = \true; } } $this->infoCache[$identifier] = $composer; } return $this->infoCache[$identifier]; } /** * @inheritDoc */ public function getFileContent(string $file, string $identifier) : ?string { if ($this->gitDriver) { return $this->gitDriver->getFileContent($file, $identifier); } // Convert the root identifier to a cacheable commit id if (!Preg::isMatch('{[a-f0-9]{40}}i', $identifier)) { $branches = $this->getBranches(); if (isset($branches[$identifier])) { $identifier = $branches[$identifier]; } } $resource = $this->getApiUrl() . '/repository/files/' . $this->urlEncodeAll($file) . '/raw?ref=' . $identifier; try { $content = $this->getContents($resource)->getBody(); } catch (TransportException $e) { if ($e->getCode() !== 404) { throw $e; } return null; } return $content; } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { if ($this->gitDriver) { return $this->gitDriver->getChangeDate($identifier); } if (isset($this->commits[$identifier])) { return new \DateTimeImmutable($this->commits[$identifier]['committed_date']); } return null; } public function getRepositoryUrl() : string { if ($this->protocol) { return $this->project["{$this->protocol}_url_to_repo"]; } return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo']; } /** * @inheritDoc */ public function getUrl() : string { if ($this->gitDriver) { return $this->gitDriver->getUrl(); } return $this->project['web_url']; } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { $url = $this->getApiUrl() . '/repository/archive.zip?sha=' . $identifier; return ['type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '']; } /** * @inheritDoc */ public function getSource(string $identifier) : array { if ($this->gitDriver) { return $this->gitDriver->getSource($identifier); } return ['type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier]; } /** * @inheritDoc */ public function getRootIdentifier() : string { if ($this->gitDriver) { return $this->gitDriver->getRootIdentifier(); } return $this->project['default_branch']; } /** * @inheritDoc */ public function getBranches() : array { if ($this->gitDriver) { return $this->gitDriver->getBranches(); } if (null === $this->branches) { $this->branches = $this->getReferences('branches'); } return $this->branches; } /** * @inheritDoc */ public function getTags() : array { if ($this->gitDriver) { return $this->gitDriver->getTags(); } if (null === $this->tags) { $this->tags = $this->getReferences('tags'); } return $this->tags; } /** * @return string Base URL for GitLab API v3 */ public function getApiUrl() : string { return $this->scheme . '://' . $this->originUrl . '/api/v4/projects/' . $this->urlEncodeAll($this->namespace) . '%2F' . $this->urlEncodeAll($this->repository); } /** * Urlencode all non alphanumeric characters. rawurlencode() can not be used as it does not encode `.` */ private function urlEncodeAll(string $string) : string { $encoded = ''; for ($i = 0; isset($string[$i]); $i++) { $character = $string[$i]; if (!\ctype_alnum($character) && !\in_array($character, ['-', '_'], \true)) { $character = '%' . \sprintf('%02X', \ord($character)); } $encoded .= $character; } return $encoded; } /** * @return string[] where keys are named references like tags or branches and the value a sha */ protected function getReferences(string $type) : array { $perPage = 100; $resource = $this->getApiUrl() . '/repository/' . $type . '?per_page=' . $perPage; $references = []; do { $response = $this->getContents($resource); $data = $response->decodeJson(); foreach ($data as $datum) { $references[$datum['name']] = $datum['commit']['id']; // Keep the last commit date of a reference to avoid // unnecessary API call when retrieving the composer file. $this->commits[$datum['commit']['id']] = $datum['commit']; } if (\count($data) >= $perPage) { $resource = $this->getNextPage($response); } else { $resource = \false; } } while ($resource); return $references; } protected function fetchProject() : void { if (!\is_null($this->project)) { return; } // we need to fetch the default branch from the api $resource = $this->getApiUrl(); $this->project = $this->getContents($resource, \true)->decodeJson(); if (isset($this->project['visibility'])) { $this->isPrivate = $this->project['visibility'] !== 'public'; } else { // client is not authenticated, therefore repository has to be public $this->isPrivate = \false; } } /** * @phpstan-impure * * @return true * @throws \RuntimeException */ protected function attemptCloneFallback() : bool { if ($this->isPrivate === \false) { $url = $this->generatePublicUrl(); } else { $url = $this->generateSshUrl(); } try { // If this repository may be private and we // cannot ask for authentication credentials (because we // are not interactive) then we fallback to GitDriver. $this->setupGitDriver($url); return \true; } catch (\RuntimeException $e) { $this->gitDriver = null; $this->io->writeError('Failed to clone the ' . $url . ' repository, try running in interactive mode so that you can enter your credentials'); throw $e; } } /** * Generate an SSH URL */ protected function generateSshUrl() : string { if ($this->hasNonstandardOrigin) { return 'ssh://git@' . $this->originUrl . '/' . $this->namespace . '/' . $this->repository . '.git'; } return 'git@' . $this->originUrl . ':' . $this->namespace . '/' . $this->repository . '.git'; } protected function generatePublicUrl() : string { return $this->scheme . '://' . $this->originUrl . '/' . $this->namespace . '/' . $this->repository . '.git'; } protected function setupGitDriver(string $url) : void { $this->gitDriver = new \Composer\Repository\Vcs\GitDriver(['url' => $url], $this->io, $this->config, $this->httpDownloader, $this->process); $this->gitDriver->initialize(); } /** * @inheritDoc */ protected function getContents(string $url, bool $fetchingRepoData = \false) : Response { try { $response = parent::getContents($url); if ($fetchingRepoData) { $json = $response->decodeJson(); // Accessing the API with a token with Guest (10) access will return // more data than unauthenticated access but no default_branch data // accessing files via the API will then also fail if (!isset($json['default_branch']) && isset($json['permissions'])) { $this->isPrivate = $json['visibility'] !== 'public'; $moreThanGuestAccess = \false; // Check both access levels (e.g. project, group) // - value will be null if no access is set // - value will be array with key access_level if set foreach ($json['permissions'] as $permission) { if ($permission && $permission['access_level'] > 10) { $moreThanGuestAccess = \true; } } if (!$moreThanGuestAccess) { $this->io->writeError('GitLab token with Guest only access detected'); $this->attemptCloneFallback(); return new Response(['url' => 'dummy'], 200, [], 'null'); } } // force auth as the unauthenticated version of the API is broken if (!isset($json['default_branch'])) { // GitLab allows you to disable the repository inside a project to use a project only for issues and wiki if (isset($json['repository_access_level']) && $json['repository_access_level'] === 'disabled') { throw new TransportException('The GitLab repository is disabled in the project', 400); } if (!empty($json['id'])) { $this->isPrivate = \false; } throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401); } } return $response; } catch (TransportException $e) { $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->httpDownloader); switch ($e->getCode()) { case 401: case 404: // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404 if (!$fetchingRepoData) { throw $e; } if ($gitLabUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } if ($gitLabUtil->isOAuthExpired($this->originUrl) && $gitLabUtil->authorizeOAuthRefresh($this->scheme, $this->originUrl)) { return parent::getContents($url); } if (!$this->io->isInteractive()) { $this->attemptCloneFallback(); return new Response(['url' => 'dummy'], 200, [], 'null'); } $this->io->writeError('Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . ''); $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (' . $this->url . ')'); return parent::getContents($url); case 403: if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) { return parent::getContents($url); } if (!$this->io->isInteractive() && $fetchingRepoData) { $this->attemptCloneFallback(); return new Response(['url' => 'dummy'], 200, [], 'null'); } throw $e; default: throw $e; } } } /** * Uses the config `gitlab-domains` to see if the driver supports the url for the * repository given. * * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { if (!Preg::isMatch(self::URL_REGEX, $url, $match)) { return \false; } $scheme = $match['scheme']; $guessedDomain = $match['domain'] ?? (string) $match['domain2']; $urlParts = \explode('/', $match['parts']); if (\false === self::determineOrigin($config->get('gitlab-domains'), $guessedDomain, $urlParts, $match['port'])) { return \false; } if ('https' === $scheme && !\extension_loaded('openssl')) { $io->writeError('Skipping GitLab driver for ' . $url . ' because the OpenSSL PHP extension is missing.', \true, IOInterface::VERBOSE); return \false; } return \true; } /** * Gives back the loaded /projects// result * * @return mixed[]|null */ public function getRepoData() : ?array { $this->fetchProject(); return $this->project; } protected function getNextPage(Response $response) : ?string { $header = $response->getHeader('link'); $links = \explode(',', $header); foreach ($links as $link) { if (Preg::isMatchStrictGroups('{<(.+?)>; *rel="next"}', $link, $match)) { return $match[1]; } } return null; } /** * @param array $configuredDomains * @param array $urlParts * @param string $portNumber * * @return string|false */ private static function determineOrigin(array $configuredDomains, string $guessedDomain, array &$urlParts, ?string $portNumber) { $guessedDomain = \strtolower($guessedDomain); if (\in_array($guessedDomain, $configuredDomains) || null !== $portNumber && \in_array($guessedDomain . ':' . $portNumber, $configuredDomains)) { if (null !== $portNumber) { return $guessedDomain . ':' . $portNumber; } return $guessedDomain; } if (null !== $portNumber) { $guessedDomain .= ':' . $portNumber; } while (null !== ($part = \array_shift($urlParts))) { $guessedDomain .= '/' . $part; if (\in_array($guessedDomain, $configuredDomains) || null !== $portNumber && \in_array(Preg::replace('{:\\d+}', '', $guessedDomain), $configuredDomains)) { return $guessedDomain; } } return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\IO\IOInterface; /** * @author Jordi Boggiano * @internal */ interface VcsDriverInterface { /** * Initializes the driver (git clone, svn checkout, fetch info etc) */ public function initialize() : void; /** * Return the composer.json file information * * @param string $identifier Any identifier to a specific branch/tag/commit * @return mixed[]|null Array containing all infos from the composer.json file, or null to denote that no file was present */ public function getComposerInformation(string $identifier) : ?array; /** * Return the content of $file or null if the file does not exist. */ public function getFileContent(string $file, string $identifier) : ?string; /** * Get the changedate for $identifier. */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable; /** * Return the root identifier (trunk, master, default/tip ..) * * @return string Identifier */ public function getRootIdentifier() : string; /** * Return list of branches in the repository * * @return array Branch names as keys, identifiers as values */ public function getBranches() : array; /** * Return list of tags in the repository * * @return array Tag names as keys, identifiers as values */ public function getTags() : array; /** * @param string $identifier Any identifier to a specific branch/tag/commit * * @return array{type: string, url: string, reference: string, shasum: string}|null */ public function getDist(string $identifier) : ?array; /** * @param string $identifier Any identifier to a specific branch/tag/commit * * @return array{type: string, url: string, reference: string} */ public function getSource(string $identifier) : array; /** * Return the URL of the repository */ public function getUrl() : string; /** * Return true if the repository has a composer file for a given identifier, * false otherwise. * * @param string $identifier Any identifier to a specific branch/tag/commit * @return bool Whether the repository has a composer file for a given identifier. */ public function hasComposerFile(string $identifier) : bool; /** * Performs any cleanup necessary as the driver is not longer needed */ public function cleanup() : void; /** * Checks if this driver can handle a given url * * @param IOInterface $io IO instance * @param Config $config current $config * @param string $url URL to validate/check * @param bool $deep unless true, only shallow checks (url matching typically) should be done */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository\Vcs; use Composer\Cache; use Composer\Config; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\IO\IOInterface; /** * @author BohwaZ */ class FossilDriver extends \Composer\Repository\Vcs\VcsDriver { /** @var array Map of tag name to identifier */ protected $tags; /** @var array Map of branch name to identifier */ protected $branches; /** @var ?string */ protected $rootIdentifier = null; /** @var ?string */ protected $repoFile = null; /** @var string */ protected $checkoutDir; /** * @inheritDoc */ public function initialize() : void { // Make sure fossil is installed and reachable. $this->checkFossil(); // Ensure we are allowed to use this URL by config. $this->config->prohibitUrlByConfig($this->url, $this->io); // Only if url points to a locally accessible directory, assume it's the checkout directory. // Otherwise, it should be something fossil can clone from. if (Filesystem::isLocalPath($this->url) && \is_dir($this->url)) { $this->checkoutDir = $this->url; } else { if (!Cache::isUsable($this->config->get('cache-repo-dir')) || !Cache::isUsable($this->config->get('cache-vcs-dir'))) { throw new \RuntimeException('FossilDriver requires a usable cache directory, and it looks like you set it to be disabled'); } $localName = Preg::replace('{[^a-z0-9]}i', '-', $this->url); $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil'; $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/'; $this->updateLocalRepo(); } $this->getTags(); $this->getBranches(); } /** * Check that fossil can be invoked via command line. */ protected function checkFossil() : void { if (0 !== $this->process->execute(['fossil', 'version'], $ignoredOutput)) { throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput()); } } /** * Clone or update existing local fossil repository. */ protected function updateLocalRepo() : void { \assert($this->repoFile !== null); $fs = new Filesystem(); $fs->ensureDirectoryExists($this->checkoutDir); if (!\is_writable(\dirname($this->checkoutDir))) { throw new \RuntimeException('Can not clone ' . $this->url . ' to access package information. The "' . $this->checkoutDir . '" directory is not writable by the current user.'); } // update the repo if it is a valid fossil repository if (\is_file($this->repoFile) && \is_dir($this->checkoutDir) && 0 === $this->process->execute(['fossil', 'info'], $output, $this->checkoutDir)) { if (0 !== $this->process->execute(['fossil', 'pull'], $output, $this->checkoutDir)) { $this->io->writeError('Failed to update ' . $this->url . ', package information from this repository may be outdated (' . $this->process->getErrorOutput() . ')'); } } else { // clean up directory and do a fresh clone into it $fs->removeDirectory($this->checkoutDir); $fs->remove($this->repoFile); $fs->ensureDirectoryExists($this->checkoutDir); if (0 !== $this->process->execute(['fossil', 'clone', '--', $this->url, $this->repoFile], $output)) { $output = $this->process->getErrorOutput(); throw new \RuntimeException('Failed to clone ' . $this->url . ' to repository ' . $this->repoFile . "\n\n" . $output); } if (0 !== $this->process->execute(['fossil', 'open', '--nested', '--', $this->repoFile], $output, $this->checkoutDir)) { $output = $this->process->getErrorOutput(); throw new \RuntimeException('Failed to open repository ' . $this->repoFile . ' in ' . $this->checkoutDir . "\n\n" . $output); } } } /** * @inheritDoc */ public function getRootIdentifier() : string { if (null === $this->rootIdentifier) { $this->rootIdentifier = 'trunk'; } return $this->rootIdentifier; } /** * @inheritDoc */ public function getUrl() : string { return $this->url; } /** * @inheritDoc */ public function getSource(string $identifier) : array { return ['type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier]; } /** * @inheritDoc */ public function getDist(string $identifier) : ?array { return null; } /** * @inheritDoc */ public function getFileContent(string $file, string $identifier) : ?string { $this->process->execute(['fossil', 'cat', '-r', $identifier, '--', $file], $content, $this->checkoutDir); if ('' === \trim($content)) { return null; } return $content; } /** * @inheritDoc */ public function getChangeDate(string $identifier) : ?\DateTimeImmutable { $this->process->execute(['fossil', 'finfo', '-b', '-n', '1', 'composer.json'], $output, $this->checkoutDir); [, $date] = \explode(' ', \trim($output), 3); return new \DateTimeImmutable($date, new \DateTimeZone('UTC')); } /** * @inheritDoc */ public function getTags() : array { if (null === $this->tags) { $tags = []; $this->process->execute(['fossil', 'tag', 'list'], $output, $this->checkoutDir); foreach ($this->process->splitLines($output) as $tag) { $tags[$tag] = $tag; } $this->tags = $tags; } return $this->tags; } /** * @inheritDoc */ public function getBranches() : array { if (null === $this->branches) { $branches = []; $this->process->execute(['fossil', 'branch', 'list'], $output, $this->checkoutDir); foreach ($this->process->splitLines($output) as $branch) { $branch = \trim(Preg::replace('/^\\*/', '', \trim($branch))); $branches[$branch] = $branch; } $this->branches = $branches; } return $this->branches; } /** * @inheritDoc */ public static function supports(IOInterface $io, Config $config, string $url, bool $deep = \false) : bool { if (Preg::isMatch('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\\.com|fossil\\.))#i', $url)) { return \true; } if (Preg::isMatch('!/fossil/|\\.fossil!', $url)) { return \true; } // local filesystem if (Filesystem::isLocalPath($url)) { $url = Filesystem::getPlatformPath($url); if (!\is_dir($url)) { return \false; } $process = new ProcessExecutor($io); // check whether there is a fossil repo in that path if ($process->execute(['fossil', 'info'], $output, $url) === 0) { return \true; } } return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Config; use Composer\EventDispatcher\EventDispatcher; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\Util\Url; use Composer\Util\Git as GitUtil; /** * This repository allows installing local packages that are not necessarily under their own VCS. * * The local packages will be symlinked when possible, else they will be copied. * * @code * "require": { * "/": "*" * }, * "repositories": [ * { * "type": "path", * "url": "../../relative/path/to/package/" * }, * { * "type": "path", * "url": "/absolute/path/to/package/" * }, * { * "type": "path", * "url": "/absolute/path/to/several/packages/*" * }, * { * "type": "path", * "url": "../../relative/path/to/package/", * "options": { * "symlink": false * } * }, * { * "type": "path", * "url": "../../relative/path/to/package/", * "options": { * "reference": "none" * } * }, * ] * @endcode * * @author Samuel Roze * @author Johann Reinke */ class PathRepository extends \Composer\Repository\ArrayRepository implements \Composer\Repository\ConfigurableRepositoryInterface { /** * @var ArrayLoader */ private $loader; /** * @var VersionGuesser */ private $versionGuesser; /** * @var string */ private $url; /** * @var mixed[] * @phpstan-var array{url: string, options?: array{symlink?: bool, reference?: string, relative?: bool, versions?: array}} */ private $repoConfig; /** * @var ProcessExecutor */ private $process; /** * @var array{symlink?: bool, reference?: string, relative?: bool, versions?: array} */ private $options; /** * Initializes path repository. * * @param array{url?: string, options?: array{symlink?: bool, reference?: string, relative?: bool, versions?: array}} $repoConfig */ public function __construct(array $repoConfig, IOInterface $io, Config $config, ?HttpDownloader $httpDownloader = null, ?EventDispatcher $dispatcher = null, ?ProcessExecutor $process = null) { if (!isset($repoConfig['url'])) { throw new \RuntimeException('You must specify the `url` configuration for the path repository'); } $this->loader = new ArrayLoader(null, \true); $this->url = Platform::expandPath($repoConfig['url']); $this->process = $process ?? new ProcessExecutor($io); $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser(), $io); $this->repoConfig = $repoConfig; $this->options = $repoConfig['options'] ?? []; if (!isset($this->options['relative'])) { $filesystem = new Filesystem(); $this->options['relative'] = !$filesystem->isAbsolutePath($this->url); } parent::__construct(); } public function getRepoName() : string { return 'path repo (' . Url::sanitize($this->repoConfig['url']) . ')'; } public function getRepoConfig() : array { return $this->repoConfig; } /** * Initializes path repository. * * This method will basically read the folder and add the found package. */ protected function initialize() : void { parent::initialize(); $urlMatches = $this->getUrlMatches(); if (empty($urlMatches)) { if (Preg::isMatch('{[*{}]}', $this->url)) { $url = $this->url; while (Preg::isMatch('{[*{}]}', $url)) { $url = \dirname($url); } // the parent directory before any wildcard exists, so we assume it is correctly configured but simply empty if (\is_dir($url)) { return; } } throw new \RuntimeException('The `url` supplied for the path (' . $this->url . ') repository does not exist'); } foreach ($urlMatches as $url) { $path = \realpath($url) . \DIRECTORY_SEPARATOR; $composerFilePath = $path . 'composer.json'; if (!\file_exists($composerFilePath)) { continue; } $json = \file_get_contents($composerFilePath); $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = ['type' => 'path', 'url' => $url]; $reference = $this->options['reference'] ?? 'auto'; if ('none' === $reference) { $package['dist']['reference'] = null; } elseif ('config' === $reference || 'auto' === $reference) { $package['dist']['reference'] = \hash('sha1', $json . \serialize($this->options)); } // copy symlink/relative options to transport options $package['transport-options'] = \array_intersect_key($this->options, ['symlink' => \true, 'relative' => \true]); // use the version provided as option if available if (isset($package['name'], $this->options['versions'][$package['name']])) { $package['version'] = $this->options['versions'][$package['name']]; } // carry over the root package version if this path repo is in the same git repository as root package if (!isset($package['version']) && ($rootVersion = Platform::getEnv('COMPOSER_ROOT_VERSION'))) { if (0 === $this->process->execute(['git', 'rev-parse', 'HEAD'], $ref1, $path) && 0 === $this->process->execute(['git', 'rev-parse', 'HEAD'], $ref2) && $ref1 === $ref2) { $package['version'] = $this->versionGuesser->getRootVersionFromEnv(); } } $output = ''; if ('auto' === $reference && \is_dir($path . \DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute(\array_merge(['git', 'log', '-n1', '--pretty=%H'], GitUtil::getNoShowSignatureFlags($this->process)), $output, $path)) { $package['dist']['reference'] = \trim($output); } if (!isset($package['version'])) { $versionData = $this->versionGuesser->guessVersion($package, $path); if (\is_array($versionData) && $versionData['pretty_version']) { // if there is a feature branch detected, we add a second packages with the feature branch version if (!empty($versionData['feature_pretty_version'])) { $package['version'] = $versionData['feature_pretty_version']; $this->addPackage($this->loader->load($package)); } $package['version'] = $versionData['pretty_version']; } else { $package['version'] = 'dev-main'; } } try { $this->addPackage($this->loader->load($package)); } catch (\Exception $e) { throw new \RuntimeException('Failed loading the package in ' . $composerFilePath, 0, $e); } } } /** * Get a list of all (possibly relative) path names matching given url (supports globbing). * * @return string[] */ private function getUrlMatches() : array { $flags = \GLOB_MARK | \GLOB_ONLYDIR; if (\defined('GLOB_BRACE')) { $flags |= \GLOB_BRACE; } elseif (\strpos($this->url, '{') !== \false || \strpos($this->url, '}') !== \false) { throw new \RuntimeException('The operating system does not support GLOB_BRACE which is required for the url ' . $this->url); } // Ensure environment-specific path separators are normalized to URL separators return \array_map(static function ($val) : string { return \rtrim(\str_replace(\DIRECTORY_SEPARATOR, '/', $val), '/'); }, \glob($this->url, $flags)); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; interface VersionCacheInterface { /** * @return mixed[]|null|false Package version data if found, false to indicate the identifier is known but has no package, null for an unknown identifier */ public function getVersionPackage(string $version, string $identifier); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; /** * Provides getCanonicalPackages() to various repository implementations * * @internal */ trait CanonicalPackagesTrait { /** * Get unique packages (at most one package of each name), with aliases resolved and removed. * * @return PackageInterface[] */ public function getCanonicalPackages() { $packages = $this->getPackages(); // get at most one package of each name, preferring non-aliased ones $packagesByName = []; foreach ($packages as $package) { if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) { $packagesByName[$package->getName()] = $package; } } $canonicalPackages = []; // unfold aliased packages foreach ($packagesByName as $package) { while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } $canonicalPackages[] = $package; } return $canonicalPackages; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\PackageInterface; use Composer\Package\BasePackage; use Composer\Pcre\Preg; /** * Filters which packages are seen as canonical on this repo by loadPackages * * @author Jordi Boggiano */ class FilterRepository implements \Composer\Repository\RepositoryInterface, \Composer\Repository\AdvisoryProviderInterface { /** @var ?string */ private $only = null; /** @var ?non-empty-string */ private $exclude = null; /** @var bool */ private $canonical = \true; /** @var RepositoryInterface */ private $repo; /** * @param array{only?: array, exclude?: array, canonical?: bool} $options */ public function __construct(\Composer\Repository\RepositoryInterface $repo, array $options) { if (isset($options['only'])) { if (!\is_array($options['only'])) { throw new \InvalidArgumentException('"only" key for repository ' . $repo->getRepoName() . ' should be an array'); } $this->only = BasePackage::packageNamesToRegexp($options['only']); } if (isset($options['exclude'])) { if (!\is_array($options['exclude'])) { throw new \InvalidArgumentException('"exclude" key for repository ' . $repo->getRepoName() . ' should be an array'); } $this->exclude = BasePackage::packageNamesToRegexp($options['exclude']); } if ($this->exclude && $this->only) { throw new \InvalidArgumentException('Only one of "only" and "exclude" can be specified for repository ' . $repo->getRepoName()); } if (isset($options['canonical'])) { if (!\is_bool($options['canonical'])) { throw new \InvalidArgumentException('"canonical" key for repository ' . $repo->getRepoName() . ' should be a boolean'); } $this->canonical = $options['canonical']; } $this->repo = $repo; } public function getRepoName() : string { return $this->repo->getRepoName(); } /** * Returns the wrapped repositories */ public function getRepository() : \Composer\Repository\RepositoryInterface { return $this->repo; } /** * @inheritDoc */ public function hasPackage(PackageInterface $package) : bool { return $this->repo->hasPackage($package); } /** * @inheritDoc */ public function findPackage($name, $constraint) : ?BasePackage { if (!$this->isAllowed($name)) { return null; } return $this->repo->findPackage($name, $constraint); } /** * @inheritDoc */ public function findPackages($name, $constraint = null) : array { if (!$this->isAllowed($name)) { return []; } return $this->repo->findPackages($name, $constraint); } /** * @inheritDoc */ public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []) : array { foreach ($packageNameMap as $name => $constraint) { if (!$this->isAllowed($name)) { unset($packageNameMap[$name]); } } if (!$packageNameMap) { return ['namesFound' => [], 'packages' => []]; } $result = $this->repo->loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded); if (!$this->canonical) { $result['namesFound'] = []; } return $result; } /** * @inheritDoc */ public function search(string $query, int $mode = 0, ?string $type = null) : array { $result = []; foreach ($this->repo->search($query, $mode, $type) as $package) { if ($this->isAllowed($package['name'])) { $result[] = $package; } } return $result; } /** * @inheritDoc */ public function getPackages() : array { $result = []; foreach ($this->repo->getPackages() as $package) { if ($this->isAllowed($package->getName())) { $result[] = $package; } } return $result; } /** * @inheritDoc */ public function getProviders($packageName) : array { $result = []; foreach ($this->repo->getProviders($packageName) as $name => $provider) { if ($this->isAllowed($provider['name'])) { $result[$name] = $provider; } } return $result; } /** * @inheritDoc */ public function count() : int { if ($this->repo->count() > 0) { return \count($this->getPackages()); } return 0; } public function hasSecurityAdvisories() : bool { if (!$this->repo instanceof \Composer\Repository\AdvisoryProviderInterface) { return \false; } return $this->repo->hasSecurityAdvisories(); } /** * @inheritDoc */ public function getSecurityAdvisories(array $packageConstraintMap, bool $allowPartialAdvisories = \false) : array { if (!$this->repo instanceof \Composer\Repository\AdvisoryProviderInterface) { return ['namesFound' => [], 'advisories' => []]; } foreach ($packageConstraintMap as $name => $constraint) { if (!$this->isAllowed($name)) { unset($packageConstraintMap[$name]); } } return $this->repo->getSecurityAdvisories($packageConstraintMap, $allowPartialAdvisories); } private function isAllowed(string $name) : bool { if (!$this->only && !$this->exclude) { return \true; } if ($this->only) { return Preg::isMatch($this->only, $name); } if ($this->exclude === null) { return \true; } return !Preg::isMatch($this->exclude, $name); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Package\RootPackageInterface; use Composer\Package\Link; /** * Installed repository is a composite of all installed repo types. * * The main use case is tagging a repo as an "installed" repository, and offering a way to get providers/replacers easily. * * Installed repos are LockArrayRepository, InstalledRepositoryInterface, RootPackageRepository and PlatformRepository * * @author Jordi Boggiano */ class InstalledRepository extends \Composer\Repository\CompositeRepository { /** * @param ConstraintInterface|string|null $constraint * * @return BasePackage[] */ public function findPackagesWithReplacersAndProviders(string $name, $constraint = null) : array { $name = \strtolower($name); if (null !== $constraint && !$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } $matches = []; foreach ($this->getRepositories() as $repo) { foreach ($repo->getPackages() as $candidate) { if ($name === $candidate->getName()) { if (null === $constraint || $constraint->matches(new Constraint('==', $candidate->getVersion()))) { $matches[] = $candidate; } continue; } foreach (\array_merge($candidate->getProvides(), $candidate->getReplaces()) as $link) { if ($name === $link->getTarget() && ($constraint === null || $constraint->matches($link->getConstraint()))) { $matches[] = $candidate; continue 2; } } } } return $matches; } /** * Returns a list of links causing the requested needle packages to be installed, as an associative array with the * dependent's name as key, and an array containing in order the PackageInterface and Link describing the relationship * as values. If recursive lookup was requested a third value is returned containing an identically formed array up * to the root package. That third value will be false in case a circular recursion was detected. * * @param string|string[] $needle The package name(s) to inspect. * @param ConstraintInterface|null $constraint Optional constraint to filter by. * @param bool $invert Whether to invert matches to discover reasons for the package *NOT* to be installed. * @param bool $recurse Whether to recursively expand the requirement tree up to the root package. * @param string[] $packagesFound Used internally when recurring * * @return array[] An associative array of arrays as described above. * @phpstan-return array|false}> */ public function getDependents($needle, ?ConstraintInterface $constraint = null, bool $invert = \false, bool $recurse = \true, ?array $packagesFound = null) : array { $needles = \array_map('strtolower', (array) $needle); $results = []; // initialize the array with the needles before any recursion occurs if (null === $packagesFound) { $packagesFound = $needles; } // locate root package for use below $rootPackage = null; foreach ($this->getPackages() as $package) { if ($package instanceof RootPackageInterface) { $rootPackage = $package; break; } } // Loop over all currently installed packages. foreach ($this->getPackages() as $package) { $links = $package->getRequires(); // each loop needs its own "tree" as we want to show the complete dependent set of every needle // without warning all the time about finding circular deps $packagesInTree = $packagesFound; // Replacements are considered valid reasons for a package to be installed during forward resolution if (!$invert) { $links += $package->getReplaces(); // On forward search, check if any replaced package was required and add the replaced // packages to the list of needles. Contrary to the cross-reference link check below, // replaced packages are the target of links. foreach ($package->getReplaces() as $link) { foreach ($needles as $needle) { if ($link->getSource() === $needle) { if ($constraint === null || $link->getConstraint()->matches($constraint) === \true) { // already displayed this node's dependencies, cutting short if (\in_array($link->getTarget(), $packagesInTree)) { $results[] = [$package, $link, \false]; continue; } $packagesInTree[] = $link->getTarget(); $dependents = $recurse ? $this->getDependents($link->getTarget(), null, \false, \true, $packagesInTree) : []; $results[] = [$package, $link, $dependents]; $needles[] = $link->getTarget(); } } } } unset($needle); } // Require-dev is only relevant for the root package if ($package instanceof RootPackageInterface) { $links += $package->getDevRequires(); } // Cross-reference all discovered links to the needles foreach ($links as $link) { foreach ($needles as $needle) { if ($link->getTarget() === $needle) { if ($constraint === null || $link->getConstraint()->matches($constraint) === !$invert) { // already displayed this node's dependencies, cutting short if (\in_array($link->getSource(), $packagesInTree)) { $results[] = [$package, $link, \false]; continue; } $packagesInTree[] = $link->getSource(); $dependents = $recurse ? $this->getDependents($link->getSource(), null, \false, \true, $packagesInTree) : []; $results[] = [$package, $link, $dependents]; } } } } // When inverting, we need to check for conflicts of the needles against installed packages if ($invert && \in_array($package->getName(), $needles, \true)) { foreach ($package->getConflicts() as $link) { foreach ($this->findPackages($link->getTarget()) as $pkg) { $version = new Constraint('=', $pkg->getVersion()); if ($link->getConstraint()->matches($version) === $invert) { $results[] = [$package, $link, \false]; } } } } // List conflicts against X as they may explain why the current version was selected, or explain why it is rejected if the conflict matched when inverting foreach ($package->getConflicts() as $link) { if (\in_array($link->getTarget(), $needles, \true)) { foreach ($this->findPackages($link->getTarget()) as $pkg) { $version = new Constraint('=', $pkg->getVersion()); if ($link->getConstraint()->matches($version) === $invert) { $results[] = [$package, $link, \false]; } } } } // When inverting, we need to check for conflicts of the needles' requirements against installed packages if ($invert && $constraint && \in_array($package->getName(), $needles, \true) && $constraint->matches(new Constraint('=', $package->getVersion()))) { foreach ($package->getRequires() as $link) { if (\Composer\Repository\PlatformRepository::isPlatformPackage($link->getTarget())) { if ($this->findPackage($link->getTarget(), $link->getConstraint())) { continue; } $platformPkg = $this->findPackage($link->getTarget(), '*'); $description = $platformPkg ? 'but ' . $platformPkg->getPrettyVersion() . ' is installed' : 'but it is missing'; $results[] = [$package, new Link($package->getName(), $link->getTarget(), new MatchAllConstraint(), Link::TYPE_REQUIRE, $link->getPrettyConstraint() . ' ' . $description), \false]; continue; } foreach ($this->getPackages() as $pkg) { if (!\in_array($link->getTarget(), $pkg->getNames())) { continue; } $version = new Constraint('=', $pkg->getVersion()); if ($link->getTarget() !== $pkg->getName()) { foreach (\array_merge($pkg->getReplaces(), $pkg->getProvides()) as $prov) { if ($link->getTarget() === $prov->getTarget()) { $version = $prov->getConstraint(); break; } } } if (!$link->getConstraint()->matches($version)) { // if we have a root package (we should but can not guarantee..) we show // the root requires as well to perhaps allow to find an issue there if ($rootPackage) { foreach (\array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) { if (\in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) { $results[] = [$package, $link, \false]; $results[] = [$rootPackage, $rootReq, \false]; continue 3; } } $results[] = [$package, $link, \false]; $results[] = [$rootPackage, new Link($rootPackage->getName(), $link->getTarget(), new MatchAllConstraint(), Link::TYPE_DOES_NOT_REQUIRE, 'but ' . $pkg->getPrettyVersion() . ' is installed'), \false]; } else { // no root so let's just print whatever we found $results[] = [$package, $link, \false]; } } continue 2; } } } } \ksort($results); return $results; } public function getRepoName() : string { return 'installed repo (' . \implode(', ', \array_map(static function ($repo) : string { return $repo->getRepoName(); }, $this->getRepositories())) . ')'; } /** * @inheritDoc */ public function addRepository(\Composer\Repository\RepositoryInterface $repository) : void { if ($repository instanceof \Composer\Repository\LockArrayRepository || $repository instanceof \Composer\Repository\InstalledRepositoryInterface || $repository instanceof \Composer\Repository\RootPackageRepository || $repository instanceof \Composer\Repository\PlatformRepository) { parent::addRepository($repository); return; } throw new \LogicException('An InstalledRepository can not contain a repository of type ' . \get_class($repository) . ' (' . $repository->getRepoName() . ')'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Advisory\PartialSecurityAdvisory; use Composer\Advisory\SecurityAdvisory; /** * Repositories that allow fetching security advisory data * * @author Jordi Boggiano * @internal */ interface AdvisoryProviderInterface { public function hasSecurityAdvisories() : bool; /** * @param array $packageConstraintMap Map of package name to constraint (can be MatchAllConstraint to fetch all advisories) * @return ($allowPartialAdvisories is true ? array{namesFound: string[], advisories: array>} : array{namesFound: string[], advisories: array>}) */ public function getSecurityAdvisories(array $packageConstraintMap, bool $allowPartialAdvisories = \false) : array; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; use Composer\Package\PackageInterface; use Composer\Package\RootAliasPackage; use Composer\Package\RootPackageInterface; use Composer\Package\AliasPackage; use Composer\Package\Dumper\ArrayDumper; use Composer\Installer\InstallationManager; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; /** * Filesystem repository. * * @author Konstantin Kudryashov * @author Jordi Boggiano */ class FilesystemRepository extends \Composer\Repository\WritableArrayRepository { /** @var JsonFile */ protected $file; /** @var bool */ private $dumpVersions; /** @var ?RootPackageInterface */ private $rootPackage; /** @var Filesystem */ private $filesystem; /** @var bool|null */ private $devMode = null; /** * Initializes filesystem repository. * * @param JsonFile $repositoryFile repository json file * @param ?RootPackageInterface $rootPackage Must be provided if $dumpVersions is true */ public function __construct(JsonFile $repositoryFile, bool $dumpVersions = \false, ?RootPackageInterface $rootPackage = null, ?Filesystem $filesystem = null) { parent::__construct(); $this->file = $repositoryFile; $this->dumpVersions = $dumpVersions; $this->rootPackage = $rootPackage; $this->filesystem = $filesystem ?: new Filesystem(); if ($dumpVersions && !$rootPackage) { throw new \InvalidArgumentException('Expected a root package instance if $dumpVersions is true'); } } /** * @return bool|null true if dev requirements were installed, false if --no-dev was used, null if yet unknown */ public function getDevMode() { return $this->devMode; } /** * Initializes repository (reads file, or remote address). */ protected function initialize() { parent::initialize(); if (!$this->file->exists()) { return; } try { $data = $this->file->read(); if (isset($data['packages'])) { $packages = $data['packages']; } else { $packages = $data; } if (isset($data['dev-package-names'])) { $this->setDevPackageNames($data['dev-package-names']); } if (isset($data['dev'])) { $this->devMode = $data['dev']; } if (!\is_array($packages)) { throw new \UnexpectedValueException('Could not parse package list from the repository'); } } catch (\Exception $e) { throw new \Composer\Repository\InvalidRepositoryException('Invalid repository data in ' . $this->file->getPath() . ', packages could not be loaded: [' . \get_class($e) . '] ' . $e->getMessage()); } $loader = new ArrayLoader(null, \true); foreach ($packages as $packageData) { $package = $loader->load($packageData); $this->addPackage($package); } } public function reload() { $this->packages = null; $this->initialize(); } /** * Writes writable repository. */ public function write(bool $devMode, InstallationManager $installationManager) { $data = ['packages' => [], 'dev' => $devMode, 'dev-package-names' => []]; $dumper = new ArrayDumper(); // make sure the directory is created so we can realpath it // as realpath() does some additional normalizations with network paths that normalizePath does not // and we need to find shortest path correctly $repoDir = \dirname($this->file->getPath()); $this->filesystem->ensureDirectoryExists($repoDir); $repoDir = $this->filesystem->normalizePath(\realpath($repoDir)); $installPaths = []; foreach ($this->getCanonicalPackages() as $package) { $pkgArray = $dumper->dump($package); $path = $installationManager->getInstallPath($package); $installPath = null; if ('' !== $path && null !== $path) { $normalizedPath = $this->filesystem->normalizePath($this->filesystem->isAbsolutePath($path) ? $path : Platform::getCwd() . '/' . $path); $installPath = $this->filesystem->findShortestPath($repoDir, $normalizedPath, \true); } $installPaths[$package->getName()] = $installPath; $pkgArray['install-path'] = $installPath; $data['packages'][] = $pkgArray; // only write to the files the names which are really installed, as we receive the full list // of dev package names before they get installed during composer install if (\in_array($package->getName(), $this->devPackageNames, \true)) { $data['dev-package-names'][] = $package->getName(); } } \sort($data['dev-package-names']); \usort($data['packages'], static function ($a, $b) : int { return \strcmp($a['name'], $b['name']); }); $this->file->write($data); if ($this->dumpVersions) { $versions = $this->generateInstalledVersions($installationManager, $installPaths, $devMode, $repoDir); $this->filesystem->filePutContentsIfModified($repoDir . '/installed.php', 'dumpToPhpCode($versions) . ';' . "\n"); $installedVersionsClass = \file_get_contents(__DIR__ . '/../InstalledVersions.php'); // this normally should not happen but during upgrades of Composer when it is installed in the project it is a possibility if ($installedVersionsClass !== \false) { $this->filesystem->filePutContentsIfModified($repoDir . '/InstalledVersions.php', $installedVersionsClass); \Composer\InstalledVersions::reload($versions); } } } /** * As we load the file from vendor dir during bootstrap, we need to make sure it contains only expected code before executing it * * @internal */ public static function safelyLoadInstalledVersions(string $path) : bool { $installedVersionsData = @\file_get_contents($path); $pattern = <<<'REGEX' {(?(DEFINE) (? -? \s*+ \d++ (?:\.\d++)? ) (? true | false | null ) (? (?&string) (?: \s*+ \. \s*+ (?&string))*+ ) (? (?: " (?:[^"\\$]*+ | \\ ["\\0] )* " | ' (?:[^'\\]*+ | \\ ['\\] )* ' ) ) (? array\( \s*+ (?: (?:(?&number)|(?&strings)) \s*+ => \s*+ (?: (?:__DIR__ \s*+ \. \s*+)? (?&strings) | (?&value) ) \s*+, \s*+ )*+ \s*+ \) ) (? (?: (?&number) | (?&boolean) | (?&strings) | (?&array) ) ) ) ^<\?php\s++return\s++(?&array)\s*+;$}ix REGEX; if (\is_string($installedVersionsData) && Preg::isMatch($pattern, \trim($installedVersionsData))) { \Composer\InstalledVersions::reload(eval('?>' . Preg::replace('{=>\\s*+__DIR__\\s*+\\.\\s*+([\'"])}', '=> ' . \var_export(\dirname($path), \true) . ' . $1', $installedVersionsData))); return \true; } return \false; } /** * @param array $array */ private function dumpToPhpCode(array $array = [], int $level = 0) : string { $lines = "array(\n"; $level++; foreach ($array as $key => $value) { $lines .= \str_repeat(' ', $level); $lines .= \is_int($key) ? $key . ' => ' : \var_export($key, \true) . ' => '; if (\is_array($value)) { if (!empty($value)) { $lines .= $this->dumpToPhpCode($value, $level); } else { $lines .= "array(),\n"; } } elseif ($key === 'install_path' && \is_string($value)) { if ($this->filesystem->isAbsolutePath($value)) { $lines .= \var_export($value, \true) . ",\n"; } else { $lines .= "__DIR__ . " . \var_export('/' . $value, \true) . ",\n"; } } elseif (\is_string($value)) { $lines .= \var_export($value, \true) . ",\n"; } elseif (\is_bool($value)) { $lines .= ($value ? 'true' : 'false') . ",\n"; } elseif (\is_null($value)) { $lines .= "null,\n"; } else { throw new \UnexpectedValueException('Unexpected type ' . \gettype($value)); } } $lines .= \str_repeat(' ', $level - 1) . ')' . ($level - 1 === 0 ? '' : ",\n"); return $lines; } /** * @param array $installPaths * * @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} */ private function generateInstalledVersions(InstallationManager $installationManager, array $installPaths, bool $devMode, string $repoDir) : array { $devPackages = \array_flip($this->devPackageNames); $packages = $this->getPackages(); if (null === $this->rootPackage) { throw new \LogicException('It should not be possible to dump packages if no root package is given'); } $packages[] = $rootPackage = $this->rootPackage; while ($rootPackage instanceof RootAliasPackage) { $rootPackage = $rootPackage->getAliasOf(); $packages[] = $rootPackage; } $versions = ['root' => $this->dumpRootPackage($rootPackage, $installPaths, $devMode, $repoDir, $devPackages), 'versions' => []]; // add real installed packages foreach ($packages as $package) { if ($package instanceof AliasPackage) { continue; } $versions['versions'][$package->getName()] = $this->dumpInstalledPackage($package, $installPaths, $repoDir, $devPackages); } // add provided/replaced packages foreach ($packages as $package) { $isDevPackage = isset($devPackages[$package->getName()]); foreach ($package->getReplaces() as $replace) { // exclude platform replaces as when they are really there we can not check for their presence if (\Composer\Repository\PlatformRepository::isPlatformPackage($replace->getTarget())) { continue; } if (!isset($versions['versions'][$replace->getTarget()]['dev_requirement'])) { $versions['versions'][$replace->getTarget()]['dev_requirement'] = $isDevPackage; } elseif (!$isDevPackage) { $versions['versions'][$replace->getTarget()]['dev_requirement'] = \false; } $replaced = $replace->getPrettyConstraint(); if ($replaced === 'self.version') { $replaced = $package->getPrettyVersion(); } if (!isset($versions['versions'][$replace->getTarget()]['replaced']) || !\in_array($replaced, $versions['versions'][$replace->getTarget()]['replaced'], \true)) { $versions['versions'][$replace->getTarget()]['replaced'][] = $replaced; } } foreach ($package->getProvides() as $provide) { // exclude platform provides as when they are really there we can not check for their presence if (\Composer\Repository\PlatformRepository::isPlatformPackage($provide->getTarget())) { continue; } if (!isset($versions['versions'][$provide->getTarget()]['dev_requirement'])) { $versions['versions'][$provide->getTarget()]['dev_requirement'] = $isDevPackage; } elseif (!$isDevPackage) { $versions['versions'][$provide->getTarget()]['dev_requirement'] = \false; } $provided = $provide->getPrettyConstraint(); if ($provided === 'self.version') { $provided = $package->getPrettyVersion(); } if (!isset($versions['versions'][$provide->getTarget()]['provided']) || !\in_array($provided, $versions['versions'][$provide->getTarget()]['provided'], \true)) { $versions['versions'][$provide->getTarget()]['provided'][] = $provided; } } } // add aliases foreach ($packages as $package) { if (!$package instanceof AliasPackage) { continue; } $versions['versions'][$package->getName()]['aliases'][] = $package->getPrettyVersion(); if ($package instanceof RootPackageInterface) { $versions['root']['aliases'][] = $package->getPrettyVersion(); } } \ksort($versions['versions']); \ksort($versions); foreach ($versions['versions'] as $name => $version) { foreach (['aliases', 'replaced', 'provided'] as $key) { if (isset($versions['versions'][$name][$key])) { \sort($versions['versions'][$name][$key], \SORT_NATURAL); } } } return $versions; } /** * @param array $installPaths * @param array $devPackages * @return array{pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev_requirement: bool} */ private function dumpInstalledPackage(PackageInterface $package, array $installPaths, string $repoDir, array $devPackages) : array { $reference = null; if ($package->getInstallationSource()) { $reference = $package->getInstallationSource() === 'source' ? $package->getSourceReference() : $package->getDistReference(); } if (null === $reference) { $reference = ($package->getSourceReference() ?: $package->getDistReference()) ?: null; } if ($package instanceof RootPackageInterface) { $to = $this->filesystem->normalizePath(\realpath(Platform::getCwd())); $installPath = $this->filesystem->findShortestPath($repoDir, $to, \true); } else { $installPath = $installPaths[$package->getName()]; } $data = ['pretty_version' => $package->getPrettyVersion(), 'version' => $package->getVersion(), 'reference' => $reference, 'type' => $package->getType(), 'install_path' => $installPath, 'aliases' => [], 'dev_requirement' => isset($devPackages[$package->getName()])]; return $data; } /** * @param array $installPaths * @param array $devPackages * @return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} */ private function dumpRootPackage(RootPackageInterface $package, array $installPaths, bool $devMode, string $repoDir, array $devPackages) { $data = $this->dumpInstalledPackage($package, $installPaths, $repoDir, $devPackages); return ['name' => $package->getName(), 'pretty_version' => $data['pretty_version'], 'version' => $data['version'], 'reference' => $data['reference'], 'type' => $data['type'], 'install_path' => $data['install_path'], 'aliases' => $data['aliases'], 'dev' => $devMode]; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Installed array repository. * * This is used as an in-memory InstalledRepository mostly for testing purposes * * @author Jordi Boggiano */ class InstalledArrayRepository extends \Composer\Repository\WritableArrayRepository implements \Composer\Repository\InstalledRepositoryInterface { public function getRepoName() : string { return 'installed ' . parent::getRepoName(); } /** * @inheritDoc */ public function isFresh() : bool { // this is not a completely correct implementation but there is no way to // distinguish an empty repo and a newly created one given this is all in-memory return $this->count() === 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Configurable repository interface. * * @author Lukas Homza */ interface ConfigurableRepositoryInterface { /** * @return mixed[] */ public function getRepoConfig(); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Repository; /** * Exception thrown when a package repository is utterly broken * * @author Jordi Boggiano */ class InvalidRepositoryException extends \Exception { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; class PackageSorter { /** * Returns the most recent version of a set of packages * * This is ideally the default branch version, or failing that it will return the package with the highest version * * @template T of PackageInterface * @param array $packages * @return ($packages is non-empty-array ? T : T|null) */ public static function getMostCurrentVersion(array $packages) : ?PackageInterface { if (\count($packages) === 0) { return null; } $highest = \reset($packages); foreach ($packages as $candidate) { if ($candidate->isDefaultBranch()) { return $candidate; } if (\version_compare($highest->getVersion(), $candidate->getVersion(), '<')) { $highest = $candidate; } } return $highest; } /** * Sorts packages by name * * @template T of PackageInterface * @param array $packages * @return array */ public static function sortPackagesAlphabetically(array $packages) : array { \usort($packages, static function (PackageInterface $a, PackageInterface $b) { return $a->getName() <=> $b->getName(); }); return $packages; } /** * Sorts packages by dependency weight * * Packages of equal weight are sorted alphabetically * * @param PackageInterface[] $packages * @param array $weights Pre-set weights for some packages to give them more (negative number) or less (positive) weight offsets * @return PackageInterface[] sorted array */ public static function sortPackages(array $packages, array $weights = []) : array { $usageList = []; foreach ($packages as $package) { $links = $package->getRequires(); if ($package instanceof RootPackageInterface) { $links = \array_merge($links, $package->getDevRequires()); } foreach ($links as $link) { $target = $link->getTarget(); $usageList[$target][] = $package->getName(); } } $computing = []; $computed = []; $computeImportance = static function ($name) use(&$computeImportance, &$computing, &$computed, $usageList, $weights) { // reusing computed importance if (isset($computed[$name])) { return $computed[$name]; } // canceling circular dependency if (isset($computing[$name])) { return 0; } $computing[$name] = \true; $weight = $weights[$name] ?? 0; if (isset($usageList[$name])) { foreach ($usageList[$name] as $user) { $weight -= 1 - $computeImportance($user); } } unset($computing[$name]); $computed[$name] = $weight; return $weight; }; $weightedPackages = []; foreach ($packages as $index => $package) { $name = $package->getName(); $weight = $computeImportance($name); $weightedPackages[] = ['name' => $name, 'weight' => $weight, 'index' => $index]; } \usort($weightedPackages, static function (array $a, array $b) : int { if ($a['weight'] !== $b['weight']) { return $a['weight'] - $b['weight']; } return \strnatcasecmp($a['name'], $b['name']); }); $sortedPackages = []; foreach ($weightedPackages as $pkg) { $sortedPackages[] = $packages[$pkg['index']]; } return $sortedPackages; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Package\Loader\InvalidPackageException; use Composer\Json\JsonValidationException; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Pcre\Preg; use Composer\Spdx\SpdxLicenses; use _ContaoManager\Seld\JsonLint\DuplicateKeyException; use _ContaoManager\Seld\JsonLint\JsonParser; /** * Validates a composer configuration. * * @author Robert Schönthal * @author Jordi Boggiano */ class ConfigValidator { public const CHECK_VERSION = 1; /** @var IOInterface */ private $io; public function __construct(IOInterface $io) { $this->io = $io; } /** * Validates the config, and returns the result. * * @param string $file The path to the file * @param int $arrayLoaderValidationFlags Flags for ArrayLoader validation * @param int $flags Flags for validation * * @return array{list, list, list} a triple containing the errors, publishable errors, and warnings */ public function validate(string $file, int $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL, int $flags = self::CHECK_VERSION) : array { $errors = []; $publishErrors = []; $warnings = []; // validate json schema $laxValid = \false; $manifest = null; try { $json = new JsonFile($file, null, $this->io); $manifest = $json->read(); $json->validateSchema(JsonFile::LAX_SCHEMA); $laxValid = \true; $json->validateSchema(); } catch (JsonValidationException $e) { foreach ($e->getErrors() as $message) { if ($laxValid) { $publishErrors[] = $message; } else { $errors[] = $message; } } } catch (\Exception $e) { $errors[] = $e->getMessage(); return [$errors, $publishErrors, $warnings]; } if (\is_array($manifest)) { $jsonParser = new JsonParser(); try { $jsonParser->parse((string) \file_get_contents($file), JsonParser::DETECT_KEY_CONFLICTS); } catch (DuplicateKeyException $e) { $details = $e->getDetails(); $warnings[] = 'Key ' . $details['key'] . ' is a duplicate in ' . $file . ' at line ' . $details['line']; } } // validate actual data if (empty($manifest['license'])) { $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.'; } else { $licenses = (array) $manifest['license']; // strip proprietary since it's not a valid SPDX identifier, but is accepted by composer foreach ($licenses as $key => $license) { if ('proprietary' === $license) { unset($licenses[$key]); } } $licenseValidator = new SpdxLicenses(); foreach ($licenses as $license) { $spdxLicense = $licenseValidator->getLicenseByIdentifier($license); if ($spdxLicense && $spdxLicense[3]) { if (Preg::isMatch('{^[AL]?GPL-[123](\\.[01])?\\+$}i', $license)) { $warnings[] = \sprintf('License "%s" is a deprecated SPDX license identifier, use "' . \str_replace('+', '', $license) . '-or-later" instead', $license); } elseif (Preg::isMatch('{^[AL]?GPL-[123](\\.[01])?$}i', $license)) { $warnings[] = \sprintf('License "%s" is a deprecated SPDX license identifier, use "' . $license . '-only" or "' . $license . '-or-later" instead', $license); } else { $warnings[] = \sprintf('License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/', $license); } } } } if ($flags & self::CHECK_VERSION && isset($manifest['version'])) { $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.'; } if (!empty($manifest['name']) && Preg::isMatch('{[A-Z]}', $manifest['name'])) { $suggestName = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '_ContaoManager\\1\\3-\\2\\4', $manifest['name']); $suggestName = \strtolower($suggestName); $publishErrors[] = \sprintf('Name "%s" does not match the best practice (e.g. lower-cased/with-dashes). We suggest using "%s" instead. As such you will not be able to submit it to Packagist.', $manifest['name'], $suggestName); } if (!empty($manifest['type']) && $manifest['type'] === 'composer-installer') { $warnings[] = "The package type 'composer-installer' is deprecated. Please distribute your custom installers as plugins from now on. See https://getcomposer.org/doc/articles/plugins.md for plugin documentation."; } // check for require-dev overrides if (isset($manifest['require'], $manifest['require-dev'])) { $requireOverrides = \array_intersect_key($manifest['require'], $manifest['require-dev']); if (!empty($requireOverrides)) { $plural = \count($requireOverrides) > 1 ? 'are' : 'is'; $warnings[] = \implode(', ', \array_keys($requireOverrides)) . " {$plural} required both in require and require-dev, this can lead to unexpected behavior"; } } // check for meaningless provide/replace satisfying requirements foreach (['provide', 'replace'] as $linkType) { if (isset($manifest[$linkType])) { foreach (['require', 'require-dev'] as $requireType) { if (isset($manifest[$requireType])) { foreach ($manifest[$linkType] as $provide => $constraint) { if (isset($manifest[$requireType][$provide])) { $warnings[] = 'The package ' . $provide . ' in ' . $requireType . ' is also listed in ' . $linkType . ' which satisfies the requirement. Remove it from ' . $linkType . ' if you wish to install it.'; } } } } } } // check for commit references $require = $manifest['require'] ?? []; $requireDev = $manifest['require-dev'] ?? []; $packages = \array_merge($require, $requireDev); foreach ($packages as $package => $version) { if (Preg::isMatch('/#/', $version)) { $warnings[] = \sprintf('The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.', $package); } } // report scripts-descriptions for non-existent scripts $scriptsDescriptions = $manifest['scripts-descriptions'] ?? []; $scripts = $manifest['scripts'] ?? []; foreach ($scriptsDescriptions as $scriptName => $scriptDescription) { if (!\array_key_exists($scriptName, $scripts)) { $warnings[] = \sprintf('Description for non-existent script "%s" found in "scripts-descriptions"', $scriptName); } } // report scripts-aliases for non-existent scripts $scriptAliases = $manifest['scripts-aliases'] ?? []; foreach ($scriptAliases as $scriptName => $scriptAlias) { if (!\array_key_exists($scriptName, $scripts)) { $warnings[] = \sprintf('Aliases for non-existent script "%s" found in "scripts-aliases"', $scriptName); } } // check for empty psr-0/psr-4 namespace prefixes if (isset($manifest['autoload']['psr-0'][''])) { $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance"; } if (isset($manifest['autoload']['psr-4'][''])) { $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance"; } $loader = new ValidatingArrayLoader(new ArrayLoader(), \true, null, $arrayLoaderValidationFlags); try { if (!isset($manifest['version'])) { $manifest['version'] = '1.0.0'; } if (!isset($manifest['name'])) { $manifest['name'] = 'dummy/dummy'; } $loader->load($manifest); } catch (InvalidPackageException $e) { $errors = \array_merge($errors, $e->getErrors()); } $warnings = \array_merge($warnings, $loader->getWarnings()); return [$errors, $publishErrors, $warnings]; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; use Composer\Pcre\Preg; /** * @author Jordi Boggiano */ class Git { /** @var string|false|null */ private static $version = \false; /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var ProcessExecutor */ protected $process; /** @var Filesystem */ protected $filesystem; /** @var HttpDownloader */ protected $httpDownloader; public function __construct(IOInterface $io, Config $config, \Composer\Util\ProcessExecutor $process, \Composer\Util\Filesystem $fs) { $this->io = $io; $this->config = $config; $this->process = $process; $this->filesystem = $fs; } /** * @param IOInterface|null $io If present, a warning is output there instead of throwing, so pass this in only for cases where this is a soft failure */ public static function checkForRepoOwnershipError(string $output, string $path, ?IOInterface $io = null) : void { if (\str_contains($output, 'fatal: detected dubious ownership')) { $msg = 'The repository at "' . $path . '" does not have the correct ownership and git refuses to use it:' . \PHP_EOL . \PHP_EOL . $output; if ($io === null) { throw new \RuntimeException($msg); } $io->writeError('' . $msg . ''); } } public function setHttpDownloader(\Composer\Util\HttpDownloader $httpDownloader) : void { $this->httpDownloader = $httpDownloader; } /** * Runs a set of commands using the $url or a variation of it (with auth, ssh, ..) * * Commands should use %url% placeholders for the URL instead of inlining it to allow this function to do its job * %sanitizedUrl% is also automatically replaced by the url without user/pass * * As soon as a single command fails it will halt, so assume the commands are run as && in bash * * @param non-empty-array> $commands * @param mixed $commandOutput the output will be written into this var if passed by ref * if a callable is passed it will be used as output handler */ public function runCommands(array $commands, string $url, ?string $cwd, bool $initialClone = \false, &$commandOutput = null) : void { $callables = []; foreach ($commands as $cmd) { $callables[] = static function (string $url) use($cmd) : array { $map = ['%url%' => $url, '%sanitizedUrl%' => Preg::replace('{://([^@]+?):(.+?)@}', '://', $url)]; return \array_map(static function ($value) use($map) : string { return $map[$value] ?? $value; }, $cmd); }; } // @phpstan-ignore method.deprecated $this->runCommand($callables, $url, $cwd, $initialClone, $commandOutput); } /** * @param callable|array $commandCallable * @param mixed $commandOutput the output will be written into this var if passed by ref * if a callable is passed it will be used as output handler * @deprecated Use runCommands with placeholders instead of callbacks for simplicity */ public function runCommand($commandCallable, string $url, ?string $cwd, bool $initialClone = \false, &$commandOutput = null) : void { $commandCallables = \is_callable($commandCallable) ? [$commandCallable] : $commandCallable; $lastCommand = ''; // Ensure we are allowed to use this URL by config $this->config->prohibitUrlByConfig($url, $this->io); if ($initialClone) { $origCwd = $cwd; } $runCommands = function ($url) use($commandCallables, $cwd, &$commandOutput, &$lastCommand, $initialClone) { $collectOutputs = !\is_callable($commandOutput); $outputs = []; $status = 0; $counter = 0; foreach ($commandCallables as $callable) { $lastCommand = $callable($url); if ($collectOutputs) { $outputs[] = ''; $output =& $outputs[\count($outputs) - 1]; } else { $output =& $commandOutput; } $status = $this->process->execute($lastCommand, $output, $initialClone && $counter === 0 ? null : $cwd); if ($status !== 0) { break; } $counter++; } if ($collectOutputs) { $commandOutput = \implode('', $outputs); } return $status; }; if (Preg::isMatch('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) { throw new \InvalidArgumentException('The source URL ' . $url . ' is invalid, ssh URLs should have a port number after ":".' . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.'); } if (!$initialClone) { // capture username/password from URL if there is one and we have no auth configured yet $this->process->execute(['git', 'remote', '-v'], $output, $cwd); if (Preg::isMatchStrictGroups('{^(?:composer|origin)\\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) { $this->io->setAuthentication($match[3], \rawurldecode($match[1]), \rawurldecode($match[2])); } } $protocols = $this->config->get('github-protocols'); // public github, autoswitch protocols // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups if (Preg::isMatchStrictGroups('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) { $messages = []; foreach ($protocols as $protocol) { if ('ssh' === $protocol) { $protoUrl = "git@" . $match[1] . ":" . $match[2]; } else { $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2]; } if (0 === $runCommands($protoUrl)) { return; } $messages[] = '- ' . $protoUrl . "\n" . Preg::replace('#^#m', ' ', $this->process->getErrorOutput()); if ($initialClone && isset($origCwd)) { $this->filesystem->removeDirectory($origCwd); } } // failed to checkout, first check git accessibility if (!$this->io->hasAuthentication($match[1]) && !$this->io->isInteractive()) { $this->throwException('Failed to clone ' . $url . ' via ' . \implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . \implode("\n", $messages), $url); } } // if we have a private github url and the ssh protocol is disabled then we skip it and directly fallback to https $bypassSshForGitHub = Preg::isMatch('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\\.git$}i', $url) && !\in_array('ssh', $protocols, \true); $auth = null; $credentials = []; if ($bypassSshForGitHub || 0 !== $runCommands($url)) { $errorMsg = $this->process->getErrorOutput(); // private github repository without ssh key access, try https with auth // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups if (Preg::isMatchStrictGroups('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\\.git$}i', $url, $match) || Preg::isMatchStrictGroups('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*?)(?:\\.git)?$}i', $url, $match)) { if (!$this->io->hasAuthentication($match[1])) { $gitHubUtil = new \Composer\Util\GitHub($this->io, $this->config, $this->process); $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos'; if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) { $gitHubUtil->authorizeOAuthInteractively($match[1], $message); } } if ($this->io->hasAuthentication($match[1])) { $auth = $this->io->getAuthentication($match[1]); $authUrl = 'https://' . \rawurlencode($auth['username']) . ':' . \rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git'; if (0 === $runCommands($authUrl)) { return; } $credentials = [\rawurlencode($auth['username']), \rawurlencode($auth['password'])]; $errorMsg = $this->process->getErrorOutput(); } // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups } elseif (Preg::isMatchStrictGroups('{^(https?)://(bitbucket\\.org)/(.*?)(?:\\.git)?$}i', $url, $match) || Preg::isMatchStrictGroups('{^(git)@(bitbucket\\.org):(.+?\\.git)$}i', $url, $match)) { //bitbucket either through oauth or app password, with fallback to ssh. $bitbucketUtil = new \Composer\Util\Bitbucket($this->io, $this->config, $this->process, $this->httpDownloader); $domain = $match[2]; $repo_with_git_part = $match[3]; if (!\str_ends_with($repo_with_git_part, '.git')) { $repo_with_git_part .= '.git'; } if (!$this->io->hasAuthentication($domain)) { $message = 'Enter your Bitbucket credentials to access private repos'; if (!$bitbucketUtil->authorizeOAuth($domain) && $this->io->isInteractive()) { $bitbucketUtil->authorizeOAuthInteractively($match[1], $message); $accessToken = $bitbucketUtil->getToken(); $this->io->setAuthentication($domain, 'x-token-auth', $accessToken); } } // First we try to authenticate with whatever we have stored. // This will be successful if there is for example an app // password in there. if ($this->io->hasAuthentication($domain)) { $auth = $this->io->getAuthentication($domain); $authUrl = 'https://' . \rawurlencode($auth['username']) . ':' . \rawurlencode($auth['password']) . '@' . $domain . '/' . $repo_with_git_part; if (0 === $runCommands($authUrl)) { // Well if that succeeded on our first try, let's just // take the win. return; } //We already have an access_token from a previous request. if ($auth['username'] !== 'x-token-auth') { $accessToken = $bitbucketUtil->requestToken($domain, $auth['username'], $auth['password']); if (!empty($accessToken)) { $this->io->setAuthentication($domain, 'x-token-auth', $accessToken); } } } if ($this->io->hasAuthentication($domain)) { $auth = $this->io->getAuthentication($domain); $authUrl = 'https://' . \rawurlencode($auth['username']) . ':' . \rawurlencode($auth['password']) . '@' . $domain . '/' . $repo_with_git_part; if (0 === $runCommands($authUrl)) { return; } $credentials = [\rawurlencode($auth['username']), \rawurlencode($auth['password'])]; } //Falling back to ssh $sshUrl = 'git@bitbucket.org:' . $repo_with_git_part; $this->io->writeError(' No bitbucket authentication configured. Falling back to ssh.'); if (0 === $runCommands($sshUrl)) { return; } $errorMsg = $this->process->getErrorOutput(); } elseif (Preg::isMatchStrictGroups('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?\\.git)$}i', $url, $match) || Preg::isMatchStrictGroups('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}i', $url, $match)) { if ($match[1] === 'git') { $match[1] = 'https'; } if (!$this->io->hasAuthentication($match[2])) { $gitLabUtil = new \Composer\Util\GitLab($this->io, $this->config, $this->process); $message = 'Cloning failed, enter your GitLab credentials to access private repos'; if (!$gitLabUtil->authorizeOAuth($match[2]) && $this->io->isInteractive()) { $gitLabUtil->authorizeOAuthInteractively($match[1], $match[2], $message); } } if ($this->io->hasAuthentication($match[2])) { $auth = $this->io->getAuthentication($match[2]); if ($auth['password'] === 'private-token' || $auth['password'] === 'oauth2' || $auth['password'] === 'gitlab-ci-token') { $authUrl = $match[1] . '://' . \rawurlencode($auth['password']) . ':' . \rawurlencode((string) $auth['username']) . '@' . $match[2] . '/' . $match[3]; // swap username and password } else { $authUrl = $match[1] . '://' . \rawurlencode((string) $auth['username']) . ':' . \rawurlencode((string) $auth['password']) . '@' . $match[2] . '/' . $match[3]; } if (0 === $runCommands($authUrl)) { return; } $credentials = [\rawurlencode((string) $auth['username']), \rawurlencode((string) $auth['password'])]; $errorMsg = $this->process->getErrorOutput(); } } elseif (null !== ($match = $this->getAuthenticationFailure($url))) { // private non-github/gitlab/bitbucket repo that failed to authenticate if (\str_contains($match[2], '@')) { [$authParts, $match[2]] = \explode('@', $match[2], 2); } $storeAuth = \false; if ($this->io->hasAuthentication($match[2])) { $auth = $this->io->getAuthentication($match[2]); } elseif ($this->io->isInteractive()) { $defaultUsername = null; if (isset($authParts) && $authParts !== '') { if (\str_contains($authParts, ':')) { [$defaultUsername] = \explode(':', $authParts, 2); } else { $defaultUsername = $authParts; } } $this->io->writeError(' Authentication required (' . $match[2] . '):'); $this->io->writeError('' . \trim($errorMsg) . '', \true, IOInterface::VERBOSE); $auth = ['username' => $this->io->ask(' Username: ', $defaultUsername), 'password' => $this->io->askAndHideAnswer(' Password: ')]; $storeAuth = $this->config->get('store-auths'); } if (null !== $auth) { $authUrl = $match[1] . \rawurlencode((string) $auth['username']) . ':' . \rawurlencode((string) $auth['password']) . '@' . $match[2] . $match[3]; if (0 === $runCommands($authUrl)) { $this->io->setAuthentication($match[2], $auth['username'], $auth['password']); $authHelper = new \Composer\Util\AuthHelper($this->io, $this->config); $authHelper->storeAuth($match[2], $storeAuth); return; } $credentials = [\rawurlencode((string) $auth['username']), \rawurlencode((string) $auth['password'])]; $errorMsg = $this->process->getErrorOutput(); } } if ($initialClone && isset($origCwd)) { $this->filesystem->removeDirectory($origCwd); } $lastCommand = \implode(' ', $lastCommand); if (\count($credentials) > 0) { $lastCommand = $this->maskCredentials($lastCommand, $credentials); $errorMsg = $this->maskCredentials($errorMsg, $credentials); } $this->throwException('Failed to execute ' . $lastCommand . "\n\n" . $errorMsg, $url); } } public function syncMirror(string $url, string $dir) : bool { if ((bool) \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK') && \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK') !== 'prime') { $this->io->writeError('Aborting git mirror sync of ' . $url . ' as network is disabled'); return \false; } // update the repo if it is a valid git repository if (\is_dir($dir) && 0 === $this->process->execute(['git', 'rev-parse', '--git-dir'], $output, $dir) && \trim($output) === '.') { try { $commands = [['git', 'remote', 'set-url', 'origin', '--', '%url%'], ['git', 'remote', 'update', '--prune', 'origin'], ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%'], ['git', 'gc', '--auto']]; $this->runCommands($commands, $url, $dir); } catch (\Exception $e) { $this->io->writeError('Sync mirror failed: ' . $e->getMessage() . '', \true, IOInterface::DEBUG); return \false; } return \true; } self::checkForRepoOwnershipError($this->process->getErrorOutput(), $dir); // clean up directory and do a fresh clone into it $this->filesystem->removeDirectory($dir); $this->runCommands([['git', 'clone', '--mirror', '--', '%url%', $dir]], $url, $dir, \true); return \true; } public function fetchRefOrSyncMirror(string $url, string $dir, string $ref, ?string $prettyVersion = null) : bool { if ($this->checkRefIsInMirror($dir, $ref)) { if (Preg::isMatch('{^[a-f0-9]{40}$}', $ref) && $prettyVersion !== null) { $branch = Preg::replace('{(?:^dev-|(?:\\.x)?-dev$)}i', '', $prettyVersion); $branches = null; $tags = null; if (0 === $this->process->execute(['git', 'branch'], $output, $dir)) { $branches = $output; } if (0 === $this->process->execute(['git', 'tag'], $output, $dir)) { $tags = $output; } // if the pretty version cannot be found as a branch (nor branch with 'v' in front of the branch as it may have been stripped when generating pretty name), // nor as a tag, then we sync the mirror as otherwise it will likely fail during install. // this can occur if a git tag gets created *after* the reference is already put into the cache, as the ref check above will then not sync the new tags // see https://github.com/composer/composer/discussions/11002 if (null !== $branches && !Preg::isMatch('{^[\\s*]*v?' . \preg_quote($branch) . '$}m', $branches) && null !== $tags && !Preg::isMatch('{^[\\s*]*' . \preg_quote($branch) . '$}m', $tags)) { $this->syncMirror($url, $dir); } } return \true; } if ($this->syncMirror($url, $dir)) { return $this->checkRefIsInMirror($dir, $ref); } return \false; } public static function getNoShowSignatureFlag(\Composer\Util\ProcessExecutor $process) : string { $gitVersion = self::getVersion($process); if ($gitVersion && \version_compare($gitVersion, '2.10.0-rc0', '>=')) { return ' --no-show-signature'; } return ''; } /** * @return list */ public static function getNoShowSignatureFlags(\Composer\Util\ProcessExecutor $process) : array { $flags = static::getNoShowSignatureFlag($process); if ('' === $flags) { return []; } return \explode(' ', \substr($flags, 1)); } private function checkRefIsInMirror(string $dir, string $ref) : bool { if (\is_dir($dir) && 0 === $this->process->execute(['git', 'rev-parse', '--git-dir'], $output, $dir) && \trim($output) === '.') { $exitCode = $this->process->execute(['git', 'rev-parse', '--quiet', '--verify', $ref . '^{commit}'], $ignoredOutput, $dir); if ($exitCode === 0) { return \true; } } self::checkForRepoOwnershipError($this->process->getErrorOutput(), $dir); return \false; } /** * @return array|null */ private function getAuthenticationFailure(string $url) : ?array { if (!Preg::isMatchStrictGroups('{^(https?://)([^/]+)(.*)$}i', $url, $match)) { return null; } $authFailures = ['fatal: Authentication failed', 'remote error: Invalid username or password.', 'error: 401 Unauthorized', 'fatal: unable to access', 'fatal: could not read Username']; $errorOutput = $this->process->getErrorOutput(); foreach ($authFailures as $authFailure) { if (\strpos($errorOutput, $authFailure) !== \false) { return $match; } } return null; } public function getMirrorDefaultBranch(string $url, string $dir, bool $isLocalPathRepository) : ?string { if ((bool) \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK')) { return null; } try { if ($isLocalPathRepository) { $this->process->execute(['git', 'remote', 'show', 'origin'], $output, $dir); } else { $commands = [['git', 'remote', 'set-url', 'origin', '--', '%url%'], ['git', 'remote', 'show', 'origin'], ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%']]; $this->runCommands($commands, $url, $dir, \false, $output); } $lines = $this->process->splitLines($output); foreach ($lines as $line) { if (Preg::isMatch('{^\\s*HEAD branch:\\s(.+)\\s*$}m', $line, $matches)) { return $matches[1]; } } } catch (\Exception $e) { $this->io->writeError('Failed to fetch root identifier from remote: ' . $e->getMessage() . '', \true, IOInterface::DEBUG); } return null; } public static function cleanEnv() : void { // added in git 1.7.1, prevents prompting the user for username/password if (\Composer\Util\Platform::getEnv('GIT_ASKPASS') !== 'echo') { \Composer\Util\Platform::putEnv('GIT_ASKPASS', 'echo'); } // clean up rogue git env vars in case this is running in a git hook if (\Composer\Util\Platform::getEnv('GIT_DIR')) { \Composer\Util\Platform::clearEnv('GIT_DIR'); } if (\Composer\Util\Platform::getEnv('GIT_WORK_TREE')) { \Composer\Util\Platform::clearEnv('GIT_WORK_TREE'); } // Run processes with predictable LANGUAGE if (\Composer\Util\Platform::getEnv('LANGUAGE') !== 'C') { \Composer\Util\Platform::putEnv('LANGUAGE', 'C'); } // clean up env for OSX, see https://github.com/composer/composer/issues/2146#issuecomment-35478940 \Composer\Util\Platform::clearEnv('DYLD_LIBRARY_PATH'); } /** * @return non-empty-string */ public static function getGitHubDomainsRegex(Config $config) : string { return '(' . \implode('|', \array_map('preg_quote', $config->get('github-domains'))) . ')'; } /** * @return non-empty-string */ public static function getGitLabDomainsRegex(Config $config) : string { return '(' . \implode('|', \array_map('preg_quote', $config->get('gitlab-domains'))) . ')'; } /** * @param non-empty-string $message * * @return never */ private function throwException($message, string $url) : void { // git might delete a directory when it fails and php will not know \clearstatcache(); if (0 !== $this->process->execute(['git', '--version'], $ignoredOutput)) { throw new \RuntimeException(\Composer\Util\Url::sanitize('Failed to clone ' . $url . ', git was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput())); } throw new \RuntimeException(\Composer\Util\Url::sanitize($message)); } /** * Retrieves the current git version. * * @return string|null The git version number, if present. */ public static function getVersion(\Composer\Util\ProcessExecutor $process) : ?string { if (\false === self::$version) { self::$version = null; if (0 === $process->execute(['git', '--version'], $output) && Preg::isMatch('/^git version (\\d+(?:\\.\\d+)+)/m', $output, $matches)) { self::$version = $matches[1]; } } return self::$version; } /** * @param string[] $credentials */ private function maskCredentials(string $error, array $credentials) : string { $maskedCredentials = []; foreach ($credentials as $credential) { if (\in_array($credential, ['private-token', 'x-token-auth', 'oauth2', 'gitlab-ci-token', 'x-oauth-basic'])) { $maskedCredentials[] = $credential; } elseif (\strlen($credential) > 6) { $maskedCredentials[] = \substr($credential, 0, 3) . '...' . \substr($credential, -3); } elseif (\strlen($credential) > 3) { $maskedCredentials[] = \substr($credential, 0, 3) . '...'; } else { $maskedCredentials[] = 'XXX'; } } return \str_replace($credentials, $maskedCredentials, $error); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; use Composer\Pcre\Preg; /** * @author Till Klampaeckel * @author Jordi Boggiano */ class Svn { private const MAX_QTY_AUTH_TRIES = 5; /** * @var ?array{username: string, password: string} */ protected $credentials; /** * @var bool */ protected $hasAuth; /** * @var \Composer\IO\IOInterface */ protected $io; /** * @var string */ protected $url; /** * @var bool */ protected $cacheCredentials = \true; /** * @var ProcessExecutor */ protected $process; /** * @var int */ protected $qtyAuthTries = 0; /** * @var \Composer\Config */ protected $config; /** * @var string|null */ private static $version; /** * @param ProcessExecutor $process */ public function __construct(string $url, IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null) { $this->url = $url; $this->io = $io; $this->config = $config; $this->process = $process ?: new \Composer\Util\ProcessExecutor($io); } public static function cleanEnv() : void { // clean up env for OSX, see https://github.com/composer/composer/issues/2146#issuecomment-35478940 \Composer\Util\Platform::clearEnv('DYLD_LIBRARY_PATH'); } /** * Execute an SVN remote command and try to fix up the process with credentials * if necessary. * * @param non-empty-list $command SVN command to run * @param string $url SVN url * @param ?string $cwd Working directory * @param ?string $path Target for a checkout * @param bool $verbose Output all output to the user * * @throws \RuntimeException */ public function execute(array $command, string $url, ?string $cwd = null, ?string $path = null, bool $verbose = \false) : string { // Ensure we are allowed to use this URL by config $this->config->prohibitUrlByConfig($url, $this->io); return $this->executeWithAuthRetry($command, $cwd, $url, $path, $verbose); } /** * Execute an SVN local command and try to fix up the process with credentials * if necessary. * * @param non-empty-list $command SVN command to run * @param string $path Path argument passed thru to the command * @param string $cwd Working directory * @param bool $verbose Output all output to the user * * @throws \RuntimeException */ public function executeLocal(array $command, string $path, ?string $cwd = null, bool $verbose = \false) : string { // A local command has no remote url return $this->executeWithAuthRetry($command, $cwd, '', $path, $verbose); } /** * @param non-empty-list $svnCommand */ private function executeWithAuthRetry(array $svnCommand, ?string $cwd, string $url, ?string $path, bool $verbose) : ?string { // Regenerate the command at each try, to use the newly user-provided credentials $command = $this->getCommand($svnCommand, $url, $path); $output = null; $io = $this->io; $handler = static function ($type, $buffer) use(&$output, $io, $verbose) { if ($type !== 'out') { return null; } if (\strpos($buffer, 'Redirecting to URL ') === 0) { return null; } $output .= $buffer; if ($verbose) { $io->writeError($buffer, \false); } }; $status = $this->process->execute($command, $handler, $cwd); if (0 === $status) { return $output; } $errorOutput = $this->process->getErrorOutput(); $fullOutput = \trim(\implode("\n", [$output, $errorOutput])); // the error is not auth-related if (\false === \stripos($fullOutput, 'Could not authenticate to server:') && \false === \stripos($fullOutput, 'authorization failed') && \false === \stripos($fullOutput, 'svn: E170001:') && \false === \stripos($fullOutput, 'svn: E215004:')) { throw new \RuntimeException($fullOutput); } if (!$this->hasAuth()) { $this->doAuthDance(); } // try to authenticate if maximum quantity of tries not reached if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) { // restart the process return $this->executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose); } throw new \RuntimeException('wrong credentials provided (' . $fullOutput . ')'); } public function setCacheCredentials(bool $cacheCredentials) : void { $this->cacheCredentials = $cacheCredentials; } /** * Repositories requests credentials, let's put them in. * * @throws \RuntimeException * @return \Composer\Util\Svn */ protected function doAuthDance() : \Composer\Util\Svn { // cannot ask for credentials in non interactive mode if (!$this->io->isInteractive()) { throw new \RuntimeException('can not ask for authentication in non interactive mode'); } $this->io->writeError("The Subversion server ({$this->url}) requested credentials:"); $this->hasAuth = \true; $this->credentials = ['username' => (string) $this->io->ask("Username: ", ''), 'password' => (string) $this->io->askAndHideAnswer("Password: ")]; $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) "); return $this; } /** * A method to create the svn commands run. * * @param non-empty-list $cmd Usually 'svn ls' or something like that. * @param string $url Repo URL. * @param string $path Target for a checkout * * @return non-empty-list */ protected function getCommand(array $cmd, string $url, ?string $path = null) : array { $cmd = \array_merge($cmd, ['--non-interactive'], $this->getCredentialArgs(), ['--', $url]); if ($path !== null) { $cmd[] = $path; } return $cmd; } /** * Return the credential string for the svn command. * * Adds --no-auth-cache when credentials are present. * * @return list */ protected function getCredentialArgs() : array { if (!$this->hasAuth()) { return []; } return \array_merge($this->getAuthCacheArgs(), ['--username', $this->getUsername(), '--password', $this->getPassword()]); } /** * Get the password for the svn command. Can be empty. * * @throws \LogicException */ protected function getPassword() : string { if ($this->credentials === null) { throw new \LogicException("No svn auth detected."); } return $this->credentials['password']; } /** * Get the username for the svn command. * * @throws \LogicException */ protected function getUsername() : string { if ($this->credentials === null) { throw new \LogicException("No svn auth detected."); } return $this->credentials['username']; } /** * Detect Svn Auth. */ protected function hasAuth() : bool { if (null !== $this->hasAuth) { return $this->hasAuth; } if (\false === $this->createAuthFromConfig()) { $this->createAuthFromUrl(); } return (bool) $this->hasAuth; } /** * Return the no-auth-cache switch. * * @return list */ protected function getAuthCacheArgs() : array { return $this->cacheCredentials ? [] : ['--no-auth-cache']; } /** * Create the auth params from the configuration file. */ private function createAuthFromConfig() : bool { if (!$this->config->has('http-basic')) { return $this->hasAuth = \false; } $authConfig = $this->config->get('http-basic'); $host = \parse_url($this->url, \PHP_URL_HOST); if (isset($authConfig[$host])) { $this->credentials = ['username' => $authConfig[$host]['username'], 'password' => $authConfig[$host]['password']]; return $this->hasAuth = \true; } return $this->hasAuth = \false; } /** * Create the auth params from the url */ private function createAuthFromUrl() : bool { $uri = \parse_url($this->url); if (empty($uri['user'])) { return $this->hasAuth = \false; } $this->credentials = ['username' => $uri['user'], 'password' => !empty($uri['pass']) ? $uri['pass'] : '']; return $this->hasAuth = \true; } /** * Returns the version of the svn binary contained in PATH */ public function binaryVersion() : ?string { if (!self::$version) { if (0 === $this->process->execute(['svn', '--version'], $output)) { if (Preg::isMatch('{(\\d+(?:\\.\\d+)+)}', $output, $match)) { self::$version = $match[1]; } } } return self::$version; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Pcre\Preg; use stdClass; /** * Tests URLs against NO_PROXY patterns */ class NoProxyPattern { /** * @var string[] */ protected $hostNames = []; /** * @var (null|object)[] */ protected $rules = []; /** * @var bool */ protected $noproxy; /** * @param string $pattern NO_PROXY pattern */ public function __construct(string $pattern) { $this->hostNames = Preg::split('{[\\s,]+}', $pattern, -1, \PREG_SPLIT_NO_EMPTY); $this->noproxy = empty($this->hostNames) || '*' === $this->hostNames[0]; } /** * Returns true if a URL matches the NO_PROXY pattern */ public function test(string $url) : bool { if ($this->noproxy) { return \true; } if (!($urlData = $this->getUrlData($url))) { return \false; } foreach ($this->hostNames as $index => $hostName) { if ($this->match($index, $hostName, $urlData)) { return \true; } } return \false; } /** * Returns false is the url cannot be parsed, otherwise a data object * * @return bool|stdClass */ protected function getUrlData(string $url) { if (!($host = \parse_url($url, \PHP_URL_HOST))) { return \false; } $port = \parse_url($url, \PHP_URL_PORT); if (empty($port)) { switch (\parse_url($url, \PHP_URL_SCHEME)) { case 'http': $port = 80; break; case 'https': $port = 443; break; } } $hostName = $host . ($port ? ':' . $port : ''); [$host, $port, $err] = $this->splitHostPort($hostName); if ($err || !$this->ipCheckData($host, $ipdata)) { return \false; } return $this->makeData($host, $port, $ipdata); } /** * Returns true if the url is matched by a rule */ protected function match(int $index, string $hostName, stdClass $url) : bool { if (!($rule = $this->getRule($index, $hostName))) { // Data must have been misformatted return \false; } if ($rule->ipdata) { // Match ipdata first if (!$url->ipdata) { return \false; } if ($rule->ipdata->netmask) { return $this->matchRange($rule->ipdata, $url->ipdata); } $match = $rule->ipdata->ip === $url->ipdata->ip; } else { // Match host and port $haystack = \substr($url->name, -\strlen($rule->name)); $match = \stripos($haystack, $rule->name) === 0; } if ($match && $rule->port) { $match = $rule->port === $url->port; } return $match; } /** * Returns true if the target ip is in the network range */ protected function matchRange(stdClass $network, stdClass $target) : bool { $net = \unpack('C*', $network->ip); $mask = \unpack('C*', $network->netmask); $ip = \unpack('C*', $target->ip); if (\false === $net) { throw new \RuntimeException('Could not parse network IP ' . $network->ip); } if (\false === $mask) { throw new \RuntimeException('Could not parse netmask ' . $network->netmask); } if (\false === $ip) { throw new \RuntimeException('Could not parse target IP ' . $target->ip); } for ($i = 1; $i < 17; ++$i) { if (($net[$i] & $mask[$i]) !== ($ip[$i] & $mask[$i])) { return \false; } } return \true; } /** * Finds or creates rule data for a hostname * * @return null|stdClass Null if the hostname is invalid */ private function getRule(int $index, string $hostName) : ?stdClass { if (\array_key_exists($index, $this->rules)) { return $this->rules[$index]; } $this->rules[$index] = null; [$host, $port, $err] = $this->splitHostPort($hostName); if ($err || !$this->ipCheckData($host, $ipdata, \true)) { return null; } $this->rules[$index] = $this->makeData($host, $port, $ipdata); return $this->rules[$index]; } /** * Creates an object containing IP data if the host is an IP address * * @param null|stdClass $ipdata Set by method if IP address found * @param bool $allowPrefix Whether a CIDR prefix-length is expected * * @return bool False if the host contains invalid data */ private function ipCheckData(string $host, ?stdClass &$ipdata, bool $allowPrefix = \false) : bool { $ipdata = null; $netmask = null; $prefix = null; $modified = \false; // Check for a CIDR prefix-length if (\strpos($host, '/') !== \false) { [$host, $prefix] = \explode('/', $host); if (!$allowPrefix || !$this->validateInt($prefix, 0, 128)) { return \false; } $prefix = (int) $prefix; $modified = \true; } // See if this is an ip address if (!\filter_var($host, \FILTER_VALIDATE_IP)) { return !$modified; } [$ip, $size] = $this->ipGetAddr($host); if ($prefix !== null) { // Check for a valid prefix if ($prefix > $size * 8) { return \false; } [$ip, $netmask] = $this->ipGetNetwork($ip, $size, $prefix); } $ipdata = $this->makeIpData($ip, $size, $netmask); return \true; } /** * Returns an array of the IP in_addr and its byte size * * IPv4 addresses are always mapped to IPv6, which simplifies handling * and comparison. * * @return mixed[] in_addr, size */ private function ipGetAddr(string $host) : array { $ip = \inet_pton($host); $size = \strlen($ip); $mapped = $this->ipMapTo6($ip, $size); return [$mapped, $size]; } /** * Returns the binary network mask mapped to IPv6 * * @param int $prefix CIDR prefix-length * @param int $size Byte size of in_addr */ private function ipGetMask(int $prefix, int $size) : string { $mask = ''; if ($ones = \floor($prefix / 8)) { $mask = \str_repeat(\chr(255), (int) $ones); } if ($remainder = $prefix % 8) { $mask .= \chr(0xff ^ 0xff >> $remainder); } $mask = \str_pad($mask, $size, \chr(0)); return $this->ipMapTo6($mask, $size); } /** * Calculates and returns the network and mask * * @param string $rangeIp IP in_addr * @param int $size Byte size of in_addr * @param int $prefix CIDR prefix-length * * @return string[] network in_addr, binary mask */ private function ipGetNetwork(string $rangeIp, int $size, int $prefix) : array { $netmask = $this->ipGetMask($prefix, $size); // Get the network from the address and mask $mask = \unpack('C*', $netmask); $ip = \unpack('C*', $rangeIp); $net = ''; if (\false === $mask) { throw new \RuntimeException('Could not parse netmask ' . $netmask); } if (\false === $ip) { throw new \RuntimeException('Could not parse range IP ' . $rangeIp); } for ($i = 1; $i < 17; ++$i) { $net .= \chr($ip[$i] & $mask[$i]); } return [$net, $netmask]; } /** * Maps an IPv4 address to IPv6 * * @param string $binary in_addr * @param int $size Byte size of in_addr * * @return string Mapped or existing in_addr */ private function ipMapTo6(string $binary, int $size) : string { if ($size === 4) { $prefix = \str_repeat(\chr(0), 10) . \str_repeat(\chr(255), 2); $binary = $prefix . $binary; } return $binary; } /** * Creates a rule data object */ private function makeData(string $host, int $port, ?stdClass $ipdata) : stdClass { return (object) ['host' => $host, 'name' => '.' . \ltrim($host, '.'), 'port' => $port, 'ipdata' => $ipdata]; } /** * Creates an ip data object * * @param string $ip in_addr * @param int $size Byte size of in_addr * @param null|string $netmask Network mask */ private function makeIpData(string $ip, int $size, ?string $netmask) : stdClass { return (object) ['ip' => $ip, 'size' => $size, 'netmask' => $netmask]; } /** * Splits the hostname into host and port components * * @return mixed[] host, port, if there was error */ private function splitHostPort(string $hostName) : array { // host, port, err $error = ['', '', \true]; $port = 0; $ip6 = ''; // Check for square-bracket notation if ($hostName[0] === '[') { $index = \strpos($hostName, ']'); // The smallest ip6 address is :: if (\false === $index || $index < 3) { return $error; } $ip6 = \substr($hostName, 1, $index - 1); $hostName = \substr($hostName, $index + 1); if (\strpbrk($hostName, '[]') !== \false || \substr_count($hostName, ':') > 1) { return $error; } } if (\substr_count($hostName, ':') === 1) { $index = \strpos($hostName, ':'); $port = \substr($hostName, $index + 1); $hostName = \substr($hostName, 0, $index); if (!$this->validateInt($port, 1, 65535)) { return $error; } $port = (int) $port; } $host = $ip6 . $hostName; return [$host, $port, \false]; } /** * Wrapper around filter_var FILTER_VALIDATE_INT */ private function validateInt(string $int, int $min, int $max) : bool { $options = ['options' => ['min_range' => $min, 'max_range' => $max]]; return \false !== \filter_var($int, \FILTER_VALIDATE_INT, $options); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Pcre\Preg; /** * Composer mirror utilities * * @author Jordi Boggiano */ class ComposerMirror { /** * @param non-empty-string $mirrorUrl * @return non-empty-string */ public static function processUrl(string $mirrorUrl, string $packageName, string $version, ?string $reference, ?string $type, ?string $prettyVersion = null) : string { if ($reference) { $reference = Preg::isMatch('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : \hash('md5', $reference); } $version = \strpos($version, '/') === \false ? $version : \hash('md5', $version); $from = ['%package%', '%version%', '%reference%', '%type%']; $to = [$packageName, $version, $reference, $type]; if (null !== $prettyVersion) { $from[] = '%prettyVersion%'; $to[] = $prettyVersion; } $url = \str_replace($from, $to, $mirrorUrl); \assert($url !== ''); return $url; } /** * @param non-empty-string $mirrorUrl * @return string */ public static function processGitUrl(string $mirrorUrl, string $packageName, string $url, ?string $type) : string { if (Preg::isMatch('#^(?:(?:https?|git)://github\\.com/|git@github\\.com:)([^/]+)/(.+?)(?:\\.git)?$#', $url, $match)) { $url = 'gh-' . $match[1] . '/' . $match[2]; } elseif (Preg::isMatch('#^https://bitbucket\\.org/([^/]+)/(.+?)(?:\\.git)?/?$#', $url, $match)) { $url = 'bb-' . $match[1] . '/' . $match[2]; } else { $url = Preg::replace('{[^a-z0-9_.-]}i', '-', \trim($url, '/')); } return \str_replace(['%package%', '%normalizedUrl%', '%type%'], [$packageName, $url, $type], $mirrorUrl); } /** * @param non-empty-string $mirrorUrl * @return string */ public static function processHgUrl(string $mirrorUrl, string $packageName, string $url, string $type) : string { return self::processGitUrl($mirrorUrl, $packageName, $url, $type); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Package\CompletePackageInterface; use Composer\Package\PackageInterface; class PackageInfo { public static function getViewSourceUrl(PackageInterface $package) : ?string { if ($package instanceof CompletePackageInterface && isset($package->getSupport()['source']) && '' !== $package->getSupport()['source']) { return $package->getSupport()['source']; } return $package->getSourceUrl(); } public static function getViewSourceOrHomepageUrl(PackageInterface $package) : ?string { $url = self::getViewSourceUrl($package) ?? ($package instanceof CompletePackageInterface ? $package->getHomepage() : null); if ($url === '') { return null; } return $url; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; /** * @author Jordi Boggiano */ class AuthHelper { /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var array Map of origins to message displayed */ private $displayedOriginAuthentications = []; /** @var array Map of URLs and whether they already retried with authentication from Bitbucket */ private $bitbucketRetry = []; public function __construct(IOInterface $io, Config $config) { $this->io = $io; $this->config = $config; } /** * @param 'prompt'|bool $storeAuth */ public function storeAuth(string $origin, $storeAuth) : void { $store = \false; $configSource = $this->config->getAuthConfigSource(); if ($storeAuth === \true) { $store = $configSource; } elseif ($storeAuth === 'prompt') { $answer = $this->io->askAndValidate('Do you want to store credentials for ' . $origin . ' in ' . $configSource->getName() . ' ? [Yn] ', static function ($value) : string { $input = \strtolower(\substr(\trim($value), 0, 1)); if (\in_array($input, ['y', 'n'])) { return $input; } throw new \RuntimeException('Please answer (y)es or (n)o'); }, null, 'y'); if ($answer === 'y') { $store = $configSource; } } if ($store) { $store->addConfigSetting('http-basic.' . $origin, $this->io->getAuthentication($origin)); } } /** * @param int $statusCode HTTP status code that triggered this call * @param string|null $reason a message/description explaining why this was called * @param string[] $headers * @param int $retryCount the amount of retries already done on this URL * @return array containing retry (bool) and storeAuth (string|bool) keys, if retry is true the request should be * retried, if storeAuth is true then on a successful retry the authentication should be persisted to auth.json * @phpstan-return array{retry: bool, storeAuth: 'prompt'|bool} */ public function promptAuthIfNeeded(string $url, string $origin, int $statusCode, ?string $reason = null, array $headers = [], int $retryCount = 0) : array { $storeAuth = \false; if (\in_array($origin, $this->config->get('github-domains'), \true)) { $gitHubUtil = new \Composer\Util\GitHub($this->io, $this->config, null); $message = "\n"; $rateLimited = $gitHubUtil->isRateLimited($headers); $requiresSso = $gitHubUtil->requiresSso($headers); if ($requiresSso) { $ssoUrl = $gitHubUtil->getSsoUrl($headers); $message = 'GitHub API token requires SSO authorization. Authorize this token at ' . $ssoUrl . "\n"; $this->io->writeError($message); if (!$this->io->isInteractive()) { throw new TransportException('Could not authenticate against ' . $origin, 403); } $this->io->ask('After authorizing your token, confirm that you would like to retry the request'); return ['retry' => \true, 'storeAuth' => $storeAuth]; } if ($rateLimited) { $rateLimit = $gitHubUtil->getRateLimit($headers); if ($this->io->hasAuthentication($origin)) { $message = 'Review your configured GitHub OAuth token or enter a new one to go over the API rate limit.'; } else { $message = 'Create a GitHub OAuth token to go over the API rate limit.'; } $message = \sprintf('GitHub API limit (%d calls/hr) is exhausted, could not fetch ' . $url . '. ' . $message . ' You can also wait until %s for the rate limit to reset.', $rateLimit['limit'], $rateLimit['reset']) . "\n"; } else { $message .= 'Could not fetch ' . $url . ', please '; if ($this->io->hasAuthentication($origin)) { $message .= 'review your configured GitHub OAuth token or enter a new one to access private repos'; } else { $message .= 'create a GitHub OAuth token to access private repos'; } } if (!$gitHubUtil->authorizeOAuth($origin) && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($origin, $message))) { throw new TransportException('Could not authenticate against ' . $origin, 401); } } elseif (\in_array($origin, $this->config->get('gitlab-domains'), \true)) { $message = "\n" . 'Could not fetch ' . $url . ', enter your ' . $origin . ' credentials ' . ($statusCode === 401 ? 'to access private repos' : 'to go over the API rate limit'); $gitLabUtil = new \Composer\Util\GitLab($this->io, $this->config, null); $auth = null; if ($this->io->hasAuthentication($origin)) { $auth = $this->io->getAuthentication($origin); if (\in_array($auth['password'], ['gitlab-ci-token', 'private-token', 'oauth2'], \true)) { throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode); } } if (!$gitLabUtil->authorizeOAuth($origin) && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively(\parse_url($url, \PHP_URL_SCHEME), $origin, $message))) { throw new TransportException('Could not authenticate against ' . $origin, 401); } if ($auth !== null && $this->io->hasAuthentication($origin)) { if ($auth === $this->io->getAuthentication($origin)) { throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode); } } } elseif ($origin === 'bitbucket.org' || $origin === 'api.bitbucket.org') { $askForOAuthToken = \true; $origin = 'bitbucket.org'; if ($this->io->hasAuthentication($origin)) { $auth = $this->io->getAuthentication($origin); if ($auth['username'] !== 'x-token-auth') { $bitbucketUtil = new \Composer\Util\Bitbucket($this->io, $this->config); $accessToken = $bitbucketUtil->requestToken($origin, $auth['username'], $auth['password']); if (!empty($accessToken)) { $this->io->setAuthentication($origin, 'x-token-auth', $accessToken); $askForOAuthToken = \false; } } elseif (!isset($this->bitbucketRetry[$url])) { // when multiple requests fire at the same time, they will all fail and the first one resets the token to be correct above but then the others // reach the code path and without this fallback they would end up throwing below // see https://github.com/composer/composer/pull/11464 for more details $askForOAuthToken = \false; $this->bitbucketRetry[$url] = \true; } else { throw new TransportException('Could not authenticate against ' . $origin, 401); } } if ($askForOAuthToken) { $message = "\n" . 'Could not fetch ' . $url . ', please create a bitbucket OAuth token to ' . ($statusCode === 401 || $statusCode === 403 ? 'access private repos' : 'go over the API rate limit'); $bitBucketUtil = new \Composer\Util\Bitbucket($this->io, $this->config); if (!$bitBucketUtil->authorizeOAuth($origin) && (!$this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($origin, $message))) { throw new TransportException('Could not authenticate against ' . $origin, 401); } } } else { // 404s are only handled for github if ($statusCode === 404) { return ['retry' => \false, 'storeAuth' => \false]; } // fail if the console is not interactive if (!$this->io->isInteractive()) { if ($statusCode === 401) { $message = "The '" . $url . "' URL required authentication (HTTP 401).\nYou must be using the interactive console to authenticate"; } elseif ($statusCode === 403) { $message = "The '" . $url . "' URL could not be accessed (HTTP 403): " . $reason; } else { $message = "Unknown error code '" . $statusCode . "', reason: " . $reason; } throw new TransportException($message, $statusCode); } // fail if we already have auth if ($this->io->hasAuthentication($origin)) { // if two or more requests are started together for the same host, and the first // received authentication already, we let the others retry before failing them if ($retryCount === 0) { return ['retry' => \true, 'storeAuth' => \false]; } throw new TransportException("Invalid credentials (HTTP {$statusCode}) for '{$url}', aborting.", $statusCode); } $this->io->writeError(' Authentication required (' . $origin . '):'); $username = $this->io->ask(' Username: '); $password = $this->io->askAndHideAnswer(' Password: '); $this->io->setAuthentication($origin, $username, $password); $storeAuth = $this->config->get('store-auths'); } return ['retry' => \true, 'storeAuth' => $storeAuth]; } /** * @param string[] $headers * * @return string[] updated headers array */ public function addAuthenticationHeader(array $headers, string $origin, string $url) : array { if ($this->io->hasAuthentication($origin)) { $authenticationDisplayMessage = null; $auth = $this->io->getAuthentication($origin); if ($auth['password'] === 'bearer') { $headers[] = 'Authorization: Bearer ' . $auth['username']; } elseif ('github.com' === $origin && 'x-oauth-basic' === $auth['password']) { // only add the access_token if it is actually a github API URL if (Preg::isMatch('{^https?://api\\.github\\.com/}', $url)) { $headers[] = 'Authorization: token ' . $auth['username']; $authenticationDisplayMessage = 'Using GitHub token authentication'; } } elseif (\in_array($origin, $this->config->get('gitlab-domains'), \true) && \in_array($auth['password'], ['oauth2', 'private-token', 'gitlab-ci-token'], \true)) { if ($auth['password'] === 'oauth2') { $headers[] = 'Authorization: Bearer ' . $auth['username']; $authenticationDisplayMessage = 'Using GitLab OAuth token authentication'; } else { $headers[] = 'PRIVATE-TOKEN: ' . $auth['username']; $authenticationDisplayMessage = 'Using GitLab private token authentication'; } } elseif ('bitbucket.org' === $origin && $url !== \Composer\Util\Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']) { if (!$this->isPublicBitBucketDownload($url)) { $headers[] = 'Authorization: Bearer ' . $auth['password']; $authenticationDisplayMessage = 'Using Bitbucket OAuth token authentication'; } } else { $authStr = \base64_encode($auth['username'] . ':' . $auth['password']); $headers[] = 'Authorization: Basic ' . $authStr; $authenticationDisplayMessage = 'Using HTTP basic authentication with username "' . $auth['username'] . '"'; } if ($authenticationDisplayMessage && (!isset($this->displayedOriginAuthentications[$origin]) || $this->displayedOriginAuthentications[$origin] !== $authenticationDisplayMessage)) { $this->io->writeError($authenticationDisplayMessage, \true, IOInterface::DEBUG); $this->displayedOriginAuthentications[$origin] = $authenticationDisplayMessage; } } elseif (\in_array($origin, ['api.bitbucket.org', 'api.github.com'], \true)) { return $this->addAuthenticationHeader($headers, \str_replace('api.', '', $origin), $url); } return $headers; } /** * @link https://github.com/composer/composer/issues/5584 * * @param string $urlToBitBucketFile URL to a file at bitbucket.org. * * @return bool Whether the given URL is a public BitBucket download which requires no authentication. */ public function isPublicBitBucketDownload(string $urlToBitBucketFile) : bool { $domain = \parse_url($urlToBitBucketFile, \PHP_URL_HOST); if (\strpos($domain, 'bitbucket.org') === \false) { // Bitbucket downloads are hosted on amazonaws. // We do not need to authenticate there at all return \true; } $path = \parse_url($urlToBitBucketFile, \PHP_URL_PATH); // Path for a public download follows this pattern /{user}/{repo}/downloads/{whatever} // {@link https://blog.bitbucket.org/2009/04/12/new-feature-downloads/} $pathParts = \explode('/', $path); return \count($pathParts) >= 4 && $pathParts[3] === 'downloads'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; /** * @author Andreas Schempp */ class Zip { /** * Gets content of the root composer.json inside a ZIP archive. */ public static function getComposerJson(string $pathToZip) : ?string { if (!\extension_loaded('zip')) { throw new \RuntimeException('The Zip Util requires PHP\'s zip extension'); } $zip = new \ZipArchive(); if ($zip->open($pathToZip) !== \true) { return null; } if (0 === $zip->numFiles) { $zip->close(); return null; } $foundFileIndex = self::locateFile($zip, 'composer.json'); $content = null; $configurationFileName = $zip->getNameIndex($foundFileIndex); $stream = $zip->getStream($configurationFileName); if (\false !== $stream) { $content = \stream_get_contents($stream); } $zip->close(); return $content; } /** * Find a file by name, returning the one that has the shortest path. * * @throws \RuntimeException */ private static function locateFile(\ZipArchive $zip, string $filename) : int { // return root composer.json if it is there and is a file if (\false !== ($index = $zip->locateName($filename)) && $zip->getFromIndex($index) !== \false) { return $index; } $topLevelPaths = []; for ($i = 0; $i < $zip->numFiles; $i++) { $name = $zip->getNameIndex($i); $dirname = \dirname($name); // ignore OSX specific resource fork folder if (\strpos($name, '__MACOSX') !== \false) { continue; } // handle archives with proper TOC if ($dirname === '.') { $topLevelPaths[$name] = \true; if (\count($topLevelPaths) > 1) { throw new \RuntimeException('Archive has more than one top level directories, and no composer.json was found on the top level, so it\'s an invalid archive. Top level paths found were: ' . \implode(',', \array_keys($topLevelPaths))); } continue; } // handle archives which do not have a TOC record for the directory itself if (\false === \strpos($dirname, '\\') && \false === \strpos($dirname, '/')) { $topLevelPaths[$dirname . '/'] = \true; if (\count($topLevelPaths) > 1) { throw new \RuntimeException('Archive has more than one top level directories, and no composer.json was found on the top level, so it\'s an invalid archive. Top level paths found were: ' . \implode(',', \array_keys($topLevelPaths))); } } } if ($topLevelPaths && \false !== ($index = $zip->locateName(\key($topLevelPaths) . $filename)) && $zip->getFromIndex($index) !== \false) { return $index; } throw new \RuntimeException('No composer.json found either at the top level or within the topmost directory'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; /** * Temporarily suppress PHP error reporting, usually warnings and below. * * @author Niels Keurentjes */ class Silencer { /** * @var int[] Unpop stack */ private static $stack = []; /** * Suppresses given mask or errors. * * @param int|null $mask Error levels to suppress, default value NULL indicates all warnings and below. * @return int The old error reporting level. */ public static function suppress(?int $mask = null) : int { if (!isset($mask)) { $mask = \E_WARNING | \E_NOTICE | \E_USER_WARNING | \E_USER_NOTICE | \E_DEPRECATED | \E_USER_DEPRECATED; } $old = \error_reporting(); self::$stack[] = $old; \error_reporting($old & ~$mask); return $old; } /** * Restores a single state. */ public static function restore() : void { if (!empty(self::$stack)) { \error_reporting(\array_pop(self::$stack)); } } /** * Calls a specified function while silencing warnings and below. * * @param callable $callable Function to execute. * @param mixed $parameters Function to execute. * @throws \Exception Any exceptions from the callback are rethrown. * @return mixed Return value of the callback. */ public static function call(callable $callable, ...$parameters) { try { self::suppress(); $result = $callable(...$parameters); self::restore(); return $result; } catch (\Exception $e) { // Use a finally block for this when requirements are raised to PHP 5.5 self::restore(); throw $e; } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Pcre\Preg; use ErrorException; use React\Promise\PromiseInterface; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException; use _ContaoManager\Symfony\Component\Finder\Finder; /** * @author Jordi Boggiano * @author Johannes M. Schmitt */ class Filesystem { /** @var ?ProcessExecutor */ private $processExecutor; public function __construct(?\Composer\Util\ProcessExecutor $executor = null) { $this->processExecutor = $executor; } /** * @return bool */ public function remove(string $file) { if (\is_dir($file)) { return $this->removeDirectory($file); } if (\file_exists($file)) { return $this->unlink($file); } return \false; } /** * Checks if a directory is empty * * @return bool */ public function isDirEmpty(string $dir) { $finder = Finder::create()->ignoreVCS(\false)->ignoreDotFiles(\false)->depth(0)->in($dir); return \count($finder) === 0; } /** * @return void */ public function emptyDirectory(string $dir, bool $ensureDirectoryExists = \true) { if (\is_link($dir) && \file_exists($dir)) { $this->unlink($dir); } if ($ensureDirectoryExists) { $this->ensureDirectoryExists($dir); } if (\is_dir($dir)) { $finder = Finder::create()->ignoreVCS(\false)->ignoreDotFiles(\false)->depth(0)->in($dir); foreach ($finder as $path) { $this->remove((string) $path); } } } /** * Recursively remove a directory * * Uses the process component if proc_open is enabled on the PHP * installation. * * @throws \RuntimeException * @return bool */ public function removeDirectory(string $directory) { $edgeCaseResult = $this->removeEdgeCases($directory); if ($edgeCaseResult !== null) { return $edgeCaseResult; } if (\Composer\Util\Platform::isWindows()) { $cmd = ['rmdir', '/S', '/Q', \Composer\Util\Platform::realpath($directory)]; } else { $cmd = ['rm', '-rf', $directory]; } $result = $this->getProcess()->execute($cmd, $output) === 0; // clear stat cache because external processes aren't tracked by the php stat cache \clearstatcache(); if ($result && !\is_dir($directory)) { return \true; } return $this->removeDirectoryPhp($directory); } /** * Recursively remove a directory asynchronously * * Uses the process component if proc_open is enabled on the PHP * installation. * * @throws \RuntimeException * @return PromiseInterface * @phpstan-return PromiseInterface */ public function removeDirectoryAsync(string $directory) { $edgeCaseResult = $this->removeEdgeCases($directory); if ($edgeCaseResult !== null) { return \React\Promise\resolve($edgeCaseResult); } if (\Composer\Util\Platform::isWindows()) { $cmd = ['rmdir', '/S', '/Q', \Composer\Util\Platform::realpath($directory)]; } else { $cmd = ['rm', '-rf', $directory]; } $promise = $this->getProcess()->executeAsync($cmd); return $promise->then(function ($process) use($directory) { // clear stat cache because external processes aren't tracked by the php stat cache \clearstatcache(); if ($process->isSuccessful()) { if (!\is_dir($directory)) { return \React\Promise\resolve(\true); } } return \React\Promise\resolve($this->removeDirectoryPhp($directory)); }); } /** * @return bool|null Returns null, when no edge case was hit. Otherwise a bool whether removal was successful */ private function removeEdgeCases(string $directory, bool $fallbackToPhp = \true) : ?bool { if ($this->isSymlinkedDirectory($directory)) { return $this->unlinkSymlinkedDirectory($directory); } if ($this->isJunction($directory)) { return $this->removeJunction($directory); } if (\is_link($directory)) { return \unlink($directory); } if (!\is_dir($directory) || !\file_exists($directory)) { return \true; } if (Preg::isMatch('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) { throw new \RuntimeException('Aborting an attempted deletion of ' . $directory . ', this was probably not intended, if it is a real use case please report it.'); } if (!\function_exists('proc_open') && $fallbackToPhp) { return $this->removeDirectoryPhp($directory); } return null; } /** * Recursively delete directory using PHP iterators. * * Uses a CHILD_FIRST RecursiveIteratorIterator to sort files * before directories, creating a single non-recursive loop * to delete files/directories in the correct order. * * @return bool */ public function removeDirectoryPhp(string $directory) { $edgeCaseResult = $this->removeEdgeCases($directory, \false); if ($edgeCaseResult !== null) { return $edgeCaseResult; } try { $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS); } catch (\UnexpectedValueException $e) { // re-try once after clearing the stat cache if it failed as it // sometimes fails without apparent reason, see https://github.com/composer/composer/issues/4009 \clearstatcache(); \usleep(100000); if (!\is_dir($directory)) { return \true; } $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS); } $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST); foreach ($ri as $file) { if ($file->isDir()) { $this->rmdir($file->getPathname()); } else { $this->unlink($file->getPathname()); } } // release locks on the directory, see https://github.com/composer/composer/issues/9945 unset($ri, $it, $file); return $this->rmdir($directory); } /** * @return void */ public function ensureDirectoryExists(string $directory) { if (!\is_dir($directory)) { if (\file_exists($directory)) { throw new \RuntimeException($directory . ' exists and is not a directory.'); } if (\is_link($directory) && !@$this->unlinkImplementation($directory)) { throw new \RuntimeException('Could not delete symbolic link ' . $directory . ': ' . (\error_get_last()['message'] ?? '')); } if (!@\mkdir($directory, 0777, \true)) { $e = new \RuntimeException($directory . ' does not exist and could not be created: ' . (\error_get_last()['message'] ?? '')); // in pathological cases with paths like path/to/broken-symlink/../foo is_dir will fail to detect path/to/foo // but normalizing the ../ away first makes it work so we attempt this just in case, and if it still fails we // report the initial error we had with the original path, and ignore the normalized path exception // see https://github.com/composer/composer/issues/11864 $normalized = $this->normalizePath($directory); if ($normalized !== $directory) { try { $this->ensureDirectoryExists($normalized); return; } catch (\Throwable $ignoredEx) { } } throw $e; } } } /** * Attempts to unlink a file and in case of failure retries after 350ms on windows * * @throws \RuntimeException * @return bool */ public function unlink(string $path) { $unlinked = @$this->unlinkImplementation($path); if (!$unlinked) { // retry after a bit on windows since it tends to be touchy with mass removals if (\Composer\Util\Platform::isWindows()) { \usleep(350000); $unlinked = @$this->unlinkImplementation($path); } if (!$unlinked) { $error = \error_get_last(); $message = 'Could not delete ' . $path . ': ' . ($error['message'] ?? ''); if (\Composer\Util\Platform::isWindows()) { $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed"; } throw new \RuntimeException($message); } } return \true; } /** * Attempts to rmdir a file and in case of failure retries after 350ms on windows * * @throws \RuntimeException * @return bool */ public function rmdir(string $path) { $deleted = @\rmdir($path); if (!$deleted) { // retry after a bit on windows since it tends to be touchy with mass removals if (\Composer\Util\Platform::isWindows()) { \usleep(350000); $deleted = @\rmdir($path); } if (!$deleted) { $error = \error_get_last(); $message = 'Could not delete ' . $path . ': ' . ($error['message'] ?? ''); if (\Composer\Util\Platform::isWindows()) { $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed"; } throw new \RuntimeException($message); } } return \true; } /** * Copy then delete is a non-atomic version of {@link rename}. * * Some systems can't rename and also don't have proc_open, * which requires this solution. * * @return void */ public function copyThenRemove(string $source, string $target) { $this->copy($source, $target); if (!\is_dir($source)) { $this->unlink($source); return; } $this->removeDirectoryPhp($source); } /** * Copies a file or directory from $source to $target. * * @return bool */ public function copy(string $source, string $target) { // refs https://github.com/composer/composer/issues/11864 $target = $this->normalizePath($target); if (!\is_dir($source)) { try { return \copy($source, $target); } catch (ErrorException $e) { // if copy fails we attempt to copy it manually as this can help bypass issues with VirtualBox shared folders // see https://github.com/composer/composer/issues/12057 if (\str_contains($e->getMessage(), 'Bad address')) { $sourceHandle = \fopen($source, 'r'); $targetHandle = \fopen($target, 'w'); if (\false === $sourceHandle || \false === $targetHandle) { throw $e; } while (!\feof($sourceHandle)) { if (\false === \fwrite($targetHandle, (string) \fread($sourceHandle, 1024 * 1024))) { throw $e; } } \fclose($sourceHandle); \fclose($targetHandle); return \true; } throw $e; } } $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS); $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST); $this->ensureDirectoryExists($target); $result = \true; foreach ($ri as $file) { $targetPath = $target . \DIRECTORY_SEPARATOR . $ri->getSubPathname(); if ($file->isDir()) { $this->ensureDirectoryExists($targetPath); } else { $result = $result && \copy($file->getPathname(), $targetPath); } } return $result; } /** * @return void */ public function rename(string $source, string $target) { if (\true === @\rename($source, $target)) { return; } if (!\function_exists('proc_open')) { $this->copyThenRemove($source, $target); return; } if (\Composer\Util\Platform::isWindows()) { // Try to copy & delete - this is a workaround for random "Access denied" errors. $result = $this->getProcess()->execute(['xcopy', $source, $target, '/E', '/I', '/Q', '/Y'], $output); // clear stat cache because external processes aren't tracked by the php stat cache \clearstatcache(); if (0 === $result) { $this->remove($source); return; } } else { // We do not use PHP's "rename" function here since it does not support // the case where $source, and $target are located on different partitions. $result = $this->getProcess()->execute(['mv', $source, $target], $output); // clear stat cache because external processes aren't tracked by the php stat cache \clearstatcache(); if (0 === $result) { return; } } $this->copyThenRemove($source, $target); } /** * Returns the shortest path from $from to $to * * @param bool $directories if true, the source/target are considered to be directories * @param bool $preferRelative if true, relative paths will be preferred even if longer * @throws \InvalidArgumentException * @return string */ public function findShortestPath(string $from, string $to, bool $directories = \false, bool $preferRelative = \false) { if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) { throw new \InvalidArgumentException(\sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to)); } $from = $this->normalizePath($from); $to = $this->normalizePath($to); if ($directories) { $from = \rtrim($from, '/') . '/dummy_file'; } if (\dirname($from) === \dirname($to)) { return './' . \basename($to); } $commonPath = $to; while (\strpos($from . '/', $commonPath . '/') !== 0 && '/' !== $commonPath && !Preg::isMatch('{^[A-Z]:/?$}i', $commonPath)) { $commonPath = \strtr(\dirname($commonPath), '\\', '/'); } // no commonality at all if (0 !== \strpos($from, $commonPath)) { return $to; } $commonPath = \rtrim($commonPath, '/') . '/'; $sourcePathDepth = \substr_count((string) \substr($from, \strlen($commonPath)), '/'); $commonPathCode = \str_repeat('../', $sourcePathDepth); // allow top level /foo & /bar dirs to be addressed relatively as this is common in Docker setups if (!$preferRelative && '/' === $commonPath && $sourcePathDepth > 1) { return $to; } $result = $commonPathCode . \substr($to, \strlen($commonPath)); if (\strlen($result) === 0) { return './'; } return $result; } /** * Returns PHP code that, when executed in $from, will return the path to $to * * @param bool $directories if true, the source/target are considered to be directories * @param bool $preferRelative if true, relative paths will be preferred even if longer * @throws \InvalidArgumentException * @return string */ public function findShortestPathCode(string $from, string $to, bool $directories = \false, bool $staticCode = \false, bool $preferRelative = \false) { if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) { throw new \InvalidArgumentException(\sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to)); } $from = $this->normalizePath($from); $to = $this->normalizePath($to); if ($from === $to) { return $directories ? '__DIR__' : '__FILE__'; } $commonPath = $to; while (\strpos($from . '/', $commonPath . '/') !== 0 && '/' !== $commonPath && !Preg::isMatch('{^[A-Z]:/?$}i', $commonPath) && '.' !== $commonPath) { $commonPath = \strtr(\dirname($commonPath), '\\', '/'); } // no commonality at all if (0 !== \strpos($from, $commonPath) || '.' === $commonPath) { return \var_export($to, \true); } $commonPath = \rtrim($commonPath, '/') . '/'; if (\str_starts_with($to, $from . '/')) { return '__DIR__ . ' . \var_export((string) \substr($to, \strlen($from)), \true); } $sourcePathDepth = \substr_count((string) \substr($from, \strlen($commonPath)), '/') + (int) $directories; // allow top level /foo & /bar dirs to be addressed relatively as this is common in Docker setups if (!$preferRelative && '/' === $commonPath && $sourcePathDepth > 1) { return \var_export($to, \true); } if ($staticCode) { $commonPathCode = "__DIR__ . '" . \str_repeat('/..', $sourcePathDepth) . "'"; } else { $commonPathCode = \str_repeat('dirname(', $sourcePathDepth) . '__DIR__' . \str_repeat(')', $sourcePathDepth); } $relTarget = (string) \substr($to, \strlen($commonPath)); return $commonPathCode . (\strlen($relTarget) > 0 ? '.' . \var_export('/' . $relTarget, \true) : ''); } /** * Checks if the given path is absolute * * @return bool */ public function isAbsolutePath(string $path) { return \strpos($path, '/') === 0 || \substr($path, 1, 1) === ':' || \strpos($path, '\\\\') === 0; } /** * Returns size of a file or directory specified by path. If a directory is * given, its size will be computed recursively. * * @param string $path Path to the file or directory * @throws \RuntimeException * @return int */ public function size(string $path) { if (!\file_exists($path)) { throw new \RuntimeException("{$path} does not exist."); } if (\is_dir($path)) { return $this->directorySize($path); } return (int) \filesize($path); } /** * Normalize a path. This replaces backslashes with slashes, removes ending * slash and collapses redundant separators and up-level references. * * @param string $path Path to the file or directory * @return string */ public function normalizePath(string $path) { $parts = []; $path = \strtr($path, '\\', '/'); $prefix = ''; $absolute = ''; // extract windows UNC paths e.g. \\foo\bar if (\strpos($path, '//') === 0 && \strlen($path) > 2) { $absolute = '//'; $path = \substr($path, 2); } // extract a prefix being a protocol://, protocol:, protocol://drive: or simply drive: if (Preg::isMatchStrictGroups('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) { $prefix = $match[1]; $path = \substr($path, \strlen($prefix)); } if (\strpos($path, '/') === 0) { $absolute = '/'; $path = \substr($path, 1); } $up = \false; foreach (\explode('/', $path) as $chunk) { if ('..' === $chunk && (\strlen($absolute) > 0 || $up)) { \array_pop($parts); $up = !(\count($parts) === 0 || '..' === \end($parts)); } elseif ('.' !== $chunk && '' !== $chunk) { $parts[] = $chunk; $up = '..' !== $chunk; } } // ensure c: is normalized to C: $prefix = Preg::replaceCallback('{(^|://)[a-z]:$}i', static function (array $m) { return \strtoupper($m[0]); }, $prefix); return $prefix . $absolute . \implode('/', $parts); } /** * Remove trailing slashes if present to avoid issues with symlinks * * And other possible unforeseen disasters, see https://github.com/composer/composer/pull/9422 * * @return string */ public static function trimTrailingSlash(string $path) { if (!Preg::isMatch('{^[/\\\\]+$}', $path)) { $path = \rtrim($path, '/\\'); } return $path; } /** * Return if the given path is local * * @return bool */ public static function isLocalPath(string $path) { // on windows, \\foo indicates network paths so we exclude those from local paths, however it is unsafe // on linux as file:////foo (which would be a network path \\foo on windows) will resolve to /foo which could be a local path if (\Composer\Util\Platform::isWindows()) { return Preg::isMatch('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\\.\\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path); } return Preg::isMatch('{^(file://|/|/?[a-z]:[\\\\/]|\\.\\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path); } /** * @return string */ public static function getPlatformPath(string $path) { if (\Composer\Util\Platform::isWindows()) { $path = Preg::replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path); } return Preg::replace('{^file://}i', '', $path); } /** * Cross-platform safe version of is_readable() * * This will also check for readability by reading the file as is_readable can not be trusted on network-mounts * and \\wsl$ paths. See https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926 * * @return bool */ public static function isReadable(string $path) { if (\is_readable($path)) { return \true; } if (\is_file($path)) { return \false !== \Composer\Util\Silencer::call('file_get_contents', $path, \false, null, 0, 1); } if (\is_dir($path)) { return \false !== \Composer\Util\Silencer::call('opendir', $path); } // assume false otherwise return \false; } /** * @return int */ protected function directorySize(string $directory) { $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS); $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST); $size = 0; foreach ($ri as $file) { if ($file->isFile()) { $size += $file->getSize(); } } return $size; } /** * @return ProcessExecutor */ protected function getProcess() { if (null === $this->processExecutor) { $this->processExecutor = new \Composer\Util\ProcessExecutor(); } return $this->processExecutor; } /** * delete symbolic link implementation (commonly known as "unlink()") * * symbolic links on windows which link to directories need rmdir instead of unlink */ private function unlinkImplementation(string $path) : bool { if (\Composer\Util\Platform::isWindows() && \is_dir($path) && \is_link($path)) { return \rmdir($path); } return \unlink($path); } /** * Creates a relative symlink from $link to $target * * @param string $target The path of the binary file to be symlinked * @param string $link The path where the symlink should be created * @return bool */ public function relativeSymlink(string $target, string $link) { if (!\function_exists('symlink')) { return \false; } $cwd = \Composer\Util\Platform::getCwd(); $relativePath = $this->findShortestPath($link, $target); \chdir(\dirname($link)); $result = @\symlink($relativePath, $link); \chdir($cwd); return $result; } /** * return true if that directory is a symlink. * * @return bool */ public function isSymlinkedDirectory(string $directory) { if (!\is_dir($directory)) { return \false; } $resolved = $this->resolveSymlinkedDirectorySymlink($directory); return \is_link($resolved); } private function unlinkSymlinkedDirectory(string $directory) : bool { $resolved = $this->resolveSymlinkedDirectorySymlink($directory); return $this->unlink($resolved); } /** * resolve pathname to symbolic link of a directory * * @param string $pathname directory path to resolve * * @return string resolved path to symbolic link or original pathname (unresolved) */ private function resolveSymlinkedDirectorySymlink(string $pathname) : string { if (!\is_dir($pathname)) { return $pathname; } $resolved = \rtrim($pathname, '/'); if (0 === \strlen($resolved)) { return $pathname; } return $resolved; } /** * Creates an NTFS junction. * * @return void */ public function junction(string $target, string $junction) { if (!\Composer\Util\Platform::isWindows()) { throw new \LogicException(\sprintf('Function %s is not available on non-Windows platform', __CLASS__)); } if (!\is_dir($target)) { throw new IOException(\sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target); } // Removing any previously junction to ensure clean execution. if (!\is_dir($junction) || $this->isJunction($junction)) { @\rmdir($junction); } $cmd = ['mklink', '/J', \str_replace('/', \DIRECTORY_SEPARATOR, $junction), \Composer\Util\Platform::realpath($target)]; if ($this->getProcess()->execute($cmd, $output) !== 0) { throw new IOException(\sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target); } \clearstatcache(\true, $junction); } /** * Returns whether the target directory is a Windows NTFS Junction. * * We test if the path is a directory and not an ordinary link, then check * that the mode value returned from lstat (which gives the status of the * link itself) is not a directory, by replicating the POSIX S_ISDIR test. * * This logic works because PHP does not set the mode value for a junction, * since there is no universal file type flag for it. Unfortunately an * uninitialized variable in PHP prior to 7.2.16 and 7.3.3 may cause a * random value to be returned. See https://bugs.php.net/bug.php?id=77552 * * If this random value passes the S_ISDIR test, then a junction will not be * detected and a recursive delete operation could lead to loss of data in * the target directory. Note that Windows rmdir can handle this situation * and will only delete the junction (from Windows 7 onwards). * * @param string $junction Path to check. * @return bool */ public function isJunction(string $junction) { if (!\Composer\Util\Platform::isWindows()) { return \false; } // Important to clear all caches first \clearstatcache(\true, $junction); if (!\is_dir($junction) || \is_link($junction)) { return \false; } $stat = \lstat($junction); // S_ISDIR test (S_IFDIR is 0x4000, S_IFMT is 0xF000 bitmask) return \is_array($stat) ? 0x4000 !== ($stat['mode'] & 0xf000) : \false; } /** * Removes a Windows NTFS junction. * * @return bool */ public function removeJunction(string $junction) { if (!\Composer\Util\Platform::isWindows()) { return \false; } $junction = \rtrim(\str_replace('/', \DIRECTORY_SEPARATOR, $junction), \DIRECTORY_SEPARATOR); if (!$this->isJunction($junction)) { throw new IOException(\sprintf('%s is not a junction and thus cannot be removed as one', $junction)); } return $this->rmdir($junction); } /** * @return int|false */ public function filePutContentsIfModified(string $path, string $content) { $currentContent = \Composer\Util\Silencer::call('file_get_contents', $path); if (\false === $currentContent || $currentContent !== $content) { return \file_put_contents($path, $content); } return 0; } /** * Copy file using stream_copy_to_stream to work around https://bugs.php.net/bug.php?id=6463 */ public function safeCopy(string $source, string $target) : void { if (!\file_exists($target) || !\file_exists($source) || !$this->filesAreEqual($source, $target)) { $sourceHandle = \fopen($source, 'r'); \assert($sourceHandle !== \false, 'Could not open "' . $source . '" for reading.'); $targetHandle = \fopen($target, 'w+'); \assert($targetHandle !== \false, 'Could not open "' . $target . '" for writing.'); \stream_copy_to_stream($sourceHandle, $targetHandle); \fclose($sourceHandle); \fclose($targetHandle); \touch($target, (int) \filemtime($source), (int) \fileatime($source)); } } /** * compare 2 files * https://stackoverflow.com/questions/3060125/can-i-use-file-get-contents-to-compare-two-files */ private function filesAreEqual(string $a, string $b) : bool { // Check if filesize is different if (\filesize($a) !== \filesize($b)) { return \false; } // Check if content is different $aHandle = \fopen($a, 'rb'); \assert($aHandle !== \false, 'Could not open "' . $a . '" for reading.'); $bHandle = \fopen($b, 'rb'); \assert($bHandle !== \false, 'Could not open "' . $b . '" for reading.'); $result = \true; while (!\feof($aHandle)) { if (\fread($aHandle, 8192) !== \fread($bHandle, 8192)) { $result = \false; break; } } \fclose($aHandle); \fclose($bHandle); return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; /** * @author Wissem Riahi */ class Tar { public static function getComposerJson(string $pathToArchive) : ?string { $phar = new \PharData($pathToArchive); if (!$phar->valid()) { return null; } return self::extractComposerJsonFromFolder($phar); } /** * @throws \RuntimeException */ private static function extractComposerJsonFromFolder(\PharData $phar) : string { if (isset($phar['composer.json'])) { return $phar['composer.json']->getContent(); } $topLevelPaths = []; foreach ($phar as $folderFile) { $name = $folderFile->getBasename(); if ($folderFile->isDir()) { $topLevelPaths[$name] = \true; if (\count($topLevelPaths) > 1) { throw new \RuntimeException('Archive has more than one top level directories, and no composer.json was found on the top level, so it\'s an invalid archive. Top level paths found were: ' . \implode(',', \array_keys($topLevelPaths))); } } } $composerJsonPath = \key($topLevelPaths) . '/composer.json'; if (\count($topLevelPaths) > 0 && isset($phar[$composerJsonPath])) { return $phar[$composerJsonPath]->getContent(); } throw new \RuntimeException('No composer.json found either at the top level or within the topmost directory'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Factory; use Composer\IO\IOInterface; use Composer\Config; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; /** * @author Jordi Boggiano */ class GitHub { /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var ProcessExecutor */ protected $process; /** @var HttpDownloader */ protected $httpDownloader; /** * Constructor. * * @param IOInterface $io The IO instance * @param Config $config The composer configuration * @param ProcessExecutor $process Process instance, injectable for mocking * @param HttpDownloader $httpDownloader Remote Filesystem, injectable for mocking */ public function __construct(IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null, ?\Composer\Util\HttpDownloader $httpDownloader = null) { $this->io = $io; $this->config = $config; $this->process = $process ?: new \Composer\Util\ProcessExecutor($io); $this->httpDownloader = $httpDownloader ?: Factory::createHttpDownloader($this->io, $config); } /** * Attempts to authorize a GitHub domain via OAuth * * @param string $originUrl The host this GitHub instance is located at * @return bool true on success */ public function authorizeOAuth(string $originUrl) : bool { if (!\in_array($originUrl, $this->config->get('github-domains'))) { return \false; } // if available use token from git config if (0 === $this->process->execute(['git', 'config', 'github.accesstoken'], $output)) { $this->io->setAuthentication($originUrl, \trim($output), 'x-oauth-basic'); return \true; } return \false; } /** * Authorizes a GitHub domain interactively via OAuth * * @param string $originUrl The host this GitHub instance is located at * @param string $message The reason this authorization is required * @throws \RuntimeException * @throws TransportException|\Exception * @return bool true on success */ public function authorizeOAuthInteractively(string $originUrl, ?string $message = null) : bool { if ($message) { $this->io->writeError($message); } $note = 'Composer'; if ($this->config->get('github-expose-hostname') === \true && 0 === $this->process->execute(['hostname'], $output)) { $note .= ' on ' . \trim($output); } $note .= ' ' . \date('Y-m-d Hi'); $url = 'https://' . $originUrl . '/settings/tokens/new?scopes=&description=' . \str_replace('%20', '+', \rawurlencode($note)); $this->io->writeError('When working with _public_ GitHub repositories only, head here to retrieve a token:'); $this->io->writeError($url); $this->io->writeError('This token will have read-only permission for public information only.'); $localAuthConfig = $this->config->getLocalAuthConfigSource(); $url = 'https://' . $originUrl . '/settings/tokens/new?scopes=repo&description=' . \str_replace('%20', '+', \rawurlencode($note)); $this->io->writeError('When you need to access _private_ GitHub repositories as well, go to:'); $this->io->writeError($url); $this->io->writeError('Note that such tokens have broad read/write permissions on your behalf, even if not needed by Composer.'); $this->io->writeError(\sprintf('Tokens will be stored in plain text in "%s" for future use by Composer.', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName())); $this->io->writeError('For additional information, check https://getcomposer.org/doc/articles/authentication-for-private-packages.md#github-oauth'); $storeInLocalAuthConfig = \false; if ($localAuthConfig !== null) { $storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', \true); } $token = \trim((string) $this->io->askAndHideAnswer('Token (hidden): ')); if ($token === '') { $this->io->writeError('No token given, aborting.'); $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com "'); return \false; } $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic'); try { $apiUrl = 'github.com' === $originUrl ? 'api.github.com/' : $originUrl . '/api/v3/'; $this->httpDownloader->get('https://' . $apiUrl, ['retry-auth-failure' => \false]); } catch (TransportException $e) { if (\in_array($e->getCode(), [403, 401])) { $this->io->writeError('Invalid token provided.'); $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com "'); return \false; } throw $e; } // store value in local/user config $authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource(); $this->config->getConfigSource()->removeConfigSetting('github-oauth.' . $originUrl); $authConfigSource->addConfigSetting('github-oauth.' . $originUrl, $token); $this->io->writeError('Token stored successfully.'); return \true; } /** * Extract rate limit from response. * * @param string[] $headers Headers from Composer\Downloader\TransportException. * * @return array{limit: int|'?', reset: string} */ public function getRateLimit(array $headers) : array { $rateLimit = ['limit' => '?', 'reset' => '?']; foreach ($headers as $header) { $header = \trim($header); if (\false === \stripos($header, 'x-ratelimit-')) { continue; } [$type, $value] = \explode(':', $header, 2); switch (\strtolower($type)) { case 'x-ratelimit-limit': $rateLimit['limit'] = (int) \trim($value); break; case 'x-ratelimit-reset': $rateLimit['reset'] = \date('Y-m-d H:i:s', (int) \trim($value)); break; } } return $rateLimit; } /** * Extract SSO URL from response. * * @param string[] $headers Headers from Composer\Downloader\TransportException. */ public function getSsoUrl(array $headers) : ?string { foreach ($headers as $header) { $header = \trim($header); if (\false === \stripos($header, 'x-github-sso: required')) { continue; } if (Preg::isMatch('{\\burl=(?P[^\\s;]+)}', $header, $match)) { return $match['url']; } } return null; } /** * Finds whether a request failed due to rate limiting * * @param string[] $headers Headers from Composer\Downloader\TransportException. */ public function isRateLimited(array $headers) : bool { foreach ($headers as $header) { if (Preg::isMatch('{^x-ratelimit-remaining: *0$}i', \trim($header))) { return \true; } } return \false; } /** * Finds whether a request failed due to lacking SSO authorization * * @see https://docs.github.com/en/rest/overview/other-authentication-methods#authenticating-for-saml-sso * * @param string[] $headers Headers from Composer\Downloader\TransportException. */ public function requiresSso(array $headers) : bool { foreach ($headers as $header) { if (Preg::isMatch('{^x-github-sso: required}i', \trim($header))) { return \true; } } return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\IO\IOInterface; use Composer\Config; use Composer\Factory; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; /** * @author Roshan Gautam */ class GitLab { /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var ProcessExecutor */ protected $process; /** @var HttpDownloader */ protected $httpDownloader; /** * Constructor. * * @param IOInterface $io The IO instance * @param Config $config The composer configuration * @param ProcessExecutor $process Process instance, injectable for mocking * @param HttpDownloader $httpDownloader Remote Filesystem, injectable for mocking */ public function __construct(IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null, ?\Composer\Util\HttpDownloader $httpDownloader = null) { $this->io = $io; $this->config = $config; $this->process = $process ?: new \Composer\Util\ProcessExecutor($io); $this->httpDownloader = $httpDownloader ?: Factory::createHttpDownloader($this->io, $config); } /** * Attempts to authorize a GitLab domain via OAuth. * * @param string $originUrl The host this GitLab instance is located at * * @return bool true on success */ public function authorizeOAuth(string $originUrl) : bool { // before composer 1.9, origin URLs had no port number in them $bcOriginUrl = Preg::replace('{:\\d+}', '', $originUrl); if (!\in_array($originUrl, $this->config->get('gitlab-domains'), \true) && !\in_array($bcOriginUrl, $this->config->get('gitlab-domains'), \true)) { return \false; } // if available use token from git config if (0 === $this->process->execute(['git', 'config', 'gitlab.accesstoken'], $output)) { $this->io->setAuthentication($originUrl, \trim($output), 'oauth2'); return \true; } // if available use deploy token from git config if (0 === $this->process->execute(['git', 'config', 'gitlab.deploytoken.user'], $tokenUser) && 0 === $this->process->execute(['git', 'config', 'gitlab.deploytoken.token'], $tokenPassword)) { $this->io->setAuthentication($originUrl, \trim($tokenUser), \trim($tokenPassword)); return \true; } // if available use token from composer config $authTokens = $this->config->get('gitlab-token'); if (isset($authTokens[$originUrl])) { $token = $authTokens[$originUrl]; } if (isset($authTokens[$bcOriginUrl])) { $token = $authTokens[$bcOriginUrl]; } if (isset($token)) { $username = \is_array($token) ? $token["username"] : $token; $password = \is_array($token) ? $token["token"] : 'private-token'; // Composer expects the GitLab token to be stored as username and 'private-token' or 'gitlab-ci-token' to be stored as password // Detect cases where this is reversed and resolve automatically resolve it if (\in_array($username, ['private-token', 'gitlab-ci-token', 'oauth2'], \true)) { $this->io->setAuthentication($originUrl, $password, $username); } else { $this->io->setAuthentication($originUrl, $username, $password); } return \true; } return \false; } /** * Authorizes a GitLab domain interactively via OAuth. * * @param string $scheme Scheme used in the origin URL * @param string $originUrl The host this GitLab instance is located at * @param string $message The reason this authorization is required * * @throws \RuntimeException * @throws TransportException|\Exception * * @return bool true on success */ public function authorizeOAuthInteractively(string $scheme, string $originUrl, ?string $message = null) : bool { if ($message) { $this->io->writeError($message); } $localAuthConfig = $this->config->getLocalAuthConfigSource(); $personalAccessTokenLink = $scheme . '://' . $originUrl . '/-/user_settings/personal_access_tokens'; $revokeLink = $scheme . '://' . $originUrl . '/-/user_settings/applications'; $this->io->writeError(\sprintf('A token will be created and stored in "%s", your password will never be stored', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName())); $this->io->writeError('To revoke access to this token you can visit:'); $this->io->writeError($revokeLink); $this->io->writeError('Alternatively you can setup an personal access token on:'); $this->io->writeError($personalAccessTokenLink); $this->io->writeError('and store it under "gitlab-token" see https://getcomposer.org/doc/articles/authentication-for-private-packages.md#gitlab-token for more details.'); $this->io->writeError('https://getcomposer.org/doc/articles/authentication-for-private-packages.md#gitlab-token'); $this->io->writeError('for more details.'); $storeInLocalAuthConfig = \false; if ($localAuthConfig !== null) { $storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', \true); } $attemptCounter = 0; while ($attemptCounter++ < 5) { try { $response = $this->createToken($scheme, $originUrl); } catch (TransportException $e) { // 401 is bad credentials, // 403 is max login attempts exceeded if (\in_array($e->getCode(), [403, 401])) { if (401 === $e->getCode()) { $response = \json_decode($e->getResponse(), \true); if (isset($response['error']) && $response['error'] === 'invalid_grant') { $this->io->writeError('Bad credentials. If you have two factor authentication enabled you will have to manually create a personal access token'); } else { $this->io->writeError('Bad credentials.'); } } else { $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.'); } $this->io->writeError('You can also manually create a personal access token enabling the "read_api" scope at:'); $this->io->writeError($personalAccessTokenLink); $this->io->writeError('Add it using "composer config --global --auth gitlab-token.' . $originUrl . ' "'); continue; } throw $e; } $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2'); $authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource(); // store value in user config in auth file if (isset($response['expires_in'])) { $authConfigSource->addConfigSetting('gitlab-oauth.' . $originUrl, ['expires-at' => \intval($response['created_at']) + \intval($response['expires_in']), 'refresh-token' => $response['refresh_token'], 'token' => $response['access_token']]); } else { $authConfigSource->addConfigSetting('gitlab-oauth.' . $originUrl, $response['access_token']); } return \true; } throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.'); } /** * Authorizes a GitLab domain interactively via OAuth. * * @param string $scheme Scheme used in the origin URL * @param string $originUrl The host this GitLab instance is located at * * @throws \RuntimeException * @throws TransportException|\Exception * * @return bool true on success */ public function authorizeOAuthRefresh(string $scheme, string $originUrl) : bool { try { $response = $this->refreshToken($scheme, $originUrl); } catch (TransportException $e) { $this->io->writeError("Couldn't refresh access token: " . $e->getMessage()); return \false; } $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2'); // store value in user config in auth file $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.' . $originUrl, ['expires-at' => \intval($response['created_at']) + \intval($response['expires_in']), 'refresh-token' => $response['refresh_token'], 'token' => $response['access_token']]); return \true; } /** * @return array{access_token: non-empty-string, refresh_token: non-empty-string, token_type: non-empty-string, expires_in?: positive-int, created_at: positive-int} * * @see https://docs.gitlab.com/ee/api/oauth2.html#resource-owner-password-credentials-flow */ private function createToken(string $scheme, string $originUrl) : array { $username = $this->io->ask('Username: '); $password = $this->io->askAndHideAnswer('Password: '); $headers = ['Content-Type: application/x-www-form-urlencoded']; $apiUrl = $originUrl; $data = \http_build_query(['username' => $username, 'password' => $password, 'grant_type' => 'password'], '', '&'); $options = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => $headers, 'content' => $data]]; $token = $this->httpDownloader->get($scheme . '://' . $apiUrl . '/oauth/token', $options)->decodeJson(); $this->io->writeError('Token successfully created'); return $token; } /** * Is the OAuth access token expired? * * @return bool true on expired token, false if token is fresh or expiration date is not set */ public function isOAuthExpired(string $originUrl) : bool { $authTokens = $this->config->get('gitlab-oauth'); if (isset($authTokens[$originUrl]['expires-at'])) { if ($authTokens[$originUrl]['expires-at'] < \time()) { return \true; } } return \false; } /** * @return array{access_token: non-empty-string, refresh_token: non-empty-string, token_type: non-empty-string, expires_in: positive-int, created_at: positive-int} * * @see https://docs.gitlab.com/ee/api/oauth2.html#resource-owner-password-credentials-flow */ private function refreshToken(string $scheme, string $originUrl) : array { $authTokens = $this->config->get('gitlab-oauth'); if (!isset($authTokens[$originUrl]['refresh-token'])) { throw new \RuntimeException('No GitLab refresh token present for ' . $originUrl . '.'); } $refreshToken = $authTokens[$originUrl]['refresh-token']; $headers = ['Content-Type: application/x-www-form-urlencoded']; $data = \http_build_query(['refresh_token' => $refreshToken, 'grant_type' => 'refresh_token'], '', '&'); $options = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => $headers, 'content' => $data]]; $token = $this->httpDownloader->get($scheme . '://' . $originUrl . '/oauth/token', $options)->decodeJson(); $this->io->writeError('GitLab token successfully refreshed', \true, IOInterface::VERY_VERBOSE); $this->io->writeError('To revoke access to this token you can visit ' . $scheme . '://' . $originUrl . '/-/user_settings/applications', \true, IOInterface::VERY_VERBOSE); return $token; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Factory; use Composer\IO\IOInterface; use Composer\Config; use Composer\Downloader\TransportException; /** * @author Paul Wenke */ class Bitbucket { /** @var IOInterface */ private $io; /** @var Config */ private $config; /** @var ProcessExecutor */ private $process; /** @var HttpDownloader */ private $httpDownloader; /** @var array{access_token: string, expires_in?: int}|null */ private $token = null; /** @var int|null */ private $time; public const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token'; /** * Constructor. * * @param IOInterface $io The IO instance * @param Config $config The composer configuration * @param ProcessExecutor $process Process instance, injectable for mocking * @param HttpDownloader $httpDownloader Remote Filesystem, injectable for mocking * @param int $time Timestamp, injectable for mocking */ public function __construct(IOInterface $io, Config $config, ?\Composer\Util\ProcessExecutor $process = null, ?\Composer\Util\HttpDownloader $httpDownloader = null, ?int $time = null) { $this->io = $io; $this->config = $config; $this->process = $process ?: new \Composer\Util\ProcessExecutor($io); $this->httpDownloader = $httpDownloader ?: Factory::createHttpDownloader($this->io, $config); $this->time = $time; } public function getToken() : string { if (!isset($this->token['access_token'])) { return ''; } return $this->token['access_token']; } /** * Attempts to authorize a Bitbucket domain via OAuth * * @param string $originUrl The host this Bitbucket instance is located at * @return bool true on success */ public function authorizeOAuth(string $originUrl) : bool { if ($originUrl !== 'bitbucket.org') { return \false; } // if available use token from git config if (0 === $this->process->execute(['git', 'config', 'bitbucket.accesstoken'], $output)) { $this->io->setAuthentication($originUrl, 'x-token-auth', \trim($output)); return \true; } return \false; } private function requestAccessToken() : bool { try { $response = $this->httpDownloader->get(self::OAUTH2_ACCESS_TOKEN_URL, ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'content' => 'grant_type=client_credentials']]); $token = $response->decodeJson(); if (!isset($token['expires_in']) || !isset($token['access_token'])) { throw new \LogicException('Expected a token configured with expires_in and access_token present, got ' . \json_encode($token)); } $this->token = $token; } catch (TransportException $e) { if ($e->getCode() === 400) { $this->io->writeError('Invalid OAuth consumer provided.'); $this->io->writeError('This can have three reasons:'); $this->io->writeError('1. You are authenticating with a bitbucket username/password combination'); $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url'); $this->io->writeError('3. You are using an OAuth consumer, but didn\'t configure it as private consumer'); return \false; } if (\in_array($e->getCode(), [403, 401])) { $this->io->writeError('Invalid OAuth consumer provided.'); $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org "'); return \false; } throw $e; } return \true; } /** * Authorizes a Bitbucket domain interactively via OAuth * * @param string $originUrl The host this Bitbucket instance is located at * @param string $message The reason this authorization is required * @throws \RuntimeException * @throws TransportException|\Exception * @return bool true on success */ public function authorizeOAuthInteractively(string $originUrl, ?string $message = null) : bool { if ($message) { $this->io->writeError($message); } $localAuthConfig = $this->config->getLocalAuthConfigSource(); $url = 'https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/'; $this->io->writeError('Follow the instructions here:'); $this->io->writeError($url); $this->io->writeError(\sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName())); $this->io->writeError('Ensure you enter a "Callback URL" (http://example.com is fine) or it will not be possible to create an Access Token (this callback url will not be used by composer)'); $storeInLocalAuthConfig = \false; if ($localAuthConfig !== null) { $storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', \true); } $consumerKey = \trim((string) $this->io->askAndHideAnswer('Consumer Key (hidden): ')); if (!$consumerKey) { $this->io->writeError('No consumer key given, aborting.'); $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org "'); return \false; } $consumerSecret = \trim((string) $this->io->askAndHideAnswer('Consumer Secret (hidden): ')); if (!$consumerSecret) { $this->io->writeError('No consumer secret given, aborting.'); $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org "'); return \false; } $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret); if (!$this->requestAccessToken()) { return \false; } // store value in user config $authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource(); $this->storeInAuthConfig($authConfigSource, $originUrl, $consumerKey, $consumerSecret); // Remove conflicting basic auth credentials (if available) $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl); $this->io->writeError('Consumer stored successfully.'); return \true; } /** * Retrieves an access token from Bitbucket. */ public function requestToken(string $originUrl, string $consumerKey, string $consumerSecret) : string { if ($this->token !== null || $this->getTokenFromConfig($originUrl)) { return $this->token['access_token']; } $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret); if (!$this->requestAccessToken()) { return ''; } $this->storeInAuthConfig($this->config->getLocalAuthConfigSource() ?? $this->config->getAuthConfigSource(), $originUrl, $consumerKey, $consumerSecret); if (!isset($this->token['access_token'])) { throw new \LogicException('Failed to initialize token above'); } return $this->token['access_token']; } /** * Store the new/updated credentials to the configuration */ private function storeInAuthConfig(Config\ConfigSourceInterface $authConfigSource, string $originUrl, string $consumerKey, string $consumerSecret) : void { $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.' . $originUrl); if (null === $this->token || !isset($this->token['expires_in'])) { throw new \LogicException('Expected a token configured with expires_in present, got ' . \json_encode($this->token)); } $time = null === $this->time ? \time() : $this->time; $consumer = ["consumer-key" => $consumerKey, "consumer-secret" => $consumerSecret, "access-token" => $this->token['access_token'], "access-token-expiration" => $time + $this->token['expires_in']]; $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.' . $originUrl, $consumer); } /** * @phpstan-assert-if-true array{access_token: string} $this->token */ private function getTokenFromConfig(string $originUrl) : bool { $authConfig = $this->config->get('bitbucket-oauth'); if (!isset($authConfig[$originUrl]['access-token'], $authConfig[$originUrl]['access-token-expiration']) || \time() > $authConfig[$originUrl]['access-token-expiration']) { return \false; } $this->token = ['access_token' => $authConfig[$originUrl]['access-token']]; return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; use Composer\Util\Http\Response; use Composer\Util\Http\CurlDownloader; use Composer\Composer; use Composer\Package\Version\VersionParser; use Composer\Semver\Constraint\Constraint; use Composer\Exception\IrrecoverableDownloadException; use React\Promise\Promise; use React\Promise\PromiseInterface; /** * @author Jordi Boggiano * @phpstan-type Request array{url: non-empty-string, options: mixed[], copyTo: string|null} * @phpstan-type Job array{id: int, status: int, request: Request, sync: bool, origin: string, resolve?: callable, reject?: callable, curl_id?: int, response?: Response, exception?: \Throwable} */ class HttpDownloader { private const STATUS_QUEUED = 1; private const STATUS_STARTED = 2; private const STATUS_COMPLETED = 3; private const STATUS_FAILED = 4; private const STATUS_ABORTED = 5; /** @var IOInterface */ private $io; /** @var Config */ private $config; /** @var array */ private $jobs = []; /** @var mixed[] */ private $options = []; /** @var int */ private $runningJobs = 0; /** @var int */ private $maxJobs = 12; /** @var ?CurlDownloader */ private $curl; /** @var ?RemoteFilesystem */ private $rfs; /** @var int */ private $idGen = 0; /** @var bool */ private $disabled; /** @var bool */ private $allowAsync = \false; /** * @param IOInterface $io The IO instance * @param Config $config The config * @param mixed[] $options The options */ public function __construct(IOInterface $io, Config $config, array $options = [], bool $disableTls = \false) { $this->io = $io; $this->disabled = (bool) \Composer\Util\Platform::getEnv('COMPOSER_DISABLE_NETWORK'); // Setup TLS options // The cafile option can be set via config.json if ($disableTls === \false) { $this->options = \Composer\Util\StreamContextFactory::getTlsDefaults($options, $io); } // handle the other externally set options normally. $this->options = \array_replace_recursive($this->options, $options); $this->config = $config; if (self::isCurlEnabled()) { $this->curl = new CurlDownloader($io, $config, $options, $disableTls); } $this->rfs = new \Composer\Util\RemoteFilesystem($io, $config, $options, $disableTls); if (\is_numeric($maxJobs = \Composer\Util\Platform::getEnv('COMPOSER_MAX_PARALLEL_HTTP'))) { $this->maxJobs = \max(1, \min(50, (int) $maxJobs)); } } /** * Download a file synchronously * * @param string $url URL to download * @param mixed[] $options Stream context options e.g. https://www.php.net/manual/en/context.http.php * although not all options are supported when using the default curl downloader * @throws TransportException * @return Response */ public function get(string $url, array $options = []) { if ('' === $url) { throw new \InvalidArgumentException('$url must not be an empty string'); } [$job, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => null], \true); $promise->then(null, function (\Throwable $e) { // suppress error as it is rethrown to the caller by getResponse() a few lines below }); $this->wait($job['id']); $response = $this->getResponse($job['id']); return $response; } /** * Create an async download operation * * @param string $url URL to download * @param mixed[] $options Stream context options e.g. https://www.php.net/manual/en/context.http.php * although not all options are supported when using the default curl downloader * @throws TransportException * @return PromiseInterface * @phpstan-return PromiseInterface */ public function add(string $url, array $options = []) { if ('' === $url) { throw new \InvalidArgumentException('$url must not be an empty string'); } [, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => null]); return $promise; } /** * Copy a file synchronously * * @param string $url URL to download * @param string $to Path to copy to * @param mixed[] $options Stream context options e.g. https://www.php.net/manual/en/context.http.php * although not all options are supported when using the default curl downloader * @throws TransportException * @return Response */ public function copy(string $url, string $to, array $options = []) { if ('' === $url) { throw new \InvalidArgumentException('$url must not be an empty string'); } [$job] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => $to], \true); $this->wait($job['id']); return $this->getResponse($job['id']); } /** * Create an async copy operation * * @param string $url URL to download * @param string $to Path to copy to * @param mixed[] $options Stream context options e.g. https://www.php.net/manual/en/context.http.php * although not all options are supported when using the default curl downloader * @throws TransportException * @return PromiseInterface * @phpstan-return PromiseInterface */ public function addCopy(string $url, string $to, array $options = []) { if ('' === $url) { throw new \InvalidArgumentException('$url must not be an empty string'); } [, $promise] = $this->addJob(['url' => $url, 'options' => $options, 'copyTo' => $to]); return $promise; } /** * Retrieve the options set in the constructor * * @return mixed[] Options */ public function getOptions() { return $this->options; } /** * Merges new options * * @param mixed[] $options * @return void */ public function setOptions(array $options) { $this->options = \array_replace_recursive($this->options, $options); } /** * @phpstan-param Request $request * @return array{Job, PromiseInterface} * @phpstan-return array{Job, PromiseInterface} */ private function addJob(array $request, bool $sync = \false) : array { $request['options'] = \array_replace_recursive($this->options, $request['options']); /** @var Job */ $job = ['id' => $this->idGen++, 'status' => self::STATUS_QUEUED, 'request' => $request, 'sync' => $sync, 'origin' => \Composer\Util\Url::getOrigin($this->config, $request['url'])]; if (!$sync && !$this->allowAsync) { throw new \LogicException('You must use the HttpDownloader instance which is part of a Composer\\Loop instance to be able to run async http requests'); } // capture username/password from URL if there is one if (Preg::isMatchStrictGroups('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $request['url'], $match)) { $this->io->setAuthentication($job['origin'], \rawurldecode($match[1]), \rawurldecode($match[2])); } $rfs = $this->rfs; if ($this->canUseCurl($job)) { $resolver = static function ($resolve, $reject) use(&$job) : void { $job['status'] = \Composer\Util\HttpDownloader::STATUS_QUEUED; $job['resolve'] = $resolve; $job['reject'] = $reject; }; } else { $resolver = static function ($resolve, $reject) use(&$job, $rfs) : void { // start job $url = $job['request']['url']; $options = $job['request']['options']; $job['status'] = \Composer\Util\HttpDownloader::STATUS_STARTED; if ($job['request']['copyTo']) { $rfs->copy($job['origin'], $url, $job['request']['copyTo'], \false, $options); $headers = $rfs->getLastHeaders(); $response = new \Composer\Util\Http\Response($job['request'], $rfs->findStatusCode($headers), $headers, $job['request']['copyTo'] . '~'); $resolve($response); } else { $body = $rfs->getContents($job['origin'], $url, \false, $options); $headers = $rfs->getLastHeaders(); $response = new \Composer\Util\Http\Response($job['request'], $rfs->findStatusCode($headers), $headers, $body); $resolve($response); } }; } $curl = $this->curl; $canceler = static function () use(&$job, $curl) : void { if ($job['status'] === \Composer\Util\HttpDownloader::STATUS_QUEUED) { $job['status'] = \Composer\Util\HttpDownloader::STATUS_ABORTED; } if ($job['status'] !== \Composer\Util\HttpDownloader::STATUS_STARTED) { return; } $job['status'] = \Composer\Util\HttpDownloader::STATUS_ABORTED; if (isset($job['curl_id'])) { $curl->abortRequest($job['curl_id']); } throw new IrrecoverableDownloadException('Download of ' . \Composer\Util\Url::sanitize($job['request']['url']) . ' canceled'); }; $promise = new Promise($resolver, $canceler); $promise = $promise->then(function ($response) use(&$job) { $job['status'] = \Composer\Util\HttpDownloader::STATUS_COMPLETED; $job['response'] = $response; $this->markJobDone(); return $response; }, function ($e) use(&$job) : void { $job['status'] = \Composer\Util\HttpDownloader::STATUS_FAILED; $job['exception'] = $e; $this->markJobDone(); throw $e; }); $this->jobs[$job['id']] =& $job; if ($this->runningJobs < $this->maxJobs) { $this->startJob($job['id']); } return [$job, $promise]; } private function startJob(int $id) : void { $job =& $this->jobs[$id]; if ($job['status'] !== self::STATUS_QUEUED) { return; } // start job $job['status'] = self::STATUS_STARTED; $this->runningJobs++; \assert(isset($job['resolve'])); \assert(isset($job['reject'])); $resolve = $job['resolve']; $reject = $job['reject']; $url = $job['request']['url']; $options = $job['request']['options']; $origin = $job['origin']; if ($this->disabled) { if (isset($job['request']['options']['http']['header']) && \false !== \stripos(\implode('', $job['request']['options']['http']['header']), 'if-modified-since')) { $resolve(new Response(['url' => $url], 304, [], '')); } else { $e = new TransportException('Network disabled, request canceled: ' . \Composer\Util\Url::sanitize($url), 499); $e->setStatusCode(499); $reject($e); } return; } try { if ($job['request']['copyTo']) { $job['curl_id'] = $this->curl->download($resolve, $reject, $origin, $url, $options, $job['request']['copyTo']); } else { $job['curl_id'] = $this->curl->download($resolve, $reject, $origin, $url, $options); } } catch (\Exception $exception) { $reject($exception); } } private function markJobDone() : void { $this->runningJobs--; } /** * Wait for current async download jobs to complete * * @param int|null $index For internal use only, the job id * * @return void */ public function wait(?int $index = null) { do { $jobCount = $this->countActiveJobs($index); } while ($jobCount); } /** * @internal */ public function enableAsync() : void { $this->allowAsync = \true; } /** * @internal * * @param int|null $index For internal use only, the job id * @return int number of active (queued or started) jobs */ public function countActiveJobs(?int $index = null) : int { if ($this->runningJobs < $this->maxJobs) { foreach ($this->jobs as $job) { if ($job['status'] === self::STATUS_QUEUED && $this->runningJobs < $this->maxJobs) { $this->startJob($job['id']); } } } if ($this->curl) { $this->curl->tick(); } if (null !== $index) { return $this->jobs[$index]['status'] < self::STATUS_COMPLETED ? 1 : 0; } $active = 0; foreach ($this->jobs as $job) { if ($job['status'] < self::STATUS_COMPLETED) { $active++; } elseif (!$job['sync']) { unset($this->jobs[$job['id']]); } } return $active; } /** * @param int $index Job id */ private function getResponse(int $index) : Response { if (!isset($this->jobs[$index])) { throw new \LogicException('Invalid request id'); } if ($this->jobs[$index]['status'] === self::STATUS_FAILED) { \assert(isset($this->jobs[$index]['exception'])); throw $this->jobs[$index]['exception']; } if (!isset($this->jobs[$index]['response'])) { throw new \LogicException('Response not available yet, call wait() first'); } $resp = $this->jobs[$index]['response']; unset($this->jobs[$index]); return $resp; } /** * @internal * * @param array{warning?: string, info?: string, warning-versions?: string, info-versions?: string, warnings?: array, infos?: array} $data */ public static function outputWarnings(IOInterface $io, string $url, $data) : void { $cleanMessage = static function ($msg) use($io) { if (!$io->isDecorated()) { $msg = Preg::replace('{' . \chr(27) . '\\[[;\\d]*m}u', '', $msg); } return $msg; }; // legacy warning/info keys foreach (['warning', 'info'] as $type) { if (empty($data[$type])) { continue; } if (!empty($data[$type . '-versions'])) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($data[$type . '-versions']); $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion())); if (!$constraint->matches($composer)) { continue; } } $io->writeError('<' . $type . '>' . \ucfirst($type) . ' from ' . \Composer\Util\Url::sanitize($url) . ': ' . $cleanMessage($data[$type]) . ''); } // modern Composer 2.2+ format with support for multiple warning/info messages foreach (['warnings', 'infos'] as $key) { if (empty($data[$key])) { continue; } $versionParser = new VersionParser(); foreach ($data[$key] as $spec) { $type = \substr($key, 0, -1); $constraint = $versionParser->parseConstraints($spec['versions']); $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion())); if (!$constraint->matches($composer)) { continue; } $io->writeError('<' . $type . '>' . \ucfirst($type) . ' from ' . \Composer\Util\Url::sanitize($url) . ': ' . $cleanMessage($spec['message']) . ''); } } } /** * @internal * * @return ?string[] */ public static function getExceptionHints(\Throwable $e) : ?array { if (!$e instanceof TransportException) { return null; } if (\false !== \strpos($e->getMessage(), 'Resolving timed out') || \false !== \strpos($e->getMessage(), 'Could not resolve host')) { \Composer\Util\Silencer::suppress(); $testConnectivity = \file_get_contents('https://8.8.8.8', \false, \stream_context_create(['ssl' => ['verify_peer' => \false], 'http' => ['follow_location' => \false, 'ignore_errors' => \true]])); \Composer\Util\Silencer::restore(); if (\false !== $testConnectivity) { return ['The following exception probably indicates you have misconfigured DNS resolver(s)']; } return ['The following exception probably indicates you are offline or have misconfigured DNS resolver(s)']; } return null; } /** * @param Job $job */ private function canUseCurl(array $job) : bool { if (!$this->curl) { return \false; } if (!Preg::isMatch('{^https?://}i', $job['request']['url'])) { return \false; } if (!empty($job['request']['options']['ssl']['allow_self_signed'])) { return \false; } return \true; } /** * @internal */ public static function isCurlEnabled() : bool { return \extension_loaded('curl') && \function_exists('curl_multi_exec') && \function_exists('curl_multi_init'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\XdebugHandler\XdebugHandler; /** * Provides ini file location functions that work with and without a restart. * When the process has restarted it uses a tmp ini and stores the original * ini locations in an environment variable. * * @author John Stevenson */ class IniHelper { /** * Returns an array of php.ini locations with at least one entry * * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files. * The loaded ini location is the first entry and may be empty. * * @return string[] */ public static function getAll() : array { return XdebugHandler::getAllIniFiles(); } /** * Describes the location of the loaded php.ini file(s) */ public static function getMessage() : string { $paths = self::getAll(); if (empty($paths[0])) { \array_shift($paths); } $ini = \array_shift($paths); if (empty($ini)) { return 'A php.ini file does not exist. You will have to create one.'; } if (!empty($paths)) { return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.'; } return 'The php.ini used by your command-line PHP is: ' . $ini; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Pcre\Preg; /** * Platform helper for uniform platform-specific tests. * * @author Niels Keurentjes */ class Platform { /** @var ?bool */ private static $isVirtualBoxGuest = null; /** @var ?bool */ private static $isWindowsSubsystemForLinux = null; /** @var ?bool */ private static $isDocker = null; /** * getcwd() equivalent which always returns a string * * @throws \RuntimeException */ public static function getCwd(bool $allowEmpty = \false) : string { $cwd = \getcwd(); // fallback to realpath('') just in case this works but odds are it would break as well if we are in a case where getcwd fails if (\false === $cwd) { $cwd = \realpath(''); } // crappy state, assume '' and hopefully relative paths allow things to continue if (\false === $cwd) { if ($allowEmpty) { return ''; } throw new \RuntimeException('Could not determine the current working directory'); } return $cwd; } /** * Infallible realpath version that falls back on the given $path if realpath is not working */ public static function realpath(string $path) : string { $realPath = \realpath($path); if ($realPath === \false) { return $path; } return $realPath; } /** * getenv() equivalent but reads from the runtime global variables first * * @param non-empty-string $name * * @return string|false */ public static function getEnv(string $name) { if (\array_key_exists($name, $_SERVER)) { return (string) $_SERVER[$name]; } if (\array_key_exists($name, $_ENV)) { return (string) $_ENV[$name]; } return \getenv($name); } /** * putenv() equivalent but updates the runtime global variables too */ public static function putEnv(string $name, string $value) : void { \putenv($name . '=' . $value); $_SERVER[$name] = $_ENV[$name] = $value; } /** * putenv('X') equivalent but updates the runtime global variables too */ public static function clearEnv(string $name) : void { \putenv($name); unset($_SERVER[$name], $_ENV[$name]); } /** * Parses tildes and environment variables in paths. */ public static function expandPath(string $path) : string { if (Preg::isMatch('#^~[\\/]#', $path)) { return self::getUserDirectory() . \substr($path, 1); } return Preg::replaceCallback('#^(\\$|(?P%))(?P\\w++)(?(percent)%)(?P.*)#', static function ($matches) : string { // Treat HOME as an alias for USERPROFILE on Windows for legacy reasons if (\Composer\Util\Platform::isWindows() && $matches['var'] === 'HOME') { if ((bool) \Composer\Util\Platform::getEnv('HOME')) { return \Composer\Util\Platform::getEnv('HOME') . $matches['path']; } return \Composer\Util\Platform::getEnv('USERPROFILE') . $matches['path']; } return \Composer\Util\Platform::getEnv($matches['var']) . $matches['path']; }, $path); } /** * @throws \RuntimeException If the user home could not reliably be determined * @return string The formal user home as detected from environment parameters */ public static function getUserDirectory() : string { if (\false !== ($home = self::getEnv('HOME'))) { return $home; } if (self::isWindows() && \false !== ($home = self::getEnv('USERPROFILE'))) { return $home; } if (\function_exists('posix_getuid') && \function_exists('posix_getpwuid')) { $info = \posix_getpwuid(\posix_getuid()); if (\is_array($info)) { return $info['dir']; } } throw new \RuntimeException('Could not determine user directory'); } /** * @return bool Whether the host machine is running on the Windows Subsystem for Linux (WSL) */ public static function isWindowsSubsystemForLinux() : bool { if (null === self::$isWindowsSubsystemForLinux) { self::$isWindowsSubsystemForLinux = \false; // while WSL will be hosted within windows, WSL itself cannot be windows based itself. if (self::isWindows()) { return self::$isWindowsSubsystemForLinux = \false; } if (!(bool) \ini_get('open_basedir') && \is_readable('/proc/version') && \false !== \stripos((string) \Composer\Util\Silencer::call('file_get_contents', '/proc/version'), 'microsoft') && !self::isDocker()) { return self::$isWindowsSubsystemForLinux = \true; } } return self::$isWindowsSubsystemForLinux; } /** * @return bool Whether the host machine is running a Windows OS */ public static function isWindows() : bool { return \defined('PHP_WINDOWS_VERSION_BUILD'); } public static function isDocker() : bool { if (null !== self::$isDocker) { return self::$isDocker; } // cannot check so assume no if ((bool) \ini_get('open_basedir')) { return self::$isDocker = \false; } // .dockerenv and .containerenv are present in some cases but not reliably if (\file_exists('/.dockerenv') || \file_exists('/run/.containerenv') || \file_exists('/var/run/.containerenv')) { return self::$isDocker = \true; } // see https://www.baeldung.com/linux/is-process-running-inside-container $cgroups = [ '/proc/self/mountinfo', // cgroup v2 '/proc/1/cgroup', ]; foreach ($cgroups as $cgroup) { if (!\is_readable($cgroup)) { continue; } // suppress errors as some environments have these files as readable but system restrictions prevent the read from succeeding // see https://github.com/composer/composer/issues/12095 try { $data = @\file_get_contents($cgroup); } catch (\Throwable $e) { break; } if (\is_string($data) && \str_contains($data, '/var/lib/docker/')) { return self::$isDocker = \true; } } return self::$isDocker = \false; } /** * @return int return a guaranteed binary length of the string, regardless of silly mbstring configs */ public static function strlen(string $str) : int { static $useMbString = null; if (null === $useMbString) { $useMbString = \function_exists('mb_strlen') && (bool) \ini_get('mbstring.func_overload'); } if ($useMbString) { return \mb_strlen($str, '8bit'); } return \strlen($str); } /** * @param ?resource $fd Open file descriptor or null to default to STDOUT */ public static function isTty($fd = null) : bool { if ($fd === null) { $fd = \defined('STDOUT') ? \STDOUT : \fopen('php://stdout', 'w'); if ($fd === \false) { return \false; } } // detect msysgit/mingw and assume this is a tty because detection // does not work correctly, see https://github.com/composer/composer/issues/9690 if (\in_array(\strtoupper((string) self::getEnv('MSYSTEM')), ['MINGW32', 'MINGW64'], \true)) { return \true; } // modern cross-platform function, includes the fstat // fallback so if it is present we trust it if (\function_exists('stream_isatty')) { return \stream_isatty($fd); } // only trusting this if it is positive, otherwise prefer fstat fallback if (\function_exists('posix_isatty') && \posix_isatty($fd)) { return \true; } $stat = @\fstat($fd); if ($stat === \false) { return \false; } // Check if formatted mode is S_IFCHR return 020000 === ($stat['mode'] & 0170000); } /** * @return bool Whether the current command is for bash completion */ public static function isInputCompletionProcess() : bool { return '_complete' === ($_SERVER['argv'][1] ?? null); } public static function workaroundFilesystemIssues() : void { if (self::isVirtualBoxGuest()) { \usleep(200000); } } /** * Attempts detection of VirtualBox guest VMs * * This works based on the process' user being "vagrant", the COMPOSER_RUNTIME_ENV env var being set to "virtualbox", or lsmod showing the virtualbox guest additions are loaded */ private static function isVirtualBoxGuest() : bool { if (null === self::$isVirtualBoxGuest) { self::$isVirtualBoxGuest = \false; if (self::isWindows()) { return self::$isVirtualBoxGuest; } if (\function_exists('posix_getpwuid') && \function_exists('posix_geteuid')) { $processUser = \posix_getpwuid(\posix_geteuid()); if (\is_array($processUser) && $processUser['name'] === 'vagrant') { return self::$isVirtualBoxGuest = \true; } } if (self::getEnv('COMPOSER_RUNTIME_ENV') === 'virtualbox') { return self::$isVirtualBoxGuest = \true; } if (\defined('PHP_OS_FAMILY') && \PHP_OS_FAMILY === 'Linux') { $process = new \Composer\Util\ProcessExecutor(); try { if (0 === $process->execute(['lsmod'], $output) && \str_contains($output, 'vboxguest')) { return self::$isVirtualBoxGuest = \true; } } catch (\Exception $e) { // noop } } } return self::$isVirtualBoxGuest; } /** * @return 'NUL'|'/dev/null' */ public static function getDevNull() : string { if (self::isWindows()) { return 'NUL'; } return '/dev/null'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Composer; use Composer\CaBundle\CaBundle; use Composer\Downloader\TransportException; use Composer\Repository\PlatformRepository; use Composer\Util\Http\ProxyManager; use _ContaoManager\Psr\Log\LoggerInterface; /** * Allows the creation of a basic context supporting http proxy * * @author Jordan Alliot * @author Markus Tacker */ final class StreamContextFactory { /** * Creates a context supporting HTTP proxies * * @param non-empty-string $url URL the context is to be used for * @phpstan-param array{http?: array{follow_location?: int, max_redirects?: int, header?: string|array}} $defaultOptions * @param mixed[] $defaultOptions Options to merge with the default * @param mixed[] $defaultParams Parameters to specify on the context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled * @return resource Default context */ public static function getContext(string $url, array $defaultOptions = [], array $defaultParams = []) { $options = ['http' => [ // specify defaults again to try and work better with curlwrappers enabled 'follow_location' => 1, 'max_redirects' => 20, ]]; $options = \array_replace_recursive($options, self::initOptions($url, $defaultOptions)); unset($defaultOptions['http']['header']); $options = \array_replace_recursive($options, $defaultOptions); if (isset($options['http']['header'])) { $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']); } return \stream_context_create($options, $defaultParams); } /** * @param non-empty-string $url * @param mixed[] $options * @param bool $forCurl When true, will not add proxy values as these are handled separately * @phpstan-return array{http: array{header: string[], proxy?: string, request_fulluri: bool}, ssl?: mixed[]} * @return array formatted as a stream context array */ public static function initOptions(string $url, array $options, bool $forCurl = \false) : array { // Make sure the headers are in an array form if (!isset($options['http']['header'])) { $options['http']['header'] = []; } if (\is_string($options['http']['header'])) { $options['http']['header'] = \explode("\r\n", $options['http']['header']); } // Add stream proxy options if there is a proxy if (!$forCurl) { $proxy = ProxyManager::getInstance()->getProxyForRequest($url); $proxyOptions = $proxy->getContextOptions(); if ($proxyOptions !== null) { $isHttpsRequest = 0 === \strpos($url, 'https://'); if ($proxy->isSecure()) { if (!\extension_loaded('openssl')) { throw new TransportException('You must enable the openssl extension to use a secure proxy.'); } if ($isHttpsRequest) { throw new TransportException('You must enable the curl extension to make https requests through a secure proxy.'); } } elseif ($isHttpsRequest && !\extension_loaded('openssl')) { throw new TransportException('You must enable the openssl extension to make https requests through a proxy.'); } // Header will be a Proxy-Authorization string or not set if (isset($proxyOptions['http']['header'])) { $options['http']['header'][] = $proxyOptions['http']['header']; unset($proxyOptions['http']['header']); } $options = \array_replace_recursive($options, $proxyOptions); } } if (\defined('_ContaoManager\\HHVM_VERSION')) { $phpVersion = 'HHVM ' . HHVM_VERSION; } else { $phpVersion = 'PHP ' . \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION; } if ($forCurl) { $curl = \curl_version(); $httpVersion = 'cURL ' . $curl['version']; } else { $httpVersion = 'streams'; } if (!isset($options['http']['header']) || \false === \stripos(\implode('', $options['http']['header']), 'user-agent')) { $platformPhpVersion = PlatformRepository::getPlatformPhpVersion(); $options['http']['header'][] = \sprintf('User-Agent: Composer/%s (%s; %s; %s; %s%s%s)', Composer::getVersion(), \function_exists('php_uname') ? \php_uname('s') : 'Unknown', \function_exists('php_uname') ? \php_uname('r') : 'Unknown', $phpVersion, $httpVersion, $platformPhpVersion ? '; Platform-PHP ' . $platformPhpVersion : '', \Composer\Util\Platform::getEnv('CI') ? '; CI' : ''); } return $options; } /** * @param mixed[] $options * * @return mixed[] */ public static function getTlsDefaults(array $options, ?LoggerInterface $logger = null) : array { $ciphers = \implode(':', ['ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'DHE-RSA-AES128-GCM-SHA256', 'DHE-DSS-AES128-GCM-SHA256', 'kEDH+AESGCM', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-RSA-AES128-SHA', 'ECDHE-ECDSA-AES128-SHA', 'ECDHE-RSA-AES256-SHA384', 'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES256-SHA', 'ECDHE-ECDSA-AES256-SHA', 'DHE-RSA-AES128-SHA256', 'DHE-RSA-AES128-SHA', 'DHE-DSS-AES128-SHA256', 'DHE-RSA-AES256-SHA256', 'DHE-DSS-AES256-SHA', 'DHE-RSA-AES256-SHA', 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256', 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA', 'AES', 'CAMELLIA', 'DES-CBC3-SHA', '!aNULL', '!eNULL', '!EXPORT', '!DES', '!RC4', '!MD5', '!PSK', '!aECDH', '!EDH-DSS-DES-CBC3-SHA', '!EDH-RSA-DES-CBC3-SHA', '!KRB5-DES-CBC3-SHA']); /** * CN_match and SNI_server_name are only known once a URL is passed. * They will be set in the getOptionsForUrl() method which receives a URL. * * cafile or capath can be overridden by passing in those options to constructor. */ $defaults = ['ssl' => ['ciphers' => $ciphers, 'verify_peer' => \true, 'verify_depth' => 7, 'SNI_enabled' => \true, 'capture_peer_cert' => \true]]; if (isset($options['ssl'])) { $defaults['ssl'] = \array_replace_recursive($defaults['ssl'], $options['ssl']); } /** * Attempt to find a local cafile or throw an exception if none pre-set * The user may go download one if this occurs. */ if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) { $result = CaBundle::getSystemCaRootBundlePath($logger); if (\is_dir($result)) { $defaults['ssl']['capath'] = $result; } else { $defaults['ssl']['cafile'] = $result; } } if (isset($defaults['ssl']['cafile']) && (!\Composer\Util\Filesystem::isReadable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $logger))) { throw new TransportException('The configured cafile was not valid or could not be read.'); } if (isset($defaults['ssl']['capath']) && (!\is_dir($defaults['ssl']['capath']) || !\Composer\Util\Filesystem::isReadable($defaults['ssl']['capath']))) { throw new TransportException('The configured capath was not valid or could not be read.'); } /** * Disable TLS compression to prevent CRIME attacks where supported. */ $defaults['ssl']['disable_compression'] = \true; return $defaults; } /** * A bug in PHP prevents the headers from correctly being sent when a content-type header is present and * NOT at the end of the array * * This method fixes the array by moving the content-type header to the end * * @link https://bugs.php.net/bug.php?id=61548 * @param string|string[] $header * @return string[] */ private static function fixHttpHeaderField($header) : array { if (!\is_array($header)) { $header = \explode("\r\n", $header); } \uasort($header, static function ($el) : int { return \stripos($el, 'content-type') === 0 ? 1 : -1; }); return $header; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\CaBundle\CaBundle; use Composer\Pcre\Preg; /** * @author Chris Smith * @deprecated Use composer/ca-bundle and composer/composer 2.2 if you still need PHP 5 compatibility, this class will be removed in Composer 3.0 */ final class TlsHelper { /** * Match hostname against a certificate. * * @param mixed $certificate X.509 certificate * @param string $hostname Hostname in the URL * @param string $cn Set to the common name of the certificate iff match found */ public static function checkCertificateHost($certificate, string $hostname, ?string &$cn = null) : bool { $names = self::getCertificateNames($certificate); if (empty($names)) { return \false; } $combinedNames = \array_merge($names['san'], [$names['cn']]); $hostname = \strtolower($hostname); foreach ($combinedNames as $certName) { $matcher = self::certNameMatcher($certName); if ($matcher && $matcher($hostname)) { $cn = $names['cn']; return \true; } } return \false; } /** * Extract DNS names out of an X.509 certificate. * * @param mixed $certificate X.509 certificate * * @return array{cn: string, san: string[]}|null */ public static function getCertificateNames($certificate) : ?array { if (\is_array($certificate)) { $info = $certificate; } elseif (CaBundle::isOpensslParseSafe()) { $info = \openssl_x509_parse($certificate, \false); } if (!isset($info['subject']['commonName'])) { return null; } $commonName = \strtolower($info['subject']['commonName']); $subjectAltNames = []; if (isset($info['extensions']['subjectAltName'])) { $subjectAltNames = Preg::split('{\\s*,\\s*}', $info['extensions']['subjectAltName']); $subjectAltNames = \array_filter(\array_map(static function ($name) : ?string { if (0 === \strpos($name, 'DNS:')) { return \strtolower(\ltrim(\substr($name, 4))); } return null; }, $subjectAltNames), function (?string $san) { return $san !== null; }); $subjectAltNames = \array_values($subjectAltNames); } return ['cn' => $commonName, 'san' => $subjectAltNames]; } /** * Get the certificate pin. * * By Kevin McArthur of StormTide Digital Studios Inc. * @KevinSMcArthur / https://github.com/StormTide * * See https://tools.ietf.org/html/draft-ietf-websec-key-pinning-02 * * 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. */ public static function getCertificateFingerprint(string $certificate) : string { $pubkey = \openssl_get_publickey($certificate); if ($pubkey === \false) { throw new \RuntimeException('Failed to retrieve the public key from certificate'); } $pubkeydetails = \openssl_pkey_get_details($pubkey); $pubkeypem = $pubkeydetails['key']; //Convert PEM to DER before SHA1'ing $start = '-----BEGIN PUBLIC KEY-----'; $end = '-----END PUBLIC KEY-----'; $pemtrim = \substr($pubkeypem, \strpos($pubkeypem, $start) + \strlen($start), (\strlen($pubkeypem) - \strpos($pubkeypem, $end)) * -1); $der = \base64_decode($pemtrim); return \hash('sha1', $der); } /** * 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. */ public static function isOpensslParseSafe() : bool { return CaBundle::isOpensslParseSafe(); } /** * Convert certificate name into matching function. * * @param string $certName CN/SAN */ private static function certNameMatcher(string $certName) : ?callable { $wildcards = \substr_count($certName, '*'); if (0 === $wildcards) { // Literal match. return static function ($hostname) use($certName) : bool { return $hostname === $certName; }; } if (1 === $wildcards) { $components = \explode('.', $certName); if (3 > \count($components)) { // Must have 3+ components return null; } $firstComponent = $components[0]; // Wildcard must be the last character. if ('*' !== $firstComponent[\strlen($firstComponent) - 1]) { return null; } $wildcardRegex = \preg_quote($certName); $wildcardRegex = \str_replace('\\*', '[a-z0-9-]+', $wildcardRegex); $wildcardRegex = "{^{$wildcardRegex}\$}"; return static function ($hostname) use($wildcardRegex) : bool { return Preg::isMatch($wildcardRegex, $hostname); }; } return null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Config; use Composer\Pcre\Preg; /** * @author Jordi Boggiano */ class Url { /** * @param non-empty-string $url * @return non-empty-string the updated URL */ public static function updateDistReference(Config $config, string $url, string $ref) : string { $host = \parse_url($url, \PHP_URL_HOST); if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') { if (Preg::isMatch('{^https?://(?:www\\.)?github\\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) { // update legacy github archives to API calls with the proper reference $url = 'https://api.github.com/repos/' . $match[1] . '/' . $match[2] . '/' . $match[3] . 'ball/' . $ref; } elseif (Preg::isMatch('{^https?://(?:www\\.)?github\\.com/([^/]+)/([^/]+)/archive/.+\\.(zip|tar)(?:\\.gz)?$}i', $url, $match)) { // update current github web archives to API calls with the proper reference $url = 'https://api.github.com/repos/' . $match[1] . '/' . $match[2] . '/' . $match[3] . 'ball/' . $ref; } elseif (Preg::isMatch('{^https?://api\\.github\\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) { // update api archives to the proper reference $url = 'https://api.github.com/repos/' . $match[1] . '/' . $match[2] . '/' . $match[3] . 'ball/' . $ref; } } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') { if (Preg::isMatch('{^https?://(?:www\\.)?bitbucket\\.org/([^/]+)/([^/]+)/get/(.+)\\.(zip|tar\\.gz|tar\\.bz2)$}i', $url, $match)) { // update Bitbucket archives to the proper reference $url = 'https://bitbucket.org/' . $match[1] . '/' . $match[2] . '/get/' . $ref . '.' . $match[4]; } } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') { if (Preg::isMatch('{^https?://(?:www\\.)?gitlab\\.com/api/v[34]/projects/([^/]+)/repository/archive\\.(zip|tar\\.gz|tar\\.bz2|tar)\\?sha=.+$}i', $url, $match)) { // update Gitlab archives to the proper reference $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref; } } elseif (\in_array($host, $config->get('github-domains'), \true)) { $url = Preg::replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/' . $ref, $url); } elseif (\in_array($host, $config->get('gitlab-domains'), \true)) { $url = Preg::replace('{(/api/v[34]/projects/[^/]+/repository/archive\\.(?:zip|tar\\.gz|tar\\.bz2|tar)\\?sha=).+$}i', '${1}' . $ref, $url); } \assert($url !== ''); return $url; } /** * @param non-empty-string $url * @return non-empty-string */ public static function getOrigin(Config $config, string $url) : string { if (0 === \strpos($url, 'file://')) { return $url; } $origin = (string) \parse_url($url, \PHP_URL_HOST); if ($port = \parse_url($url, \PHP_URL_PORT)) { $origin .= ':' . $port; } if (\str_ends_with($origin, '.github.com') && $origin !== 'codeload.github.com') { return 'github.com'; } if ($origin === 'repo.packagist.org') { return 'packagist.org'; } if ($origin === '') { $origin = $url; } // Gitlab can be installed in a non-root context (i.e. gitlab.com/foo). When downloading archives the originUrl // is the host without the path, so we look for the registered gitlab-domains matching the host here if (\false === \strpos($origin, '/') && !\in_array($origin, $config->get('gitlab-domains'), \true)) { foreach ($config->get('gitlab-domains') as $gitlabDomain) { if ($gitlabDomain !== '' && \str_starts_with($gitlabDomain, $origin)) { return $gitlabDomain; } } } return $origin; } public static function sanitize(string $url) : string { // GitHub repository rename result in redirect locations containing the access_token as GET parameter // e.g. https://api.github.com/repositories/9999999999?access_token=github_token $url = Preg::replace('{([&?]access_token=)[^&]+}', '$1***', $url); $url = Preg::replaceCallback('{^(?P[a-z0-9]+://)?(?P[^:/\\s@]+):(?P[^@\\s/]+)@}i', static function ($m) : string { // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx) we obfuscate that if (Preg::isMatch('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+|github_pat_[a-zA-Z0-9_]+)$}', $m['user'])) { return $m['prefix'] . '***:***@'; } return $m['prefix'] . $m['user'] . ':***@'; }, $url); return $url; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use _ContaoManager\Symfony\Component\Process\ExecutableFinder; use _ContaoManager\Symfony\Component\Process\Process; /** * @author Matt Whittom * * @phpstan-type RepoConfig array{unique_perforce_client_name?: string, depot?: string, branch?: string, p4user?: string, p4password?: string} */ class Perforce { /** @var string */ protected $path; /** @var ?string */ protected $p4Depot; /** @var ?string */ protected $p4Client; /** @var ?string */ protected $p4User; /** @var ?string */ protected $p4Password; /** @var string */ protected $p4Port; /** @var ?string */ protected $p4Stream; /** @var string */ protected $p4ClientSpec; /** @var ?string */ protected $p4DepotType; /** @var ?string */ protected $p4Branch; /** @var ProcessExecutor */ protected $process; /** @var string */ protected $uniquePerforceClientName; /** @var bool */ protected $windowsFlag; /** @var string */ protected $commandResult; /** @var IOInterface */ protected $io; /** @var ?Filesystem */ protected $filesystem; /** * @phpstan-param RepoConfig $repoConfig */ public function __construct($repoConfig, string $port, string $path, \Composer\Util\ProcessExecutor $process, bool $isWindows, IOInterface $io) { $this->windowsFlag = $isWindows; $this->p4Port = $port; $this->initializePath($path); $this->process = $process; $this->initialize($repoConfig); $this->io = $io; } /** * @phpstan-param RepoConfig $repoConfig */ public static function create($repoConfig, string $port, string $path, \Composer\Util\ProcessExecutor $process, IOInterface $io) : self { return new \Composer\Util\Perforce($repoConfig, $port, $path, $process, \Composer\Util\Platform::isWindows(), $io); } public static function checkServerExists(string $url, \Composer\Util\ProcessExecutor $processExecutor) : bool { return 0 === $processExecutor->execute(['p4', '-p', $url, 'info', '-s'], $ignoredOutput); } /** * @phpstan-param RepoConfig $repoConfig */ public function initialize($repoConfig) : void { $this->uniquePerforceClientName = $this->generateUniquePerforceClientName(); if (!$repoConfig) { return; } if (isset($repoConfig['unique_perforce_client_name'])) { $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name']; } if (isset($repoConfig['depot'])) { $this->p4Depot = $repoConfig['depot']; } if (isset($repoConfig['branch'])) { $this->p4Branch = $repoConfig['branch']; } if (isset($repoConfig['p4user'])) { $this->p4User = $repoConfig['p4user']; } else { $this->p4User = $this->getP4variable('P4USER'); } if (isset($repoConfig['p4password'])) { $this->p4Password = $repoConfig['p4password']; } } public function initializeDepotAndBranch(?string $depot, ?string $branch) : void { if (isset($depot)) { $this->p4Depot = $depot; } if (isset($branch)) { $this->p4Branch = $branch; } } /** * @return non-empty-string */ public function generateUniquePerforceClientName() : string { return \gethostname() . "_" . \time(); } public function cleanupClientSpec() : void { $client = $this->getClient(); $task = 'client -d ' . \Composer\Util\ProcessExecutor::escape($client); $useP4Client = \false; $command = $this->generateP4Command($task, $useP4Client); $this->executeCommand($command); $clientSpec = $this->getP4ClientSpec(); $fileSystem = $this->getFilesystem(); $fileSystem->remove($clientSpec); } /** * @param non-empty-string $command */ protected function executeCommand($command) : int { $this->commandResult = ''; return $this->process->execute($command, $this->commandResult); } public function getClient() : string { if (!isset($this->p4Client)) { $cleanStreamName = \str_replace(['//', '/', '@'], ['', '_', ''], $this->getStream()); $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName; } return $this->p4Client; } protected function getPath() : string { return $this->path; } public function initializePath(string $path) : void { $this->path = $path; $fs = $this->getFilesystem(); $fs->ensureDirectoryExists($path); } protected function getPort() : string { return $this->p4Port; } public function setStream(string $stream) : void { $this->p4Stream = $stream; $index = \strrpos($stream, '/'); //Stream format is //depot/stream, while non-streaming depot is //depot if ($index > 2) { $this->p4DepotType = 'stream'; } } public function isStream() : bool { return \is_string($this->p4DepotType) && \strcmp($this->p4DepotType, 'stream') === 0; } public function getStream() : string { if (!isset($this->p4Stream)) { if ($this->isStream()) { $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch; } else { $this->p4Stream = '//' . $this->p4Depot; } } return $this->p4Stream; } public function getStreamWithoutLabel(string $stream) : string { $index = \strpos($stream, '@'); if ($index === \false) { return $stream; } return \substr($stream, 0, $index); } /** * @return non-empty-string */ public function getP4ClientSpec() : string { return $this->path . '/' . $this->getClient() . '.p4.spec'; } public function getUser() : ?string { return $this->p4User; } public function setUser(?string $user) : void { $this->p4User = $user; } public function queryP4User() : void { $this->getUser(); if (\strlen((string) $this->p4User) > 0) { return; } $this->p4User = $this->getP4variable('P4USER'); if (\strlen((string) $this->p4User) > 0) { return; } $this->p4User = $this->io->ask('Enter P4 User:'); if ($this->windowsFlag) { $command = $this->getP4Executable() . ' set P4USER=' . $this->p4User; } else { $command = 'export P4USER=' . $this->p4User; } $this->executeCommand($command); } /** * @return ?string */ protected function getP4variable(string $name) : ?string { if ($this->windowsFlag) { $command = $this->getP4Executable() . ' set'; $this->executeCommand($command); $result = \trim($this->commandResult); $resArray = \explode(\PHP_EOL, $result); foreach ($resArray as $line) { $fields = \explode('=', $line); if (\strcmp($name, $fields[0]) === 0) { $index = \strpos($fields[1], ' '); if ($index === \false) { $value = $fields[1]; } else { $value = \substr($fields[1], 0, $index); } $value = \trim($value); return $value; } } return null; } $command = 'echo $' . $name; $this->executeCommand($command); $result = \trim($this->commandResult); return $result; } public function queryP4Password() : ?string { if (isset($this->p4Password)) { return $this->p4Password; } $password = $this->getP4variable('P4PASSWD'); if (\strlen((string) $password) <= 0) { $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': '); } $this->p4Password = $password; return $password; } /** * @return non-empty-string */ public function generateP4Command(string $command, bool $useClient = \true) : string { $p4Command = $this->getP4Executable() . ' '; $p4Command .= '-u ' . $this->getUser() . ' '; if ($useClient) { $p4Command .= '-c ' . $this->getClient() . ' '; } $p4Command .= '-p ' . $this->getPort() . ' ' . $command; return $p4Command; } public function isLoggedIn() : bool { $command = $this->generateP4Command('login -s', \false); $exitCode = $this->executeCommand($command); if ($exitCode) { $errorOutput = $this->process->getErrorOutput(); $index = \strpos($errorOutput, $this->getUser()); if ($index === \false) { $index = \strpos($errorOutput, 'p4'); if ($index === \false) { return \false; } throw new \Exception('p4 command not found in path: ' . $errorOutput); } throw new \Exception('Invalid user name: ' . $this->getUser()); } return \true; } public function connectClient() : void { $p4CreateClientCommand = $this->generateP4Command('client -i < ' . \Composer\Util\ProcessExecutor::escape($this->getP4ClientSpec())); $this->executeCommand($p4CreateClientCommand); } public function syncCodeBase(?string $sourceReference) : void { $prevDir = \Composer\Util\Platform::getCwd(); \chdir($this->path); $p4SyncCommand = $this->generateP4Command('sync -f '); if (null !== $sourceReference) { $p4SyncCommand .= '@' . $sourceReference; } $this->executeCommand($p4SyncCommand); \chdir($prevDir); } /** * @param resource|false $spec */ public function writeClientSpecToFile($spec) : void { \fwrite($spec, 'Client: ' . $this->getClient() . \PHP_EOL . \PHP_EOL); \fwrite($spec, 'Update: ' . \date('Y/m/d H:i:s') . \PHP_EOL . \PHP_EOL); \fwrite($spec, 'Access: ' . \date('Y/m/d H:i:s') . \PHP_EOL); \fwrite($spec, 'Owner: ' . $this->getUser() . \PHP_EOL . \PHP_EOL); \fwrite($spec, 'Description:' . \PHP_EOL); \fwrite($spec, ' Created by ' . $this->getUser() . ' from composer.' . \PHP_EOL . \PHP_EOL); \fwrite($spec, 'Root: ' . $this->getPath() . \PHP_EOL . \PHP_EOL); \fwrite($spec, 'Options: noallwrite noclobber nocompress unlocked modtime rmdir' . \PHP_EOL . \PHP_EOL); \fwrite($spec, 'SubmitOptions: revertunchanged' . \PHP_EOL . \PHP_EOL); \fwrite($spec, 'LineEnd: local' . \PHP_EOL . \PHP_EOL); if ($this->isStream()) { \fwrite($spec, 'Stream:' . \PHP_EOL); \fwrite($spec, ' ' . $this->getStreamWithoutLabel($this->p4Stream) . \PHP_EOL); } else { \fwrite($spec, 'View: ' . $this->getStream() . '/... //' . $this->getClient() . '/... ' . \PHP_EOL); } } public function writeP4ClientSpec() : void { $clientSpec = $this->getP4ClientSpec(); $spec = \fopen($clientSpec, 'w'); try { $this->writeClientSpecToFile($spec); } catch (\Exception $e) { \fclose($spec); throw $e; } \fclose($spec); } /** * @param resource $pipe * @param mixed $name */ protected function read($pipe, $name) : void { if (\feof($pipe)) { return; } $line = \fgets($pipe); while ($line !== \false) { $line = \fgets($pipe); } } public function windowsLogin(?string $password) : int { $command = $this->generateP4Command(' login -a'); $process = Process::fromShellCommandline($command, null, null, $password); return $process->run(); } public function p4Login() : void { $this->queryP4User(); if (!$this->isLoggedIn()) { $password = $this->queryP4Password(); if ($this->windowsFlag) { $this->windowsLogin($password); } else { $command = 'echo ' . \Composer\Util\ProcessExecutor::escape($password) . ' | ' . $this->generateP4Command(' login -a', \false); $exitCode = $this->executeCommand($command); if ($exitCode) { throw new \Exception("Error logging in:" . $this->process->getErrorOutput()); } } } } /** * @return mixed[]|null */ public function getComposerInformation(string $identifier) : ?array { $composerFileContent = $this->getFileContent('composer.json', $identifier); if (!$composerFileContent) { return null; } return \json_decode($composerFileContent, \true); } public function getFileContent(string $file, string $identifier) : ?string { $path = $this->getFilePath($file, $identifier); $command = $this->generateP4Command(' print ' . \Composer\Util\ProcessExecutor::escape($path)); $this->executeCommand($command); $result = $this->commandResult; if (!\trim($result)) { return null; } return $result; } public function getFilePath(string $file, string $identifier) : ?string { $index = \strpos($identifier, '@'); if ($index === \false) { return $identifier . '/' . $file; } $path = \substr($identifier, 0, $index) . '/' . $file . \substr($identifier, $index); $command = $this->generateP4Command(' files ' . \Composer\Util\ProcessExecutor::escape($path), \false); $this->executeCommand($command); $result = $this->commandResult; $index2 = \strpos($result, 'no such file(s).'); if ($index2 === \false) { $index3 = \strpos($result, 'change'); if ($index3 !== \false) { $phrase = \trim(\substr($result, $index3)); $fields = \explode(' ', $phrase); return \substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1]; } } return null; } /** * @return array{master: string} */ public function getBranches() : array { $possibleBranches = []; if (!$this->isStream()) { $possibleBranches[$this->p4Branch] = $this->getStream(); } else { $command = $this->generateP4Command('streams ' . \Composer\Util\ProcessExecutor::escape('//' . $this->p4Depot . '/...')); $this->executeCommand($command); $result = $this->commandResult; $resArray = \explode(\PHP_EOL, $result); foreach ($resArray as $line) { $resBits = \explode(' ', $line); if (\count($resBits) > 4) { $branch = Preg::replace('/[^A-Za-z0-9 ]/', '', $resBits[4]); $possibleBranches[$branch] = $resBits[1]; } } } $command = $this->generateP4Command('changes ' . \Composer\Util\ProcessExecutor::escape($this->getStream() . '/...'), \false); $this->executeCommand($command); $result = $this->commandResult; $resArray = \explode(\PHP_EOL, $result); $lastCommit = $resArray[0]; $lastCommitArr = \explode(' ', $lastCommit); $lastCommitNum = $lastCommitArr[1]; return ['master' => $possibleBranches[$this->p4Branch] . '@' . $lastCommitNum]; } /** * @return array */ public function getTags() : array { $command = $this->generateP4Command('labels'); $this->executeCommand($command); $result = $this->commandResult; $resArray = \explode(\PHP_EOL, $result); $tags = []; foreach ($resArray as $line) { if (\strpos($line, 'Label') !== \false) { $fields = \explode(' ', $line); $tags[$fields[1]] = $this->getStream() . '@' . $fields[1]; } } return $tags; } public function checkStream() : bool { $command = $this->generateP4Command('depots', \false); $this->executeCommand($command); $result = $this->commandResult; $resArray = \explode(\PHP_EOL, $result); foreach ($resArray as $line) { if (\strpos($line, 'Depot') !== \false) { $fields = \explode(' ', $line); if (\strcmp($this->p4Depot, $fields[1]) === 0) { $this->p4DepotType = $fields[3]; return $this->isStream(); } } } return \false; } /** * @return mixed|null */ protected function getChangeList(string $reference) : mixed { $index = \strpos($reference, '@'); if ($index === \false) { return null; } $label = \substr($reference, $index); $command = $this->generateP4Command(' changes -m1 ' . \Composer\Util\ProcessExecutor::escape($label)); $this->executeCommand($command); $changes = $this->commandResult; if (\strpos($changes, 'Change') !== 0) { return null; } $fields = \explode(' ', $changes); return $fields[1]; } /** * @return mixed|null */ public function getCommitLogs(string $fromReference, string $toReference) : mixed { $fromChangeList = $this->getChangeList($fromReference); if ($fromChangeList === null) { return null; } $toChangeList = $this->getChangeList($toReference); if ($toChangeList === null) { return null; } $index = \strpos($fromReference, '@'); $main = \substr($fromReference, 0, $index) . '/...'; $command = $this->generateP4Command('filelog ' . \Composer\Util\ProcessExecutor::escape($main . '@' . $fromChangeList . ',' . $toChangeList)); $this->executeCommand($command); return $this->commandResult; } public function getFilesystem() : \Composer\Util\Filesystem { if (null === $this->filesystem) { $this->filesystem = new \Composer\Util\Filesystem($this->process); } return $this->filesystem; } public function setFilesystem(\Composer\Util\Filesystem $fs) : void { $this->filesystem = $fs; } private function getP4Executable() : string { static $p4Executable; if ($p4Executable) { return $p4Executable; } $finder = new ExecutableFinder(); return $p4Executable = $finder->find('p4') ?? 'p4'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util\Http; use Composer\Downloader\TransportException; use Composer\Util\NoProxyPattern; /** * @internal * @author John Stevenson */ class ProxyManager { /** @var ?string */ private $error = null; /** @var ?ProxyItem */ private $httpProxy = null; /** @var ?ProxyItem */ private $httpsProxy = null; /** @var ?NoProxyPattern */ private $noProxyHandler = null; /** @var ?self */ private static $instance = null; private function __construct() { try { $this->getProxyData(); } catch (\RuntimeException $e) { $this->error = $e->getMessage(); } } public static function getInstance() : \Composer\Util\Http\ProxyManager { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } /** * Clears the persistent instance */ public static function reset() : void { self::$instance = null; } public function hasProxy() : bool { return $this->httpProxy !== null || $this->httpsProxy !== null; } /** * Returns a RequestProxy instance for the request url * * @param non-empty-string $requestUrl */ public function getProxyForRequest(string $requestUrl) : \Composer\Util\Http\RequestProxy { if ($this->error !== null) { throw new TransportException('Unable to use a proxy: ' . $this->error); } $scheme = (string) \parse_url($requestUrl, \PHP_URL_SCHEME); $proxy = $this->getProxyForScheme($scheme); if ($proxy === null) { return \Composer\Util\Http\RequestProxy::none(); } if ($this->noProxy($requestUrl)) { return \Composer\Util\Http\RequestProxy::noProxy(); } return $proxy->toRequestProxy($scheme); } /** * Returns a ProxyItem if one is set for the scheme, otherwise null */ private function getProxyForScheme(string $scheme) : ?\Composer\Util\Http\ProxyItem { if ($scheme === 'http') { return $this->httpProxy; } if ($scheme === 'https') { return $this->httpsProxy; } return null; } /** * Finds proxy values from the environment and sets class properties */ private function getProxyData() : void { // Handle http_proxy/HTTP_PROXY on CLI only for security reasons if (\PHP_SAPI === 'cli' || \PHP_SAPI === 'phpdbg') { [$env, $name] = $this->getProxyEnv('http_proxy'); if ($env !== null) { $this->httpProxy = new \Composer\Util\Http\ProxyItem($env, $name); } } // Handle cgi_http_proxy/CGI_HTTP_PROXY if needed if ($this->httpProxy === null) { [$env, $name] = $this->getProxyEnv('cgi_http_proxy'); if ($env !== null) { $this->httpProxy = new \Composer\Util\Http\ProxyItem($env, $name); } } // Handle https_proxy/HTTPS_PROXY [$env, $name] = $this->getProxyEnv('https_proxy'); if ($env !== null) { $this->httpsProxy = new \Composer\Util\Http\ProxyItem($env, $name); } // Handle no_proxy/NO_PROXY [$env, $name] = $this->getProxyEnv('no_proxy'); if ($env !== null) { $this->noProxyHandler = new NoProxyPattern($env); } } /** * Searches $_SERVER for case-sensitive values * * @return array{0: string|null, 1: string} value, name */ private function getProxyEnv(string $envName) : array { $names = [\strtolower($envName), \strtoupper($envName)]; foreach ($names as $name) { if (\is_string($_SERVER[$name] ?? null)) { if ($_SERVER[$name] !== '') { return [$_SERVER[$name], $name]; } } } return [null, '']; } /** * Returns true if a url matches no_proxy value */ private function noProxy(string $requestUrl) : bool { if ($this->noProxyHandler === null) { return \false; } return $this->noProxyHandler->test($requestUrl); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util\Http; use Composer\Json\JsonFile; use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; /** * @phpstan-type Request array{url: non-empty-string, options?: mixed[], copyTo?: string|null} */ class Response { /** @var Request */ private $request; /** @var int */ private $code; /** @var list */ private $headers; /** @var ?string */ private $body; /** * @param Request $request * @param list $headers */ public function __construct(array $request, ?int $code, array $headers, ?string $body) { if (!isset($request['url'])) { throw new \LogicException('url key missing from request array'); } $this->request = $request; $this->code = (int) $code; $this->headers = $headers; $this->body = $body; } public function getStatusCode() : int { return $this->code; } public function getStatusMessage() : ?string { $value = null; foreach ($this->headers as $header) { if (Preg::isMatch('{^HTTP/\\S+ \\d+}i', $header)) { // In case of redirects, headers contain the headers of all responses // so we can not return directly and need to keep iterating $value = $header; } } return $value; } /** * @return string[] */ public function getHeaders() : array { return $this->headers; } /** * @return ?string */ public function getHeader(string $name) : ?string { return self::findHeaderValue($this->headers, $name); } /** * @return ?string */ public function getBody() : ?string { return $this->body; } /** * @return mixed */ public function decodeJson() { return JsonFile::parseJson($this->body, $this->request['url']); } /** * @phpstan-impure */ public function collect() : void { unset($this->request, $this->code, $this->headers, $this->body); } /** * @param string[] $headers array of returned headers like from getLastHeaders() * @param string $name header name (case insensitive) */ public static function findHeaderValue(array $headers, string $name) : ?string { $value = null; foreach ($headers as $header) { if (Preg::isMatch('{^' . \preg_quote($name) . ':\\s*(.+?)\\s*$}i', $header, $match)) { $value = $match[1]; } } return $value; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util\Http; use Composer\Downloader\TransportException; /** * @internal * @author John Stevenson * * @phpstan-type contextOptions array{http: array{proxy: string, header?: string, request_fulluri?: bool}} */ class RequestProxy { /** @var ?contextOptions */ private $contextOptions; /** @var ?non-empty-string */ private $status; /** @var ?non-empty-string */ private $url; /** @var ?non-empty-string */ private $auth; /** * @param ?non-empty-string $url The proxy url, without authorization * @param ?non-empty-string $auth Authorization for curl * @param ?contextOptions $contextOptions * @param ?non-empty-string $status */ public function __construct(?string $url, ?string $auth, ?array $contextOptions, ?string $status) { $this->url = $url; $this->auth = $auth; $this->contextOptions = $contextOptions; $this->status = $status; } public static function none() : \Composer\Util\Http\RequestProxy { return new self(null, null, null, null); } public static function noProxy() : \Composer\Util\Http\RequestProxy { return new self(null, null, null, 'excluded by no_proxy'); } /** * Returns the context options to use for this request, otherwise null * * @return ?contextOptions */ public function getContextOptions() : ?array { return $this->contextOptions; } /** * Returns an array of curl proxy options * * @param array $sslOptions * @return array */ public function getCurlOptions(array $sslOptions) : array { if ($this->isSecure() && !$this->supportsSecureProxy()) { throw new TransportException('Cannot use an HTTPS proxy. PHP >= 7.3 and cUrl >= 7.52.0 are required.'); } // Always set a proxy url, even an empty value, because it tells curl // to ignore proxy environment variables $options = [\CURLOPT_PROXY => (string) $this->url]; // If using a proxy, tell curl to ignore no_proxy environment variables if ($this->url !== null) { $options[\CURLOPT_NOPROXY] = ''; } // Set any authorization if ($this->auth !== null) { $options[\CURLOPT_PROXYAUTH] = \CURLAUTH_BASIC; $options[\CURLOPT_PROXYUSERPWD] = $this->auth; } if ($this->isSecure()) { if (isset($sslOptions['cafile'])) { $options[\CURLOPT_PROXY_CAINFO] = $sslOptions['cafile']; } if (isset($sslOptions['capath'])) { $options[\CURLOPT_PROXY_CAPATH] = $sslOptions['capath']; } } return $options; } /** * Returns proxy info associated with this request * * An empty return value means that the user has not set a proxy. * A non-empty value will either be the sanitized proxy url if a proxy is * required, or a message indicating that a no_proxy value has disabled the * proxy. * * @param ?string $format Output format specifier */ public function getStatus(?string $format = null) : string { if ($this->status === null) { return ''; } $format = $format ?? '%s'; if (\strpos($format, '%s') !== \false) { return \sprintf($format, $this->status); } throw new \InvalidArgumentException('String format specifier is missing'); } /** * Returns true if the request url has been excluded by a no_proxy value * * A false value can also mean that the user has not set a proxy. */ public function isExcludedByNoProxy() : bool { return $this->status !== null && $this->url === null; } /** * Returns true if this is a secure (HTTPS) proxy * * A false value means that this is either an HTTP proxy, or that a proxy * is not required for this request, or that the user has not set a proxy. */ public function isSecure() : bool { return 0 === \strpos((string) $this->url, 'https://'); } /** * Returns true if an HTTPS proxy can be used. * * This depends on PHP7.3+ for CURL_VERSION_HTTPS_PROXY * and curl including the feature (from version 7.52.0) */ public function supportsSecureProxy() : bool { if (\false === ($version = \curl_version()) || !\defined('CURL_VERSION_HTTPS_PROXY')) { return \false; } $features = $version['features']; return (bool) ($features & \CURL_VERSION_HTTPS_PROXY); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util\Http; use Composer\Config; use Composer\Downloader\MaxFileSizeExceededException; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; use Composer\Util\Platform; use Composer\Util\StreamContextFactory; use Composer\Util\AuthHelper; use Composer\Util\Url; use Composer\Util\HttpDownloader; use React\Promise\Promise; use _ContaoManager\Symfony\Component\HttpFoundation\IpUtils; /** * @internal * @author Jordi Boggiano * @author Nicolas Grekas * @phpstan-type Attributes array{retryAuthFailure: bool, redirects: int<0, max>, retries: int<0, max>, storeAuth: 'prompt'|bool, ipResolve: 4|6|null} * @phpstan-type Job array{url: non-empty-string, origin: string, attributes: Attributes, options: mixed[], progress: mixed[], curlHandle: \CurlHandle, filename: string|null, headerHandle: resource, bodyHandle: resource, resolve: callable, reject: callable, primaryIp: string} */ class CurlDownloader { /** * Known libcurl's broken versions when proxy is in use with HTTP/2 * multiplexing. * * @var list */ private const BAD_MULTIPLEXING_CURL_VERSIONS = ['7.87.0', '7.88.0', '7.88.1']; /** @var \CurlMultiHandle */ private $multiHandle; /** @var \CurlShareHandle */ private $shareHandle; /** @var Job[] */ private $jobs = []; /** @var IOInterface */ private $io; /** @var Config */ private $config; /** @var AuthHelper */ private $authHelper; /** @var float */ private $selectTimeout = 5.0; /** @var int */ private $maxRedirects = 20; /** @var int */ private $maxRetries = 3; /** @var array */ protected $multiErrors = [\CURLM_BAD_HANDLE => ['CURLM_BAD_HANDLE', 'The passed-in handle is not a valid CURLM handle.'], \CURLM_BAD_EASY_HANDLE => ['CURLM_BAD_EASY_HANDLE', "An easy handle was not good/valid. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle."], \CURLM_OUT_OF_MEMORY => ['CURLM_OUT_OF_MEMORY', 'You are doomed.'], \CURLM_INTERNAL_ERROR => ['CURLM_INTERNAL_ERROR', 'This can only be returned if libcurl bugs. Please report it to us!']]; /** @var mixed[] */ private static $options = ['http' => ['method' => \CURLOPT_CUSTOMREQUEST, 'content' => \CURLOPT_POSTFIELDS, 'header' => \CURLOPT_HTTPHEADER, 'timeout' => \CURLOPT_TIMEOUT], 'ssl' => ['cafile' => \CURLOPT_CAINFO, 'capath' => \CURLOPT_CAPATH, 'verify_peer' => \CURLOPT_SSL_VERIFYPEER, 'verify_peer_name' => \CURLOPT_SSL_VERIFYHOST, 'local_cert' => \CURLOPT_SSLCERT, 'local_pk' => \CURLOPT_SSLKEY, 'passphrase' => \CURLOPT_SSLKEYPASSWD]]; /** @var array */ private static $timeInfo = ['total_time' => \true, 'namelookup_time' => \true, 'connect_time' => \true, 'pretransfer_time' => \true, 'starttransfer_time' => \true, 'redirect_time' => \true]; /** * @param mixed[] $options */ public function __construct(IOInterface $io, Config $config, array $options = [], bool $disableTls = \false) { $this->io = $io; $this->config = $config; $this->multiHandle = $mh = \curl_multi_init(); if (\function_exists('curl_multi_setopt')) { if (\Composer\Util\Http\ProxyManager::getInstance()->hasProxy() && ($version = \curl_version()) !== \false && \in_array($version['version'], self::BAD_MULTIPLEXING_CURL_VERSIONS, \true)) { /** * Disable HTTP/2 multiplexing for some broken versions of libcurl. * * In certain versions of libcurl when proxy is in use with HTTP/2 * multiplexing, connections will continue stacking up. This was * fixed in libcurl 8.0.0 in curl/curl@821f6e2a89de8aec1c7da3c0f381b92b2b801efc */ \curl_multi_setopt( $mh, \CURLMOPT_PIPELINING, /* CURLPIPE_NOTHING */ 0 ); } else { \curl_multi_setopt($mh, \CURLMOPT_PIPELINING, \PHP_VERSION_ID >= 70400 ? 2 : 3); } if (\defined('CURLMOPT_MAX_HOST_CONNECTIONS') && !\defined('_ContaoManager\\HHVM_VERSION')) { \curl_multi_setopt($mh, \CURLMOPT_MAX_HOST_CONNECTIONS, 8); } } if (\function_exists('curl_share_init')) { $this->shareHandle = $sh = \curl_share_init(); \curl_share_setopt($sh, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_COOKIE); \curl_share_setopt($sh, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_DNS); \curl_share_setopt($sh, \CURLSHOPT_SHARE, \CURL_LOCK_DATA_SSL_SESSION); } $this->authHelper = new AuthHelper($io, $config); } /** * @param mixed[] $options * @param non-empty-string $url * * @return int internal job id */ public function download(callable $resolve, callable $reject, string $origin, string $url, array $options, ?string $copyTo = null) : int { $attributes = []; if (isset($options['retry-auth-failure'])) { $attributes['retryAuthFailure'] = $options['retry-auth-failure']; unset($options['retry-auth-failure']); } return $this->initDownload($resolve, $reject, $origin, $url, $options, $copyTo, $attributes); } /** * @param mixed[] $options * * @param array{retryAuthFailure?: bool, redirects?: int<0, max>, retries?: int<0, max>, storeAuth?: 'prompt'|bool, ipResolve?: 4|6|null} $attributes * @param non-empty-string $url * * @return int internal job id */ private function initDownload(callable $resolve, callable $reject, string $origin, string $url, array $options, ?string $copyTo = null, array $attributes = []) : int { $attributes = \array_merge(['retryAuthFailure' => \true, 'redirects' => 0, 'retries' => 0, 'storeAuth' => \false, 'ipResolve' => null], $attributes); if ($attributes['ipResolve'] === null && Platform::getEnv('COMPOSER_IPRESOLVE') === '4') { $attributes['ipResolve'] = 4; } elseif ($attributes['ipResolve'] === null && Platform::getEnv('COMPOSER_IPRESOLVE') === '6') { $attributes['ipResolve'] = 6; } $originalOptions = $options; // check URL can be accessed (i.e. is not insecure), but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256 if (!Preg::isMatch('{^http://(repo\\.)?packagist\\.org/p/}', $url) || \false === \strpos($url, '$') && \false === \strpos($url, '%24')) { $this->config->prohibitUrlByConfig($url, $this->io, $options); } $curlHandle = \curl_init(); $headerHandle = \fopen('php://temp/maxmemory:32768', 'w+b'); if (\false === $headerHandle) { throw new \RuntimeException('Failed to open a temp stream to store curl headers'); } if ($copyTo !== null) { $bodyTarget = $copyTo . '~'; } else { $bodyTarget = 'php://temp/maxmemory:524288'; } $errorMessage = ''; \set_error_handler(static function (int $code, string $msg) use(&$errorMessage) : bool { if ($errorMessage) { $errorMessage .= "\n"; } $errorMessage .= Preg::replace('{^fopen\\(.*?\\): }', '', $msg); return \true; }); $bodyHandle = \fopen($bodyTarget, 'w+b'); \restore_error_handler(); if (\false === $bodyHandle) { throw new TransportException('The "' . $url . '" file could not be written to ' . ($copyTo ?? 'a temporary file') . ': ' . $errorMessage); } \curl_setopt($curlHandle, \CURLOPT_URL, $url); \curl_setopt($curlHandle, \CURLOPT_FOLLOWLOCATION, \false); \curl_setopt($curlHandle, \CURLOPT_CONNECTTIMEOUT, 10); \curl_setopt($curlHandle, \CURLOPT_TIMEOUT, \max((int) \ini_get("default_socket_timeout"), 300)); \curl_setopt($curlHandle, \CURLOPT_WRITEHEADER, $headerHandle); \curl_setopt($curlHandle, \CURLOPT_FILE, $bodyHandle); \curl_setopt($curlHandle, \CURLOPT_ENCODING, ""); // let cURL set the Accept-Encoding header to what it supports \curl_setopt($curlHandle, \CURLOPT_PROTOCOLS, \CURLPROTO_HTTP | \CURLPROTO_HTTPS); if ($attributes['ipResolve'] === 4) { \curl_setopt($curlHandle, \CURLOPT_IPRESOLVE, \CURL_IPRESOLVE_V4); } elseif ($attributes['ipResolve'] === 6) { \curl_setopt($curlHandle, \CURLOPT_IPRESOLVE, \CURL_IPRESOLVE_V6); } if (\function_exists('curl_share_init')) { \curl_setopt($curlHandle, \CURLOPT_SHARE, $this->shareHandle); } if (!isset($options['http']['header'])) { $options['http']['header'] = []; } $options['http']['header'] = \array_diff($options['http']['header'], ['Connection: close']); $options['http']['header'][] = 'Connection: keep-alive'; $version = \curl_version(); $features = $version['features']; if (0 === \strpos($url, 'https://') && \defined('CURL_VERSION_HTTP2') && \defined('CURL_HTTP_VERSION_2_0') && (\CURL_VERSION_HTTP2 & $features) !== 0) { \curl_setopt($curlHandle, \CURLOPT_HTTP_VERSION, \CURL_HTTP_VERSION_2_0); } // curl 8.7.0 - 8.7.1 has a bug whereas automatic accept-encoding header results in an error when reading the response // https://github.com/composer/composer/issues/11913 if (isset($version['version']) && \in_array($version['version'], ['8.7.0', '8.7.1'], \true) && \defined('CURL_VERSION_LIBZ') && (\CURL_VERSION_LIBZ & $features) !== 0) { \curl_setopt($curlHandle, \CURLOPT_ENCODING, "gzip"); } $options['http']['header'] = $this->authHelper->addAuthenticationHeader($options['http']['header'], $origin, $url); $options = StreamContextFactory::initOptions($url, $options, \true); foreach (self::$options as $type => $curlOptions) { foreach ($curlOptions as $name => $curlOption) { if (isset($options[$type][$name])) { if ($type === 'ssl' && $name === 'verify_peer_name') { \curl_setopt($curlHandle, $curlOption, $options[$type][$name] === \true ? 2 : $options[$type][$name]); } else { \curl_setopt($curlHandle, $curlOption, $options[$type][$name]); } } } } $proxy = \Composer\Util\Http\ProxyManager::getInstance()->getProxyForRequest($url); \curl_setopt_array($curlHandle, $proxy->getCurlOptions($options['ssl'] ?? [])); $progress = \array_diff_key(\curl_getinfo($curlHandle), self::$timeInfo); $this->jobs[(int) $curlHandle] = ['url' => $url, 'origin' => $origin, 'attributes' => $attributes, 'options' => $originalOptions, 'progress' => $progress, 'curlHandle' => $curlHandle, 'filename' => $copyTo, 'headerHandle' => $headerHandle, 'bodyHandle' => $bodyHandle, 'resolve' => $resolve, 'reject' => $reject, 'primaryIp' => '']; $usingProxy = $proxy->getStatus(' using proxy (%s)'); $ifModified = \false !== \stripos(\implode(',', $options['http']['header']), 'if-modified-since:') ? ' if modified' : ''; if ($attributes['redirects'] === 0 && $attributes['retries'] === 0) { $this->io->writeError('Downloading ' . Url::sanitize($url) . $usingProxy . $ifModified, \true, IOInterface::DEBUG); } $this->checkCurlResult(\curl_multi_add_handle($this->multiHandle, $curlHandle)); // TODO progress return (int) $curlHandle; } public function abortRequest(int $id) : void { if (isset($this->jobs[$id], $this->jobs[$id]['curlHandle'])) { $job = $this->jobs[$id]; \curl_multi_remove_handle($this->multiHandle, $job['curlHandle']); \curl_close($job['curlHandle']); if (\is_resource($job['headerHandle'])) { \fclose($job['headerHandle']); } if (\is_resource($job['bodyHandle'])) { \fclose($job['bodyHandle']); } if (null !== $job['filename']) { @\unlink($job['filename'] . '~'); } unset($this->jobs[$id]); } } public function tick() : void { static $timeoutWarning = \false; if (\count($this->jobs) === 0) { return; } $active = \true; $this->checkCurlResult(\curl_multi_exec($this->multiHandle, $active)); if (-1 === \curl_multi_select($this->multiHandle, $this->selectTimeout)) { // sleep in case select returns -1 as it can happen on old php versions or some platforms where curl does not manage to do the select \usleep(150); } while ($progress = \curl_multi_info_read($this->multiHandle)) { $curlHandle = $progress['handle']; $result = $progress['result']; $i = (int) $curlHandle; if (!isset($this->jobs[$i])) { continue; } $progress = \curl_getinfo($curlHandle); if (\false === $progress) { throw new \RuntimeException('Failed getting info from curl handle ' . $i . ' (' . $this->jobs[$i]['url'] . ')'); } $job = $this->jobs[$i]; unset($this->jobs[$i]); $error = \curl_error($curlHandle); $errno = \curl_errno($curlHandle); \curl_multi_remove_handle($this->multiHandle, $curlHandle); \curl_close($curlHandle); $headers = null; $statusCode = null; $response = null; try { // TODO progress if (\CURLE_OK !== $errno || $error || $result !== \CURLE_OK) { $errno = $errno ?: $result; if (!$error && \function_exists('curl_strerror')) { $error = \curl_strerror($errno); } $progress['error_code'] = $errno; if ((!isset($job['options']['http']['method']) || $job['options']['http']['method'] === 'GET') && (\in_array($errno, [7, 16, 92, 6], \true) || \in_array($errno, [56, 35], \true) && \str_contains((string) $error, 'Connection reset by peer')) && $job['attributes']['retries'] < $this->maxRetries) { $attributes = ['retries' => $job['attributes']['retries'] + 1]; if ($errno === 7 && !isset($job['attributes']['ipResolve'])) { // CURLE_COULDNT_CONNECT, retry forcing IPv4 if no IP stack was selected $attributes['ipResolve'] = 4; } $this->io->writeError('Retrying (' . ($job['attributes']['retries'] + 1) . ') ' . Url::sanitize($job['url']) . ' due to curl error ' . $errno, \true, IOInterface::DEBUG); $this->restartJobWithDelay($job, $job['url'], $attributes); continue; } // TODO: Remove this as soon as https://github.com/curl/curl/issues/10591 is resolved if ($errno === 55) { $this->io->writeError('Retrying (' . ($job['attributes']['retries'] + 1) . ') ' . Url::sanitize($job['url']) . ' due to curl error ' . $errno, \true, IOInterface::DEBUG); $this->restartJobWithDelay($job, $job['url'], ['retries' => $job['attributes']['retries'] + 1]); continue; } if ($errno === 28 && \PHP_VERSION_ID >= 70300 && $progress['namelookup_time'] === 0.0 && !$timeoutWarning) { $timeoutWarning = \true; $this->io->writeError('A connection timeout was encountered. If you intend to run Composer without connecting to the internet, run the command again prefixed with COMPOSER_DISABLE_NETWORK=1 to make Composer run in offline mode.'); } throw new TransportException('curl error ' . $errno . ' while downloading ' . Url::sanitize($progress['url']) . ': ' . $error); } $statusCode = $progress['http_code']; \rewind($job['headerHandle']); $headers = \explode("\r\n", \rtrim(\stream_get_contents($job['headerHandle']))); \fclose($job['headerHandle']); if ($statusCode === 0) { throw new \LogicException('Received unexpected http status code 0 without error for ' . Url::sanitize($progress['url']) . ': headers ' . \var_export($headers, \true) . ' curl info ' . \var_export($progress, \true)); } // prepare response object if (null !== $job['filename']) { $contents = $job['filename'] . '~'; if ($statusCode >= 300) { \rewind($job['bodyHandle']); $contents = \stream_get_contents($job['bodyHandle']); } $response = new \Composer\Util\Http\CurlResponse(['url' => $job['url']], $statusCode, $headers, $contents, $progress); $this->io->writeError('[' . $statusCode . '] ' . Url::sanitize($job['url']), \true, IOInterface::DEBUG); } else { $maxFileSize = $job['options']['max_file_size'] ?? null; \rewind($job['bodyHandle']); if ($maxFileSize !== null) { $contents = \stream_get_contents($job['bodyHandle'], $maxFileSize); // Gzipped responses with missing Content-Length header cannot be detected during the file download // because $progress['size_download'] refers to the gzipped size downloaded, not the actual file size if ($contents !== \false && Platform::strlen($contents) >= $maxFileSize) { throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . Platform::strlen($contents) . ' of allowed ' . $maxFileSize . ' bytes'); } } else { $contents = \stream_get_contents($job['bodyHandle']); } $response = new \Composer\Util\Http\CurlResponse(['url' => $job['url']], $statusCode, $headers, $contents, $progress); $this->io->writeError('[' . $statusCode . '] ' . Url::sanitize($job['url']), \true, IOInterface::DEBUG); } \fclose($job['bodyHandle']); if ($response->getStatusCode() >= 300 && $response->getHeader('content-type') === 'application/json') { HttpDownloader::outputWarnings($this->io, $job['origin'], \json_decode($response->getBody(), \true)); } $result = $this->isAuthenticatedRetryNeeded($job, $response); if ($result['retry']) { $this->restartJob($job, $job['url'], ['storeAuth' => $result['storeAuth'], 'retries' => $job['attributes']['retries'] + 1]); continue; } // handle 3xx redirects, 304 Not Modified is excluded if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $job['attributes']['redirects'] < $this->maxRedirects) { $location = $this->handleRedirect($job, $response); if ($location) { $this->restartJob($job, $location, ['redirects' => $job['attributes']['redirects'] + 1]); continue; } } // fail 4xx and 5xx responses and capture the response if ($statusCode >= 400 && $statusCode <= 599) { if ((!isset($job['options']['http']['method']) || $job['options']['http']['method'] === 'GET') && \in_array($statusCode, [423, 425, 500, 502, 503, 504, 507, 510], \true) && $job['attributes']['retries'] < $this->maxRetries) { $this->io->writeError('Retrying (' . ($job['attributes']['retries'] + 1) . ') ' . Url::sanitize($job['url']) . ' due to status code ' . $statusCode, \true, IOInterface::DEBUG); $this->restartJobWithDelay($job, $job['url'], ['retries' => $job['attributes']['retries'] + 1]); continue; } throw $this->failResponse($job, $response, $response->getStatusMessage()); } if ($job['attributes']['storeAuth'] !== \false) { $this->authHelper->storeAuth($job['origin'], $job['attributes']['storeAuth']); } // resolve promise if (null !== $job['filename']) { \rename($job['filename'] . '~', $job['filename']); $job['resolve']($response); } else { $job['resolve']($response); } } catch (\Exception $e) { if ($e instanceof TransportException) { if (null !== $headers) { $e->setHeaders($headers); $e->setStatusCode($statusCode); } if (null !== $response) { $e->setResponse($response->getBody()); } $e->setResponseInfo($progress); } $this->rejectJob($job, $e); } } foreach ($this->jobs as $i => $curlHandle) { $curlHandle = $this->jobs[$i]['curlHandle']; $progress = \array_diff_key(\curl_getinfo($curlHandle), self::$timeInfo); if ($this->jobs[$i]['progress'] !== $progress) { $this->jobs[$i]['progress'] = $progress; if (isset($this->jobs[$i]['options']['max_file_size'])) { // Compare max_file_size with the content-length header this value will be -1 until the header is parsed if ($this->jobs[$i]['options']['max_file_size'] < $progress['download_content_length']) { $this->rejectJob($this->jobs[$i], new MaxFileSizeExceededException('Maximum allowed download size reached. Content-length header indicates ' . $progress['download_content_length'] . ' bytes. Allowed ' . $this->jobs[$i]['options']['max_file_size'] . ' bytes')); } // Compare max_file_size with the download size in bytes if ($this->jobs[$i]['options']['max_file_size'] < $progress['size_download']) { $this->rejectJob($this->jobs[$i], new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . $progress['size_download'] . ' of allowed ' . $this->jobs[$i]['options']['max_file_size'] . ' bytes')); } } if (isset($progress['primary_ip']) && $progress['primary_ip'] !== $this->jobs[$i]['primaryIp']) { if (isset($this->jobs[$i]['options']['prevent_ip_access_callable']) && \is_callable($this->jobs[$i]['options']['prevent_ip_access_callable']) && $this->jobs[$i]['options']['prevent_ip_access_callable']($progress['primary_ip'])) { $this->rejectJob($this->jobs[$i], new TransportException(\sprintf('IP "%s" is blocked for "%s".', $progress['primary_ip'], $progress['url']))); } $this->jobs[$i]['primaryIp'] = (string) $progress['primary_ip']; } // TODO progress } } } /** * @param Job $job */ private function handleRedirect(array $job, \Composer\Util\Http\Response $response) : string { if ($locationHeader = $response->getHeader('location')) { if (\parse_url($locationHeader, \PHP_URL_SCHEME)) { // Absolute URL; e.g. https://example.com/composer $targetUrl = $locationHeader; } elseif (\parse_url($locationHeader, \PHP_URL_HOST)) { // Scheme relative; e.g. //example.com/foo $targetUrl = \parse_url($job['url'], \PHP_URL_SCHEME) . ':' . $locationHeader; } elseif ('/' === $locationHeader[0]) { // Absolute path; e.g. /foo $urlHost = \parse_url($job['url'], \PHP_URL_HOST); // Replace path using hostname as an anchor. $targetUrl = Preg::replace('{^(.+(?://|@)' . \preg_quote($urlHost) . '(?::\\d+)?)(?:[/\\?].*)?$}', '\\1' . $locationHeader, $job['url']); } else { // Relative path; e.g. foo // This actually differs from PHP which seems to add duplicate slashes. $targetUrl = Preg::replace('{^(.+/)[^/?]*(?:\\?.*)?$}', '\\1' . $locationHeader, $job['url']); } } if (!empty($targetUrl)) { $this->io->writeError(\sprintf('Following redirect (%u) %s', $job['attributes']['redirects'] + 1, Url::sanitize($targetUrl)), \true, IOInterface::DEBUG); return $targetUrl; } throw new TransportException('The "' . $job['url'] . '" file could not be downloaded, got redirect without Location (' . $response->getStatusMessage() . ')'); } /** * @param Job $job * @return array{retry: bool, storeAuth: 'prompt'|bool} */ private function isAuthenticatedRetryNeeded(array $job, \Composer\Util\Http\Response $response) : array { if (\in_array($response->getStatusCode(), [401, 403]) && $job['attributes']['retryAuthFailure']) { $result = $this->authHelper->promptAuthIfNeeded($job['url'], $job['origin'], $response->getStatusCode(), $response->getStatusMessage(), $response->getHeaders(), $job['attributes']['retries']); if ($result['retry']) { return $result; } } $locationHeader = $response->getHeader('location'); $needsAuthRetry = \false; // check for bitbucket login page asking to authenticate if ($job['origin'] === 'bitbucket.org' && !$this->authHelper->isPublicBitBucketDownload($job['url']) && \substr($job['url'], -4) === '.zip' && (!$locationHeader || \substr($locationHeader, -4) !== '.zip') && Preg::isMatch('{^text/html\\b}i', $response->getHeader('content-type'))) { $needsAuthRetry = 'Bitbucket requires authentication and it was not provided'; } // check for gitlab 404 when downloading archives if ($response->getStatusCode() === 404 && \in_array($job['origin'], $this->config->get('gitlab-domains'), \true) && \false !== \strpos($job['url'], 'archive.zip')) { $needsAuthRetry = 'GitLab requires authentication and it was not provided'; } if ($needsAuthRetry) { if ($job['attributes']['retryAuthFailure']) { $result = $this->authHelper->promptAuthIfNeeded($job['url'], $job['origin'], 401, null, [], $job['attributes']['retries']); if ($result['retry']) { return $result; } } throw $this->failResponse($job, $response, $needsAuthRetry); } return ['retry' => \false, 'storeAuth' => \false]; } /** * @param Job $job * @param non-empty-string $url * * @param array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries?: int<1, max>, ipResolve?: 4|6} $attributes */ private function restartJob(array $job, string $url, array $attributes = []) : void { if (null !== $job['filename']) { @\unlink($job['filename'] . '~'); } $attributes = \array_merge($job['attributes'], $attributes); $origin = Url::getOrigin($this->config, $url); $this->initDownload($job['resolve'], $job['reject'], $origin, $url, $job['options'], $job['filename'], $attributes); } /** * @param Job $job * @param non-empty-string $url * * @param array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries: int<1, max>, ipResolve?: 4|6} $attributes */ private function restartJobWithDelay(array $job, string $url, array $attributes) : void { if ($attributes['retries'] >= 3) { \usleep(500000); // half a second delay for 3rd retry and beyond } elseif ($attributes['retries'] >= 2) { \usleep(100000); // 100ms delay for 2nd retry } // no sleep for the first retry $this->restartJob($job, $url, $attributes); } /** * @param Job $job */ private function failResponse(array $job, \Composer\Util\Http\Response $response, string $errorMessage) : TransportException { if (null !== $job['filename']) { @\unlink($job['filename'] . '~'); } $details = ''; if (\in_array(\strtolower((string) $response->getHeader('content-type')), ['application/json', 'application/json; charset=utf-8'], \true)) { $details = ':' . \PHP_EOL . \substr($response->getBody(), 0, 200) . (\strlen($response->getBody()) > 200 ? '...' : ''); } return new TransportException('The "' . $job['url'] . '" file could not be downloaded (' . $errorMessage . ')' . $details, $response->getStatusCode()); } /** * @param Job $job */ private function rejectJob(array $job, \Exception $e) : void { if (\is_resource($job['headerHandle'])) { \fclose($job['headerHandle']); } if (\is_resource($job['bodyHandle'])) { \fclose($job['bodyHandle']); } if (null !== $job['filename']) { @\unlink($job['filename'] . '~'); } $job['reject']($e); } private function checkCurlResult(int $code) : void { if ($code !== \CURLM_OK && $code !== \CURLM_CALL_MULTI_PERFORM) { throw new \RuntimeException(isset($this->multiErrors[$code]) ? "cURL error: {$code} ({$this->multiErrors[$code][0]}): cURL message: {$this->multiErrors[$code][1]}" : 'Unexpected cURL error: ' . $code); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util\Http; /** * @phpstan-type CurlInfo array{url: mixed, content_type: mixed, http_code: mixed, header_size: mixed, request_size: mixed, filetime: mixed, ssl_verify_result: mixed, redirect_count: mixed, total_time: mixed, namelookup_time: mixed, connect_time: mixed, pretransfer_time: mixed, size_upload: mixed, size_download: mixed, speed_download: mixed, speed_upload: mixed, download_content_length: mixed, upload_content_length: mixed, starttransfer_time: mixed, redirect_time: mixed, certinfo: mixed, primary_ip: mixed, primary_port: mixed, local_ip: mixed, local_port: mixed, redirect_url: mixed} */ class CurlResponse extends \Composer\Util\Http\Response { /** * @see https://www.php.net/curl_getinfo * @var array * @phpstan-var CurlInfo */ private $curlInfo; /** * @phpstan-param CurlInfo $curlInfo */ public function __construct(array $request, ?int $code, array $headers, ?string $body, array $curlInfo) { parent::__construct($request, $code, $headers, $body); $this->curlInfo = $curlInfo; } /** * @phpstan-return CurlInfo */ public function getCurlInfo() : array { return $this->curlInfo; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util\Http; /** * @internal * @author John Stevenson */ class ProxyItem { /** @var non-empty-string */ private $url; /** @var non-empty-string */ private $safeUrl; /** @var ?non-empty-string */ private $curlAuth; /** @var string */ private $optionsProxy; /** @var ?non-empty-string */ private $optionsAuth; /** * @param string $proxyUrl The value from the environment * @param string $envName The name of the environment variable * @throws \RuntimeException If the proxy url is invalid */ public function __construct(string $proxyUrl, string $envName) { $syntaxError = \sprintf('unsupported `%s` syntax', $envName); if (\strpbrk($proxyUrl, "\r\n\t") !== \false) { throw new \RuntimeException($syntaxError); } if (\false === ($proxy = \parse_url($proxyUrl))) { throw new \RuntimeException($syntaxError); } if (!isset($proxy['host'])) { throw new \RuntimeException('unable to find proxy host in ' . $envName); } $scheme = isset($proxy['scheme']) ? \strtolower($proxy['scheme']) . '://' : 'http://'; $safe = ''; if (isset($proxy['user'])) { $safe = '***'; $user = $proxy['user']; $auth = \rawurldecode($proxy['user']); if (isset($proxy['pass'])) { $safe .= ':***'; $user .= ':' . $proxy['pass']; $auth .= ':' . \rawurldecode($proxy['pass']); } $safe .= '@'; if (\strlen($user) > 0) { $this->curlAuth = $user; $this->optionsAuth = 'Proxy-Authorization: Basic ' . \base64_encode($auth); } } $host = $proxy['host']; $port = null; if (isset($proxy['port'])) { $port = $proxy['port']; } elseif ($scheme === 'http://') { $port = 80; } elseif ($scheme === 'https://') { $port = 443; } // We need a port because curl uses 1080 for http. Port 0 is reserved, // but is considered valid depending on the PHP or Curl version. if ($port === null) { throw new \RuntimeException('unable to find proxy port in ' . $envName); } if ($port === 0) { throw new \RuntimeException('port 0 is reserved in ' . $envName); } $this->url = \sprintf('%s%s:%d', $scheme, $host, $port); $this->safeUrl = \sprintf('%s%s%s:%d', $scheme, $safe, $host, $port); $scheme = \str_replace(['http://', 'https://'], ['tcp://', 'ssl://'], $scheme); $this->optionsProxy = \sprintf('%s%s:%d', $scheme, $host, $port); } /** * Returns a RequestProxy instance for the scheme of the request url * * @param string $scheme The scheme of the request url */ public function toRequestProxy(string $scheme) : \Composer\Util\Http\RequestProxy { $options = ['http' => ['proxy' => $this->optionsProxy]]; if ($this->optionsAuth !== null) { $options['http']['header'] = $this->optionsAuth; } if ($scheme === 'http') { $options['http']['request_fulluri'] = \true; } return new \Composer\Util\Http\RequestProxy($this->url, $this->curlAuth, $options, $this->safeUrl); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; @\trigger_error('Composer\\Util\\MetadataMinifier is deprecated, use Composer\\MetadataMinifier\\MetadataMinifier from composer/metadata-minifier instead.', \E_USER_DEPRECATED); /** * @deprecated Use Composer\MetadataMinifier\MetadataMinifier instead */ class MetadataMinifier extends \Composer\MetadataMinifier\MetadataMinifier { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use _ContaoManager\Seld\Signal\SignalHandler; use _ContaoManager\Symfony\Component\Process\Exception\ProcessSignaledException; use _ContaoManager\Symfony\Component\Process\Process; use _ContaoManager\Symfony\Component\Process\Exception\RuntimeException; use React\Promise\Promise; use React\Promise\PromiseInterface; use _ContaoManager\Symfony\Component\Process\ExecutableFinder; /** * @author Robert Schönthal * @author Jordi Boggiano */ class ProcessExecutor { private const STATUS_QUEUED = 1; private const STATUS_STARTED = 2; private const STATUS_COMPLETED = 3; private const STATUS_FAILED = 4; private const STATUS_ABORTED = 5; private const BUILTIN_CMD_COMMANDS = ['assoc', 'break', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date', 'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype', 'goto', 'help', 'if', 'label', 'md', 'mkdir', 'mklink', 'move', 'path', 'pause', 'popd', 'prompt', 'pushd', 'rd', 'rem', 'ren', 'rename', 'rmdir', 'set', 'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver', 'vol']; private const GIT_CMDS_NEED_GIT_DIR = [['show'], ['log'], ['branch'], ['remote', 'set-url']]; /** @var int */ protected static $timeout = 300; /** @var bool */ protected $captureOutput = \false; /** @var string */ protected $errorOutput = ''; /** @var ?IOInterface */ protected $io; /** * @phpstan-var array> */ private $jobs = []; /** @var int */ private $runningJobs = 0; /** @var int */ private $maxJobs = 10; /** @var int */ private $idGen = 0; /** @var bool */ private $allowAsync = \false; /** @var array */ private static $executables = []; public function __construct(?IOInterface $io = null) { $this->io = $io; } /** * runs a process on the commandline * * @param string|non-empty-list $command the command to execute * @param mixed $output the output will be written into this var if passed by ref * if a callable is passed it will be used as output handler * @param null|string $cwd the working directory * @return int statuscode */ public function execute($command, &$output = null, ?string $cwd = null) : int { if (\func_num_args() > 1) { return $this->doExecute($command, $cwd, \false, $output); } return $this->doExecute($command, $cwd, \false); } /** * runs a process on the commandline in TTY mode * * @param string|non-empty-list $command the command to execute * @param null|string $cwd the working directory * @return int statuscode */ public function executeTty($command, ?string $cwd = null) : int { if (\Composer\Util\Platform::isTty()) { return $this->doExecute($command, $cwd, \true); } return $this->doExecute($command, $cwd, \false); } /** * @param string|non-empty-list $command * @param array|null $env * @param mixed $output */ private function runProcess($command, ?string $cwd, ?array $env, bool $tty, &$output = null) : ?int { // On Windows, we don't rely on the OS to find the executable if possible to avoid lookups // in the current directory which could be untrusted. Instead we use the ExecutableFinder. if (\is_string($command)) { if (\Composer\Util\Platform::isWindows() && Preg::isMatch('{^([^:/\\\\]++) }', $command, $match)) { $command = \substr_replace($command, self::escape(self::getExecutable($match[1])), 0, \strlen($match[1])); } $process = Process::fromShellCommandline($command, $cwd, $env, null, static::getTimeout()); } else { if (\Composer\Util\Platform::isWindows() && \strlen($command[0]) === \strcspn($command[0], ':/\\')) { $command[0] = self::getExecutable($command[0]); } $process = new Process($command, $cwd, $env, null, static::getTimeout()); } if (!\Composer\Util\Platform::isWindows() && $tty) { try { $process->setTty(\true); } catch (RuntimeException $e) { // ignore TTY enabling errors } } $callback = \is_callable($output) ? $output : function (string $type, string $buffer) : void { $this->outputHandler($type, $buffer); }; $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal) { if ($this->io !== null) { $this->io->writeError('Received ' . $signal . ', aborting when child process is done', \true, IOInterface::DEBUG); } }); try { $process->run($callback); if ($this->captureOutput && !\is_callable($output)) { $output = $process->getOutput(); } $this->errorOutput = $process->getErrorOutput(); } catch (ProcessSignaledException $e) { if ($signalHandler->isTriggered()) { // exiting as we were signaled and the child process exited too due to the signal $signalHandler->exitWithLastSignal(); } } finally { $signalHandler->unregister(); } return $process->getExitCode(); } /** * @param string|non-empty-list $command * @param mixed $output */ private function doExecute($command, ?string $cwd, bool $tty, &$output = null) : int { $this->outputCommandRun($command, $cwd, \false); $this->captureOutput = \func_num_args() > 3; $this->errorOutput = ''; $env = null; $requiresGitDirEnv = $this->requiresGitDirEnv($command); if ($cwd !== null && $requiresGitDirEnv) { $isBareRepository = !\is_dir(\sprintf('%s/.git', \rtrim($cwd, '/'))); if ($isBareRepository) { $configValue = ''; $this->runProcess(['git', 'config', 'safe.bareRepository'], $cwd, ['GIT_DIR' => $cwd], $tty, $configValue); $configValue = \trim($configValue); if ($configValue === 'explicit') { $env = ['GIT_DIR' => $cwd]; } } } return $this->runProcess($command, $cwd, $env, $tty, $output); } /** * starts a process on the commandline in async mode * * @param string|list $command the command to execute * @param string $cwd the working directory * @phpstan-return PromiseInterface */ public function executeAsync($command, ?string $cwd = null) : PromiseInterface { if (!$this->allowAsync) { throw new \LogicException('You must use the ProcessExecutor instance which is part of a Composer\\Loop instance to be able to run async processes'); } $job = ['id' => $this->idGen++, 'status' => self::STATUS_QUEUED, 'command' => $command, 'cwd' => $cwd]; $resolver = static function ($resolve, $reject) use(&$job) : void { $job['status'] = \Composer\Util\ProcessExecutor::STATUS_QUEUED; $job['resolve'] = $resolve; $job['reject'] = $reject; }; $canceler = static function () use(&$job) : void { if ($job['status'] === \Composer\Util\ProcessExecutor::STATUS_QUEUED) { $job['status'] = \Composer\Util\ProcessExecutor::STATUS_ABORTED; } if ($job['status'] !== \Composer\Util\ProcessExecutor::STATUS_STARTED) { return; } $job['status'] = \Composer\Util\ProcessExecutor::STATUS_ABORTED; try { if (\defined('SIGINT')) { $job['process']->signal(\SIGINT); } } catch (\Exception $e) { // signal can throw in various conditions, but we don't care if it fails } $job['process']->stop(1); throw new \RuntimeException('Aborted process'); }; $promise = new Promise($resolver, $canceler); $promise = $promise->then(function () use(&$job) { if ($job['process']->isSuccessful()) { $job['status'] = \Composer\Util\ProcessExecutor::STATUS_COMPLETED; } else { $job['status'] = \Composer\Util\ProcessExecutor::STATUS_FAILED; } $this->markJobDone(); return $job['process']; }, function ($e) use(&$job) : void { $job['status'] = \Composer\Util\ProcessExecutor::STATUS_FAILED; $this->markJobDone(); throw $e; }); $this->jobs[$job['id']] =& $job; if ($this->runningJobs < $this->maxJobs) { $this->startJob($job['id']); } return $promise; } protected function outputHandler(string $type, string $buffer) : void { if ($this->captureOutput) { return; } if (null === $this->io) { echo $buffer; return; } if (Process::ERR === $type) { $this->io->writeErrorRaw($buffer, \false); } else { $this->io->writeRaw($buffer, \false); } } private function startJob(int $id) : void { $job =& $this->jobs[$id]; if ($job['status'] !== self::STATUS_QUEUED) { return; } // start job $job['status'] = self::STATUS_STARTED; $this->runningJobs++; $command = $job['command']; $cwd = $job['cwd']; $this->outputCommandRun($command, $cwd, \true); try { if (\is_string($command)) { $process = Process::fromShellCommandline($command, $cwd, null, null, static::getTimeout()); } else { $process = new Process($command, $cwd, null, null, static::getTimeout()); } } catch (\Throwable $e) { $job['reject']($e); return; } $job['process'] = $process; try { $process->start(); } catch (\Throwable $e) { $job['reject']($e); return; } } public function setMaxJobs(int $maxJobs) : void { $this->maxJobs = $maxJobs; } public function resetMaxJobs() : void { $this->maxJobs = 10; } /** * @param ?int $index job id */ public function wait($index = null) : void { while (\true) { if (0 === $this->countActiveJobs($index)) { return; } \usleep(1000); } } /** * @internal */ public function enableAsync() : void { $this->allowAsync = \true; } /** * @internal * * @param ?int $index job id * @return int number of active (queued or started) jobs */ public function countActiveJobs($index = null) : int { // tick foreach ($this->jobs as $job) { if ($job['status'] === self::STATUS_STARTED) { if (!$job['process']->isRunning()) { \call_user_func($job['resolve'], $job['process']); } $job['process']->checkTimeout(); } if ($this->runningJobs < $this->maxJobs) { if ($job['status'] === self::STATUS_QUEUED) { $this->startJob($job['id']); } } } if (null !== $index) { return $this->jobs[$index]['status'] < self::STATUS_COMPLETED ? 1 : 0; } $active = 0; foreach ($this->jobs as $job) { if ($job['status'] < self::STATUS_COMPLETED) { $active++; } else { unset($this->jobs[$job['id']]); } } return $active; } private function markJobDone() : void { $this->runningJobs--; } /** * @return string[] */ public function splitLines(?string $output) : array { $output = \trim((string) $output); return $output === '' ? [] : Preg::split('{\\r?\\n}', $output); } /** * Get any error output from the last command */ public function getErrorOutput() : string { return $this->errorOutput; } /** * @return int the timeout in seconds */ public static function getTimeout() : int { return static::$timeout; } /** * @param int $timeout the timeout in seconds */ public static function setTimeout(int $timeout) : void { static::$timeout = $timeout; } /** * Escapes a string to be used as a shell argument. * * @param string|false|null $argument The argument that will be escaped * * @return string The escaped argument */ public static function escape($argument) : string { return self::escapeArgument($argument); } /** * @param string|list $command */ private function outputCommandRun($command, ?string $cwd, bool $async) : void { if (null === $this->io || !$this->io->isDebug()) { return; } $commandString = \is_string($command) ? $command : \implode(' ', \array_map(self::class . '::escape', $command)); $safeCommand = Preg::replaceCallback('{://(?P[^:/\\s]+):(?P[^@\\s/]+)@}i', static function ($m) : string { // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx) we obfuscate that if (Preg::isMatch('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) { return '://***:***@'; } if (Preg::isMatch('{^[a-f0-9]{12,}$}', $m['user'])) { return '://***:***@'; } return '://' . $m['user'] . ':***@'; }, $commandString); $safeCommand = Preg::replace("{--password (.*[^\\\\]\\') }", '--password \'***\' ', $safeCommand); $this->io->writeError('Executing' . ($async ? ' async' : '') . ' command (' . ($cwd ?: 'CWD') . '): ' . $safeCommand); } /** * Escapes a string to be used as a shell argument for Symfony Process. * * This method expects cmd.exe to be started with the /V:ON option, which * enables delayed environment variable expansion using ! as the delimiter. * If this is not the case, any escaped ^^!var^^! will be transformed to * ^!var^! and introduce two unintended carets. * * Modified from https://github.com/johnstevenson/winbox-args * MIT Licensed (c) John Stevenson * * @param string|false|null $argument */ private static function escapeArgument($argument) : string { if ('' === ($argument = (string) $argument)) { return \escapeshellarg($argument); } if (!\Composer\Util\Platform::isWindows()) { return "'" . \str_replace("'", "'\\''", $argument) . "'"; } // New lines break cmd.exe command parsing // and special chars like the fullwidth quote can be used to break out // of parameter encoding via "Best Fit" encoding conversion $argument = \strtr($argument, ["\n" => ' ', """ => '"', "ʺ" => '"', "〝" => '"', "〞" => '"', "̎" => '"', ":" => ':', "։" => ':', "∶" => ':', "/" => '/', "⁄" => '/', "∕" => '/', "´" => '/']); // In addition to whitespace, commas need quoting to preserve paths $quote = \strpbrk($argument, " \t,") !== \false; $argument = Preg::replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes); $meta = $dquotes > 0 || Preg::isMatch('/%[^%]+%|![^!]+!/', $argument); if (!$meta && !$quote) { $quote = \strpbrk($argument, '^&|<>()') !== \false; } if ($quote) { $argument = '"' . Preg::replace('/(\\\\*)$/', '$1$1', $argument) . '"'; } if ($meta) { $argument = Preg::replace('/(["^&|<>()%])/', '^$1', $argument); $argument = Preg::replace('/(!)/', '^^$1', $argument); } return $argument; } /** * @param string[]|string $command */ public function requiresGitDirEnv($command) : bool { $cmd = !\is_array($command) ? \explode(' ', $command) : $command; if ($cmd[0] !== 'git') { return \false; } foreach (self::GIT_CMDS_NEED_GIT_DIR as $gitCmd) { if (\array_intersect($cmd, $gitCmd) === $gitCmd) { return \true; } } return \false; } /** * Resolves executable paths on Windows */ private static function getExecutable(string $name) : string { if (\in_array(\strtolower($name), self::BUILTIN_CMD_COMMANDS, \true)) { return $name; } if (!isset(self::$executables[$name])) { $path = (new ExecutableFinder())->find($name, $name); if ($path !== null) { self::$executables[$name] = $path; } } return self::$executables[$name] ?? $name; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; use Composer\Pcre\Preg; /** * @author Jonas Renaudot */ class Hg { /** @var string|false|null */ private static $version = \false; /** * @var \Composer\IO\IOInterface */ private $io; /** * @var \Composer\Config */ private $config; /** * @var \Composer\Util\ProcessExecutor */ private $process; public function __construct(IOInterface $io, Config $config, \Composer\Util\ProcessExecutor $process) { $this->io = $io; $this->config = $config; $this->process = $process; } public function runCommand(callable $commandCallable, string $url, ?string $cwd) : void { $this->config->prohibitUrlByConfig($url, $this->io); // Try as is $command = $commandCallable($url); if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) { return; } // Try with the authentication information available if (Preg::isMatch('{^(?Pssh|https?)://(?:(?P[^:@]+)(?::(?P[^:@]+))?@)?(?P[^/]+)(?P/.*)?}mi', $url, $matches) && $this->io->hasAuthentication($matches['host'])) { if ($matches['proto'] === 'ssh') { $user = ''; if ($matches['user'] !== null) { $user = \rawurlencode($matches['user']) . '@'; } $authenticatedUrl = $matches['proto'] . '://' . $user . $matches['host'] . $matches['path']; } else { $auth = $this->io->getAuthentication($matches['host']); $authenticatedUrl = $matches['proto'] . '://' . \rawurlencode((string) $auth['username']) . ':' . \rawurlencode((string) $auth['password']) . '@' . $matches['host'] . $matches['path']; } $command = $commandCallable($authenticatedUrl); if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) { return; } $error = $this->process->getErrorOutput(); } else { $error = 'The given URL (' . $url . ') does not match the required format (ssh|http(s)://(username:password@)example.com/path-to-repository)'; } $this->throwException("Failed to clone {$url}, \n\n" . $error, $url); } /** * @param non-empty-string $message * * @return never */ private function throwException($message, string $url) : void { if (null === self::getVersion($this->process)) { throw new \RuntimeException(\Composer\Util\Url::sanitize('Failed to clone ' . $url . ', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput())); } throw new \RuntimeException(\Composer\Util\Url::sanitize($message)); } /** * Retrieves the current hg version. * * @return string|null The hg version number, if present. */ public static function getVersion(\Composer\Util\ProcessExecutor $process) : ?string { if (\false === self::$version) { self::$version = null; if (0 === $process->execute(['hg', '--version'], $output) && Preg::isMatch('/^.+? (\\d+(?:\\.\\d+)+)(?:\\+.*?)?\\)?\\r?\\n/', $output, $matches)) { self::$version = $matches[1]; } } return self::$version; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Config; use Composer\Downloader\MaxFileSizeExceededException; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; use Composer\Pcre\Preg; use Composer\Util\Http\Response; use Composer\Util\Http\ProxyManager; /** * @internal * @author François Pluchino * @author Jordi Boggiano * @author Nils Adermann */ class RemoteFilesystem { /** @var IOInterface */ private $io; /** @var Config */ private $config; /** @var string */ private $scheme; /** @var int */ private $bytesMax; /** @var string */ private $originUrl; /** @var non-empty-string */ private $fileUrl; /** @var ?string */ private $fileName; /** @var bool */ private $retry = \false; /** @var bool */ private $progress; /** @var ?int */ private $lastProgress; /** @var mixed[] */ private $options = []; /** @var bool */ private $disableTls = \false; /** @var list */ private $lastHeaders; /** @var bool */ private $storeAuth = \false; /** @var AuthHelper */ private $authHelper; /** @var bool */ private $degradedMode = \false; /** @var int */ private $redirects; /** @var int */ private $maxRedirects = 20; /** * Constructor. * * @param IOInterface $io The IO instance * @param Config $config The config * @param mixed[] $options The options * @param AuthHelper $authHelper */ public function __construct(IOInterface $io, Config $config, array $options = [], bool $disableTls = \false, ?\Composer\Util\AuthHelper $authHelper = null) { $this->io = $io; // Setup TLS options // The cafile option can be set via config.json if ($disableTls === \false) { $this->options = \Composer\Util\StreamContextFactory::getTlsDefaults($options, $io); } else { $this->disableTls = \true; } // handle the other externally set options normally. $this->options = \array_replace_recursive($this->options, $options); $this->config = $config; $this->authHelper = $authHelper ?? new \Composer\Util\AuthHelper($io, $config); } /** * Copy the remote file in local. * * @param string $originUrl The origin URL * @param non-empty-string $fileUrl The file URL * @param string $fileName the local filename * @param bool $progress Display the progression * @param mixed[] $options Additional context options * * @return bool true */ public function copy(string $originUrl, string $fileUrl, string $fileName, bool $progress = \true, array $options = []) { return $this->get($originUrl, $fileUrl, $options, $fileName, $progress); } /** * Get the content. * * @param string $originUrl The origin URL * @param non-empty-string $fileUrl The file URL * @param bool $progress Display the progression * @param mixed[] $options Additional context options * * @return bool|string The content */ public function getContents(string $originUrl, string $fileUrl, bool $progress = \true, array $options = []) { return $this->get($originUrl, $fileUrl, $options, null, $progress); } /** * Retrieve the options set in the constructor * * @return mixed[] Options */ public function getOptions() { return $this->options; } /** * Merges new options * * @param mixed[] $options * @return void */ public function setOptions(array $options) { $this->options = \array_replace_recursive($this->options, $options); } /** * Check is disable TLS. * * @return bool */ public function isTlsDisabled() { return $this->disableTls === \true; } /** * Returns the headers of the last request * * @return list */ public function getLastHeaders() { return $this->lastHeaders; } /** * @param string[] $headers array of returned headers like from getLastHeaders() * @return int|null */ public static function findStatusCode(array $headers) { $value = null; foreach ($headers as $header) { if (Preg::isMatch('{^HTTP/\\S+ (\\d+)}i', $header, $match)) { // In case of redirects, http_response_headers contains the headers of all responses // so we can not return directly and need to keep iterating $value = (int) $match[1]; } } return $value; } /** * @param string[] $headers array of returned headers like from getLastHeaders() * @return string|null */ public function findStatusMessage(array $headers) { $value = null; foreach ($headers as $header) { if (Preg::isMatch('{^HTTP/\\S+ \\d+}i', $header)) { // In case of redirects, http_response_headers contains the headers of all responses // so we can not return directly and need to keep iterating $value = $header; } } return $value; } /** * Get file content or copy action. * * @param string $originUrl The origin URL * @param non-empty-string $fileUrl The file URL * @param mixed[] $additionalOptions context options * @param string $fileName the local filename * @param bool $progress Display the progression * * @throws TransportException|\Exception * @throws TransportException When the file could not be downloaded * * @return bool|string */ protected function get(string $originUrl, string $fileUrl, array $additionalOptions = [], ?string $fileName = null, bool $progress = \true) { $this->scheme = \parse_url(\strtr($fileUrl, '\\', '/'), \PHP_URL_SCHEME); $this->bytesMax = 0; $this->originUrl = $originUrl; $this->fileUrl = $fileUrl; $this->fileName = $fileName; $this->progress = $progress; $this->lastProgress = null; $retryAuthFailure = \true; $this->lastHeaders = []; $this->redirects = 1; // The first request counts. $tempAdditionalOptions = $additionalOptions; if (isset($tempAdditionalOptions['retry-auth-failure'])) { $retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure']; unset($tempAdditionalOptions['retry-auth-failure']); } $isRedirect = \false; if (isset($tempAdditionalOptions['redirects'])) { $this->redirects = $tempAdditionalOptions['redirects']; $isRedirect = \true; unset($tempAdditionalOptions['redirects']); } $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions); unset($tempAdditionalOptions); $origFileUrl = $fileUrl; if (isset($options['prevent_ip_access_callable'])) { throw new \RuntimeException("RemoteFilesystem doesn't support the 'prevent_ip_access_callable' config."); } if (isset($options['gitlab-token'])) { $fileUrl .= (\false === \strpos($fileUrl, '?') ? '?' : '&') . 'access_token=' . $options['gitlab-token']; unset($options['gitlab-token']); } if (isset($options['http'])) { $options['http']['ignore_errors'] = \true; } if ($this->degradedMode && \strpos($fileUrl, 'http://repo.packagist.org/') === 0) { // access packagist using the resolved IPv4 instead of the hostname to force IPv4 protocol $fileUrl = 'http://' . \gethostbyname('repo.packagist.org') . \substr($fileUrl, 20); $degradedPackagist = \true; } $maxFileSize = null; if (isset($options['max_file_size'])) { $maxFileSize = $options['max_file_size']; unset($options['max_file_size']); } $ctx = \Composer\Util\StreamContextFactory::getContext($fileUrl, $options, ['notification' => [$this, 'callbackGet']]); $proxy = ProxyManager::getInstance()->getProxyForRequest($fileUrl); $usingProxy = $proxy->getStatus(' using proxy (%s)'); $this->io->writeError((\strpos($origFileUrl, 'http') === 0 ? 'Downloading ' : 'Reading ') . \Composer\Util\Url::sanitize($origFileUrl) . $usingProxy, \true, IOInterface::DEBUG); unset($origFileUrl, $proxy, $usingProxy); // Check for secure HTTP, but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256 if ((!Preg::isMatch('{^http://(repo\\.)?packagist\\.org/p/}', $fileUrl) || \false === \strpos($fileUrl, '$') && \false === \strpos($fileUrl, '%24')) && empty($degradedPackagist)) { $this->config->prohibitUrlByConfig($fileUrl, $this->io); } if ($this->progress && !$isRedirect) { $this->io->writeError("Downloading (connecting...)", \false); } $errorMessage = ''; $errorCode = 0; $result = \false; \set_error_handler(static function ($code, $msg) use(&$errorMessage) : bool { if ($errorMessage) { $errorMessage .= "\n"; } $errorMessage .= Preg::replace('{^file_get_contents\\(.*?\\): }', '', $msg); return \true; }); $http_response_header = []; try { $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header, $maxFileSize); if (!empty($http_response_header[0])) { $statusCode = self::findStatusCode($http_response_header); if ($statusCode >= 300 && Response::findHeaderValue($http_response_header, 'content-type') === 'application/json') { \Composer\Util\HttpDownloader::outputWarnings($this->io, $originUrl, \json_decode($result, \true)); } if (\in_array($statusCode, [401, 403]) && $retryAuthFailure) { $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), $http_response_header); } } $contentLength = !empty($http_response_header[0]) ? Response::findHeaderValue($http_response_header, 'content-length') : null; if ($contentLength && \Composer\Util\Platform::strlen($result) < $contentLength) { // alas, this is not possible via the stream callback because STREAM_NOTIFY_COMPLETED is documented, but not implemented anywhere in PHP $e = new TransportException('Content-Length mismatch, received ' . \Composer\Util\Platform::strlen($result) . ' bytes out of the expected ' . $contentLength); $e->setHeaders($http_response_header); $e->setStatusCode(self::findStatusCode($http_response_header)); try { $e->setResponse($this->decodeResult($result, $http_response_header)); } catch (\Exception $discarded) { $e->setResponse($this->normalizeResult($result)); } $this->io->writeError('Content-Length mismatch, received ' . \Composer\Util\Platform::strlen($result) . ' out of ' . $contentLength . ' bytes: (' . \base64_encode($result) . ')', \true, IOInterface::DEBUG); throw $e; } } catch (\Exception $e) { if ($e instanceof TransportException && !empty($http_response_header[0])) { $e->setHeaders($http_response_header); $e->setStatusCode(self::findStatusCode($http_response_header)); } if ($e instanceof TransportException && $result !== \false) { $e->setResponse($this->decodeResult($result, $http_response_header)); } $result = \false; } if ($errorMessage && !\filter_var(\ini_get('allow_url_fopen'), \FILTER_VALIDATE_BOOLEAN)) { $errorMessage = 'allow_url_fopen must be enabled in php.ini (' . $errorMessage . ')'; } \restore_error_handler(); if (isset($e) && !$this->retry) { if (!$this->degradedMode && \false !== \strpos($e->getMessage(), 'Operation timed out')) { $this->degradedMode = \true; $this->io->writeError(''); $this->io->writeError(['' . $e->getMessage() . '', 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info']); return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); } throw $e; } $statusCode = null; $contentType = null; $locationHeader = null; if (!empty($http_response_header[0])) { $statusCode = self::findStatusCode($http_response_header); $contentType = Response::findHeaderValue($http_response_header, 'content-type'); $locationHeader = Response::findHeaderValue($http_response_header, 'location'); } // check for bitbucket login page asking to authenticate if ($originUrl === 'bitbucket.org' && !$this->authHelper->isPublicBitBucketDownload($fileUrl) && \substr($fileUrl, -4) === '.zip' && (!$locationHeader || \substr(\parse_url($locationHeader, \PHP_URL_PATH), -4) !== '.zip') && $contentType && Preg::isMatch('{^text/html\\b}i', $contentType)) { $result = \false; if ($retryAuthFailure) { $this->promptAuthAndRetry(401); } } // check for gitlab 404 when downloading archives if ($statusCode === 404 && \in_array($originUrl, $this->config->get('gitlab-domains'), \true) && \false !== \strpos($fileUrl, 'archive.zip')) { $result = \false; if ($retryAuthFailure) { $this->promptAuthAndRetry(401); } } // handle 3xx redirects, 304 Not Modified is excluded $hasFollowedRedirect = \false; if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) { $hasFollowedRedirect = \true; $result = $this->handleRedirect($http_response_header, $additionalOptions, $result); } // fail 4xx and 5xx responses and capture the response if ($statusCode && $statusCode >= 400 && $statusCode <= 599) { if (!$this->retry) { if ($this->progress && !$isRedirect) { $this->io->overwriteError("Downloading (failed)", \false); } $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded (' . $http_response_header[0] . ')', $statusCode); $e->setHeaders($http_response_header); $e->setResponse($this->decodeResult($result, $http_response_header)); $e->setStatusCode($statusCode); throw $e; } $result = \false; } if ($this->progress && !$this->retry && !$isRedirect) { $this->io->overwriteError("Downloading (" . ($result === \false ? 'failed' : '100%') . ")", \false); } // decode gzip if ($result && \extension_loaded('zlib') && \strpos($fileUrl, 'http') === 0 && !$hasFollowedRedirect) { try { $result = $this->decodeResult($result, $http_response_header); } catch (\Exception $e) { if ($this->degradedMode) { throw $e; } $this->degradedMode = \true; $this->io->writeError(['', 'Failed to decode response: ' . $e->getMessage() . '', 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info']); return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); } } // handle copy command if download was successful if (\false !== $result && null !== $fileName && !$isRedirect) { if ('' === $result) { throw new TransportException('"' . $this->fileUrl . '" appears broken, and returned an empty 200 response'); } $errorMessage = ''; \set_error_handler(static function ($code, $msg) use(&$errorMessage) : bool { if ($errorMessage) { $errorMessage .= "\n"; } $errorMessage .= Preg::replace('{^file_put_contents\\(.*?\\): }', '', $msg); return \true; }); $result = (bool) \file_put_contents($fileName, $result); \restore_error_handler(); if (\false === $result) { throw new TransportException('The "' . $this->fileUrl . '" file could not be written to ' . $fileName . ': ' . $errorMessage); } } if ($this->retry) { $this->retry = \false; $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); if ($this->storeAuth) { $this->authHelper->storeAuth($this->originUrl, $this->storeAuth); $this->storeAuth = \false; } return $result; } if (\false === $result) { $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded: ' . $errorMessage, $errorCode); if (!empty($http_response_header[0])) { $e->setHeaders($http_response_header); } if (!$this->degradedMode && \false !== \strpos($e->getMessage(), 'Operation timed out')) { $this->degradedMode = \true; $this->io->writeError(''); $this->io->writeError(['' . $e->getMessage() . '', 'Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info']); return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress); } throw $e; } if (!empty($http_response_header[0])) { $this->lastHeaders = $http_response_header; } return $result; } /** * Get contents of remote URL. * * @param string $originUrl The origin URL * @param string $fileUrl The file URL * @param resource $context The stream context * @param string[] $responseHeaders * @param int $maxFileSize The maximum allowed file size * * @return string|false The response contents or false on failure * * @param-out list $responseHeaders */ protected function getRemoteContents(string $originUrl, string $fileUrl, $context, ?array &$responseHeaders = null, ?int $maxFileSize = null) { $result = \false; try { $e = null; if ($maxFileSize !== null) { $result = \file_get_contents($fileUrl, \false, $context, 0, $maxFileSize); } else { // passing `null` to file_get_contents will convert `null` to `0` and return 0 bytes $result = \file_get_contents($fileUrl, \false, $context); } } catch (\Throwable $e) { } if ($result !== \false && $maxFileSize !== null && \Composer\Util\Platform::strlen($result) >= $maxFileSize) { throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . \Composer\Util\Platform::strlen($result) . ' of allowed ' . $maxFileSize . ' bytes'); } // https://www.php.net/manual/en/reserved.variables.httpresponseheader.php if (\PHP_VERSION_ID >= 80400) { $responseHeaders = http_get_last_response_headers(); http_clear_last_response_headers(); } else { $responseHeaders = $http_response_header ?? []; } if (null !== $e) { throw $e; } return $result; } /** * Get notification action. * * @param int $notificationCode The notification code * @param int $severity The severity level * @param string $message The message * @param int $messageCode The message code * @param int $bytesTransferred The loaded size * @param int $bytesMax The total size * * @return void * * @throws TransportException */ protected function callbackGet(int $notificationCode, int $severity, ?string $message, int $messageCode, int $bytesTransferred, int $bytesMax) { switch ($notificationCode) { case \STREAM_NOTIFY_FAILURE: if (400 === $messageCode) { // This might happen if your host is secured by ssl client certificate authentication // but you do not send an appropriate certificate throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode); } break; case \STREAM_NOTIFY_FILE_SIZE_IS: $this->bytesMax = $bytesMax; break; case \STREAM_NOTIFY_PROGRESS: if ($this->bytesMax > 0 && $this->progress) { $progression = \min(100, (int) \round($bytesTransferred / $this->bytesMax * 100)); if (0 === $progression % 5 && 100 !== $progression && $progression !== $this->lastProgress) { $this->lastProgress = $progression; $this->io->overwriteError("Downloading ({$progression}%)", \false); } } break; default: break; } } /** * @param positive-int $httpStatus * @param string[] $headers * * @return void */ protected function promptAuthAndRetry($httpStatus, ?string $reason = null, array $headers = []) { $result = $this->authHelper->promptAuthIfNeeded($this->fileUrl, $this->originUrl, $httpStatus, $reason, $headers, 1); $this->storeAuth = $result['storeAuth']; $this->retry = $result['retry']; if ($this->retry) { throw new TransportException('RETRY'); } } /** * @param mixed[] $additionalOptions * * @return mixed[] */ protected function getOptionsForUrl(string $originUrl, array $additionalOptions) { $tlsOptions = []; $headers = []; if (\extension_loaded('zlib')) { $headers[] = 'Accept-Encoding: gzip'; } $options = \array_replace_recursive($this->options, $tlsOptions, $additionalOptions); if (!$this->degradedMode) { // degraded mode disables HTTP/1.1 which causes issues with some bad // proxies/software due to the use of chunked encoding $options['http']['protocol_version'] = 1.1; $headers[] = 'Connection: close'; } $headers = $this->authHelper->addAuthenticationHeader($headers, $originUrl, $this->fileUrl); $options['http']['follow_location'] = 0; if (isset($options['http']['header']) && !\is_array($options['http']['header'])) { $options['http']['header'] = \explode("\r\n", \trim($options['http']['header'], "\r\n")); } foreach ($headers as $header) { $options['http']['header'][] = $header; } return $options; } /** * @param string[] $http_response_header * @param mixed[] $additionalOptions * @param string|false $result * * @return bool|string */ private function handleRedirect(array $http_response_header, array $additionalOptions, $result) { if ($locationHeader = Response::findHeaderValue($http_response_header, 'location')) { if (\parse_url($locationHeader, \PHP_URL_SCHEME)) { // Absolute URL; e.g. https://example.com/composer $targetUrl = $locationHeader; } elseif (\parse_url($locationHeader, \PHP_URL_HOST)) { // Scheme relative; e.g. //example.com/foo $targetUrl = $this->scheme . ':' . $locationHeader; } elseif ('/' === $locationHeader[0]) { // Absolute path; e.g. /foo $urlHost = \parse_url($this->fileUrl, \PHP_URL_HOST); // Replace path using hostname as an anchor. $targetUrl = Preg::replace('{^(.+(?://|@)' . \preg_quote($urlHost) . '(?::\\d+)?)(?:[/\\?].*)?$}', '\\1' . $locationHeader, $this->fileUrl); } else { // Relative path; e.g. foo // This actually differs from PHP which seems to add duplicate slashes. $targetUrl = Preg::replace('{^(.+/)[^/?]*(?:\\?.*)?$}', '\\1' . $locationHeader, $this->fileUrl); } } if (!empty($targetUrl)) { $this->redirects++; $this->io->writeError('', \true, IOInterface::DEBUG); $this->io->writeError(\sprintf('Following redirect (%u) %s', $this->redirects, \Composer\Util\Url::sanitize($targetUrl)), \true, IOInterface::DEBUG); $additionalOptions['redirects'] = $this->redirects; return $this->get(\parse_url($targetUrl, \PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress); } if (!$this->retry) { $e = new TransportException('The "' . $this->fileUrl . '" file could not be downloaded, got redirect without Location (' . $http_response_header[0] . ')'); $e->setHeaders($http_response_header); $e->setResponse($this->decodeResult($result, $http_response_header)); throw $e; } return \false; } /** * @param string|false $result * @param string[] $http_response_header */ private function decodeResult($result, array $http_response_header) : ?string { // decode gzip if ($result && \extension_loaded('zlib')) { $contentEncoding = Response::findHeaderValue($http_response_header, 'content-encoding'); $decode = $contentEncoding && 'gzip' === \strtolower($contentEncoding); if ($decode) { $result = \zlib_decode($result); if ($result === \false) { throw new TransportException('Failed to decode zlib stream'); } } } return $this->normalizeResult($result); } /** * @param string|false $result */ private function normalizeResult($result) : ?string { if ($result === \false) { return null; } return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\IO\IOInterface; /** * Convert PHP errors into exceptions * * @author Artem Lopata */ class ErrorHandler { /** @var ?IOInterface */ private static $io; /** * Error handler * * @param int $level Level of the error raised * @param string $message Error message * @param string $file Filename that the error was raised in * @param int $line Line number the error was raised at * * @static * @throws \ErrorException */ public static function handle(int $level, string $message, string $file, int $line) : bool { $isDeprecationNotice = $level === \E_DEPRECATED || $level === \E_USER_DEPRECATED; // error code is not included in error_reporting if (!$isDeprecationNotice && 0 === (\error_reporting() & $level)) { return \true; } if (\filter_var(\ini_get('xdebug.scream'), \FILTER_VALIDATE_BOOLEAN)) { $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be" . "\na legitimately suppressed error that you were not supposed to see."; } if (!$isDeprecationNotice) { throw new \ErrorException($message, 0, $level, $file, $line); } if (self::$io !== null) { self::$io->writeError('Deprecation Notice: ' . $message . ' in ' . $file . ':' . $line . ''); if (self::$io->isVerbose()) { self::$io->writeError('Stack trace:'); self::$io->writeError(\array_filter(\array_map(static function ($a) : ?string { if (isset($a['line'], $a['file'])) { return ' ' . $a['file'] . ':' . $a['line'] . ''; } return null; }, \array_slice(\debug_backtrace(), 2)), function (?string $line) { return $line !== null; })); } } return \true; } /** * Register error handler. */ public static function register(?IOInterface $io = null) : void { \set_error_handler([__CLASS__, 'handle']); \error_reporting(\E_ALL); self::$io = $io; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use Composer\Downloader\DownloaderInterface; use Composer\Downloader\DownloadManager; use Composer\Package\PackageInterface; use React\Promise\PromiseInterface; class SyncHelper { /** * Helps you download + install a single package in a synchronous way * * This executes all the required steps and waits for promises to complete * * @param Loop $loop Loop instance which you can get from $composer->getLoop() * @param DownloaderInterface|DownloadManager $downloader DownloadManager instance or Downloader instance you can get from $composer->getDownloadManager()->getDownloader('zip') for example * @param string $path The installation path for the package * @param PackageInterface $package The package to install * @param PackageInterface|null $prevPackage The previous package if this is an update and not an initial installation */ public static function downloadAndInstallPackageSync(\Composer\Util\Loop $loop, $downloader, string $path, PackageInterface $package, ?PackageInterface $prevPackage = null) : void { \assert($downloader instanceof DownloaderInterface || $downloader instanceof DownloadManager); $type = $prevPackage !== null ? 'update' : 'install'; try { self::await($loop, $downloader->download($package, $path, $prevPackage)); self::await($loop, $downloader->prepare($type, $package, $path, $prevPackage)); if ($type === 'update' && $prevPackage !== null) { self::await($loop, $downloader->update($package, $prevPackage, $path)); } else { self::await($loop, $downloader->install($package, $path)); } } catch (\Exception $e) { self::await($loop, $downloader->cleanup($type, $package, $path, $prevPackage)); throw $e; } self::await($loop, $downloader->cleanup($type, $package, $path, $prevPackage)); } /** * Waits for a promise to resolve * * @param Loop $loop Loop instance which you can get from $composer->getLoop() * @phpstan-param PromiseInterface|null $promise */ public static function await(\Composer\Util\Loop $loop, ?PromiseInterface $promise = null) : void { if ($promise !== null) { $loop->wait([$promise]); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Util; use React\Promise\CancellablePromiseInterface; use _ContaoManager\Symfony\Component\Console\Helper\ProgressBar; use React\Promise\PromiseInterface; /** * @author Jordi Boggiano */ class Loop { /** @var HttpDownloader */ private $httpDownloader; /** @var ProcessExecutor|null */ private $processExecutor; /** @var array>> */ private $currentPromises = []; /** @var int */ private $waitIndex = 0; public function __construct(\Composer\Util\HttpDownloader $httpDownloader, ?\Composer\Util\ProcessExecutor $processExecutor = null) { $this->httpDownloader = $httpDownloader; $this->httpDownloader->enableAsync(); $this->processExecutor = $processExecutor; if ($this->processExecutor) { $this->processExecutor->enableAsync(); } } public function getHttpDownloader() : \Composer\Util\HttpDownloader { return $this->httpDownloader; } public function getProcessExecutor() : ?\Composer\Util\ProcessExecutor { return $this->processExecutor; } /** * @param array> $promises * @param ProgressBar|null $progress */ public function wait(array $promises, ?ProgressBar $progress = null) : void { $uncaught = null; \React\Promise\all($promises)->then(static function () : void { }, static function (\Throwable $e) use(&$uncaught) : void { $uncaught = $e; }); // keep track of every group of promises that is waited on, so abortJobs can // cancel them all, even if wait() was called within a wait() $waitIndex = $this->waitIndex++; $this->currentPromises[$waitIndex] = $promises; if ($progress) { $totalJobs = 0; $totalJobs += $this->httpDownloader->countActiveJobs(); if ($this->processExecutor) { $totalJobs += $this->processExecutor->countActiveJobs(); } $progress->start($totalJobs); } $lastUpdate = 0; while (\true) { $activeJobs = 0; $activeJobs += $this->httpDownloader->countActiveJobs(); if ($this->processExecutor) { $activeJobs += $this->processExecutor->countActiveJobs(); } if ($progress && \microtime(\true) - $lastUpdate > 0.1) { $lastUpdate = \microtime(\true); $progress->setProgress($progress->getMaxSteps() - $activeJobs); } if (!$activeJobs) { break; } } // as we skip progress updates if they are too quick, make sure we do one last one here at 100% if ($progress) { $progress->finish(); } unset($this->currentPromises[$waitIndex]); if (null !== $uncaught) { throw $uncaught; } } public function abortJobs() : void { foreach ($this->currentPromises as $promiseGroup) { foreach ($promiseGroup as $promise) { // to support react/promise 2.x we wrap the promise in a resolve() call for safety \React\Promise\resolve($promise)->cancel(); } } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Config; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; use Composer\Json\JsonValidationException; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Silencer; /** * JSON Configuration Source * * @author Jordi Boggiano * @author Beau Simensen */ class JsonConfigSource implements \Composer\Config\ConfigSourceInterface { /** * @var JsonFile */ private $file; /** * @var bool */ private $authConfig; /** * Constructor */ public function __construct(JsonFile $file, bool $authConfig = \false) { $this->file = $file; $this->authConfig = $authConfig; } /** * @inheritDoc */ public function getName() : string { return $this->file->getPath(); } /** * @inheritDoc */ public function addRepository(string $name, $config, bool $append = \true) : void { $this->manipulateJson('addRepository', static function (&$config, $repo, $repoConfig) use($append) : void { // if converting from an array format to hashmap format, and there is a {"packagist.org":false} repo, we have // to convert it to "packagist.org": false key on the hashmap otherwise it fails schema validation if (isset($config['repositories'])) { foreach ($config['repositories'] as $index => $val) { if ($index === $repo) { continue; } if (\is_numeric($index) && ($val === ['packagist' => \false] || $val === ['packagist.org' => \false])) { unset($config['repositories'][$index]); $config['repositories']['packagist.org'] = \false; break; } } } if ($append) { $config['repositories'][$repo] = $repoConfig; } else { $config['repositories'] = [$repo => $repoConfig] + $config['repositories']; } }, $name, $config, $append); } /** * @inheritDoc */ public function removeRepository(string $name) : void { $this->manipulateJson('removeRepository', static function (&$config, $repo) : void { unset($config['repositories'][$repo]); }, $name); } /** * @inheritDoc */ public function addConfigSetting(string $name, $value) : void { $authConfig = $this->authConfig; $this->manipulateJson('addConfigSetting', static function (&$config, $key, $val) use($authConfig) : void { if (Preg::isMatch('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\\.}', $key)) { [$key, $host] = \explode('.', $key, 2); if ($authConfig) { $config[$key][$host] = $val; } else { $config['config'][$key][$host] = $val; } } else { $config['config'][$key] = $val; } }, $name, $value); } /** * @inheritDoc */ public function removeConfigSetting(string $name) : void { $authConfig = $this->authConfig; $this->manipulateJson('removeConfigSetting', static function (&$config, $key) use($authConfig) : void { if (Preg::isMatch('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\\.}', $key)) { [$key, $host] = \explode('.', $key, 2); if ($authConfig) { unset($config[$key][$host]); } else { unset($config['config'][$key][$host]); } } else { unset($config['config'][$key]); } }, $name); } /** * @inheritDoc */ public function addProperty(string $name, $value) : void { $this->manipulateJson('addProperty', static function (&$config, $key, $val) : void { if (\strpos($key, 'extra.') === 0 || \strpos($key, 'scripts.') === 0) { $bits = \explode('.', $key); $last = \array_pop($bits); $arr =& $config[\reset($bits)]; foreach ($bits as $bit) { if (!isset($arr[$bit])) { $arr[$bit] = []; } $arr =& $arr[$bit]; } $arr[$last] = $val; } else { $config[$key] = $val; } }, $name, $value); } /** * @inheritDoc */ public function removeProperty(string $name) : void { $this->manipulateJson('removeProperty', static function (&$config, $key) : void { if (\strpos($key, 'extra.') === 0 || \strpos($key, 'scripts.') === 0 || \stripos($key, 'autoload.') === 0 || \stripos($key, 'autoload-dev.') === 0) { $bits = \explode('.', $key); $last = \array_pop($bits); $arr =& $config[\reset($bits)]; foreach ($bits as $bit) { if (!isset($arr[$bit])) { return; } $arr =& $arr[$bit]; } unset($arr[$last]); } else { unset($config[$key]); } }, $name); } /** * @inheritDoc */ public function addLink(string $type, string $name, string $value) : void { $this->manipulateJson('addLink', static function (&$config, $type, $name, $value) : void { $config[$type][$name] = $value; }, $type, $name, $value); } /** * @inheritDoc */ public function removeLink(string $type, string $name) : void { $this->manipulateJson('removeSubNode', static function (&$config, $type, $name) : void { unset($config[$type][$name]); }, $type, $name); $this->manipulateJson('removeMainKeyIfEmpty', static function (&$config, $type) : void { if (0 === \count($config[$type])) { unset($config[$type]); } }, $type); } /** * @param mixed ...$args */ private function manipulateJson(string $method, callable $fallback, ...$args) : void { if ($this->file->exists()) { if (!\is_writable($this->file->getPath())) { throw new \RuntimeException(\sprintf('The file "%s" is not writable.', $this->file->getPath())); } if (!Filesystem::isReadable($this->file->getPath())) { throw new \RuntimeException(\sprintf('The file "%s" is not readable.', $this->file->getPath())); } $contents = \file_get_contents($this->file->getPath()); } elseif ($this->authConfig) { $contents = "{\n}\n"; } else { $contents = "{\n \"config\": {\n }\n}\n"; } $manipulator = new JsonManipulator($contents); $newFile = !$this->file->exists(); // override manipulator method for auth config files if ($this->authConfig && $method === 'addConfigSetting') { $method = 'addSubNode'; [$mainNode, $name] = \explode('.', $args[0], 2); $args = [$mainNode, $name, $args[1]]; } elseif ($this->authConfig && $method === 'removeConfigSetting') { $method = 'removeSubNode'; [$mainNode, $name] = \explode('.', $args[0], 2); $args = [$mainNode, $name]; } // try to update cleanly if (\call_user_func_array([$manipulator, $method], $args)) { \file_put_contents($this->file->getPath(), $manipulator->getContents()); } else { // on failed clean update, call the fallback and rewrite the whole file $config = $this->file->read(); $this->arrayUnshiftRef($args, $config); $fallback(...$args); // avoid ending up with arrays for keys that should be objects foreach (['require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev', 'scripts', 'scripts-descriptions', 'scripts-aliases', 'support'] as $prop) { if (isset($config[$prop]) && $config[$prop] === []) { $config[$prop] = new \stdClass(); } } foreach (['psr-0', 'psr-4'] as $prop) { if (isset($config['autoload'][$prop]) && $config['autoload'][$prop] === []) { $config['autoload'][$prop] = new \stdClass(); } if (isset($config['autoload-dev'][$prop]) && $config['autoload-dev'][$prop] === []) { $config['autoload-dev'][$prop] = new \stdClass(); } } foreach (['platform', 'http-basic', 'bearer', 'gitlab-token', 'gitlab-oauth', 'github-oauth', 'preferred-install'] as $prop) { if (isset($config['config'][$prop]) && $config['config'][$prop] === []) { $config['config'][$prop] = new \stdClass(); } } $this->file->write($config); } try { $this->file->validateSchema(JsonFile::LAX_SCHEMA); } catch (JsonValidationException $e) { // restore contents to the original state \file_put_contents($this->file->getPath(), $contents); throw new \RuntimeException('Failed to update composer.json with a valid format, reverting to the original content. Please report an issue to us with details (command you run and a copy of your composer.json). ' . \PHP_EOL . \implode(\PHP_EOL, $e->getErrors()), 0, $e); } if ($newFile) { Silencer::call('chmod', $this->file->getPath(), 0600); } } /** * Prepend a reference to an element to the beginning of an array. * * @param mixed[] $array * @param mixed $value */ private function arrayUnshiftRef(array &$array, &$value) : int { $return = \array_unshift($array, ''); $array[0] =& $value; return $return; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Config; /** * Configuration Source Interface * * @author Jordi Boggiano * @author Beau Simensen */ interface ConfigSourceInterface { /** * Add a repository * * @param string $name Name * @param mixed[]|false $config Configuration * @param bool $append Whether the repo should be appended (true) or prepended (false) */ public function addRepository(string $name, $config, bool $append = \true) : void; /** * Remove a repository */ public function removeRepository(string $name) : void; /** * Add a config setting * * @param string $name Name * @param mixed $value Value */ public function addConfigSetting(string $name, $value) : void; /** * Remove a config setting */ public function removeConfigSetting(string $name) : void; /** * Add a property * * @param string $name Name * @param string|string[] $value Value */ public function addProperty(string $name, $value) : void; /** * Remove a property */ public function removeProperty(string $name) : void; /** * Add a package link * * @param string $type Type (require, require-dev, provide, suggest, replace, conflict) * @param string $name Name * @param string $value Value */ public function addLink(string $type, string $name, string $value) : void; /** * Remove a package link * * @param string $type Type (require, require-dev, provide, suggest, replace, conflict) * @param string $name Name */ public function removeLink(string $type, string $name) : void; /** * Gives a user-friendly name to this source (file path or so) */ public function getName() : string; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\SelfUpdate; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; use Composer\Config; /** * @author Jordi Boggiano */ class Versions { /** * @var string[] * @deprecated use Versions::CHANNELS */ public static $channels = self::CHANNELS; public const CHANNELS = ['stable', 'preview', 'snapshot', '1', '2', '2.2']; /** @var HttpDownloader */ private $httpDownloader; /** @var Config */ private $config; /** @var string */ private $channel; /** @var array>|null */ private $versionsData = null; public function __construct(Config $config, HttpDownloader $httpDownloader) { $this->httpDownloader = $httpDownloader; $this->config = $config; } public function getChannel() : string { if ($this->channel) { return $this->channel; } $channelFile = $this->config->get('home') . '/update-channel'; if (\file_exists($channelFile)) { $channel = \trim(\file_get_contents($channelFile)); if (\in_array($channel, ['stable', 'preview', 'snapshot', '2.2'], \true)) { return $this->channel = $channel; } } return $this->channel = 'stable'; } public function setChannel(string $channel, ?IOInterface $io = null) : void { if (!\in_array($channel, self::CHANNELS, \true)) { throw new \InvalidArgumentException('Invalid channel ' . $channel . ', must be one of: ' . \implode(', ', self::CHANNELS)); } $channelFile = $this->config->get('home') . '/update-channel'; $this->channel = $channel; // rewrite '2' and '1' channels to stable for future self-updates, but LTS ones like '2.2' remain pinned $storedChannel = Preg::isMatch('{^\\d+$}D', $channel) ? 'stable' : $channel; $previouslyStored = \file_exists($channelFile) ? \trim((string) \file_get_contents($channelFile)) : null; \file_put_contents($channelFile, $storedChannel . \PHP_EOL); if ($io !== null && $previouslyStored !== $storedChannel) { $io->writeError('Storing "' . $storedChannel . '" as default update channel for the next self-update run.'); } } /** * @return array{path: string, version: string, min-php: int, eol?: true} */ public function getLatest(?string $channel = null) : array { $versions = $this->getVersionsData(); foreach ($versions[$channel ?: $this->getChannel()] as $version) { if ($version['min-php'] <= \PHP_VERSION_ID) { return $version; } } throw new \UnexpectedValueException('There is no version of Composer available for your PHP version (' . \PHP_VERSION . ')'); } /** * @return array> */ private function getVersionsData() : array { if (null === $this->versionsData) { if ($this->config->get('disable-tls') === \true) { $protocol = 'http'; } else { $protocol = 'https'; } $this->versionsData = $this->httpDownloader->get($protocol . '://getcomposer.org/versions')->decodeJson(); } return $this->versionsData; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\SelfUpdate; use Composer\Pcre\Preg; /** * @author Jordi Boggiano */ class Keys { public static function fingerprint(string $path) : string { $hash = \strtoupper(\hash('sha256', Preg::replace('{\\s}', '', \file_get_contents($path)))); return \implode(' ', [ \substr($hash, 0, 8), \substr($hash, 8, 8), \substr($hash, 16, 8), \substr($hash, 24, 8), '', // Extra space \substr($hash, 32, 8), \substr($hash, 40, 8), \substr($hash, 48, 8), \substr($hash, 56, 8), ]); } } * 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\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\Silencer; use _ContaoManager\Symfony\Component\Finder\Finder; /** * Reads/writes to a filesystem cache * * @author Jordi Boggiano */ class Cache { /** @var bool|null */ private static $cacheCollected = null; /** @var IOInterface */ private $io; /** @var string */ private $root; /** @var ?bool */ private $enabled = null; /** @var string */ private $allowlist; /** @var Filesystem */ private $filesystem; /** @var bool */ private $readOnly; /** * @param string $cacheDir location of the cache * @param string $allowlist List of characters that are allowed in path names (used in a regex character class) * @param Filesystem $filesystem optional filesystem instance * @param bool $readOnly whether the cache is in readOnly mode */ public function __construct(IOInterface $io, string $cacheDir, string $allowlist = 'a-z0-9._', ?Filesystem $filesystem = null, bool $readOnly = \false) { $this->io = $io; $this->root = \rtrim($cacheDir, '/\\') . '/'; $this->allowlist = $allowlist; $this->filesystem = $filesystem ?: new Filesystem(); $this->readOnly = $readOnly; if (!self::isUsable($cacheDir)) { $this->enabled = \false; } } /** * @return void */ public function setReadOnly(bool $readOnly) { $this->readOnly = $readOnly; } /** * @return bool */ public function isReadOnly() { return $this->readOnly; } /** * @return bool */ public static function isUsable(string $path) { return !Preg::isMatch('{(^|[\\\\/])(\\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path); } /** * @return bool */ public function isEnabled() { if ($this->enabled === null) { $this->enabled = \true; if (!$this->readOnly && (!\is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, \true) || !\is_writable($this->root))) { $this->io->writeError('Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache. See also cache-read-only config if your filesystem is read-only.'); $this->enabled = \false; } } return $this->enabled; } /** * @return string */ public function getRoot() { return $this->root; } /** * @return string|false */ public function read(string $file) { if ($this->isEnabled()) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); if (\file_exists($this->root . $file)) { $this->io->writeError('Reading ' . $this->root . $file . ' from cache', \true, IOInterface::DEBUG); return \file_get_contents($this->root . $file); } } return \false; } /** * @return bool */ public function write(string $file, string $contents) { $wasEnabled = $this->enabled === \true; if ($this->isEnabled() && !$this->readOnly) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); $this->io->writeError('Writing ' . $this->root . $file . ' into cache', \true, IOInterface::DEBUG); $tempFileName = $this->root . $file . \bin2hex(\random_bytes(5)) . '.tmp'; try { return \file_put_contents($tempFileName, $contents) !== \false && \rename($tempFileName, $this->root . $file); } catch (\ErrorException $e) { // If the write failed despite isEnabled checks passing earlier, rerun the isEnabled checks to // see if they are still current and recreate the cache dir if needed. Refs https://github.com/composer/composer/issues/11076 if ($wasEnabled) { \clearstatcache(); $this->enabled = null; return $this->write($file, $contents); } $this->io->writeError('Failed to write into cache: ' . $e->getMessage() . '', \true, IOInterface::DEBUG); if (Preg::isMatch('{^file_put_contents\\(\\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) { // Remove partial file. \unlink($tempFileName); $message = \sprintf('Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$s bytes of free space available', $tempFileName, $m[1], $m[2], \function_exists('disk_free_space') ? @\disk_free_space(\dirname($tempFileName)) : 'unknown'); $this->io->writeError($message); return \false; } throw $e; } } return \false; } /** * Copy a file into the cache * * @return bool */ public function copyFrom(string $file, string $source) { if ($this->isEnabled() && !$this->readOnly) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); $this->filesystem->ensureDirectoryExists(\dirname($this->root . $file)); if (!\file_exists($source)) { $this->io->writeError('' . $source . ' does not exist, can not write into cache'); } elseif ($this->io->isDebug()) { $this->io->writeError('Writing ' . $this->root . $file . ' into cache from ' . $source); } return $this->filesystem->copy($source, $this->root . $file); } return \false; } /** * Copy a file out of the cache * * @return bool */ public function copyTo(string $file, string $target) { if ($this->isEnabled()) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); if (\file_exists($this->root . $file)) { try { \touch($this->root . $file, (int) \filemtime($this->root . $file), \time()); } catch (\ErrorException $e) { // fallback in case the above failed due to incorrect ownership // see https://github.com/composer/composer/issues/4070 Silencer::call('touch', $this->root . $file); } $this->io->writeError('Reading ' . $this->root . $file . ' from cache', \true, IOInterface::DEBUG); return $this->filesystem->copy($this->root . $file, $target); } } return \false; } /** * @return bool */ public function gcIsNecessary() { if (self::$cacheCollected) { return \false; } self::$cacheCollected = \true; if (Platform::getEnv('COMPOSER_TEST_SUITE')) { return \false; } if (Platform::isInputCompletionProcess()) { return \false; } return !\random_int(0, 50); } /** * @return bool */ public function remove(string $file) { if ($this->isEnabled() && !$this->readOnly) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); if (\file_exists($this->root . $file)) { return $this->filesystem->unlink($this->root . $file); } } return \false; } /** * @return bool */ public function clear() { if ($this->isEnabled() && !$this->readOnly) { $this->filesystem->emptyDirectory($this->root); return \true; } return \false; } /** * @return int|false * @phpstan-return int<0, max>|false */ public function getAge(string $file) { if ($this->isEnabled()) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); if (\file_exists($this->root . $file) && ($mtime = \filemtime($this->root . $file)) !== \false) { return \abs(\time() - $mtime); } } return \false; } /** * @return bool */ public function gc(int $ttl, int $maxSize) { if ($this->isEnabled() && !$this->readOnly) { $expire = new \DateTime(); $expire->modify('-' . $ttl . ' seconds'); $finder = $this->getFinder()->date('until ' . $expire->format('Y-m-d H:i:s')); foreach ($finder as $file) { $this->filesystem->unlink($file->getPathname()); } $totalSize = $this->filesystem->size($this->root); if ($totalSize > $maxSize) { $iterator = $this->getFinder()->sortByAccessedTime()->getIterator(); while ($totalSize > $maxSize && $iterator->valid()) { $filepath = $iterator->current()->getPathname(); $totalSize -= $this->filesystem->size($filepath); $this->filesystem->unlink($filepath); $iterator->next(); } } self::$cacheCollected = \true; return \true; } return \false; } public function gcVcsCache(int $ttl) : bool { if ($this->isEnabled()) { $expire = new \DateTime(); $expire->modify('-' . $ttl . ' seconds'); $finder = Finder::create()->in($this->root)->directories()->depth(0)->date('until ' . $expire->format('Y-m-d H:i:s')); foreach ($finder as $file) { $this->filesystem->removeDirectory($file->getPathname()); } self::$cacheCollected = \true; return \true; } return \false; } /** * @return string|false */ public function sha1(string $file) { if ($this->isEnabled()) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); if (\file_exists($this->root . $file)) { return \hash_file('sha1', $this->root . $file); } } return \false; } /** * @return string|false */ public function sha256(string $file) { if ($this->isEnabled()) { $file = Preg::replace('{[^' . $this->allowlist . ']}i', '-', $file); if (\file_exists($this->root . $file)) { return \hash_file('sha256', $this->root . $file); } } return \false; } /** * @return Finder */ protected function getFinder() { return Finder::create()->in($this->root)->files(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\EventDispatcher; /** * The base event class * * @author Nils Adermann */ class Event { /** * @var string This event's name */ protected $name; /** * @var string[] Arguments passed by the user, these will be forwarded to CLI script handlers */ protected $args; /** * @var mixed[] Flags usable in PHP script handlers */ protected $flags; /** * @var bool Whether the event should not be passed to more listeners */ private $propagationStopped = \false; /** * Constructor. * * @param string $name The event name * @param string[] $args Arguments passed by the user * @param mixed[] $flags Optional flags to pass data not as argument */ public function __construct(string $name, array $args = [], array $flags = []) { $this->name = $name; $this->args = $args; $this->flags = $flags; } /** * Returns the event's name. * * @return string The event name */ public function getName() : string { return $this->name; } /** * Returns the event's arguments. * * @return string[] The event arguments */ public function getArguments() : array { return $this->args; } /** * Returns the event's flags. * * @return mixed[] The event flags */ public function getFlags() : array { return $this->flags; } /** * Checks if stopPropagation has been called * * @return bool Whether propagation has been stopped */ public function isPropagationStopped() : bool { return $this->propagationStopped; } /** * Prevents the event from being passed to further listeners */ public function stopPropagation() : void { $this->propagationStopped = \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\EventDispatcher; /** * Thrown when a script running an external process exits with a non-0 status code * * @author Jordi Boggiano */ class ScriptExecutionException extends \RuntimeException { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\EventDispatcher; use Composer\DependencyResolver\Transaction; use Composer\Installer\InstallerEvent; use Composer\IO\BufferIO; use Composer\IO\ConsoleIO; use Composer\IO\IOInterface; use Composer\Composer; use Composer\PartialComposer; use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PreCommandRunEvent; use Composer\Util\Platform; use Composer\DependencyResolver\Operation\OperationInterface; use Composer\Repository\RepositoryInterface; use Composer\Script; use Composer\Installer\PackageEvent; use Composer\Installer\BinaryInstaller; use Composer\Util\ProcessExecutor; use Composer\Script\Event as ScriptEvent; use Composer\Autoload\ClassLoader; use _ContaoManager\Symfony\Component\Console\Application; use _ContaoManager\Symfony\Component\Console\Command\Command; use _ContaoManager\Symfony\Component\Console\Input\StringInput; use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutput; use _ContaoManager\Symfony\Component\Process\PhpExecutableFinder; use _ContaoManager\Symfony\Component\Process\ExecutableFinder; /** * The Event Dispatcher. * * Example in command: * $dispatcher = new EventDispatcher($this->requireComposer(), $this->getApplication()->getIO()); * // ... * $dispatcher->dispatch(ScriptEvents::POST_INSTALL_CMD); * // ... * * @author François Pluchino * @author Jordi Boggiano * @author Nils Adermann */ class EventDispatcher { /** @var PartialComposer */ protected $composer; /** @var IOInterface */ protected $io; /** @var ?ClassLoader */ protected $loader; /** @var ProcessExecutor */ protected $process; /** @var array>> */ protected $listeners = []; /** @var bool */ protected $runScripts = \true; /** @var list */ private $eventStack; /** * Constructor. * * @param PartialComposer $composer The composer instance * @param IOInterface $io The IOInterface instance * @param ProcessExecutor $process */ public function __construct(PartialComposer $composer, IOInterface $io, ?ProcessExecutor $process = null) { $this->composer = $composer; $this->io = $io; $this->process = $process ?? new ProcessExecutor($io); $this->eventStack = []; } /** * Set whether script handlers are active or not * * @return $this */ public function setRunScripts(bool $runScripts = \true) : self { $this->runScripts = $runScripts; return $this; } /** * Dispatch an event * * @param string|null $eventName The event name, required if no $event is provided * @param Event $event An event instance, required if no $eventName is provided * @return int return code of the executed script if any, for php scripts a false return * value is changed to 1, anything else to 0 */ public function dispatch(?string $eventName, ?\Composer\EventDispatcher\Event $event = null) : int { if (null === $event) { if (null === $eventName) { throw new \InvalidArgumentException('If no $event is passed in to ' . __METHOD__ . ' you have to pass in an $eventName, got null.'); } $event = new \Composer\EventDispatcher\Event($eventName); } return $this->doDispatch($event); } /** * Dispatch a script event. * * @param string $eventName The constant in ScriptEvents * @param array $additionalArgs Arguments passed by the user * @param array $flags Optional flags to pass data not as argument * @return int return code of the executed script if any, for php scripts a false return * value is changed to 1, anything else to 0 */ public function dispatchScript(string $eventName, bool $devMode = \false, array $additionalArgs = [], array $flags = []) : int { \assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer')); return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags)); } /** * Dispatch a package event. * * @param string $eventName The constant in PackageEvents * @param bool $devMode Whether or not we are in dev mode * @param RepositoryInterface $localRepo The installed repository * @param OperationInterface[] $operations The list of operations * @param OperationInterface $operation The package being installed/updated/removed * * @return int return code of the executed script if any, for php scripts a false return * value is changed to 1, anything else to 0 */ public function dispatchPackageEvent(string $eventName, bool $devMode, RepositoryInterface $localRepo, array $operations, OperationInterface $operation) : int { \assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer')); return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $localRepo, $operations, $operation)); } /** * Dispatch a installer event. * * @param string $eventName The constant in InstallerEvents * @param bool $devMode Whether or not we are in dev mode * @param bool $executeOperations True if operations will be executed, false in --dry-run * @param Transaction $transaction The transaction contains the list of operations * * @return int return code of the executed script if any, for php scripts a false return * value is changed to 1, anything else to 0 */ public function dispatchInstallerEvent(string $eventName, bool $devMode, bool $executeOperations, Transaction $transaction) : int { \assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer')); return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $executeOperations, $transaction)); } /** * Triggers the listeners of an event. * * @param Event $event The event object to pass to the event handlers/listeners. * @throws \RuntimeException|\Exception * @return int return code of the executed script if any, for php scripts a false return * value is changed to 1, anything else to 0 */ protected function doDispatch(\Composer\EventDispatcher\Event $event) { if (Platform::getEnv('COMPOSER_DEBUG_EVENTS')) { $details = null; if ($event instanceof PackageEvent) { $details = (string) $event->getOperation(); } elseif ($event instanceof CommandEvent) { $details = $event->getCommandName(); } elseif ($event instanceof PreCommandRunEvent) { $details = $event->getCommand(); } $this->io->writeError('Dispatching ' . $event->getName() . '' . ($details ? ' (' . $details . ')' : '') . ' event'); } $listeners = $this->getListeners($event); $this->pushEvent($event); $autoloadersBefore = \spl_autoload_functions(); try { $returnMax = 0; foreach ($listeners as $callable) { $return = 0; $this->ensureBinDirIsInPath(); $additionalArgs = $event->getArguments(); if (\is_string($callable) && \str_contains($callable, '@no_additional_args')) { $callable = Preg::replace('{ ?@no_additional_args}', '', $callable); $additionalArgs = []; } $formattedEventNameWithArgs = $event->getName() . ($additionalArgs !== [] ? ' (' . \implode(', ', $additionalArgs) . ')' : ''); if (!\is_string($callable)) { if (!\is_callable($callable)) { $className = \is_object($callable[0]) ? \get_class($callable[0]) : $callable[0]; throw new \RuntimeException('Subscriber ' . $className . '::' . $callable[1] . ' for event ' . $event->getName() . ' is not callable, make sure the function is defined and public'); } if (\is_array($callable) && (\is_string($callable[0]) || \is_object($callable[0])) && \is_string($callable[1])) { $this->io->writeError(\sprintf('> %s: %s', $formattedEventNameWithArgs, (\is_object($callable[0]) ? \get_class($callable[0]) : $callable[0]) . '->' . $callable[1]), \true, IOInterface::VERBOSE); } $return = \false === $callable($event) ? 1 : 0; } elseif ($this->isComposerScript($callable)) { $this->io->writeError(\sprintf('> %s: %s', $formattedEventNameWithArgs, $callable), \true, IOInterface::VERBOSE); $script = \explode(' ', \substr($callable, 1)); $scriptName = $script[0]; unset($script[0]); $index = \array_search('@additional_args', $script, \true); if ($index !== \false) { $args = \array_splice($script, $index, 0, $additionalArgs); } else { $args = \array_merge($script, $additionalArgs); } $flags = $event->getFlags(); if (isset($flags['script-alias-input'])) { $argsString = \implode(' ', \array_map(static function ($arg) { return ProcessExecutor::escape($arg); }, $script)); $flags['script-alias-input'] = $argsString . ' ' . $flags['script-alias-input']; unset($argsString); } if (\strpos($callable, '@composer ') === 0) { $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(Platform::getEnv('COMPOSER_BINARY')) . ' ' . \implode(' ', $args); if (0 !== ($exitCode = $this->executeTty($exec))) { $this->io->writeError(\sprintf('Script %s handling the %s event returned with error code ' . $exitCode . '', $callable, $event->getName()), \true, IOInterface::QUIET); throw new \Composer\EventDispatcher\ScriptExecutionException('Error Output: ' . $this->process->getErrorOutput(), $exitCode); } } else { if (!$this->getListeners(new \Composer\EventDispatcher\Event($scriptName))) { $this->io->writeError(\sprintf('You made a reference to a non-existent script %s', $callable), \true, IOInterface::QUIET); } try { /** @var InstallerEvent $event */ $scriptEvent = new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags); $scriptEvent->setOriginatingEvent($event); $return = $this->dispatch($scriptName, $scriptEvent); } catch (\Composer\EventDispatcher\ScriptExecutionException $e) { $this->io->writeError(\sprintf('Script %s was called via %s', $callable, $event->getName()), \true, IOInterface::QUIET); throw $e; } } } elseif ($this->isPhpScript($callable)) { $className = \substr($callable, 0, \strpos($callable, '::')); $methodName = \substr($callable, \strpos($callable, '::') + 2); if (!\class_exists($className)) { $this->io->writeError('Class ' . $className . ' is not autoloadable, can not call ' . $event->getName() . ' script', \true, IOInterface::QUIET); continue; } if (!\is_callable($callable)) { $this->io->writeError('Method ' . $callable . ' is not callable, can not call ' . $event->getName() . ' script', \true, IOInterface::QUIET); continue; } try { $return = \false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0; } catch (\Exception $e) { $message = "Script %s handling the %s event terminated with an exception"; $this->io->writeError('' . \sprintf($message, $callable, $event->getName()) . '', \true, IOInterface::QUIET); throw $e; } } elseif ($this->isCommandClass($callable)) { $className = $callable; if (!\class_exists($className)) { $this->io->writeError('Class ' . $className . ' is not autoloadable, can not call ' . $event->getName() . ' script', \true, IOInterface::QUIET); continue; } if (!\is_a($className, Command::class, \true)) { $this->io->writeError('Class ' . $className . ' does not extend ' . Command::class . ', can not call ' . $event->getName() . ' script', \true, IOInterface::QUIET); continue; } if (\defined('Composer\\Script\\ScriptEvents::' . \str_replace('-', '_', \strtoupper($event->getName())))) { $this->io->writeError('You cannot bind ' . $event->getName() . ' to a Command class, use a non-reserved name', \true, IOInterface::QUIET); continue; } $app = new Application(); $app->setCatchExceptions(\false); if (\method_exists($app, 'setCatchErrors')) { $app->setCatchErrors(\false); } $app->setAutoExit(\false); $cmd = new $className($event->getName()); $app->add($cmd); $app->setDefaultCommand((string) $cmd->getName(), \true); try { $args = \implode(' ', \array_map(static function ($arg) { return ProcessExecutor::escape($arg); }, $additionalArgs)); // reusing the output from $this->io is mostly needed for tests, but generally speaking // it does not hurt to keep the same stream as the current Application if ($this->io instanceof ConsoleIO) { $reflProp = new \ReflectionProperty($this->io, 'output'); if (\PHP_VERSION_ID < 80100) { $reflProp->setAccessible(\true); } $output = $reflProp->getValue($this->io); } else { $output = new ConsoleOutput(); } $return = $app->run(new StringInput($event->getFlags()['script-alias-input'] ?? $args), $output); } catch (\Exception $e) { $message = "Script %s handling the %s event terminated with an exception"; $this->io->writeError('' . \sprintf($message, $callable, $event->getName()) . '', \true, IOInterface::QUIET); throw $e; } } else { $args = \implode(' ', \array_map(['Composer\\Util\\ProcessExecutor', 'escape'], $additionalArgs)); // @putenv does not receive arguments if (\strpos($callable, '@putenv ') === 0) { $exec = $callable; } else { if (\str_contains($callable, '@additional_args')) { $exec = \str_replace('@additional_args', $args, $callable); } else { $exec = $callable . ($args === '' ? '' : ' ' . $args); } } if ($this->io->isVerbose()) { $this->io->writeError(\sprintf('> %s: %s', $event->getName(), $exec)); } elseif ($event->getName() !== '__exec_command') { // do not output the command being run when using `composer exec` as it is fairly obvious the user is running it $this->io->writeError(\sprintf('> %s', $exec)); } $possibleLocalBinaries = $this->composer->getPackage()->getBinaries(); if (\count($possibleLocalBinaries) > 0) { foreach ($possibleLocalBinaries as $localExec) { if (Preg::isMatch('{\\b' . \preg_quote($callable) . '$}', $localExec)) { $caller = BinaryInstaller::determineBinaryCaller($localExec); $exec = Preg::replace('{^' . \preg_quote($callable) . '}', $caller . ' ' . $localExec, $exec); break; } } } if (\strpos($exec, '@putenv ') === 0) { if (\false === \strpos($exec, '=')) { Platform::clearEnv(\substr($exec, 8)); } else { [$var, $value] = \explode('=', \substr($exec, 8), 2); Platform::putEnv($var, $value); } continue; } if (\strpos($exec, '@php ') === 0) { $pathAndArgs = \substr($exec, 5); if (Platform::isWindows()) { $pathAndArgs = Preg::replaceCallback('{^\\S+}', static function ($path) { return \str_replace('/', '\\', $path[0]); }, $pathAndArgs); } // match somename (not in quote, and not a qualified path) and if it is not a valid path from CWD then try to find it // in $PATH. This allows support for `@php foo` where foo is a binary name found in PATH but not an actual relative path $matched = Preg::isMatchStrictGroups('{^[^\'"\\s/\\\\]+}', $pathAndArgs, $match); if ($matched && !\file_exists($match[0])) { $finder = new ExecutableFinder(); if ($pathToExec = $finder->find($match[0])) { if (Platform::isWindows()) { $execWithoutExt = Preg::replace('{\\.(exe|bat|cmd|com)$}i', '', $pathToExec); // prefer non-extension file if it exists when executing with PHP if (\file_exists($execWithoutExt)) { $pathToExec = $execWithoutExt; } unset($execWithoutExt); } $pathAndArgs = $pathToExec . \substr($pathAndArgs, \strlen($match[0])); } } $exec = $this->getPhpExecCommand() . ' ' . $pathAndArgs; } else { $finder = new PhpExecutableFinder(); $phpPath = $finder->find(\false); if ($phpPath) { Platform::putEnv('PHP_BINARY', $phpPath); } if (Platform::isWindows()) { $exec = Preg::replaceCallback('{^\\S+}', static function ($path) { return \str_replace('/', '\\', $path[0]); }, $exec); } } // if composer is being executed, make sure it runs the expected composer from current path // resolution, even if bin-dir contains composer too because the project requires composer/composer // see https://github.com/composer/composer/issues/8748 if (\strpos($exec, 'composer ') === 0) { $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(Platform::getEnv('COMPOSER_BINARY')) . \substr($exec, 8); } if (0 !== ($exitCode = $this->executeTty($exec))) { $this->io->writeError(\sprintf('Script %s handling the %s event returned with error code ' . $exitCode . '', $callable, $event->getName()), \true, IOInterface::QUIET); throw new \Composer\EventDispatcher\ScriptExecutionException('Error Output: ' . $this->process->getErrorOutput(), $exitCode); } } $returnMax = \max($returnMax, $return); if ($event->isPropagationStopped()) { break; } } } finally { $this->popEvent(); $knownIdentifiers = []; foreach ($autoloadersBefore as $key => $cb) { $knownIdentifiers[$this->getCallbackIdentifier($cb)] = ['key' => $key, 'callback' => $cb]; } foreach (\spl_autoload_functions() as $cb) { // once we get to the first known autoloader, we can leave any appended autoloader without problems if (isset($knownIdentifiers[$this->getCallbackIdentifier($cb)]) && $knownIdentifiers[$this->getCallbackIdentifier($cb)]['key'] === 0) { break; } // other newly appeared prepended autoloaders should be appended instead to ensure Composer loads its classes first if ($cb instanceof ClassLoader) { $cb->unregister(); $cb->register(\false); } else { \spl_autoload_unregister($cb); \spl_autoload_register($cb); } } } return $returnMax; } protected function executeTty(string $exec) : int { if ($this->io->isInteractive()) { return $this->process->executeTty($exec); } return $this->process->execute($exec); } protected function getPhpExecCommand() : string { $finder = new PhpExecutableFinder(); $phpPath = $finder->find(\false); if (!$phpPath) { throw new \RuntimeException('Failed to locate PHP binary to execute ' . $phpPath); } $phpArgs = $finder->findArguments(); $phpArgs = $phpArgs ? ' ' . \implode(' ', $phpArgs) : ''; $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(\ini_get('allow_url_fopen')); $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(\ini_get('disable_functions')); $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(\ini_get('memory_limit')); return ProcessExecutor::escape($phpPath) . $phpArgs . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag; } /** * @param Event $event Event invoking the PHP callable * * @return mixed */ protected function executeEventPhpScript(string $className, string $methodName, \Composer\EventDispatcher\Event $event) { if ($this->io->isVerbose()) { $this->io->writeError(\sprintf('> %s: %s::%s', $event->getName(), $className, $methodName)); } else { $this->io->writeError(\sprintf('> %s::%s', $className, $methodName)); } return $className::$methodName($event); } /** * Add a listener for a particular event * * @param string $eventName The event name - typically a constant * @param callable|string $listener A callable expecting an event argument, or a command string to be executed (same as a composer.json "scripts" entry) * @param int $priority A higher value represents a higher priority */ public function addListener(string $eventName, $listener, int $priority = 0) : void { $this->listeners[$eventName][$priority][] = $listener; } /** * @param callable|object $listener A callable or an object instance for which all listeners should be removed */ public function removeListener($listener) : void { foreach ($this->listeners as $eventName => $priorities) { foreach ($priorities as $priority => $listeners) { foreach ($listeners as $index => $candidate) { if ($listener === $candidate || \is_array($candidate) && \is_object($listener) && $candidate[0] === $listener) { unset($this->listeners[$eventName][$priority][$index]); } } } } } /** * Adds object methods as listeners for the events in getSubscribedEvents * * @see EventSubscriberInterface */ public function addSubscriber(\Composer\EventDispatcher\EventSubscriberInterface $subscriber) : void { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (\is_string($params)) { $this->addListener($eventName, [$subscriber, $params]); } elseif (\is_string($params[0])) { $this->addListener($eventName, [$subscriber, $params[0]], $params[1] ?? 0); } else { foreach ($params as $listener) { $this->addListener($eventName, [$subscriber, $listener[0]], $listener[1] ?? 0); } } } } /** * Retrieves all listeners for a given event * * @return array All listeners: callables and scripts */ protected function getListeners(\Composer\EventDispatcher\Event $event) : array { $scriptListeners = $this->runScripts ? $this->getScriptListeners($event) : []; if (!isset($this->listeners[$event->getName()][0])) { $this->listeners[$event->getName()][0] = []; } \krsort($this->listeners[$event->getName()]); $listeners = $this->listeners; $listeners[$event->getName()][0] = \array_merge($listeners[$event->getName()][0], $scriptListeners); return \array_merge(...$listeners[$event->getName()]); } /** * Checks if an event has listeners registered */ public function hasEventListeners(\Composer\EventDispatcher\Event $event) : bool { $listeners = $this->getListeners($event); return \count($listeners) > 0; } /** * Finds all listeners defined as scripts in the package * * @param Event $event Event object * @return string[] Listeners */ protected function getScriptListeners(\Composer\EventDispatcher\Event $event) : array { $package = $this->composer->getPackage(); $scripts = $package->getScripts(); if (empty($scripts[$event->getName()])) { return []; } \assert($this->composer instanceof Composer, new \LogicException('This should only be reached with a fully loaded Composer')); if ($this->loader) { $this->loader->unregister(); } $generator = $this->composer->getAutoloadGenerator(); if ($event instanceof ScriptEvent) { $generator->setDevMode($event->isDevMode()); } $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages(); $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages); $map = $generator->parseAutoloads($packageMap, $package); $this->loader = $generator->createLoader($map, $this->composer->getConfig()->get('vendor-dir')); $this->loader->register(\false); return $scripts[$event->getName()]; } /** * Checks if string given references a class path and method */ protected function isPhpScript(string $callable) : bool { return \false === \strpos($callable, ' ') && \false !== \strpos($callable, '::'); } /** * Checks if string given references a command class */ protected function isCommandClass(string $callable) : bool { return \str_contains($callable, '\\') && !\str_contains($callable, ' ') && \str_ends_with($callable, 'Command'); } /** * Checks if string given references a composer run-script */ protected function isComposerScript(string $callable) : bool { return \strpos($callable, '@') === 0 && \strpos($callable, '@php ') !== 0 && \strpos($callable, '@putenv ') !== 0; } /** * Push an event to the stack of active event * * @throws \RuntimeException */ protected function pushEvent(\Composer\EventDispatcher\Event $event) : int { $eventName = $event->getName(); if (\in_array($eventName, $this->eventStack)) { throw new \RuntimeException(\sprintf("Circular call to script handler '%s' detected", $eventName)); } return \array_push($this->eventStack, $eventName); } /** * Pops the active event from the stack */ protected function popEvent() : ?string { return \array_pop($this->eventStack); } private function ensureBinDirIsInPath() : void { $pathEnv = 'PATH'; // checking if only Path and not PATH is set then we probably need to update the Path env // on Windows getenv is case-insensitive so we cannot check it via Platform::getEnv and // we need to check in $_SERVER directly if (!isset($_SERVER[$pathEnv]) && isset($_SERVER['Path'])) { $pathEnv = 'Path'; } // add the bin dir to the PATH to make local binaries of deps usable in scripts $binDir = $this->composer->getConfig()->get('bin-dir'); if (\is_dir($binDir)) { $binDir = \realpath($binDir); $pathValue = (string) Platform::getEnv($pathEnv); if (!Preg::isMatch('{(^|' . \PATH_SEPARATOR . ')' . \preg_quote($binDir) . '($|' . \PATH_SEPARATOR . ')}', $pathValue)) { Platform::putEnv($pathEnv, $binDir . \PATH_SEPARATOR . $pathValue); } } } /** * @param callable $cb DO NOT MOVE TO TYPE HINT as private autoload callbacks are not technically callable */ private function getCallbackIdentifier($cb) : string { if (\is_string($cb)) { return 'fn:' . $cb; } if (\is_object($cb)) { return 'obj:' . \spl_object_hash($cb); } if (\is_array($cb)) { return 'array:' . (\is_string($cb[0]) ? $cb[0] : \get_class($cb[0]) . '#' . \spl_object_hash($cb[0])) . '::' . $cb[1]; } // not great but also do not want to break everything here return 'unsupported'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\EventDispatcher; /** * An EventSubscriber knows which events it is interested in. * * If an EventSubscriber is added to an EventDispatcher, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek */ interface EventSubscriberInterface { /** * Returns an array of event names this subscriber wants to listen to. * * The array keys are event names and the value can be: * * * The method name to call (priority defaults to 0) * * An array composed of the method name to call and the priority * * An array of arrays composed of the method names to call and respective * priorities, or 0 if unset * * For instance: * * * array('eventName' => 'methodName') * * array('eventName' => array('methodName', $priority)) * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) * * @return array> The event names to listen to */ public static function getSubscribedEvents(); } * 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\Package\RootPackageInterface; use Composer\Util\Loop; use Composer\Repository\RepositoryManager; use Composer\Installer\InstallationManager; use Composer\EventDispatcher\EventDispatcher; /** * @author Jordi Boggiano */ class PartialComposer { /** * @var bool */ private $global = \false; /** * @var RootPackageInterface */ private $package; /** * @var Loop */ private $loop; /** * @var Repository\RepositoryManager */ private $repositoryManager; /** * @var Installer\InstallationManager */ private $installationManager; /** * @var Config */ private $config; /** * @var EventDispatcher */ private $eventDispatcher; public function setPackage(RootPackageInterface $package) : void { $this->package = $package; } public function getPackage() : RootPackageInterface { return $this->package; } public function setConfig(\Composer\Config $config) : void { $this->config = $config; } public function getConfig() : \Composer\Config { return $this->config; } public function setLoop(Loop $loop) : void { $this->loop = $loop; } public function getLoop() : Loop { return $this->loop; } public function setRepositoryManager(RepositoryManager $manager) : void { $this->repositoryManager = $manager; } public function getRepositoryManager() : RepositoryManager { return $this->repositoryManager; } public function setInstallationManager(InstallationManager $manager) : void { $this->installationManager = $manager; } public function getInstallationManager() : InstallationManager { return $this->installationManager; } public function setEventDispatcher(EventDispatcher $eventDispatcher) : void { $this->eventDispatcher = $eventDispatcher; } public function getEventDispatcher() : EventDispatcher { return $this->eventDispatcher; } public function isGlobal() : bool { return $this->global; } public function setGlobal() : void { $this->global = \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Platform; class Runtime { /** * @param class-string $class */ public function hasConstant(string $constant, ?string $class = null) : bool { return \defined(\ltrim($class . '::' . $constant, ':')); } /** * @param class-string $class * * @return mixed */ public function getConstant(string $constant, ?string $class = null) { return \constant(\ltrim($class . '::' . $constant, ':')); } public function hasFunction(string $fn) : bool { return \function_exists($fn); } /** * @param mixed[] $arguments * * @return mixed */ public function invoke(callable $callable, array $arguments = []) { return $callable(...$arguments); } /** * @param class-string $class */ public function hasClass(string $class) : bool { return \class_exists($class, \false); } /** * @template T of object * @param mixed[] $arguments * * @phpstan-param class-string $class * @phpstan-return T * * @throws \ReflectionException */ public function construct(string $class, array $arguments = []) : object { if (empty($arguments)) { return new $class(); } $refl = new \ReflectionClass($class); return $refl->newInstanceArgs($arguments); } /** @return string[] */ public function getExtensions() : array { return \get_loaded_extensions(); } public function getExtensionVersion(string $extension) : string { $version = \phpversion($extension); if ($version === \false) { $version = '0'; } return $version; } /** * @throws \ReflectionException */ public function getExtensionInfo(string $extension) : string { $reflector = new \ReflectionExtension($extension); \ob_start(); $reflector->info(); return \ob_get_clean(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Platform; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use _ContaoManager\Symfony\Component\Process\ExecutableFinder; class HhvmDetector { /** @var string|false|null */ private static $hhvmVersion = null; /** @var ?ExecutableFinder */ private $executableFinder; /** @var ?ProcessExecutor */ private $processExecutor; public function __construct(?ExecutableFinder $executableFinder = null, ?ProcessExecutor $processExecutor = null) { $this->executableFinder = $executableFinder; $this->processExecutor = $processExecutor; } public function reset() : void { self::$hhvmVersion = null; } public function getVersion() : ?string { if (null !== self::$hhvmVersion) { return self::$hhvmVersion ?: null; } self::$hhvmVersion = \defined('_ContaoManager\\HHVM_VERSION') ? HHVM_VERSION : null; if (self::$hhvmVersion === null && !Platform::isWindows()) { self::$hhvmVersion = \false; $this->executableFinder = $this->executableFinder ?: new ExecutableFinder(); $hhvmPath = $this->executableFinder->find('hhvm'); if ($hhvmPath !== null) { $this->processExecutor = $this->processExecutor ?? new ProcessExecutor(); $exitCode = $this->processExecutor->execute([$hhvmPath, '--php', '-d', 'hhvm.jit=0', '-r', 'echo HHVM_VERSION;'], self::$hhvmVersion); if ($exitCode !== 0) { self::$hhvmVersion = \false; } } } return self::$hhvmVersion ?: null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Platform; use Composer\Pcre\Preg; /** * @author Lars Strojny */ class Version { /** * @param bool $isFips Set by the method * * @param-out bool $isFips */ public static function parseOpenssl(string $opensslVersion, ?bool &$isFips) : ?string { $isFips = \false; if (!Preg::isMatchStrictGroups('/^(?[0-9.]+)(?[a-z]{0,2})(?(?:-?(?:dev|pre|alpha|beta|rc|fips)[\\d]*)*)(?:-\\w+)?(?: \\(.+?\\))?$/', $opensslVersion, $matches)) { return null; } // OpenSSL 1 used 1.2.3a style versioning, 3+ uses semver $patch = ''; if (\version_compare($matches['version'], '3.0.0', '<')) { $patch = '.' . self::convertAlphaVersionToIntVersion($matches['patch']); } $isFips = \strpos($matches['suffix'], 'fips') !== \false; $suffix = \strtr('-' . \ltrim($matches['suffix'], '-'), ['-fips' => '', '-pre' => '-alpha']); return \rtrim($matches['version'] . $patch . $suffix, '-'); } public static function parseLibjpeg(string $libjpegVersion) : ?string { if (!Preg::isMatchStrictGroups('/^(?\\d+)(?[a-z]*)$/', $libjpegVersion, $matches)) { return null; } return $matches['major'] . '.' . self::convertAlphaVersionToIntVersion($matches['minor']); } public static function parseZoneinfoVersion(string $zoneinfoVersion) : ?string { if (!Preg::isMatchStrictGroups('/^(?\\d{4})(?[a-z]*)$/', $zoneinfoVersion, $matches)) { return null; } return $matches['year'] . '.' . self::convertAlphaVersionToIntVersion($matches['revision']); } /** * "" => 0, "a" => 1, "zg" => 33 */ private static function convertAlphaVersionToIntVersion(string $alpha) : int { return \strlen($alpha) * (-\ord('a') + 1) + \array_sum(\array_map('ord', \str_split($alpha))); } public static function convertLibxpmVersionId(int $versionId) : string { return self::convertVersionId($versionId, 100); } public static function convertOpenldapVersionId(int $versionId) : string { return self::convertVersionId($versionId, 100); } private static function convertVersionId(int $versionId, int $base) : string { return \sprintf('%d.%d.%d', $versionId / ($base * $base), (int) ($versionId / $base) % $base, $versionId % $base); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\IO; use Composer\Pcre\Preg; use _ContaoManager\Symfony\Component\Console\Helper\QuestionHelper; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Console\Output\StreamOutput; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterInterface; use _ContaoManager\Symfony\Component\Console\Input\StreamableInputInterface; use _ContaoManager\Symfony\Component\Console\Input\StringInput; use _ContaoManager\Symfony\Component\Console\Helper\HelperSet; /** * @author Jordi Boggiano */ class BufferIO extends \Composer\IO\ConsoleIO { public function __construct(string $input = '', int $verbosity = StreamOutput::VERBOSITY_NORMAL, ?OutputFormatterInterface $formatter = null) { $input = new StringInput($input); $input->setInteractive(\false); $stream = \fopen('php://memory', 'rw'); if ($stream === \false) { throw new \RuntimeException('Unable to open memory output stream'); } $output = new StreamOutput($stream, $verbosity, $formatter !== null ? $formatter->isDecorated() : \false, $formatter); parent::__construct($input, $output, new HelperSet([new QuestionHelper()])); } /** * @return string output */ public function getOutput() : string { \assert($this->output instanceof StreamOutput); \fseek($this->output->getStream(), 0); $output = (string) \stream_get_contents($this->output->getStream()); $output = Preg::replaceCallback("{(?<=^|\n|\x08)(.+?)(\x08+)}", static function ($matches) : string { $pre = \strip_tags($matches[1]); if (\strlen($pre) === \strlen($matches[2])) { return ''; } // TODO reverse parse the string, skipping span tags and \033\[([0-9;]+)m(.*?)\033\[0m style blobs return \rtrim($matches[1]) . "\n"; }, $output); return $output; } /** * @param string[] $inputs * * @see createStream */ public function setUserInputs(array $inputs) : void { if (!$this->input instanceof StreamableInputInterface) { throw new \RuntimeException('Setting the user inputs requires at least the version 3.2 of the symfony/console component.'); } $this->input->setStream($this->createStream($inputs)); $this->input->setInteractive(\true); } /** * @param string[] $inputs * * @return resource stream */ private function createStream(array $inputs) { $stream = \fopen('php://memory', 'r+'); if ($stream === \false) { throw new \RuntimeException('Unable to open memory output stream'); } foreach ($inputs as $input) { \fwrite($stream, $input . \PHP_EOL); } \rewind($stream); return $stream; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\IO; use Composer\Question\StrictConfirmationQuestion; use _ContaoManager\Symfony\Component\Console\Helper\HelperSet; use _ContaoManager\Symfony\Component\Console\Helper\ProgressBar; use _ContaoManager\Symfony\Component\Console\Helper\Table; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Console\Question\ChoiceQuestion; use _ContaoManager\Symfony\Component\Console\Question\Question; /** * The Input/Output helper. * * @author François Pluchino * @author Jordi Boggiano */ class ConsoleIO extends \Composer\IO\BaseIO { /** @var InputInterface */ protected $input; /** @var OutputInterface */ protected $output; /** @var HelperSet */ protected $helperSet; /** @var string */ protected $lastMessage = ''; /** @var string */ protected $lastMessageErr = ''; /** @var float */ private $startTime; /** @var array */ private $verbosityMap; /** * Constructor. * * @param InputInterface $input The input instance * @param OutputInterface $output The output instance * @param HelperSet $helperSet The helperSet instance */ public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet) { $this->input = $input; $this->output = $output; $this->helperSet = $helperSet; $this->verbosityMap = [self::QUIET => OutputInterface::VERBOSITY_QUIET, self::NORMAL => OutputInterface::VERBOSITY_NORMAL, self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE, self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE, self::DEBUG => OutputInterface::VERBOSITY_DEBUG]; } /** * @return void */ public function enableDebugging(float $startTime) { $this->startTime = $startTime; } /** * @inheritDoc */ public function isInteractive() { return $this->input->isInteractive(); } /** * @inheritDoc */ public function isDecorated() { return $this->output->isDecorated(); } /** * @inheritDoc */ public function isVerbose() { return $this->output->isVerbose(); } /** * @inheritDoc */ public function isVeryVerbose() { return $this->output->isVeryVerbose(); } /** * @inheritDoc */ public function isDebug() { return $this->output->isDebug(); } /** * @inheritDoc */ public function write($messages, bool $newline = \true, int $verbosity = self::NORMAL) { $this->doWrite($messages, $newline, \false, $verbosity); } /** * @inheritDoc */ public function writeError($messages, bool $newline = \true, int $verbosity = self::NORMAL) { $this->doWrite($messages, $newline, \true, $verbosity); } /** * @inheritDoc */ public function writeRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL) { $this->doWrite($messages, $newline, \false, $verbosity, \true); } /** * @inheritDoc */ public function writeErrorRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL) { $this->doWrite($messages, $newline, \true, $verbosity, \true); } /** * @param string[]|string $messages */ private function doWrite($messages, bool $newline, bool $stderr, int $verbosity, bool $raw = \false) : void { $sfVerbosity = $this->verbosityMap[$verbosity]; if ($sfVerbosity > $this->output->getVerbosity()) { return; } if ($raw) { $sfVerbosity |= OutputInterface::OUTPUT_RAW; } if (null !== $this->startTime) { $memoryUsage = \memory_get_usage() / 1024 / 1024; $timeSpent = \microtime(\true) - $this->startTime; $messages = \array_map(static function ($message) use($memoryUsage, $timeSpent) : string { return \sprintf('[%.1fMiB/%.2fs] %s', $memoryUsage, $timeSpent, $message); }, (array) $messages); } if (\true === $stderr && $this->output instanceof ConsoleOutputInterface) { $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity); $this->lastMessageErr = \implode($newline ? "\n" : '', (array) $messages); return; } $this->output->write($messages, $newline, $sfVerbosity); $this->lastMessage = \implode($newline ? "\n" : '', (array) $messages); } /** * @inheritDoc */ public function overwrite($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL) { $this->doOverwrite($messages, $newline, $size, \false, $verbosity); } /** * @inheritDoc */ public function overwriteError($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL) { $this->doOverwrite($messages, $newline, $size, \true, $verbosity); } /** * @param string[]|string $messages */ private function doOverwrite($messages, bool $newline, ?int $size, bool $stderr, int $verbosity) : void { // messages can be an array, let's convert it to string anyway $messages = \implode($newline ? "\n" : '', (array) $messages); // since overwrite is supposed to overwrite last message... if (!isset($size)) { // removing possible formatting of lastMessage with strip_tags $size = \strlen(\strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage)); } // ...let's fill its length with backspaces $this->doWrite(\str_repeat("\x08", $size), \false, $stderr, $verbosity); // write the new message $this->doWrite($messages, \false, $stderr, $verbosity); // In cmd.exe on Win8.1 (possibly 10?), the line can not be cleared, so we need to // track the length of previous output and fill it with spaces to make sure the line is cleared. // See https://github.com/composer/composer/pull/5836 for more details $fill = $size - \strlen(\strip_tags($messages)); if ($fill > 0) { // whitespace whatever has left $this->doWrite(\str_repeat(' ', $fill), \false, $stderr, $verbosity); // move the cursor back $this->doWrite(\str_repeat("\x08", $fill), \false, $stderr, $verbosity); } if ($newline) { $this->doWrite('', \true, $stderr, $verbosity); } if ($stderr) { $this->lastMessageErr = $messages; } else { $this->lastMessage = $messages; } } /** * @return ProgressBar */ public function getProgressBar(int $max = 0) { return new ProgressBar($this->getErrorOutput(), $max); } /** * @inheritDoc */ public function ask($question, $default = null) { /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */ $helper = $this->helperSet->get('question'); $question = new Question($question, $default); return $helper->ask($this->input, $this->getErrorOutput(), $question); } /** * @inheritDoc */ public function askConfirmation($question, $default = \true) { /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */ $helper = $this->helperSet->get('question'); $question = new StrictConfirmationQuestion($question, $default); return $helper->ask($this->input, $this->getErrorOutput(), $question); } /** * @inheritDoc */ public function askAndValidate($question, $validator, $attempts = null, $default = null) { /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */ $helper = $this->helperSet->get('question'); $question = new Question($question, $default); $question->setValidator($validator); $question->setMaxAttempts($attempts); return $helper->ask($this->input, $this->getErrorOutput(), $question); } /** * @inheritDoc */ public function askAndHideAnswer($question) { /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */ $helper = $this->helperSet->get('question'); $question = new Question($question); $question->setHidden(\true); return $helper->ask($this->input, $this->getErrorOutput(), $question); } /** * @inheritDoc */ public function select($question, $choices, $default, $attempts = \false, $errorMessage = 'Value "%s" is invalid', $multiselect = \false) { /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */ $helper = $this->helperSet->get('question'); $question = new ChoiceQuestion($question, $choices, $default); $question->setMaxAttempts($attempts ?: null); // IOInterface requires false, and Question requires null or int $question->setErrorMessage($errorMessage); $question->setMultiselect($multiselect); $result = $helper->ask($this->input, $this->getErrorOutput(), $question); $isAssoc = (bool) \count(\array_filter(\array_keys($choices), 'is_string')); if ($isAssoc) { return $result; } if (!\is_array($result)) { return (string) \array_search($result, $choices, \true); } $results = []; foreach ($choices as $index => $choice) { if (\in_array($choice, $result, \true)) { $results[] = (string) $index; } } return $results; } public function getTable() : Table { return new Table($this->output); } private function getErrorOutput() : OutputInterface { if ($this->output instanceof ConsoleOutputInterface) { return $this->output->getErrorOutput(); } return $this->output; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\IO; use Composer\Config; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Silencer; use _ContaoManager\Psr\Log\LogLevel; abstract class BaseIO implements \Composer\IO\IOInterface { /** @var array */ protected $authentications = []; /** * @inheritDoc */ public function getAuthentications() { return $this->authentications; } /** * @return void */ public function resetAuthentications() { $this->authentications = []; } /** * @inheritDoc */ public function hasAuthentication($repositoryName) { return isset($this->authentications[$repositoryName]); } /** * @inheritDoc */ public function getAuthentication($repositoryName) { if (isset($this->authentications[$repositoryName])) { return $this->authentications[$repositoryName]; } return ['username' => null, 'password' => null]; } /** * @inheritDoc */ public function setAuthentication($repositoryName, $username, $password = null) { $this->authentications[$repositoryName] = ['username' => $username, 'password' => $password]; } /** * @inheritDoc */ public function writeRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL) { $this->write($messages, $newline, $verbosity); } /** * @inheritDoc */ public function writeErrorRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL) { $this->writeError($messages, $newline, $verbosity); } /** * Check for overwrite and set the authentication information for the repository. * * @param string $repositoryName The unique name of repository * @param string $username The username * @param string $password The password * * @return void */ protected function checkAndSetAuthentication(string $repositoryName, string $username, ?string $password = null) { if ($this->hasAuthentication($repositoryName)) { $auth = $this->getAuthentication($repositoryName); if ($auth['username'] === $username && $auth['password'] === $password) { return; } $this->writeError(\sprintf("Warning: You should avoid overwriting already defined auth settings for %s.", $repositoryName)); } $this->setAuthentication($repositoryName, $username, $password); } /** * @inheritDoc */ public function loadConfiguration(Config $config) { $bitbucketOauth = $config->get('bitbucket-oauth'); $githubOauth = $config->get('github-oauth'); $gitlabOauth = $config->get('gitlab-oauth'); $gitlabToken = $config->get('gitlab-token'); $httpBasic = $config->get('http-basic'); $bearerToken = $config->get('bearer'); // reload oauth tokens from config if available foreach ($bitbucketOauth as $domain => $cred) { $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']); } foreach ($githubOauth as $domain => $token) { if ($domain !== 'github.com' && !\in_array($domain, $config->get('github-domains'), \true)) { $this->debug($domain . ' is not in the configured github-domains, adding it implicitly as authentication is configured for this domain'); $config->merge(['config' => ['github-domains' => \array_merge($config->get('github-domains'), [$domain])]], 'implicit-due-to-auth'); } // allowed chars for GH tokens are from https://github.blog/changelog/2021-03-04-authentication-token-format-updates/ // plus dots which were at some point used for GH app integration tokens if (!Preg::isMatch('{^[.A-Za-z0-9_]+$}', $token)) { throw new \UnexpectedValueException('Your github oauth token for ' . $domain . ' contains invalid characters: "' . $token . '"'); } $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic'); } foreach ($gitlabOauth as $domain => $token) { if ($domain !== 'gitlab.com' && !\in_array($domain, $config->get('gitlab-domains'), \true)) { $this->debug($domain . ' is not in the configured gitlab-domains, adding it implicitly as authentication is configured for this domain'); $config->merge(['config' => ['gitlab-domains' => \array_merge($config->get('gitlab-domains'), [$domain])]], 'implicit-due-to-auth'); } $token = \is_array($token) ? $token["token"] : $token; $this->checkAndSetAuthentication($domain, $token, 'oauth2'); } foreach ($gitlabToken as $domain => $token) { if ($domain !== 'gitlab.com' && !\in_array($domain, $config->get('gitlab-domains'), \true)) { $this->debug($domain . ' is not in the configured gitlab-domains, adding it implicitly as authentication is configured for this domain'); $config->merge(['config' => ['gitlab-domains' => \array_merge($config->get('gitlab-domains'), [$domain])]], 'implicit-due-to-auth'); } $username = \is_array($token) ? $token["username"] : $token; $password = \is_array($token) ? $token["token"] : 'private-token'; $this->checkAndSetAuthentication($domain, $username, $password); } // reload http basic credentials from config if available foreach ($httpBasic as $domain => $cred) { $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']); } foreach ($bearerToken as $domain => $token) { $this->checkAndSetAuthentication($domain, $token, 'bearer'); } // setup process timeout ProcessExecutor::setTimeout($config->get('process-timeout')); } /** * @param string|\Stringable $message */ public function emergency($message, array $context = []) : void { $this->log(LogLevel::EMERGENCY, $message, $context); } /** * @param string|\Stringable $message */ public function alert($message, array $context = []) : void { $this->log(LogLevel::ALERT, $message, $context); } /** * @param string|\Stringable $message */ public function critical($message, array $context = []) : void { $this->log(LogLevel::CRITICAL, $message, $context); } /** * @param string|\Stringable $message */ public function error($message, array $context = []) : void { $this->log(LogLevel::ERROR, $message, $context); } /** * @param string|\Stringable $message */ public function warning($message, array $context = []) : void { $this->log(LogLevel::WARNING, $message, $context); } /** * @param string|\Stringable $message */ public function notice($message, array $context = []) : void { $this->log(LogLevel::NOTICE, $message, $context); } /** * @param string|\Stringable $message */ public function info($message, array $context = []) : void { $this->log(LogLevel::INFO, $message, $context); } /** * @param string|\Stringable $message */ public function debug($message, array $context = []) : void { $this->log(LogLevel::DEBUG, $message, $context); } /** * @param mixed|LogLevel::* $level * @param string|\Stringable $message */ public function log($level, $message, array $context = []) : void { $message = (string) $message; if ($context !== []) { $json = Silencer::call('json_encode', $context, \JSON_INVALID_UTF8_IGNORE | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); if ($json !== \false) { $message .= ' ' . $json; } } if (\in_array($level, [LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR])) { $this->writeError('' . $message . ''); } elseif ($level === LogLevel::WARNING) { $this->writeError('' . $message . ''); } elseif ($level === LogLevel::NOTICE) { $this->writeError('' . $message . '', \true, self::VERBOSE); } elseif ($level === LogLevel::INFO) { $this->writeError('' . $message . '', \true, self::VERY_VERBOSE); } else { $this->writeError($message, \true, self::DEBUG); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\IO; /** * IOInterface that is not interactive and never writes the output * * @author Christophe Coevoet */ class NullIO extends \Composer\IO\BaseIO { /** * @inheritDoc */ public function isInteractive() : bool { return \false; } /** * @inheritDoc */ public function isVerbose() : bool { return \false; } /** * @inheritDoc */ public function isVeryVerbose() : bool { return \false; } /** * @inheritDoc */ public function isDebug() : bool { return \false; } /** * @inheritDoc */ public function isDecorated() : bool { return \false; } /** * @inheritDoc */ public function write($messages, bool $newline = \true, int $verbosity = self::NORMAL) : void { } /** * @inheritDoc */ public function writeError($messages, bool $newline = \true, int $verbosity = self::NORMAL) : void { } /** * @inheritDoc */ public function overwrite($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL) : void { } /** * @inheritDoc */ public function overwriteError($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL) : void { } /** * @inheritDoc */ public function ask($question, $default = null) { return $default; } /** * @inheritDoc */ public function askConfirmation($question, $default = \true) : bool { return $default; } /** * @inheritDoc */ public function askAndValidate($question, $validator, $attempts = null, $default = null) { return $default; } /** * @inheritDoc */ public function askAndHideAnswer($question) : ?string { return null; } /** * @inheritDoc */ public function select($question, $choices, $default, $attempts = \false, $errorMessage = 'Value "%s" is invalid', $multiselect = \false) { return $default; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\IO; use Composer\Config; use _ContaoManager\Psr\Log\LoggerInterface; /** * The Input/Output helper interface. * * @author François Pluchino */ interface IOInterface extends LoggerInterface { public const QUIET = 1; public const NORMAL = 2; public const VERBOSE = 4; public const VERY_VERBOSE = 8; public const DEBUG = 16; /** * Is this input means interactive? * * @return bool */ public function isInteractive(); /** * Is this output verbose? * * @return bool */ public function isVerbose(); /** * Is the output very verbose? * * @return bool */ public function isVeryVerbose(); /** * Is the output in debug verbosity? * * @return bool */ public function isDebug(); /** * Is this output decorated? * * @return bool */ public function isDecorated(); /** * Writes a message to the output. * * @param string|string[] $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not * @param int $verbosity Verbosity level from the VERBOSITY_* constants * * @return void */ public function write($messages, bool $newline = \true, int $verbosity = self::NORMAL); /** * Writes a message to the error output. * * @param string|string[] $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not * @param int $verbosity Verbosity level from the VERBOSITY_* constants * * @return void */ public function writeError($messages, bool $newline = \true, int $verbosity = self::NORMAL); /** * Writes a message to the output, without formatting it. * * @param string|string[] $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not * @param int $verbosity Verbosity level from the VERBOSITY_* constants * * @return void */ public function writeRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL); /** * Writes a message to the error output, without formatting it. * * @param string|string[] $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not * @param int $verbosity Verbosity level from the VERBOSITY_* constants * * @return void */ public function writeErrorRaw($messages, bool $newline = \true, int $verbosity = self::NORMAL); /** * Overwrites a previous message to the output. * * @param string|string[] $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not * @param int $size The size of line * @param int $verbosity Verbosity level from the VERBOSITY_* constants * * @return void */ public function overwrite($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL); /** * Overwrites a previous message to the error output. * * @param string|string[] $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not * @param int $size The size of line * @param int $verbosity Verbosity level from the VERBOSITY_* constants * * @return void */ public function overwriteError($messages, bool $newline = \true, ?int $size = null, int $verbosity = self::NORMAL); /** * Asks a question to the user. * * @param string $question The question to ask * @param string|bool|int|float|null $default The default answer if none is given by the user * * @throws \RuntimeException If there is no data to read in the input stream * @return mixed The user answer */ public function ask(string $question, $default = null); /** * Asks a confirmation to the user. * * The question will be asked until the user answers by nothing, yes, or no. * * @param string $question The question to ask * @param bool $default The default answer if the user enters nothing * * @return bool true if the user has confirmed, false otherwise */ public function askConfirmation(string $question, bool $default = \true); /** * Asks for a value and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param string $question The question to ask * @param callable $validator A PHP callback * @param null|int $attempts Max number of times to ask before giving up (default of null means infinite) * @param mixed $default The default answer if none is given by the user * * @throws \Exception When any of the validators return an error * @return mixed */ public function askAndValidate(string $question, callable $validator, ?int $attempts = null, $default = null); /** * Asks a question to the user and hide the answer. * * @param string $question The question to ask * * @return string|null The answer */ public function askAndHideAnswer(string $question); /** * Asks the user to select a value. * * @param string $question The question to ask * @param string[] $choices List of choices to pick from * @param bool|string $default The default answer if the user enters nothing * @param bool|int $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked * @param bool $multiselect Select more than one value separated by comma * * @throws \InvalidArgumentException * * @return int|string|list|bool The selected value or values (the key of the choices array) * @phpstan-return ($multiselect is true ? list : string|int|bool) */ public function select(string $question, array $choices, $default, $attempts = \false, string $errorMessage = 'Value "%s" is invalid', bool $multiselect = \false); /** * Get all authentication information entered. * * @return array The map of authentication data */ public function getAuthentications(); /** * Verify if the repository has a authentication information. * * @param string $repositoryName The unique name of repository * * @return bool */ public function hasAuthentication(string $repositoryName); /** * Get the username and password of repository. * * @param string $repositoryName The unique name of repository * * @return array{username: string|null, password: string|null} */ public function getAuthentication(string $repositoryName); /** * Set the authentication information for the repository. * * @param string $repositoryName The unique name of repository * @param string $username The username * @param null|string $password The password * * @return void */ public function setAuthentication(string $repositoryName, string $username, ?string $password = null); /** * Loads authentications from a config instance * * @return void */ public function loadConfiguration(Config $config); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; /** * The Plugin Events. * * @author Nils Adermann */ class PluginEvents { /** * The INIT event occurs after a Composer instance is done being initialized * * The event listener method receives a * Composer\EventDispatcher\Event instance. * * @var string */ public const INIT = 'init'; /** * The COMMAND event occurs as a command begins * * The event listener method receives a * Composer\Plugin\CommandEvent instance. * * @var string */ public const COMMAND = 'command'; /** * The PRE_FILE_DOWNLOAD event occurs before downloading a file * * The event listener method receives a * Composer\Plugin\PreFileDownloadEvent instance. * * @var string */ public const PRE_FILE_DOWNLOAD = 'pre-file-download'; /** * The POST_FILE_DOWNLOAD event occurs after downloading a package dist file * * The event listener method receives a * Composer\Plugin\PostFileDownloadEvent instance. * * @var string */ public const POST_FILE_DOWNLOAD = 'post-file-download'; /** * The PRE_COMMAND_RUN event occurs before a command is executed and lets you modify the input arguments/options * * The event listener method receives a * Composer\Plugin\PreCommandRunEvent instance. * * @var string */ public const PRE_COMMAND_RUN = 'pre-command-run'; /** * The PRE_POOL_CREATE event occurs before the Pool of packages is created, and lets * you filter the list of packages which is going to enter the Solver * * The event listener method receives a * Composer\Plugin\PrePoolCreateEvent instance. * * @var string */ public const PRE_POOL_CREATE = 'pre-pool-create'; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use Composer\EventDispatcher\Event; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; /** * The pre command run event. * * @author Jordi Boggiano */ class PreCommandRunEvent extends Event { /** * @var InputInterface */ private $input; /** * @var string */ private $command; /** * Constructor. * * @param string $name The event name * @param string $command The command about to be executed */ public function __construct(string $name, InputInterface $input, string $command) { parent::__construct($name); $this->input = $input; $this->command = $command; } /** * Returns the console input */ public function getInput() : InputInterface { return $this->input; } /** * Returns the command about to be executed */ public function getCommand() : string { return $this->command; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin\Capability; /** * Commands Provider Interface * * This capability will receive an array with 'composer' and 'io' keys as * constructor argument. Those contain Composer\Composer and Composer\IO\IOInterface * instances. It also contains a 'plugin' key containing the plugin instance that * created the capability. * * @author Jérémy Derussé */ interface CommandProvider extends \Composer\Plugin\Capability\Capability { /** * Retrieves an array of commands * * @return \Composer\Command\BaseCommand[] */ public function getCommands(); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin\Capability; /** * Marker interface for Plugin capabilities. * Every new Capability which is added to the Plugin API must implement this interface. * * @api */ interface Capability { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use UnexpectedValueException; class PluginBlockedException extends UnexpectedValueException { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use Composer\EventDispatcher\Event; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * An event for all commands. * * @author Nils Adermann */ class CommandEvent extends Event { /** * @var string */ private $commandName; /** * @var InputInterface */ private $input; /** * @var OutputInterface */ private $output; /** * Constructor. * * @param string $name The event name * @param string $commandName The command name * @param mixed[] $args Arguments passed by the user * @param mixed[] $flags Optional flags to pass data not as argument */ public function __construct(string $name, string $commandName, InputInterface $input, OutputInterface $output, array $args = [], array $flags = []) { parent::__construct($name, $args, $flags); $this->commandName = $commandName; $this->input = $input; $this->output = $output; } /** * Returns the command input interface */ public function getInput() : InputInterface { return $this->input; } /** * Retrieves the command output interface */ public function getOutput() : OutputInterface { return $this->output; } /** * Retrieves the name of the command being run */ public function getCommandName() : string { return $this->commandName; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use Composer\Composer; use Composer\IO\IOInterface; /** * Plugin interface * * @author Nils Adermann */ interface PluginInterface { /** * Version number of the internal composer-plugin-api package * * This is used to denote the API version of Plugin specific * features, but is also bumped to a new major if Composer * includes a major break in internal APIs which are susceptible * to be used by plugins. * * @var string */ public const PLUGIN_API_VERSION = '2.6.0'; /** * Apply plugin modifications to Composer * * @return void */ public function activate(Composer $composer, IOInterface $io); /** * Remove any hooks from Composer * * This will be called when a plugin is deactivated before being * uninstalled, but also before it gets upgraded to a new version * so the old one can be deactivated and the new one activated. * * @return void */ public function deactivate(Composer $composer, IOInterface $io); /** * Prepare the plugin to be uninstalled * * This will be called after deactivate. * * @return void */ public function uninstall(Composer $composer, IOInterface $io); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use Composer\Composer; use Composer\EventDispatcher\EventSubscriberInterface; use Composer\Installer\InstallerInterface; use Composer\IO\IOInterface; use Composer\Package\BasePackage; use Composer\Package\CompletePackage; use Composer\Package\Locker; use Composer\Package\Package; use Composer\Package\RootPackageInterface; use Composer\Package\Version\VersionParser; use Composer\PartialComposer; use Composer\Pcre\Preg; use Composer\Repository\RepositoryInterface; use Composer\Repository\InstalledRepository; use Composer\Repository\RepositoryUtils; use Composer\Repository\RootPackageRepository; use Composer\Package\PackageInterface; use Composer\Package\Link; use Composer\Semver\Constraint\Constraint; use Composer\Plugin\Capability\Capability; use Composer\Util\PackageSorter; /** * Plugin manager * * @author Nils Adermann * @author Jordi Boggiano */ class PluginManager { /** @var Composer */ protected $composer; /** @var IOInterface */ protected $io; /** @var PartialComposer|null */ protected $globalComposer; /** @var VersionParser */ protected $versionParser; /** @var bool|'local'|'global' */ protected $disablePlugins = \false; /** @var array */ protected $plugins = []; /** @var array> */ protected $registeredPlugins = []; /** * @var array|null */ private $allowPluginRules; /** * @var array|null */ private $allowGlobalPluginRules; /** @var bool */ private $runningInGlobalDir = \false; /** @var int */ private static $classCounter = 0; /** * @param bool|'local'|'global' $disablePlugins Whether plugins should not be loaded, can be set to local or global to only disable local/global plugins */ public function __construct(IOInterface $io, Composer $composer, ?PartialComposer $globalComposer = null, $disablePlugins = \false) { $this->io = $io; $this->composer = $composer; $this->globalComposer = $globalComposer; $this->versionParser = new VersionParser(); $this->disablePlugins = $disablePlugins; $this->allowPluginRules = $this->parseAllowedPlugins($composer->getConfig()->get('allow-plugins'), $composer->getLocker()); $this->allowGlobalPluginRules = $this->parseAllowedPlugins($globalComposer !== null ? $globalComposer->getConfig()->get('allow-plugins') : \false); } public function setRunningInGlobalDir(bool $runningInGlobalDir) : void { $this->runningInGlobalDir = $runningInGlobalDir; } /** * Loads all plugins from currently installed plugin packages */ public function loadInstalledPlugins() : void { if (!$this->arePluginsDisabled('local')) { $repo = $this->composer->getRepositoryManager()->getLocalRepository(); $this->loadRepository($repo, \false, $this->composer->getPackage()); } if ($this->globalComposer !== null && !$this->arePluginsDisabled('global')) { $this->loadRepository($this->globalComposer->getRepositoryManager()->getLocalRepository(), \true); } } /** * Deactivate all plugins from currently installed plugin packages */ public function deactivateInstalledPlugins() : void { if (!$this->arePluginsDisabled('local')) { $repo = $this->composer->getRepositoryManager()->getLocalRepository(); $this->deactivateRepository($repo, \false); } if ($this->globalComposer !== null && !$this->arePluginsDisabled('global')) { $this->deactivateRepository($this->globalComposer->getRepositoryManager()->getLocalRepository(), \true); } } /** * Gets all currently active plugin instances * * @return array plugins */ public function getPlugins() : array { return $this->plugins; } /** * Gets global composer or null when main composer is not fully loaded */ public function getGlobalComposer() : ?PartialComposer { return $this->globalComposer; } /** * Register a plugin package, activate it etc. * * If it's of type composer-installer it is registered as an installer * instead for BC * * @param bool $failOnMissingClasses By default this silently skips plugins that can not be found, but if set to true it fails with an exception * @param bool $isGlobalPlugin Set to true to denote plugins which are installed in the global Composer directory * * @throws \UnexpectedValueException */ public function registerPackage(PackageInterface $package, bool $failOnMissingClasses = \false, bool $isGlobalPlugin = \false) : void { if ($this->arePluginsDisabled($isGlobalPlugin ? 'global' : 'local')) { $this->io->writeError('The "' . $package->getName() . '" plugin was not loaded as plugins are disabled.'); return; } if ($package->getType() === 'composer-plugin') { $requiresComposer = null; foreach ($package->getRequires() as $link) { /** @var Link $link */ if ('composer-plugin-api' === $link->getTarget()) { $requiresComposer = $link->getConstraint(); break; } } if (!$requiresComposer) { throw new \RuntimeException("Plugin " . $package->getName() . " is missing a require statement for a version of the composer-plugin-api package."); } $currentPluginApiVersion = $this->getPluginApiVersion(); $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion)); if ($requiresComposer->getPrettyString() === $this->getPluginApiVersion()) { $this->io->writeError('The "' . $package->getName() . '" plugin requires composer-plugin-api ' . $this->getPluginApiVersion() . ', this *WILL* break in the future and it should be fixed ASAP (require ^' . $this->getPluginApiVersion() . ' instead for example).'); } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) { $this->io->writeError('The "' . $package->getName() . '" plugin ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'was skipped because it requires a Plugin API version ("' . $requiresComposer->getPrettyString() . '") that does not match your Composer installation ("' . $currentPluginApiVersion . '"). You may need to run composer update with the "--no-plugins" option.'); return; } if ($package->getName() === 'symfony/flex' && Preg::isMatch('{^[0-9.]+$}', $package->getVersion()) && \version_compare($package->getVersion(), '1.9.8', '<')) { $this->io->writeError('The "' . $package->getName() . '" plugin ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'was skipped because it is not compatible with Composer 2+. Make sure to update it to version 1.9.8 or greater.'); return; } } if (!$this->isPluginAllowed($package->getName(), $isGlobalPlugin, \true === ($package->getExtra()['plugin-optional'] ?? \false))) { $this->io->writeError('Skipped loading "' . $package->getName() . '" ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'as it is not in config.allow-plugins', \true, IOInterface::DEBUG); return; } $oldInstallerPlugin = $package->getType() === 'composer-installer'; if (isset($this->registeredPlugins[$package->getName()])) { return; } $this->registeredPlugins[$package->getName()] = []; $extra = $package->getExtra(); if (empty($extra['class'])) { throw new \UnexpectedValueException('Error while installing ' . $package->getPrettyName() . ', composer-plugin packages should have a class defined in their extra key to be usable.'); } $classes = \is_array($extra['class']) ? $extra['class'] : [$extra['class']]; $localRepo = $this->composer->getRepositoryManager()->getLocalRepository(); $globalRepo = $this->globalComposer !== null ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null; $rootPackage = clone $this->composer->getPackage(); // clear files autoload rules from the root package as the root dependencies are not // necessarily all present yet when booting this runtime autoloader $rootPackageAutoloads = $rootPackage->getAutoload(); $rootPackageAutoloads['files'] = []; $rootPackage->setAutoload($rootPackageAutoloads); $rootPackageAutoloads = $rootPackage->getDevAutoload(); $rootPackageAutoloads['files'] = []; $rootPackage->setDevAutoload($rootPackageAutoloads); unset($rootPackageAutoloads); $rootPackageRepo = new RootPackageRepository($rootPackage); $installedRepo = new InstalledRepository([$localRepo, $rootPackageRepo]); if ($globalRepo) { $installedRepo->addRepository($globalRepo); } $autoloadPackages = [$package->getName() => $package]; $autoloadPackages = $this->collectDependencies($installedRepo, $autoloadPackages, $package); $generator = $this->composer->getAutoloadGenerator(); $autoloads = [[$rootPackage, '']]; foreach ($autoloadPackages as $autoloadPackage) { if ($autoloadPackage === $rootPackage) { continue; } $installPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage)); if ($installPath === null) { continue; } $autoloads[] = [$autoloadPackage, $installPath]; } $map = $generator->parseAutoloads($autoloads, $rootPackage); $classLoader = $generator->createLoader($map, $this->composer->getConfig()->get('vendor-dir')); $classLoader->register(\false); foreach ($map['files'] as $fileIdentifier => $file) { // exclude laminas/laminas-zendframework-bridge:src/autoload.php as it breaks Composer in some conditions // see https://github.com/composer/composer/issues/10349 and https://github.com/composer/composer/issues/10401 // this hack can be removed once this deprecated package stop being installed if ($fileIdentifier === '7e9bd612cc444b3eed788ebbe46263a0') { continue; } \Composer\Autoload\composerRequire($fileIdentifier, $file); } foreach ($classes as $class) { if (\class_exists($class, \false)) { $class = \trim($class, '\\'); $path = $classLoader->findFile($class); $code = \file_get_contents($path); $separatorPos = \strrpos($class, '\\'); $className = $class; if ($separatorPos) { $className = \substr($class, $separatorPos + 1); } $code = Preg::replace('{^((?:(?:final|readonly)\\s+)*(?:\\s*))class\\s+(' . \preg_quote($className) . ')}mi', '$1class $2_composer_tmp' . self::$classCounter, $code, 1); $code = \strtr($code, ['__FILE__' => \var_export($path, \true), '__DIR__' => \var_export(\dirname($path), \true), '__CLASS__' => \var_export($class, \true)]); $code = Preg::replace('/^\\s*<\\?(php)?/i', '', $code, 1); eval($code); $class .= '_composer_tmp' . self::$classCounter; self::$classCounter++; } if ($oldInstallerPlugin) { if (!\is_a($class, 'Composer\\Installer\\InstallerInterface', \true)) { throw new \RuntimeException('Could not activate plugin "' . $package->getName() . '" as "' . $class . '" does not implement Composer\\Installer\\InstallerInterface'); } $this->io->writeError('Loading "' . $package->getName() . '" ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . 'which is a legacy composer-installer built for Composer 1.x, it is likely to cause issues as you are running Composer 2.x.'); $installer = new $class($this->io, $this->composer); $this->composer->getInstallationManager()->addInstaller($installer); $this->registeredPlugins[$package->getName()][] = $installer; } elseif (\class_exists($class)) { if (!\is_a($class, 'Composer\\Plugin\\PluginInterface', \true)) { throw new \RuntimeException('Could not activate plugin "' . $package->getName() . '" as "' . $class . '" does not implement Composer\\Plugin\\PluginInterface'); } $plugin = new $class(); $this->addPlugin($plugin, $isGlobalPlugin, $package); $this->registeredPlugins[$package->getName()][] = $plugin; } elseif ($failOnMissingClasses) { throw new \UnexpectedValueException('Plugin ' . $package->getName() . ' could not be initialized, class not found: ' . $class); } } } /** * Deactivates a plugin package * * If it's of type composer-installer it is unregistered from the installers * instead for BC * * @throws \UnexpectedValueException */ public function deactivatePackage(PackageInterface $package) : void { if (!isset($this->registeredPlugins[$package->getName()])) { return; } $plugins = $this->registeredPlugins[$package->getName()]; foreach ($plugins as $plugin) { if ($plugin instanceof InstallerInterface) { $this->composer->getInstallationManager()->removeInstaller($plugin); } else { $this->removePlugin($plugin); } } unset($this->registeredPlugins[$package->getName()]); } /** * Uninstall a plugin package * * If it's of type composer-installer it is unregistered from the installers * instead for BC * * @throws \UnexpectedValueException */ public function uninstallPackage(PackageInterface $package) : void { if (!isset($this->registeredPlugins[$package->getName()])) { return; } $plugins = $this->registeredPlugins[$package->getName()]; foreach ($plugins as $plugin) { if ($plugin instanceof InstallerInterface) { $this->composer->getInstallationManager()->removeInstaller($plugin); } else { $this->removePlugin($plugin); $this->uninstallPlugin($plugin); } } unset($this->registeredPlugins[$package->getName()]); } /** * Returns the version of the internal composer-plugin-api package. */ protected function getPluginApiVersion() : string { return \Composer\Plugin\PluginInterface::PLUGIN_API_VERSION; } /** * Adds a plugin, activates it and registers it with the event dispatcher * * Ideally plugin packages should be registered via registerPackage, but if you use Composer * programmatically and want to register a plugin class directly this is a valid way * to do it. * * @param PluginInterface $plugin plugin instance * @param ?PackageInterface $sourcePackage Package from which the plugin comes from */ public function addPlugin(\Composer\Plugin\PluginInterface $plugin, bool $isGlobalPlugin = \false, ?PackageInterface $sourcePackage = null) : void { if ($this->arePluginsDisabled($isGlobalPlugin ? 'global' : 'local')) { return; } if ($sourcePackage === null) { \trigger_error('Calling PluginManager::addPlugin without $sourcePackage is deprecated, if you are using this please get in touch with us to explain the use case', \E_USER_DEPRECATED); } elseif (!$this->isPluginAllowed($sourcePackage->getName(), $isGlobalPlugin, \true === ($sourcePackage->getExtra()['plugin-optional'] ?? \false))) { $this->io->writeError('Skipped loading "' . \get_class($plugin) . ' from ' . $sourcePackage->getName() . '" ' . ($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '') . ' as it is not in config.allow-plugins', \true, IOInterface::DEBUG); return; } $details = []; if ($sourcePackage) { $details[] = 'from ' . $sourcePackage->getName(); } if ($isGlobalPlugin || $this->runningInGlobalDir) { $details[] = 'installed globally'; } $this->io->writeError('Loading plugin ' . \get_class($plugin) . ($details ? ' (' . \implode(', ', $details) . ')' : ''), \true, IOInterface::DEBUG); $this->plugins[] = $plugin; $plugin->activate($this->composer, $this->io); if ($plugin instanceof EventSubscriberInterface) { $this->composer->getEventDispatcher()->addSubscriber($plugin); } } /** * Removes a plugin, deactivates it and removes any listener the plugin has set on the plugin instance * * Ideally plugin packages should be deactivated via deactivatePackage, but if you use Composer * programmatically and want to deregister a plugin class directly this is a valid way * to do it. * * @param PluginInterface $plugin plugin instance */ public function removePlugin(\Composer\Plugin\PluginInterface $plugin) : void { $index = \array_search($plugin, $this->plugins, \true); if ($index === \false) { return; } $this->io->writeError('Unloading plugin ' . \get_class($plugin), \true, IOInterface::DEBUG); unset($this->plugins[$index]); $plugin->deactivate($this->composer, $this->io); $this->composer->getEventDispatcher()->removeListener($plugin); } /** * Notifies a plugin it is being uninstalled and should clean up * * Ideally plugin packages should be uninstalled via uninstallPackage, but if you use Composer * programmatically and want to deregister a plugin class directly this is a valid way * to do it. * * @param PluginInterface $plugin plugin instance */ public function uninstallPlugin(\Composer\Plugin\PluginInterface $plugin) : void { $this->io->writeError('Uninstalling plugin ' . \get_class($plugin), \true, IOInterface::DEBUG); $plugin->uninstall($this->composer, $this->io); } /** * Load all plugins and installers from a repository * * If a plugin requires another plugin, the required one will be loaded first * * Note that plugins in the specified repository that rely on events that * have fired prior to loading will be missed. This means you likely want to * call this method as early as possible. * * @param RepositoryInterface $repo Repository to scan for plugins to install * * @phpstan-param ($isGlobalRepo is true ? null : RootPackageInterface) $rootPackage * * @throws \RuntimeException */ private function loadRepository(RepositoryInterface $repo, bool $isGlobalRepo, ?RootPackageInterface $rootPackage = null) : void { $packages = $repo->getPackages(); $weights = []; foreach ($packages as $package) { if ($package->getType() === 'composer-plugin') { $extra = $package->getExtra(); if ($package->getName() === 'composer/installers' || \true === ($extra['plugin-modifies-install-path'] ?? \false)) { $weights[$package->getName()] = -10000; } } } $sortedPackages = PackageSorter::sortPackages($packages, $weights); if (!$isGlobalRepo) { $requiredPackages = RepositoryUtils::filterRequiredPackages($packages, $rootPackage, \true); } foreach ($sortedPackages as $package) { if (!$package instanceof CompletePackage) { continue; } if (!\in_array($package->getType(), ['composer-plugin', 'composer-installer'], \true)) { continue; } if (!$isGlobalRepo && !\in_array($package, $requiredPackages, \true) && !$this->isPluginAllowed($package->getName(), \false, \true, \false)) { $this->io->writeError('The "' . $package->getName() . '" plugin was not loaded as it is not listed in allow-plugins and is not required by the root package anymore.'); continue; } if ('composer-plugin' === $package->getType()) { $this->registerPackage($package, \false, $isGlobalRepo); // Backward compatibility } elseif ('composer-installer' === $package->getType()) { $this->registerPackage($package, \false, $isGlobalRepo); } } } /** * Deactivate all plugins and installers from a repository * * If a plugin requires another plugin, the required one will be deactivated last * * @param RepositoryInterface $repo Repository to scan for plugins to install */ private function deactivateRepository(RepositoryInterface $repo, bool $isGlobalRepo) : void { $packages = $repo->getPackages(); $sortedPackages = \array_reverse(PackageSorter::sortPackages($packages)); foreach ($sortedPackages as $package) { if (!$package instanceof CompletePackage) { continue; } if ('composer-plugin' === $package->getType()) { $this->deactivatePackage($package); // Backward compatibility } elseif ('composer-installer' === $package->getType()) { $this->deactivatePackage($package); } } } /** * Recursively generates a map of package names to packages for all deps * * @param InstalledRepository $installedRepo Set of local repos * @param array $collected Current state of the map for recursion * @param PackageInterface $package The package to analyze * * @return array Map of package names to packages */ private function collectDependencies(InstalledRepository $installedRepo, array $collected, PackageInterface $package) : array { foreach ($package->getRequires() as $requireLink) { foreach ($installedRepo->findPackagesWithReplacersAndProviders($requireLink->getTarget()) as $requiredPackage) { if (!isset($collected[$requiredPackage->getName()])) { $collected[$requiredPackage->getName()] = $requiredPackage; $collected = $this->collectDependencies($installedRepo, $collected, $requiredPackage); } } } return $collected; } /** * Retrieves the path a package is installed to. * * @param bool $global Whether this is a global package * * @return string|null Install path */ private function getInstallPath(PackageInterface $package, bool $global = \false) : ?string { if (!$global) { return $this->composer->getInstallationManager()->getInstallPath($package); } \assert(null !== $this->globalComposer); return $this->globalComposer->getInstallationManager()->getInstallPath($package); } /** * @throws \RuntimeException On empty or non-string implementation class name value * @return null|string The fully qualified class of the implementation or null if Plugin is not of Capable type or does not provide it */ protected function getCapabilityImplementationClassName(\Composer\Plugin\PluginInterface $plugin, string $capability) : ?string { if (!$plugin instanceof \Composer\Plugin\Capable) { return null; } $capabilities = (array) $plugin->getCapabilities(); if (!empty($capabilities[$capability]) && \is_string($capabilities[$capability]) && \trim($capabilities[$capability])) { return \trim($capabilities[$capability]); } if (\array_key_exists($capability, $capabilities) && (empty($capabilities[$capability]) || !\is_string($capabilities[$capability]) || !\trim($capabilities[$capability]))) { throw new \UnexpectedValueException('Plugin ' . \get_class($plugin) . ' provided invalid capability class name(s), got ' . \var_export($capabilities[$capability], \true)); } return null; } /** * @template CapabilityClass of Capability * @param class-string $capabilityClassName The fully qualified name of the API interface which the plugin may provide * an implementation of. * @param array $ctorArgs Arguments passed to Capability's constructor. * Keeping it an array will allow future values to be passed w\o changing the signature. * @phpstan-param class-string $capabilityClassName * @phpstan-return null|CapabilityClass */ public function getPluginCapability(\Composer\Plugin\PluginInterface $plugin, $capabilityClassName, array $ctorArgs = []) : ?Capability { if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) { if (!\class_exists($capabilityClass)) { throw new \RuntimeException("Cannot instantiate Capability, as class {$capabilityClass} from plugin " . \get_class($plugin) . " does not exist."); } $ctorArgs['plugin'] = $plugin; $capabilityObj = new $capabilityClass($ctorArgs); // FIXME these could use is_a and do the check *before* instantiating once drop support for php<5.3.9 if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) { throw new \RuntimeException('Class ' . $capabilityClass . ' must implement both Composer\\Plugin\\Capability\\Capability and ' . $capabilityClassName . '.'); } return $capabilityObj; } return null; } /** * @template CapabilityClass of Capability * @param class-string $capabilityClassName The fully qualified name of the API interface which the plugin may provide * an implementation of. * @param array $ctorArgs Arguments passed to Capability's constructor. * Keeping it an array will allow future values to be passed w\o changing the signature. * @return CapabilityClass[] */ public function getPluginCapabilities($capabilityClassName, array $ctorArgs = []) : array { $capabilities = []; foreach ($this->getPlugins() as $plugin) { $capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs); if (null !== $capability) { $capabilities[] = $capability; } } return $capabilities; } /** * @param array|bool $allowPluginsConfig * @return array|null */ private function parseAllowedPlugins($allowPluginsConfig, ?Locker $locker = null) : ?array { if ([] === $allowPluginsConfig && $locker !== null && $locker->isLocked() && \version_compare($locker->getPluginApi(), '2.2.0', '<')) { return null; } if (\true === $allowPluginsConfig) { return ['{}' => \true]; } if (\false === $allowPluginsConfig) { return ['{}' => \false]; } $rules = []; foreach ($allowPluginsConfig as $pattern => $allow) { $rules[BasePackage::packageNameToRegexp($pattern)] = $allow; } return $rules; } /** * @internal * * @param 'local'|'global' $type * @return bool */ public function arePluginsDisabled($type) { return $this->disablePlugins === \true || $this->disablePlugins === $type; } /** * @internal */ public function disablePlugins() : void { $this->disablePlugins = \true; } /** * @internal */ public function isPluginAllowed(string $package, bool $isGlobalPlugin, bool $optional = \false, bool $prompt = \true) : bool { if ($isGlobalPlugin) { $rules =& $this->allowGlobalPluginRules; } else { $rules =& $this->allowPluginRules; } // This is a BC mode for lock files created pre-Composer-2.2 where the expectation of // an allow-plugins config being present cannot be made. if ($rules === null) { if (!$this->io->isInteractive()) { $this->io->writeError('For additional security you should declare the allow-plugins config with a list of packages names that are allowed to run code. See https://getcomposer.org/allow-plugins'); $this->io->writeError('This warning will become an exception once you run composer update!'); $rules = ['{}' => \true]; // if no config is defined we allow all plugins for BC return \true; } // keep going and prompt the user $rules = []; } foreach ($rules as $pattern => $allow) { if (Preg::isMatch($pattern, $package)) { return $allow === \true; } } if ($package === 'composer/package-versions-deprecated') { return \false; } if ($this->io->isInteractive() && $prompt) { $composer = $isGlobalPlugin && $this->globalComposer !== null ? $this->globalComposer : $this->composer; $this->io->writeError('' . $package . ($isGlobalPlugin || $this->runningInGlobalDir ? ' (installed globally)' : '') . ' contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins'); $attempts = 0; while (\true) { // do not allow more than 5 prints of the help message, at some point assume the // input is not interactive and bail defaulting to a disabled plugin $default = '?'; if ($attempts > 5) { $this->io->writeError('Too many failed prompts, aborting.'); break; } switch ($answer = $this->io->ask('Do you trust "' . $package . '" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] ', $default)) { case 'y': case 'n': case 'd': $allow = $answer === 'y'; // persist answer in current rules to avoid prompting again if the package gets reloaded $rules[BasePackage::packageNameToRegexp($package)] = $allow; // persist answer in composer.json if it wasn't simply discarded if ($answer === 'y' || $answer === 'n') { $allowPlugins = $composer->getConfig()->get('allow-plugins'); if (\is_array($allowPlugins)) { $allowPlugins[$package] = $allow; if ($composer->getConfig()->get('sort-packages')) { \ksort($allowPlugins); } $composer->getConfig()->getConfigSource()->addConfigSetting('allow-plugins', $allowPlugins); $composer->getConfig()->merge(['config' => ['allow-plugins' => $allowPlugins]]); } } return $allow; case '?': default: $attempts++; $this->io->writeError(['y - add package to allow-plugins in composer.json and let it run immediately', 'n - add package (as disallowed) to allow-plugins in composer.json to suppress further prompts', 'd - discard this, do not change composer.json and do not allow the plugin to run', '? - print help']); break; } } } elseif ($optional) { return \false; } throw new \Composer\Plugin\PluginBlockedException($package . ($isGlobalPlugin || $this->runningInGlobalDir ? ' (installed globally)' : '') . ' contains a Composer plugin which is blocked by your allow-plugins config. You may add it to the list if you consider it safe.' . \PHP_EOL . 'You can run "composer ' . ($isGlobalPlugin || $this->runningInGlobalDir ? 'global ' : '') . 'config --no-plugins allow-plugins.' . $package . ' [true|false]" to enable it (true) or disable it explicitly and suppress this exception (false)' . \PHP_EOL . 'See https://getcomposer.org/allow-plugins'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use Composer\EventDispatcher\Event; use Composer\Util\HttpDownloader; /** * The pre file download event. * * @author Nils Adermann */ class PreFileDownloadEvent extends Event { /** * @var HttpDownloader */ private $httpDownloader; /** * @var non-empty-string */ private $processedUrl; /** * @var string|null */ private $customCacheKey; /** * @var string */ private $type; /** * @var mixed */ private $context; /** * @var mixed[] */ private $transportOptions = []; /** * Constructor. * * @param string $name The event name * @param mixed $context * @param non-empty-string $processedUrl */ public function __construct(string $name, HttpDownloader $httpDownloader, string $processedUrl, string $type, $context = null) { parent::__construct($name); $this->httpDownloader = $httpDownloader; $this->processedUrl = $processedUrl; $this->type = $type; $this->context = $context; } public function getHttpDownloader() : HttpDownloader { return $this->httpDownloader; } /** * Retrieves the processed URL that will be downloaded. * * @return non-empty-string */ public function getProcessedUrl() : string { return $this->processedUrl; } /** * Sets the processed URL that will be downloaded. * * @param non-empty-string $processedUrl New processed URL */ public function setProcessedUrl(string $processedUrl) : void { $this->processedUrl = $processedUrl; } /** * Retrieves a custom package cache key for this download. */ public function getCustomCacheKey() : ?string { return $this->customCacheKey; } /** * Sets a custom package cache key for this download. * * @param string|null $customCacheKey New cache key */ public function setCustomCacheKey(?string $customCacheKey) : void { $this->customCacheKey = $customCacheKey; } /** * Returns the type of this download (package, metadata). */ public function getType() : string { return $this->type; } /** * Returns the context of this download, if any. * * If this download is of type package, the package object is returned. * If the type is metadata, an array{repository: RepositoryInterface} is returned. * * @return mixed */ public function getContext() { return $this->context; } /** * Returns transport options for the download. * * Only available for events with type metadata, for packages set the transport options on the package itself. * * @return mixed[] */ public function getTransportOptions() : array { return $this->transportOptions; } /** * Sets transport options for the download. * * Only available for events with type metadata, for packages set the transport options on the package itself. * * @param mixed[] $options */ public function setTransportOptions(array $options) : void { $this->transportOptions = $options; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use Composer\EventDispatcher\Event; use Composer\Package\PackageInterface; /** * The post file download event. * * @author Nils Adermann */ class PostFileDownloadEvent extends Event { /** * @var string */ private $fileName; /** * @var string|null */ private $checksum; /** * @var string */ private $url; /** * @var mixed */ private $context; /** * @var string */ private $type; /** * Constructor. * * @param string $name The event name * @param string|null $fileName The file name * @param string|null $checksum The checksum * @param string $url The processed url * @param string $type The type (package or metadata). * @param mixed $context Additional context for the download. */ public function __construct(string $name, ?string $fileName, ?string $checksum, string $url, string $type, $context = null) { /** @phpstan-ignore instanceof.alwaysFalse, booleanAnd.alwaysFalse */ if ($context === null && $type instanceof PackageInterface) { $context = $type; $type = 'package'; \trigger_error('PostFileDownloadEvent::__construct should receive a $type=package and the package object in $context since Composer 2.1.', \E_USER_DEPRECATED); } parent::__construct($name); $this->fileName = $fileName; $this->checksum = $checksum; $this->url = $url; $this->context = $context; $this->type = $type; } /** * Retrieves the target file name location. * * If this download is of type metadata, null is returned. */ public function getFileName() : ?string { return $this->fileName; } /** * Gets the checksum. */ public function getChecksum() : ?string { return $this->checksum; } /** * Gets the processed URL. */ public function getUrl() : string { return $this->url; } /** * Returns the context of this download, if any. * * If this download is of type package, the package object is returned. If * this download is of type metadata, an array{response: Response, repository: RepositoryInterface} is returned. * * @return mixed */ public function getContext() { return $this->context; } /** * Get the package. * * If this download is of type metadata, null is returned. * * @return \Composer\Package\PackageInterface|null The package. * @deprecated Use getContext instead */ public function getPackage() : ?PackageInterface { \trigger_error('PostFileDownloadEvent::getPackage is deprecated since Composer 2.1, use getContext instead.', \E_USER_DEPRECATED); $context = $this->getContext(); return $context instanceof PackageInterface ? $context : null; } /** * Returns the type of this download (package, metadata). */ public function getType() : string { return $this->type; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; /** * Plugins which need to expose various implementations * of the Composer Plugin Capabilities must have their * declared Plugin class implementing this interface. * * @api */ interface Capable { /** * Method by which a Plugin announces its API implementations, through an array * with a special structure. * * The key must be a string, representing a fully qualified class/interface name * which Composer Plugin API exposes. * The value must be a string as well, representing the fully qualified class name * of the implementing class. * * @tutorial * * return array( * 'Composer\Plugin\Capability\CommandProvider' => 'My\CommandProvider', * 'Composer\Plugin\Capability\Validator' => 'My\Validator', * ); * * @return string[] */ public function getCapabilities(); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Plugin; use Composer\EventDispatcher\Event; use Composer\Repository\RepositoryInterface; use Composer\DependencyResolver\Request; use Composer\Package\BasePackage; /** * The pre command run event. * * @author Jordi Boggiano */ class PrePoolCreateEvent extends Event { /** * @var RepositoryInterface[] */ private $repositories; /** * @var Request */ private $request; /** * @var int[] array of stability => BasePackage::STABILITY_* value * @phpstan-var array */ private $acceptableStabilities; /** * @var int[] array of package name => BasePackage::STABILITY_* value * @phpstan-var array */ private $stabilityFlags; /** * @var array[] of package => version => [alias, alias_normalized] * @phpstan-var array> */ private $rootAliases; /** * @var string[] * @phpstan-var array */ private $rootReferences; /** * @var BasePackage[] */ private $packages; /** * @var BasePackage[] */ private $unacceptableFixedPackages; /** * @param string $name The event name * @param RepositoryInterface[] $repositories * @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value * @param int[] $stabilityFlags array of package name => BasePackage::STABILITY_* value * @param array[] $rootAliases array of package => version => [alias, alias_normalized] * @param string[] $rootReferences * @param BasePackage[] $packages * @param BasePackage[] $unacceptableFixedPackages * * @phpstan-param array $acceptableStabilities * @phpstan-param array $stabilityFlags * @phpstan-param array> $rootAliases * @phpstan-param array $rootReferences */ public function __construct(string $name, array $repositories, Request $request, array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, array $packages, array $unacceptableFixedPackages) { parent::__construct($name); $this->repositories = $repositories; $this->request = $request; $this->acceptableStabilities = $acceptableStabilities; $this->stabilityFlags = $stabilityFlags; $this->rootAliases = $rootAliases; $this->rootReferences = $rootReferences; $this->packages = $packages; $this->unacceptableFixedPackages = $unacceptableFixedPackages; } /** * @return RepositoryInterface[] */ public function getRepositories() : array { return $this->repositories; } public function getRequest() : Request { return $this->request; } /** * @return int[] array of stability => BasePackage::STABILITY_* value * @phpstan-return array */ public function getAcceptableStabilities() : array { return $this->acceptableStabilities; } /** * @return int[] array of package name => BasePackage::STABILITY_* value * @phpstan-return array */ public function getStabilityFlags() : array { return $this->stabilityFlags; } /** * @return array[] of package => version => [alias, alias_normalized] * @phpstan-return array> */ public function getRootAliases() : array { return $this->rootAliases; } /** * @return string[] * @phpstan-return array */ public function getRootReferences() : array { return $this->rootReferences; } /** * @return BasePackage[] */ public function getPackages() : array { return $this->packages; } /** * @return BasePackage[] */ public function getUnacceptableFixedPackages() : array { return $this->unacceptableFixedPackages; } /** * @param BasePackage[] $packages */ public function setPackages(array $packages) : void { $this->packages = $packages; } /** * @param BasePackage[] $packages */ public function setUnacceptableFixedPackages(array $packages) : void { $this->unacceptableFixedPackages = $packages; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use React\Promise\PromiseInterface; use Composer\Util\IniHelper; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Package\PackageInterface; use RarArchive; /** * RAR archive downloader. * * Based on previous work by Jordi Boggiano ({@see ZipDownloader}). * * @author Derrick Nelson */ class RarDownloader extends \Composer\Downloader\ArchiveDownloader { protected function extract(PackageInterface $package, string $file, string $path) : PromiseInterface { $processError = null; // Try to use unrar on *nix if (!Platform::isWindows()) { $command = ['sh', '-c', 'unrar x -- "$0" "$1" >/dev/null && chmod -R u+w "$1"', $file, $path]; if (0 === $this->process->execute($command, $ignoredOutput)) { return \React\Promise\resolve(null); } $processError = 'Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput(); } if (!\class_exists('RarArchive')) { // php.ini path is added to the error message to help users find the correct file $iniMessage = IniHelper::getMessage(); $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n" . $iniMessage . "\n" . $processError; if (!Platform::isWindows()) { $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage; } throw new \RuntimeException($error); } $rarArchive = RarArchive::open($file); if (\false === $rarArchive) { throw new \UnexpectedValueException('Could not open RAR archive: ' . $file); } $entries = $rarArchive->getEntries(); if (\false === $entries) { throw new \RuntimeException('Could not retrieve RAR archive entries'); } foreach ($entries as $entry) { if (\false === $entry->extract($path)) { throw new \RuntimeException('Could not extract entry'); } } $rarArchive->close(); return \React\Promise\resolve(null); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; /** * VCS Capable Downloader interface. * * @author Steve Buzonas */ interface VcsCapableDownloaderInterface { /** * Gets the VCS Reference for the package at path * * @param PackageInterface $package package instance * @param string $path package directory * @return string|null reference or null */ public function getVcsReference(PackageInterface $package, string $path) : ?string; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Config; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; use Composer\Util\Filesystem; use React\Promise\PromiseInterface; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UninstallOperation; /** * @author Jordi Boggiano */ abstract class VcsDownloader implements \Composer\Downloader\DownloaderInterface, \Composer\Downloader\ChangeReportInterface, \Composer\Downloader\VcsCapableDownloaderInterface { /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var ProcessExecutor */ protected $process; /** @var Filesystem */ protected $filesystem; /** @var array */ protected $hasCleanedChanges = []; public function __construct(IOInterface $io, Config $config, ?ProcessExecutor $process = null, ?Filesystem $fs = null) { $this->io = $io; $this->config = $config; $this->process = $process ?? new ProcessExecutor($io); $this->filesystem = $fs ?? new Filesystem($this->process); } /** * @inheritDoc */ public function getInstallationSource() : string { return 'source'; } /** * @inheritDoc */ public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface { if (!$package->getSourceReference()) { throw new \InvalidArgumentException('Package ' . $package->getPrettyName() . ' is missing reference information'); } $urls = $this->prepareUrls($package->getSourceUrls()); while ($url = \array_shift($urls)) { try { return $this->doDownload($package, $path, $url, $prevPackage); } catch (\Exception $e) { // rethrow phpunit exceptions to avoid hard to debug bug failures if ($e instanceof \_ContaoManager\PHPUnit\Framework\Exception) { throw $e; } if ($this->io->isDebug()) { $this->io->writeError('Failed: [' . \get_class($e) . '] ' . $e->getMessage()); } elseif (\count($urls)) { $this->io->writeError(' Failed, trying the next URL'); } if (!\count($urls)) { throw $e; } } } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface { if ($type === 'update') { $this->cleanChanges($prevPackage, $path, \true); $this->hasCleanedChanges[$prevPackage->getUniqueName()] = \true; } elseif ($type === 'install') { $this->filesystem->emptyDirectory($path); } elseif ($type === 'uninstall') { $this->cleanChanges($package, $path, \false); } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface { if ($type === 'update' && isset($this->hasCleanedChanges[$prevPackage->getUniqueName()])) { $this->reapplyChanges($path); unset($this->hasCleanedChanges[$prevPackage->getUniqueName()]); } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function install(PackageInterface $package, string $path) : PromiseInterface { if (!$package->getSourceReference()) { throw new \InvalidArgumentException('Package ' . $package->getPrettyName() . ' is missing reference information'); } $this->io->writeError(" - " . InstallOperation::format($package) . ': ', \false); $urls = $this->prepareUrls($package->getSourceUrls()); while ($url = \array_shift($urls)) { try { $this->doInstall($package, $path, $url); break; } catch (\Exception $e) { // rethrow phpunit exceptions to avoid hard to debug bug failures if ($e instanceof \_ContaoManager\PHPUnit\Framework\Exception) { throw $e; } if ($this->io->isDebug()) { $this->io->writeError('Failed: [' . \get_class($e) . '] ' . $e->getMessage()); } elseif (\count($urls)) { $this->io->writeError(' Failed, trying the next URL'); } if (!\count($urls)) { throw $e; } } } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function update(PackageInterface $initial, PackageInterface $target, string $path) : PromiseInterface { if (!$target->getSourceReference()) { throw new \InvalidArgumentException('Package ' . $target->getPrettyName() . ' is missing reference information'); } $this->io->writeError(" - " . UpdateOperation::format($initial, $target) . ': ', \false); $urls = $this->prepareUrls($target->getSourceUrls()); $exception = null; while ($url = \array_shift($urls)) { try { $this->doUpdate($initial, $target, $path, $url); $exception = null; break; } catch (\Exception $exception) { // rethrow phpunit exceptions to avoid hard to debug bug failures if ($exception instanceof \_ContaoManager\PHPUnit\Framework\Exception) { throw $exception; } if ($this->io->isDebug()) { $this->io->writeError('Failed: [' . \get_class($exception) . '] ' . $exception->getMessage()); } elseif (\count($urls)) { $this->io->writeError(' Failed, trying the next URL'); } } } // print the commit logs if in verbose mode and VCS metadata is present // because in case of missing metadata code would trigger another exception if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) { $message = 'Pulling in changes:'; $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path); if ('' === \trim($logs)) { $message = 'Rolling back changes:'; $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path); } if ('' !== \trim($logs)) { $logs = \implode("\n", \array_map(static function ($line) : string { return ' ' . $line; }, \explode("\n", $logs))); // escape angle brackets for proper output in the console $logs = \str_replace('<', '\\<', $logs); $this->io->writeError(' ' . $message); $this->io->writeError($logs); } } if (!$urls && $exception) { throw $exception; } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function remove(PackageInterface $package, string $path) : PromiseInterface { $this->io->writeError(" - " . UninstallOperation::format($package)); $promise = $this->filesystem->removeDirectoryAsync($path); return $promise->then(static function (bool $result) use($path) { if (!$result) { throw new \RuntimeException('Could not completely delete ' . $path . ', aborting.'); } }); } /** * @inheritDoc */ public function getVcsReference(PackageInterface $package, string $path) : ?string { $parser = new VersionParser(); $guesser = new VersionGuesser($this->config, $this->process, $parser, $this->io); $dumper = new ArrayDumper(); $packageConfig = $dumper->dump($package); if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) { return $packageVersion['commit']; } return null; } /** * Prompt the user to check if changes should be stashed/removed or the operation aborted * * @param bool $update if true (update) the changes can be stashed and reapplied after an update, * if false (remove) the changes should be assumed to be lost if the operation is not aborted * * @throws \RuntimeException in case the operation must be aborted * @phpstan-return PromiseInterface */ protected function cleanChanges(PackageInterface $package, string $path, bool $update) : PromiseInterface { // the default implementation just fails if there are any changes, override in child classes to provide stash-ability if (null !== $this->getLocalChanges($package, $path)) { throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.'); } return \React\Promise\resolve(null); } /** * Reapply previously stashes changes if applicable, only called after an update (regardless if successful or not) * * @throws \RuntimeException in case the operation must be aborted or the patch does not apply cleanly */ protected function reapplyChanges(string $path) : void { } /** * Downloads data needed to run an install/update later * * @param PackageInterface $package package instance * @param string $path download path * @param string $url package url * @param PackageInterface|null $prevPackage previous package (in case of an update) * @phpstan-return PromiseInterface */ protected abstract function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null) : PromiseInterface; /** * Downloads specific package into specific folder. * * @param PackageInterface $package package instance * @param string $path download path * @param string $url package url * @phpstan-return PromiseInterface */ protected abstract function doInstall(PackageInterface $package, string $path, string $url) : PromiseInterface; /** * Updates specific package in specific folder from initial to target version. * * @param PackageInterface $initial initial package * @param PackageInterface $target updated package * @param string $path download path * @param string $url package url * @phpstan-return PromiseInterface */ protected abstract function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url) : PromiseInterface; /** * Fetches the commit logs between two commits * * @param string $fromReference the source reference * @param string $toReference the target reference * @param string $path the package path */ protected abstract function getCommitLogs(string $fromReference, string $toReference, string $path) : string; /** * Checks if VCS metadata repository has been initialized * repository example: .git|.svn|.hg */ protected abstract function hasMetadataRepository(string $path) : bool; /** * @param string[] $urls * * @return string[] */ private function prepareUrls(array $urls) : array { foreach ($urls as $index => $url) { if (Filesystem::isLocalPath($url)) { // realpath() below will not understand // url that starts with "file://" $fileProtocol = 'file://'; $isFileProtocol = \false; if (0 === \strpos($url, $fileProtocol)) { $url = \substr($url, \strlen($fileProtocol)); $isFileProtocol = \true; } // realpath() below will not understand %20 spaces etc. if (\false !== \strpos($url, '%')) { $url = \rawurldecode($url); } $urls[$index] = \realpath($url); if ($isFileProtocol) { $urls[$index] = $fileProtocol . $urls[$index]; } } } return $urls; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; /** * Exception thrown when issues exist on local filesystem * * @author Javier Spagnoletti */ class FilesystemException extends \Exception { public function __construct(string $message = '', int $code = 0, ?\Exception $previous = null) { parent::__construct("Filesystem exception: \n" . $message, $code, $previous); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Exception\IrrecoverableDownloadException; use React\Promise\PromiseInterface; /** * Downloaders manager. * * @author Konstantin Kudryashov */ class DownloadManager { /** @var IOInterface */ private $io; /** @var bool */ private $preferDist = \false; /** @var bool */ private $preferSource; /** @var array */ private $packagePreferences = []; /** @var Filesystem */ private $filesystem; /** @var array */ private $downloaders = []; /** * Initializes download manager. * * @param IOInterface $io The Input Output Interface * @param bool $preferSource prefer downloading from source * @param Filesystem|null $filesystem custom Filesystem object */ public function __construct(IOInterface $io, bool $preferSource = \false, ?Filesystem $filesystem = null) { $this->io = $io; $this->preferSource = $preferSource; $this->filesystem = $filesystem ?: new Filesystem(); } /** * Makes downloader prefer source installation over the dist. * * @param bool $preferSource prefer downloading from source * @return DownloadManager */ public function setPreferSource(bool $preferSource) : self { $this->preferSource = $preferSource; return $this; } /** * Makes downloader prefer dist installation over the source. * * @param bool $preferDist prefer downloading from dist * @return DownloadManager */ public function setPreferDist(bool $preferDist) : self { $this->preferDist = $preferDist; return $this; } /** * Sets fine tuned preference settings for package level source/dist selection. * * @param array $preferences array of preferences by package patterns * * @return DownloadManager */ public function setPreferences(array $preferences) : self { $this->packagePreferences = $preferences; return $this; } /** * Sets installer downloader for a specific installation type. * * @param string $type installation type * @param DownloaderInterface $downloader downloader instance * @return DownloadManager */ public function setDownloader(string $type, \Composer\Downloader\DownloaderInterface $downloader) : self { $type = \strtolower($type); $this->downloaders[$type] = $downloader; return $this; } /** * Returns downloader for a specific installation type. * * @param string $type installation type * @throws \InvalidArgumentException if downloader for provided type is not registered */ public function getDownloader(string $type) : \Composer\Downloader\DownloaderInterface { $type = \strtolower($type); if (!isset($this->downloaders[$type])) { throw new \InvalidArgumentException(\sprintf('Unknown downloader type: %s. Available types: %s.', $type, \implode(', ', \array_keys($this->downloaders)))); } return $this->downloaders[$type]; } /** * Returns downloader for already installed package. * * @param PackageInterface $package package instance * @throws \InvalidArgumentException if package has no installation source specified * @throws \LogicException if specific downloader used to load package with * wrong type */ public function getDownloaderForPackage(PackageInterface $package) : ?\Composer\Downloader\DownloaderInterface { $installationSource = $package->getInstallationSource(); if ('metapackage' === $package->getType()) { return null; } if ('dist' === $installationSource) { $downloader = $this->getDownloader($package->getDistType()); } elseif ('source' === $installationSource) { $downloader = $this->getDownloader($package->getSourceType()); } else { throw new \InvalidArgumentException('Package ' . $package . ' does not have an installation source set'); } if ($installationSource !== $downloader->getInstallationSource()) { throw new \LogicException(\sprintf('Downloader "%s" is a %s type downloader and can not be used to download %s for package %s', \get_class($downloader), $downloader->getInstallationSource(), $installationSource, $package)); } return $downloader; } public function getDownloaderType(\Composer\Downloader\DownloaderInterface $downloader) : string { return \array_search($downloader, $this->downloaders); } /** * Downloads package into target dir. * * @param PackageInterface $package package instance * @param string $targetDir target dir * @param PackageInterface|null $prevPackage previous package instance in case of updates * @phpstan-return PromiseInterface * * @throws \InvalidArgumentException if package have no urls to download from * @throws \RuntimeException */ public function download(PackageInterface $package, string $targetDir, ?PackageInterface $prevPackage = null) : PromiseInterface { $targetDir = $this->normalizeTargetDir($targetDir); $this->filesystem->ensureDirectoryExists(\dirname($targetDir)); $sources = $this->getAvailableSources($package, $prevPackage); $io = $this->io; $download = function ($retry = \false) use(&$sources, $io, $package, $targetDir, &$download, $prevPackage) { $source = \array_shift($sources); if ($retry) { $io->writeError(' Now trying to download from ' . $source . ''); } $package->setInstallationSource($source); $downloader = $this->getDownloaderForPackage($package); if (!$downloader) { return \React\Promise\resolve(null); } $handleError = static function ($e) use($sources, $source, $package, $io, $download) { if ($e instanceof \RuntimeException && !$e instanceof IrrecoverableDownloadException) { if (!$sources) { throw $e; } $io->writeError(' Failed to download ' . $package->getPrettyName() . ' from ' . $source . ': ' . $e->getMessage() . ''); return $download(\true); } throw $e; }; try { $result = $downloader->download($package, $targetDir, $prevPackage); } catch (\Exception $e) { return $handleError($e); } $res = $result->then(static function ($res) { return $res; }, $handleError); return $res; }; return $download(); } /** * Prepares an operation execution * * @param string $type one of install/update/uninstall * @param PackageInterface $package package instance * @param string $targetDir target dir * @param PackageInterface|null $prevPackage previous package instance in case of updates * @phpstan-return PromiseInterface */ public function prepare(string $type, PackageInterface $package, string $targetDir, ?PackageInterface $prevPackage = null) : PromiseInterface { $targetDir = $this->normalizeTargetDir($targetDir); $downloader = $this->getDownloaderForPackage($package); if ($downloader) { return $downloader->prepare($type, $package, $targetDir, $prevPackage); } return \React\Promise\resolve(null); } /** * Installs package into target dir. * * @param PackageInterface $package package instance * @param string $targetDir target dir * @phpstan-return PromiseInterface * * @throws \InvalidArgumentException if package have no urls to download from * @throws \RuntimeException */ public function install(PackageInterface $package, string $targetDir) : PromiseInterface { $targetDir = $this->normalizeTargetDir($targetDir); $downloader = $this->getDownloaderForPackage($package); if ($downloader) { return $downloader->install($package, $targetDir); } return \React\Promise\resolve(null); } /** * Updates package from initial to target version. * * @param PackageInterface $initial initial package version * @param PackageInterface $target target package version * @param string $targetDir target dir * @phpstan-return PromiseInterface * * @throws \InvalidArgumentException if initial package is not installed */ public function update(PackageInterface $initial, PackageInterface $target, string $targetDir) : PromiseInterface { $targetDir = $this->normalizeTargetDir($targetDir); $downloader = $this->getDownloaderForPackage($target); $initialDownloader = $this->getDownloaderForPackage($initial); // no downloaders present means update from metapackage to metapackage, nothing to do if (!$initialDownloader && !$downloader) { return \React\Promise\resolve(null); } // if we have a downloader present before, but not after, the package became a metapackage and its files should be removed if (!$downloader) { return $initialDownloader->remove($initial, $targetDir); } $initialType = $this->getDownloaderType($initialDownloader); $targetType = $this->getDownloaderType($downloader); if ($initialType === $targetType) { try { return $downloader->update($initial, $target, $targetDir); } catch (\RuntimeException $e) { if (!$this->io->isInteractive()) { throw $e; } $this->io->writeError(' Update failed (' . $e->getMessage() . ')'); if (!$this->io->askConfirmation(' Would you like to try reinstalling the package instead [yes]? ')) { throw $e; } } } // if downloader type changed, or update failed and user asks for reinstall, // we wipe the dir and do a new install instead of updating it $promise = $initialDownloader->remove($initial, $targetDir); return $promise->then(function ($res) use($target, $targetDir) : PromiseInterface { return $this->install($target, $targetDir); }); } /** * Removes package from target dir. * * @param PackageInterface $package package instance * @param string $targetDir target dir * @phpstan-return PromiseInterface */ public function remove(PackageInterface $package, string $targetDir) : PromiseInterface { $targetDir = $this->normalizeTargetDir($targetDir); $downloader = $this->getDownloaderForPackage($package); if ($downloader) { return $downloader->remove($package, $targetDir); } return \React\Promise\resolve(null); } /** * Cleans up a failed operation * * @param string $type one of install/update/uninstall * @param PackageInterface $package package instance * @param string $targetDir target dir * @param PackageInterface|null $prevPackage previous package instance in case of updates * @phpstan-return PromiseInterface */ public function cleanup(string $type, PackageInterface $package, string $targetDir, ?PackageInterface $prevPackage = null) : PromiseInterface { $targetDir = $this->normalizeTargetDir($targetDir); $downloader = $this->getDownloaderForPackage($package); if ($downloader) { return $downloader->cleanup($type, $package, $targetDir, $prevPackage); } return \React\Promise\resolve(null); } /** * Determines the install preference of a package * * @param PackageInterface $package package instance */ protected function resolvePackageInstallPreference(PackageInterface $package) : string { foreach ($this->packagePreferences as $pattern => $preference) { $pattern = '{^' . \str_replace('\\*', '.*', \preg_quote($pattern)) . '$}i'; if (Preg::isMatch($pattern, $package->getName())) { if ('dist' === $preference || !$package->isDev() && 'auto' === $preference) { return 'dist'; } return 'source'; } } return $package->isDev() ? 'source' : 'dist'; } /** * @return string[] * @phpstan-return array<'dist'|'source'>&non-empty-array */ private function getAvailableSources(PackageInterface $package, ?PackageInterface $prevPackage = null) : array { $sourceType = $package->getSourceType(); $distType = $package->getDistType(); // add source before dist by default $sources = []; if ($sourceType) { $sources[] = 'source'; } if ($distType) { $sources[] = 'dist'; } if (empty($sources)) { throw new \InvalidArgumentException('Package ' . $package . ' must have a source or dist specified'); } if ($prevPackage && \in_array($prevPackage->getInstallationSource(), $sources, \true) && !(!$prevPackage->isDev() && $prevPackage->getInstallationSource() === 'dist' && $package->isDev())) { $prevSource = $prevPackage->getInstallationSource(); \usort($sources, static function ($a, $b) use($prevSource) : int { return $a === $prevSource ? -1 : 1; }); return $sources; } // reverse sources in case dist is the preferred source for this package if (!$this->preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) { $sources = \array_reverse($sources); } return $sources; } /** * Downloaders expect a /path/to/dir without trailing slash * * If any Installer provides a path with a trailing slash, this can cause bugs so make sure we remove them */ private function normalizeTargetDir(string $dir) : string { if ($dir === '\\' || $dir === '/') { return $dir; } return \rtrim($dir, '\\/'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; use React\Promise\PromiseInterface; /** * Downloader for tar files: tar, tar.gz or tar.bz2 * * @author Kirill chEbba Chebunin */ class TarDownloader extends \Composer\Downloader\ArchiveDownloader { /** * @inheritDoc */ protected function extract(PackageInterface $package, string $file, string $path) : PromiseInterface { // Can throw an UnexpectedValueException $archive = new \PharData($file); $archive->extractTo($path, null, \true); return \React\Promise\resolve(null); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Util\Platform; use React\Promise\PromiseInterface; use Composer\Package\PackageInterface; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use RuntimeException; /** * @author BohwaZ */ class FossilDownloader extends \Composer\Downloader\VcsDownloader { /** * @inheritDoc */ protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null) : PromiseInterface { return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doInstall(PackageInterface $package, string $path, string $url) : PromiseInterface { // Ensure we are allowed to use this URL by config $this->config->prohibitUrlByConfig($url, $this->io); $repoFile = $path . '.fossil'; $realPath = Platform::realpath($path); $this->io->writeError("Cloning " . $package->getSourceReference()); $this->execute(['fossil', 'clone', '--', $url, $repoFile]); $this->execute(['fossil', 'open', '--nested', '--', $repoFile], $realPath); $this->execute(['fossil', 'update', '--', (string) $package->getSourceReference()], $realPath); return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url) : PromiseInterface { // Ensure we are allowed to use this URL by config $this->config->prohibitUrlByConfig($url, $this->io); $this->io->writeError(" Updating to " . $target->getSourceReference()); if (!$this->hasMetadataRepository($path)) { throw new \RuntimeException('The .fslckout file is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information'); } $realPath = Platform::realpath($path); $this->execute(['fossil', 'pull'], $realPath); $this->execute(['fossil', 'up', (string) $target->getSourceReference()], $realPath); return \React\Promise\resolve(null); } /** * @inheritDoc */ public function getLocalChanges(PackageInterface $package, string $path) : ?string { if (!$this->hasMetadataRepository($path)) { return null; } $this->process->execute(['fossil', 'changes'], $output, Platform::realpath($path)); $output = \trim($output); return \strlen($output) > 0 ? $output : null; } /** * @inheritDoc */ protected function getCommitLogs(string $fromReference, string $toReference, string $path) : string { $this->execute(['fossil', 'timeline', '-t', 'ci', '-W', '0', '-n', '0', 'before', $toReference], Platform::realpath($path), $output); $log = ''; $match = '/\\d\\d:\\d\\d:\\d\\d\\s+\\[' . $toReference . '\\]/'; foreach ($this->process->splitLines($output) as $line) { if (Preg::isMatch($match, $line)) { break; } $log .= $line; } return $log; } /** * @param non-empty-list $command * @throws \RuntimeException */ private function execute(array $command, ?string $cwd = null, ?string &$output = null) : void { if (0 !== $this->process->execute($command, $output, $cwd)) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } } /** * @inheritDoc */ protected function hasMetadataRepository(string $path) : bool { return \is_file($path . '/.fslckout') || \is_file($path . '/_FOSSIL_'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; class MaxFileSizeExceededException extends \Composer\Downloader\TransportException { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; use React\Promise\PromiseInterface; /** * Downloader interface. * * @author Konstantin Kudryashov * @author Jordi Boggiano */ interface DownloaderInterface { /** * Returns installation source (either source or dist). * * @return string "source" or "dist" */ public function getInstallationSource() : string; /** * This should do any network-related tasks to prepare for an upcoming install/update * * @param string $path download path * @phpstan-return PromiseInterface */ public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface; /** * Do anything that needs to be done between all downloads have been completed and the actual operation is executed * * All packages get first downloaded, then all together prepared, then all together installed/updated/uninstalled. Therefore * for error recovery it is important to avoid failing during install/update/uninstall as much as possible, and risky things or * user prompts should happen in the prepare step rather. In case of failure, cleanup() will be called so that changes can * be undone as much as possible. * * @param string $type one of install/update/uninstall * @param PackageInterface $package package instance * @param string $path download path * @param PackageInterface $prevPackage previous package instance in case of an update * @phpstan-return PromiseInterface */ public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface; /** * Installs specific package into specific folder. * * @param PackageInterface $package package instance * @param string $path download path * @phpstan-return PromiseInterface */ public function install(PackageInterface $package, string $path) : PromiseInterface; /** * Updates specific package in specific folder from initial to target version. * * @param PackageInterface $initial initial package * @param PackageInterface $target updated package * @param string $path download path * @phpstan-return PromiseInterface */ public function update(PackageInterface $initial, PackageInterface $target, string $path) : PromiseInterface; /** * Removes specific package from specific folder. * * @param PackageInterface $package package instance * @param string $path download path * @phpstan-return PromiseInterface */ public function remove(PackageInterface $package, string $path) : PromiseInterface; /** * Do anything to cleanup changes applied in the prepare or install/update/uninstall steps * * Note that cleanup will be called for all packages, either after install/update/uninstall is complete, * or if any package failed any operation. This is to give all installers a change to cleanup things * they did previously, so you need to keep track of changes applied in the installer/downloader themselves. * * @param string $type one of install/update/uninstall * @param PackageInterface $package package instance * @param string $path download path * @param PackageInterface $prevPackage previous package instance in case of an update * @phpstan-return PromiseInterface */ public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use React\Promise\PromiseInterface; use Composer\Package\PackageInterface; use Composer\Util\ProcessExecutor; /** * Xz archive downloader. * * @author Pavel Puchkin * @author Pierre Rudloff */ class XzDownloader extends \Composer\Downloader\ArchiveDownloader { protected function extract(PackageInterface $package, string $file, string $path) : PromiseInterface { $command = ['tar', '-xJf', $file, '-C', $path]; if (0 === $this->process->execute($command, $ignoredOutput)) { return \React\Promise\resolve(null); } $processError = 'Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput(); throw new \RuntimeException($processError); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use React\Promise\PromiseInterface; use Composer\Package\PackageInterface; use Composer\Util\ProcessExecutor; use Composer\Util\Hg as HgUtils; /** * @author Per Bernhardt */ class HgDownloader extends \Composer\Downloader\VcsDownloader { /** * @inheritDoc */ protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null) : PromiseInterface { if (null === HgUtils::getVersion($this->process)) { throw new \RuntimeException('hg was not found in your PATH, skipping source download'); } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doInstall(PackageInterface $package, string $path, string $url) : PromiseInterface { $hgUtils = new HgUtils($this->io, $this->config, $this->process); $cloneCommand = static function (string $url) use($path) : array { return ['hg', 'clone', '--', $url, $path]; }; $hgUtils->runCommand($cloneCommand, $url, $path); $command = ['hg', 'up', '--', (string) $package->getSourceReference()]; if (0 !== $this->process->execute($command, $ignoredOutput, \realpath($path))) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url) : PromiseInterface { $hgUtils = new HgUtils($this->io, $this->config, $this->process); $ref = $target->getSourceReference(); $this->io->writeError(" Updating to " . $target->getSourceReference()); if (!$this->hasMetadataRepository($path)) { throw new \RuntimeException('The .hg directory is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information'); } $command = static function ($url) : array { return ['hg', 'pull', '--', $url]; }; $hgUtils->runCommand($command, $url, $path); $command = static function () use($ref) : array { return ['hg', 'up', '--', $ref]; }; $hgUtils->runCommand($command, $url, $path); return \React\Promise\resolve(null); } /** * @inheritDoc */ public function getLocalChanges(PackageInterface $package, string $path) : ?string { if (!\is_dir($path . '/.hg')) { return null; } $this->process->execute(['hg', 'st'], $output, \realpath($path)); $output = \trim($output); return \strlen($output) > 0 ? $output : null; } /** * @inheritDoc */ protected function getCommitLogs(string $fromReference, string $toReference, string $path) : string { $command = ['hg', 'log', '-r', $fromReference . ':' . $toReference, '--style', 'compact']; if (0 !== $this->process->execute($command, $output, \realpath($path))) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } return $output; } /** * @inheritDoc */ protected function hasMetadataRepository(string $path) : bool { return \is_dir($path . '/.hg'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\Pcre\Preg; use Composer\Util\Svn as SvnUtil; use Composer\Repository\VcsRepository; use Composer\Util\ProcessExecutor; use React\Promise\PromiseInterface; /** * @author Ben Bieker * @author Till Klampaeckel */ class SvnDownloader extends \Composer\Downloader\VcsDownloader { /** @var bool */ protected $cacheCredentials = \true; /** * @inheritDoc */ protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null) : PromiseInterface { SvnUtil::cleanEnv(); $util = new SvnUtil($url, $this->io, $this->config, $this->process); if (null === $util->binaryVersion()) { throw new \RuntimeException('svn was not found in your PATH, skipping source download'); } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doInstall(PackageInterface $package, string $path, string $url) : PromiseInterface { SvnUtil::cleanEnv(); $ref = $package->getSourceReference(); $repo = $package->getRepository(); if ($repo instanceof VcsRepository) { $repoConfig = $repo->getRepoConfig(); if (\array_key_exists('svn-cache-credentials', $repoConfig)) { $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials']; } } $this->io->writeError(" Checking out " . $package->getSourceReference()); $this->execute($package, $url, ['svn', 'co'], \sprintf("%s/%s", $url, $ref), null, $path); return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url) : PromiseInterface { SvnUtil::cleanEnv(); $ref = $target->getSourceReference(); if (!$this->hasMetadataRepository($path)) { throw new \RuntimeException('The .svn directory is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information'); } $util = new SvnUtil($url, $this->io, $this->config, $this->process); $flags = []; if (\version_compare($util->binaryVersion(), '1.7.0', '>=')) { $flags[] = '--ignore-ancestry'; } $this->io->writeError(" Checking out " . $ref); $this->execute($target, $url, \array_merge(['svn', 'switch'], $flags), \sprintf("%s/%s", $url, $ref), $path); return \React\Promise\resolve(null); } /** * @inheritDoc */ public function getLocalChanges(PackageInterface $package, string $path) : ?string { if (!$this->hasMetadataRepository($path)) { return null; } $this->process->execute(['svn', 'status', '--ignore-externals'], $output, $path); return Preg::isMatch('{^ *[^X ] +}m', $output) ? $output : null; } /** * Execute an SVN command and try to fix up the process with credentials * if necessary. * * @param string $baseUrl Base URL of the repository * @param non-empty-list $command SVN command to run * @param string $url SVN url * @param string $cwd Working directory * @param string $path Target for a checkout * @throws \RuntimeException */ protected function execute(PackageInterface $package, string $baseUrl, array $command, string $url, ?string $cwd = null, ?string $path = null) : string { $util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process); $util->setCacheCredentials($this->cacheCredentials); try { return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose()); } catch (\RuntimeException $e) { throw new \RuntimeException($package->getPrettyName() . ' could not be downloaded, ' . $e->getMessage()); } } /** * @inheritDoc */ protected function cleanChanges(PackageInterface $package, string $path, bool $update) : PromiseInterface { if (null === ($changes = $this->getLocalChanges($package, $path))) { return \React\Promise\resolve(null); } if (!$this->io->isInteractive()) { if (\true === $this->config->get('discard-changes')) { return $this->discardChanges($path); } return parent::cleanChanges($package, $path, $update); } $changes = \array_map(static function ($elem) : string { return ' ' . $elem; }, Preg::split('{\\s*\\r?\\n\\s*}', $changes)); $countChanges = \count($changes); $this->io->writeError(\sprintf(' ' . $package->getPrettyName() . ' has modified file%s:', $countChanges === 1 ? '' : 's')); $this->io->writeError(\array_slice($changes, 0, 10)); if ($countChanges > 10) { $remainingChanges = $countChanges - 10; $this->io->writeError(\sprintf(' ' . $remainingChanges . ' more file%s modified, choose "v" to view the full list', $remainingChanges === 1 ? '' : 's')); } while (\true) { switch ($this->io->ask(' Discard changes [y,n,v,?]? ', '?')) { case 'y': $this->discardChanges($path); break 2; case 'n': throw new \RuntimeException('Update aborted'); case 'v': $this->io->writeError($changes); break; case '?': default: $this->io->writeError([' y - discard changes and apply the ' . ($update ? 'update' : 'uninstall'), ' n - abort the ' . ($update ? 'update' : 'uninstall') . ' and let you manually clean things up', ' v - view modified files', ' ? - print help']); break; } } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function getCommitLogs(string $fromReference, string $toReference, string $path) : string { if (Preg::isMatch('{@(\\d+)$}', $fromReference) && Preg::isMatch('{@(\\d+)$}', $toReference)) { // retrieve the svn base url from the checkout folder $command = ['svn', 'info', '--non-interactive', '--xml', '--', $path]; if (0 !== $this->process->execute($command, $output, $path)) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } $urlPattern = '#(.*)#'; if (Preg::isMatchStrictGroups($urlPattern, $output, $matches)) { $baseUrl = $matches[1]; } else { throw new \RuntimeException('Unable to determine svn url for path ' . $path); } // strip paths from references and only keep the actual revision $fromRevision = Preg::replace('{.*@(\\d+)$}', '$1', $fromReference); $toRevision = Preg::replace('{.*@(\\d+)$}', '$1', $toReference); $command = ['svn', 'log', '-r', $fromRevision . ':' . $toRevision, '--incremental']; $util = new SvnUtil($baseUrl, $this->io, $this->config, $this->process); $util->setCacheCredentials($this->cacheCredentials); try { return $util->executeLocal($command, $path, null, $this->io->isVerbose()); } catch (\RuntimeException $e) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $e->getMessage()); } } return "Could not retrieve changes between {$fromReference} and {$toReference} due to missing revision information"; } /** * @phpstan-return PromiseInterface */ protected function discardChanges(string $path) : PromiseInterface { if (0 !== $this->process->execute(['svn', 'revert', '-R', '.'], $output, $path)) { throw new \RuntimeException("Could not reset changes\n\n:" . $this->process->getErrorOutput()); } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function hasMetadataRepository(string $path) : bool { return \is_dir($path . '/.svn'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Config; use Composer\Cache; use Composer\IO\IOInterface; use Composer\IO\NullIO; use Composer\Exception\IrrecoverableDownloadException; use Composer\Package\Comparer\Comparer; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UninstallOperation; use Composer\Package\PackageInterface; use Composer\Plugin\PluginEvents; use Composer\Plugin\PostFileDownloadEvent; use Composer\Plugin\PreFileDownloadEvent; use Composer\EventDispatcher\EventDispatcher; use Composer\Util\Filesystem; use Composer\Util\Http\Response; use Composer\Util\Platform; use Composer\Util\Silencer; use Composer\Util\HttpDownloader; use Composer\Util\Url as UrlUtil; use Composer\Util\ProcessExecutor; use React\Promise\PromiseInterface; /** * Base downloader for files * * @author Kirill chEbba Chebunin * @author Jordi Boggiano * @author François Pluchino * @author Nils Adermann */ class FileDownloader implements \Composer\Downloader\DownloaderInterface, \Composer\Downloader\ChangeReportInterface { /** @var IOInterface */ protected $io; /** @var Config */ protected $config; /** @var HttpDownloader */ protected $httpDownloader; /** @var Filesystem */ protected $filesystem; /** @var ?Cache */ protected $cache; /** @var ?EventDispatcher */ protected $eventDispatcher; /** @var ProcessExecutor */ protected $process; /** * @var array * @private * @internal */ public static $downloadMetadata = []; /** * Collects response headers when running on GH Actions * * @see https://github.com/composer/composer/issues/11148 * @var array> * @private * @internal */ public static $responseHeaders = []; /** * @var array Map of package name to cache key */ private $lastCacheWrites = []; /** @var array Map of package name to list of paths */ private $additionalCleanupPaths = []; /** * Constructor. * * @param IOInterface $io The IO instance * @param Config $config The config * @param HttpDownloader $httpDownloader The remote filesystem * @param EventDispatcher $eventDispatcher The event dispatcher * @param Cache $cache Cache instance * @param Filesystem $filesystem The filesystem */ public function __construct(IOInterface $io, Config $config, HttpDownloader $httpDownloader, ?EventDispatcher $eventDispatcher = null, ?Cache $cache = null, ?Filesystem $filesystem = null, ?ProcessExecutor $process = null) { $this->io = $io; $this->config = $config; $this->eventDispatcher = $eventDispatcher; $this->httpDownloader = $httpDownloader; $this->cache = $cache; $this->process = $process ?? new ProcessExecutor($io); $this->filesystem = $filesystem ?? new Filesystem($this->process); if ($this->cache !== null && $this->cache->gcIsNecessary()) { $this->io->writeError('Running cache garbage collection', \true, IOInterface::VERY_VERBOSE); $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize')); } } /** * @inheritDoc */ public function getInstallationSource() : string { return 'dist'; } /** * @inheritDoc */ public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null, bool $output = \true) : PromiseInterface { if (null === $package->getDistUrl()) { throw new \InvalidArgumentException('The given package is missing url information'); } $cacheKeyGenerator = static function (PackageInterface $package, $key) : string { $cacheKey = \hash('sha1', $key); return $package->getName() . '/' . $cacheKey . '.' . $package->getDistType(); }; $retries = 3; $distUrls = $package->getDistUrls(); /** @var array $urls */ $urls = []; foreach ($distUrls as $index => $url) { $processedUrl = $this->processUrl($package, $url); $urls[$index] = [ 'base' => $url, 'processed' => $processedUrl, // we use the complete download url here to avoid conflicting entries // from different packages, which would potentially allow a given package // in a third party repo to pre-populate the cache for the same package in // packagist for example. 'cacheKey' => $cacheKeyGenerator($package, $processedUrl), ]; } \assert(\count($urls) > 0); $fileName = $this->getFileName($package, $path); $this->filesystem->ensureDirectoryExists($path); $this->filesystem->ensureDirectoryExists(\dirname($fileName)); $accept = null; $reject = null; $download = function () use($output, $cacheKeyGenerator, $package, $fileName, &$urls, &$accept, &$reject) { $url = \reset($urls); $index = \key($urls); if ($this->eventDispatcher !== null) { $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $url['processed'], 'package', $package); $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent); if ($preFileDownloadEvent->getCustomCacheKey() !== null) { $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getCustomCacheKey()); } elseif ($preFileDownloadEvent->getProcessedUrl() !== $url['processed']) { $url['cacheKey'] = $cacheKeyGenerator($package, $preFileDownloadEvent->getProcessedUrl()); } $url['processed'] = $preFileDownloadEvent->getProcessedUrl(); } $urls[$index] = $url; $checksum = $package->getDistSha1Checksum(); $cacheKey = $url['cacheKey']; // use from cache if it is present and has a valid checksum or we have no checksum to check against if ($this->cache !== null && ($checksum === null || $checksum === '' || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) { if ($output) { $this->io->writeError(" - Loading " . $package->getName() . " (" . $package->getFullPrettyVersion() . ") from cache", \true, IOInterface::VERY_VERBOSE); } // mark the file as having been written in cache even though it is only read from cache, so that if // the cache is corrupt the archive will be deleted and the next attempt will re-download it // see https://github.com/composer/composer/issues/10028 if (!$this->cache->isReadOnly()) { $this->lastCacheWrites[$package->getName()] = $cacheKey; } $result = \React\Promise\resolve($fileName); } else { if ($output) { $this->io->writeError(" - Downloading " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")"); } $result = $this->httpDownloader->addCopy($url['processed'], $fileName, $package->getTransportOptions())->then($accept, $reject); } return $result->then(function ($result) use($fileName, $checksum, $url, $package) : string { // in case of retry, the first call's Promise chain finally calls this twice at the end, // once with $result being the returned $fileName from $accept, and then once for every // failed request with a null result, which can be skipped. if (null === $result) { return $fileName; } if (!\file_exists($fileName)) { throw new \UnexpectedValueException($url['base'] . ' could not be saved to ' . $fileName . ', make sure the' . ' directory is writable and you have internet connectivity'); } if ($checksum !== null && $checksum !== '' && \hash_file('sha1', $fileName) !== $checksum) { throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from ' . $url['base'] . ')'); } if ($this->eventDispatcher !== null) { $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, $fileName, $checksum, $url['processed'], 'package', $package); $this->eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent); } return $fileName; }); }; $accept = function (Response $response) use($package, $fileName, &$urls) : string { $url = \reset($urls); $cacheKey = $url['cacheKey']; $fileSize = @\filesize($fileName); if (\false === $fileSize) { $fileSize = $response->getHeader('Content-Length') ?? '?'; } \Composer\Downloader\FileDownloader::$downloadMetadata[$package->getName()] = $fileSize; if (Platform::getEnv('GITHUB_ACTIONS') !== \false && Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') === \false) { \Composer\Downloader\FileDownloader::$responseHeaders[$package->getName()] = $response->getHeaders(); } if ($this->cache !== null && !$this->cache->isReadOnly()) { $this->lastCacheWrites[$package->getName()] = $cacheKey; $this->cache->copyFrom($cacheKey, $fileName); } $response->collect(); return $fileName; }; $reject = function ($e) use(&$urls, $download, $fileName, $package, &$retries) { // clean up if (\file_exists($fileName)) { $this->filesystem->unlink($fileName); } $this->clearLastCacheWrite($package); if ($e instanceof IrrecoverableDownloadException) { throw $e; } if ($e instanceof \Composer\Downloader\MaxFileSizeExceededException) { throw $e; } if ($e instanceof \Composer\Downloader\TransportException) { // if we got an http response with a proper code, then requesting again will probably not help, abort if (0 !== $e->getCode() && !\in_array($e->getCode(), [500, 502, 503, 504], \true)) { $retries = 0; } } // special error code returned when network is being artificially disabled if ($e instanceof \Composer\Downloader\TransportException && $e->getStatusCode() === 499) { $retries = 0; $urls = []; } if ($retries > 0) { \usleep(500000); $retries--; return $download(); } \array_shift($urls); if (\count($urls) > 0) { if ($this->io->isDebug()) { $this->io->writeError(' Failed downloading ' . $package->getName() . ': [' . \get_class($e) . '] ' . $e->getCode() . ': ' . $e->getMessage()); $this->io->writeError(' Trying the next URL for ' . $package->getName()); } else { $this->io->writeError(' Failed downloading ' . $package->getName() . ', trying the next URL (' . $e->getCode() . ': ' . $e->getMessage() . ')'); } $retries = 3; \usleep(100000); return $download(); } throw $e; }; return $download(); } /** * @inheritDoc */ public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface { return \React\Promise\resolve(null); } /** * @inheritDoc */ public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface { $fileName = $this->getFileName($package, $path); if (\file_exists($fileName)) { $this->filesystem->unlink($fileName); } $dirsToCleanUp = [$path, $this->config->get('vendor-dir') . '/' . \explode('/', $package->getPrettyName())[0], $this->config->get('vendor-dir') . '/composer/', $this->config->get('vendor-dir')]; if (isset($this->additionalCleanupPaths[$package->getName()])) { foreach ($this->additionalCleanupPaths[$package->getName()] as $pathToClean) { $this->filesystem->remove($pathToClean); } } foreach ($dirsToCleanUp as $dir) { if (\is_dir($dir) && $this->filesystem->isDirEmpty($dir) && \realpath($dir) !== Platform::getCwd()) { $this->filesystem->removeDirectoryPhp($dir); } } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function install(PackageInterface $package, string $path, bool $output = \true) : PromiseInterface { if ($output) { $this->io->writeError(" - " . InstallOperation::format($package)); } $vendorDir = $this->config->get('vendor-dir'); // clean up the target directory, unless it contains the vendor dir, as the vendor dir contains // the file to be installed. This is the case when installing with create-project in the current directory // but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here. if (\false === \strpos($this->filesystem->normalizePath($vendorDir), $this->filesystem->normalizePath($path . \DIRECTORY_SEPARATOR))) { $this->filesystem->emptyDirectory($path); } $this->filesystem->ensureDirectoryExists($path); $this->filesystem->rename($this->getFileName($package, $path), $path . '/' . $this->getDistPath($package, \PATHINFO_BASENAME)); // Single files can not have a mode set like files in archives // so we make sure if the file is a binary that it is executable foreach ($package->getBinaries() as $bin) { if (\file_exists($path . '/' . $bin) && !\is_executable($path . '/' . $bin)) { Silencer::call('chmod', $path . '/' . $bin, 0777 & ~\umask()); } } return \React\Promise\resolve(null); } /** * @param PATHINFO_EXTENSION|PATHINFO_BASENAME $component */ protected function getDistPath(PackageInterface $package, int $component) : string { return \pathinfo((string) \parse_url(\strtr((string) $package->getDistUrl(), '\\', '/'), \PHP_URL_PATH), $component); } protected function clearLastCacheWrite(PackageInterface $package) : void { if ($this->cache !== null && isset($this->lastCacheWrites[$package->getName()])) { $this->cache->remove($this->lastCacheWrites[$package->getName()]); unset($this->lastCacheWrites[$package->getName()]); } } protected function addCleanupPath(PackageInterface $package, string $path) : void { $this->additionalCleanupPaths[$package->getName()][] = $path; } protected function removeCleanupPath(PackageInterface $package, string $path) : void { if (isset($this->additionalCleanupPaths[$package->getName()])) { $idx = \array_search($path, $this->additionalCleanupPaths[$package->getName()], \true); if (\false !== $idx) { unset($this->additionalCleanupPaths[$package->getName()][$idx]); } } } /** * @inheritDoc */ public function update(PackageInterface $initial, PackageInterface $target, string $path) : PromiseInterface { $this->io->writeError(" - " . UpdateOperation::format($initial, $target) . $this->getInstallOperationAppendix($target, $path)); $promise = $this->remove($initial, $path, \false); return $promise->then(function () use($target, $path) : PromiseInterface { return $this->install($target, $path, \false); }); } /** * @inheritDoc */ public function remove(PackageInterface $package, string $path, bool $output = \true) : PromiseInterface { if ($output) { $this->io->writeError(" - " . UninstallOperation::format($package)); } $promise = $this->filesystem->removeDirectoryAsync($path); return $promise->then(static function ($result) use($path) : void { if (!$result) { throw new \RuntimeException('Could not completely delete ' . $path . ', aborting.'); } }); } /** * Gets file name for specific package * * @param PackageInterface $package package instance * @param string $path download path * @return string file name */ protected function getFileName(PackageInterface $package, string $path) : string { $extension = $this->getDistPath($package, \PATHINFO_EXTENSION); if ($extension === '') { $extension = $package->getDistType(); } return \rtrim($this->config->get('vendor-dir') . '/composer/tmp-' . \hash('md5', $package . \spl_object_hash($package)) . '.' . $extension, '.'); } /** * Gets appendix message to add to the "- Upgrading x" string being output on update * * @param PackageInterface $package package instance * @param string $path download path */ protected function getInstallOperationAppendix(PackageInterface $package, string $path) : string { return ''; } /** * Process the download url * * @param PackageInterface $package package instance * @param non-empty-string $url download url * @throws \RuntimeException If any problem with the url * @return non-empty-string url */ protected function processUrl(PackageInterface $package, string $url) : string { if (!\extension_loaded('openssl') && 0 === \strpos($url, 'https:')) { throw new \RuntimeException('You must enable the openssl extension to download files via https'); } if ($package->getDistReference() !== null) { $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference()); } return $url; } /** * @inheritDoc * @throws \RuntimeException */ public function getLocalChanges(PackageInterface $package, string $path) : ?string { $prevIO = $this->io; $this->io = new NullIO(); $this->io->loadConfiguration($this->config); $e = null; $output = ''; $targetDir = Filesystem::trimTrailingSlash($path); try { if (\is_dir($targetDir . '_compare')) { $this->filesystem->removeDirectory($targetDir . '_compare'); } $promise = $this->download($package, $targetDir . '_compare', null, \false); $promise->then(null, function ($ex) use(&$e) { $e = $ex; }); $this->httpDownloader->wait(); if ($e !== null) { throw $e; } $promise = $this->install($package, $targetDir . '_compare', \false); $promise->then(null, function ($ex) use(&$e) { $e = $ex; }); $this->process->wait(); if ($e !== null) { throw $e; } $comparer = new Comparer(); $comparer->setSource($targetDir . '_compare'); $comparer->setUpdate($targetDir); $comparer->doCompare(); $output = $comparer->getChangedAsString(\true); $this->filesystem->removeDirectory($targetDir . '_compare'); } catch (\Exception $e) { } $this->io = $prevIO; if ($e !== null) { if ($this->io->isDebug()) { throw $e; } return 'Failed to detect changes: [' . \get_class($e) . '] ' . $e->getMessage(); } $output = \trim($output); return \strlen($output) > 0 ? $output : null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; /** * ChangeReport interface. * * @author Sascha Egerer */ interface ChangeReportInterface { /** * Checks for changes to the local copy * * @param PackageInterface $package package instance * @param string $path package directory * @return string|null changes or null */ public function getLocalChanges(PackageInterface $package, string $path) : ?string; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; /** * @author Jordi Boggiano */ class TransportException extends \RuntimeException { /** @var ?array */ protected $headers; /** @var ?string */ protected $response; /** @var ?int */ protected $statusCode; /** @var array */ protected $responseInfo = []; public function __construct(string $message = "", int $code = 400, ?\Throwable $previous = null) { parent::__construct($message, $code, $previous); } /** * @param array $headers */ public function setHeaders(array $headers) : void { $this->headers = $headers; } /** * @return ?array */ public function getHeaders() : ?array { return $this->headers; } public function setResponse(?string $response) : void { $this->response = $response; } /** * @return ?string */ public function getResponse() : ?string { return $this->response; } /** * @param ?int $statusCode */ public function setStatusCode($statusCode) : void { $this->statusCode = $statusCode; } /** * @return ?int */ public function getStatusCode() : ?int { return $this->statusCode; } /** * @return array */ public function getResponseInfo() : array { return $this->responseInfo; } /** * @param array $responseInfo */ public function setResponseInfo(array $responseInfo) : void { $this->responseInfo = $responseInfo; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\Util\Platform; use _ContaoManager\Symfony\Component\Finder\Finder; use React\Promise\PromiseInterface; use Composer\DependencyResolver\Operation\InstallOperation; /** * Base downloader for archives * * @author Kirill chEbba Chebunin * @author Jordi Boggiano * @author François Pluchino */ abstract class ArchiveDownloader extends \Composer\Downloader\FileDownloader { /** * @var array */ protected $cleanupExecuted = []; public function prepare(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface { unset($this->cleanupExecuted[$package->getName()]); return parent::prepare($type, $package, $path, $prevPackage); } public function cleanup(string $type, PackageInterface $package, string $path, ?PackageInterface $prevPackage = null) : PromiseInterface { $this->cleanupExecuted[$package->getName()] = \true; return parent::cleanup($type, $package, $path, $prevPackage); } /** * @inheritDoc * * @throws \RuntimeException * @throws \UnexpectedValueException */ public function install(PackageInterface $package, string $path, bool $output = \true) : PromiseInterface { if ($output) { $this->io->writeError(" - " . InstallOperation::format($package) . $this->getInstallOperationAppendix($package, $path)); } $vendorDir = $this->config->get('vendor-dir'); // clean up the target directory, unless it contains the vendor dir, as the vendor dir contains // the archive to be extracted. This is the case when installing with create-project in the current directory // but in that case we ensure the directory is empty already in ProjectInstaller so no need to empty it here. if (\false === \strpos($this->filesystem->normalizePath($vendorDir), $this->filesystem->normalizePath($path . \DIRECTORY_SEPARATOR))) { $this->filesystem->emptyDirectory($path); } do { $temporaryDir = $vendorDir . '/composer/' . \bin2hex(\random_bytes(4)); } while (\is_dir($temporaryDir)); $this->addCleanupPath($package, $temporaryDir); // avoid cleaning up $path if installing in "." for eg create-project as we can not // delete the directory we are currently in on windows if (!\is_dir($path) || \realpath($path) !== Platform::getCwd()) { $this->addCleanupPath($package, $path); } $this->filesystem->ensureDirectoryExists($temporaryDir); $fileName = $this->getFileName($package, $path); $filesystem = $this->filesystem; $cleanup = function () use($path, $filesystem, $temporaryDir, $package) { // remove cache if the file was corrupted $this->clearLastCacheWrite($package); // clean up $filesystem->removeDirectory($temporaryDir); if (\is_dir($path) && \realpath($path) !== Platform::getCwd()) { $filesystem->removeDirectory($path); } $this->removeCleanupPath($package, $temporaryDir); $realpath = \realpath($path); if ($realpath !== \false) { $this->removeCleanupPath($package, $realpath); } }; try { $promise = $this->extract($package, $fileName, $temporaryDir); } catch (\Exception $e) { $cleanup(); throw $e; } return $promise->then(function () use($package, $filesystem, $fileName, $temporaryDir, $path) : \React\Promise\PromiseInterface { if (\file_exists($fileName)) { $filesystem->unlink($fileName); } /** * Returns the folder content, excluding .DS_Store * * @param string $dir Directory * @return \SplFileInfo[] */ $getFolderContent = static function ($dir) : array { $finder = Finder::create()->ignoreVCS(\false)->ignoreDotFiles(\false)->notName('.DS_Store')->depth(0)->in($dir); return \iterator_to_array($finder); }; $renameRecursively = null; /** * Renames (and recursively merges if needed) a folder into another one * * For custom installers, where packages may share paths, and given Composer 2's parallelism, we need to make sure * that the source directory gets merged into the target one if the target exists. Otherwise rename() by default would * put the source into the target e.g. src/ => target/src/ (assuming target exists) instead of src/ => target/ * * @param string $from Directory * @param string $to Directory * @return void */ $renameRecursively = static function ($from, $to) use($filesystem, $getFolderContent, $package, &$renameRecursively) { $contentDir = $getFolderContent($from); // move files back out of the temp dir foreach ($contentDir as $file) { $file = (string) $file; if (\is_dir($to . '/' . \basename($file))) { if (!\is_dir($file)) { throw new \RuntimeException('Installing ' . $package . ' would lead to overwriting the ' . $to . '/' . \basename($file) . ' directory with a file from the package, invalid operation.'); } $renameRecursively($file, $to . '/' . \basename($file)); } else { $filesystem->rename($file, $to . '/' . \basename($file)); } } }; $renameAsOne = \false; if (!\file_exists($path)) { $renameAsOne = \true; } elseif ($filesystem->isDirEmpty($path)) { try { if ($filesystem->removeDirectoryPhp($path)) { $renameAsOne = \true; } } catch (\RuntimeException $e) { // ignore error, and simply do not renameAsOne } } $contentDir = $getFolderContent($temporaryDir); $singleDirAtTopLevel = 1 === \count($contentDir) && \is_dir((string) \reset($contentDir)); if ($renameAsOne) { // if the target $path is clear, we can rename the whole package in one go instead of looping over the contents if ($singleDirAtTopLevel) { $extractedDir = (string) \reset($contentDir); } else { $extractedDir = $temporaryDir; } $filesystem->rename($extractedDir, $path); } else { // only one dir in the archive, extract its contents out of it $from = $temporaryDir; if ($singleDirAtTopLevel) { $from = (string) \reset($contentDir); } $renameRecursively($from, $path); } $promise = $filesystem->removeDirectoryAsync($temporaryDir); return $promise->then(function () use($package, $path, $temporaryDir) { $this->removeCleanupPath($package, $temporaryDir); $this->removeCleanupPath($package, $path); }); }, static function ($e) use($cleanup) { $cleanup(); throw $e; }); } /** * @inheritDoc */ protected function getInstallOperationAppendix(PackageInterface $package, string $path) : string { return ': Extracting archive'; } /** * Extract file to directory * * @param string $file Extracted file * @param string $path Directory * @phpstan-return PromiseInterface * * @throws \UnexpectedValueException If can not extract downloaded file to path */ protected abstract function extract(PackageInterface $package, string $file, string $path) : PromiseInterface; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; /** * DVCS Downloader interface. * * @author James Titcumb */ interface DvcsDownloaderInterface { /** * Checks for unpushed changes to a current branch * * @param PackageInterface $package package instance * @param string $path package directory * @return string|null changes or null */ public function getUnpushedChanges(PackageInterface $package, string $path) : ?string; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use React\Promise\PromiseInterface; use Composer\Package\PackageInterface; /** * Downloader for phar files * * @author Kirill chEbba Chebunin */ class PharDownloader extends \Composer\Downloader\ArchiveDownloader { /** * @inheritDoc */ protected function extract(PackageInterface $package, string $file, string $path) : PromiseInterface { // Can throw an UnexpectedValueException $archive = new \Phar($file); $archive->extractTo($path, null, \true); /* TODO: handle openssl signed phars * https://github.com/composer/composer/pull/33#issuecomment-2250768 * https://github.com/koto/phar-util * http://blog.kotowicz.net/2010/08/hardening-php-how-to-securely-include.html */ return \React\Promise\resolve(null); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use React\Promise\PromiseInterface; use Composer\Package\Archiver\ArchivableFilesFinder; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Util\Platform; use Composer\Util\Filesystem; use _ContaoManager\Symfony\Component\Filesystem\Exception\IOException; use _ContaoManager\Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UninstallOperation; /** * Download a package from a local path. * * @author Samuel Roze * @author Johann Reinke */ class PathDownloader extends \Composer\Downloader\FileDownloader implements \Composer\Downloader\VcsCapableDownloaderInterface { private const STRATEGY_SYMLINK = 10; private const STRATEGY_MIRROR = 20; /** * @inheritDoc */ public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null, bool $output = \true) : PromiseInterface { $path = Filesystem::trimTrailingSlash($path); $url = $package->getDistUrl(); if (null === $url) { throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot download.'); } $realUrl = \realpath($url); if (\false === $realUrl || !\file_exists($realUrl) || !\is_dir($realUrl)) { throw new \RuntimeException(\sprintf('Source path "%s" is not found for package %s', $url, $package->getName())); } if (\realpath($path) === $realUrl) { return \React\Promise\resolve(null); } if (\strpos(\realpath($path) . \DIRECTORY_SEPARATOR, $realUrl . \DIRECTORY_SEPARATOR) === 0) { // IMPORTANT NOTICE: If you wish to change this, don't. You are wasting your time and ours. // // Please see https://github.com/composer/composer/pull/5974 and https://github.com/composer/composer/pull/6174 // for previous attempts that were shut down because they did not work well enough or introduced too many risks. throw new \RuntimeException(\sprintf('Package %s cannot install to "%s" inside its source at "%s"', $package->getName(), \realpath($path), $realUrl)); } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function install(PackageInterface $package, string $path, bool $output = \true) : PromiseInterface { $path = Filesystem::trimTrailingSlash($path); $url = $package->getDistUrl(); if (null === $url) { throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot install.'); } $realUrl = \realpath($url); if (\false === $realUrl) { throw new \RuntimeException('Failed to realpath ' . $url); } if (\realpath($path) === $realUrl) { if ($output) { $this->io->writeError(" - " . InstallOperation::format($package) . $this->getInstallOperationAppendix($package, $path)); } return \React\Promise\resolve(null); } // Get the transport options with default values $transportOptions = $package->getTransportOptions() + ['relative' => \true]; [$currentStrategy, $allowedStrategies] = $this->computeAllowedStrategies($transportOptions); $symfonyFilesystem = new SymfonyFilesystem(); $this->filesystem->removeDirectory($path); if ($output) { $this->io->writeError(" - " . InstallOperation::format($package) . ': ', \false); } $isFallback = \false; if (self::STRATEGY_SYMLINK === $currentStrategy) { try { if (Platform::isWindows()) { // Implement symlinks as NTFS junctions on Windows if ($output) { $this->io->writeError(\sprintf('Junctioning from %s', $url), \false); } $this->filesystem->junction($realUrl, $path); } else { $path = \rtrim($path, "/"); if ($output) { $this->io->writeError(\sprintf('Symlinking from %s', $url), \false); } if ($transportOptions['relative'] === \true) { $absolutePath = $path; if (!$this->filesystem->isAbsolutePath($absolutePath)) { $absolutePath = Platform::getCwd() . \DIRECTORY_SEPARATOR . $path; } $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl, \false, \true); $symfonyFilesystem->symlink($shortestPath . '/', $path); } else { $symfonyFilesystem->symlink($realUrl . '/', $path); } } } catch (IOException $e) { if (\in_array(self::STRATEGY_MIRROR, $allowedStrategies, \true)) { if ($output) { $this->io->writeError(''); $this->io->writeError(' Symlink failed, fallback to use mirroring!'); } $currentStrategy = self::STRATEGY_MIRROR; $isFallback = \true; } else { throw new \RuntimeException(\sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path)); } } } // Fallback if symlink failed or if symlink is not allowed for the package if (self::STRATEGY_MIRROR === $currentStrategy) { $realUrl = $this->filesystem->normalizePath($realUrl); if ($output) { $this->io->writeError(\sprintf('%sMirroring from %s', $isFallback ? ' ' : '', $url), \false); } $iterator = new ArchivableFilesFinder($realUrl, []); $symfonyFilesystem->mirror($realUrl, $path, $iterator); } if ($output) { $this->io->writeError(''); } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function remove(PackageInterface $package, string $path, bool $output = \true) : PromiseInterface { $path = Filesystem::trimTrailingSlash($path); /** * realpath() may resolve Windows junctions to the source path, so we'll check for a junction first * to prevent a false positive when checking if the dist and install paths are the same. * See https://bugs.php.net/bug.php?id=77639 * * For junctions don't blindly rely on Filesystem::removeDirectory as it may be overzealous. If a process * inadvertently locks the file the removal will fail, but it would fall back to recursive delete which * is disastrous within a junction. So in that case we have no other real choice but to fail hard. */ if (Platform::isWindows() && $this->filesystem->isJunction($path)) { if ($output) { $this->io->writeError(" - " . UninstallOperation::format($package) . ", source is still present in {$path}"); } if (!$this->filesystem->removeJunction($path)) { $this->io->writeError(" Could not remove junction at " . $path . " - is another process locking it?"); throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName()); } return \React\Promise\resolve(null); } $url = $package->getDistUrl(); if (null === $url) { throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot remove.'); } // ensure that the source path (dist url) is not the same as the install path, which // can happen when using custom installers, see https://github.com/composer/composer/pull/9116 // not using realpath here as we do not want to resolve the symlink to the original dist url // it points to $fs = new Filesystem(); $absPath = $fs->isAbsolutePath($path) ? $path : Platform::getCwd() . '/' . $path; $absDistUrl = $fs->isAbsolutePath($url) ? $url : Platform::getCwd() . '/' . $url; if ($fs->normalizePath($absPath) === $fs->normalizePath($absDistUrl)) { if ($output) { $this->io->writeError(" - " . UninstallOperation::format($package) . ", source is still present in {$path}"); } return \React\Promise\resolve(null); } return parent::remove($package, $path, $output); } /** * @inheritDoc */ public function getVcsReference(PackageInterface $package, string $path) : ?string { $path = Filesystem::trimTrailingSlash($path); $parser = new VersionParser(); $guesser = new VersionGuesser($this->config, $this->process, $parser, $this->io); $dumper = new ArrayDumper(); $packageConfig = $dumper->dump($package); $packageVersion = $guesser->guessVersion($packageConfig, $path); if ($packageVersion !== null) { return $packageVersion['commit']; } return null; } /** * @inheritDoc */ protected function getInstallOperationAppendix(PackageInterface $package, string $path) : string { $url = $package->getDistUrl(); if (null === $url) { throw new \RuntimeException('The package ' . $package->getPrettyName() . ' has no dist url configured, cannot install.'); } $realUrl = \realpath($url); if (\false === $realUrl) { throw new \RuntimeException('Failed to realpath ' . $url); } if (\realpath($path) === $realUrl) { return ': Source already present'; } [$currentStrategy] = $this->computeAllowedStrategies($package->getTransportOptions()); if ($currentStrategy === self::STRATEGY_SYMLINK) { if (Platform::isWindows()) { return ': Junctioning from ' . $package->getDistUrl(); } return ': Symlinking from ' . $package->getDistUrl(); } return ': Mirroring from ' . $package->getDistUrl(); } /** * @param mixed[] $transportOptions * * @phpstan-return array{self::STRATEGY_*, non-empty-list} */ private function computeAllowedStrategies(array $transportOptions) : array { // When symlink transport option is null, both symlink and mirror are allowed $currentStrategy = self::STRATEGY_SYMLINK; $allowedStrategies = [self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR]; $mirrorPathRepos = Platform::getEnv('COMPOSER_MIRROR_PATH_REPOS'); if ((bool) $mirrorPathRepos) { $currentStrategy = self::STRATEGY_MIRROR; } $symlinkOption = $transportOptions['symlink'] ?? null; if (\true === $symlinkOption) { $currentStrategy = self::STRATEGY_SYMLINK; $allowedStrategies = [self::STRATEGY_SYMLINK]; } elseif (\false === $symlinkOption) { $currentStrategy = self::STRATEGY_MIRROR; $allowedStrategies = [self::STRATEGY_MIRROR]; } // Check we can use junctions safely if we are on Windows if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) { if (!\in_array(self::STRATEGY_MIRROR, $allowedStrategies, \true)) { throw new \RuntimeException('You are on an old Windows / old PHP combo which does not allow Composer to use junctions/symlinks and this path repository has symlink:true in its options so copying is not allowed'); } $currentStrategy = self::STRATEGY_MIRROR; $allowedStrategies = [self::STRATEGY_MIRROR]; } // Check we can use symlink() otherwise if (!Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !\function_exists('symlink')) { if (!\in_array(self::STRATEGY_MIRROR, $allowedStrategies, \true)) { throw new \RuntimeException('Your PHP has the symlink() function disabled which does not allow Composer to use symlinks and this path repository has symlink:true in its options so copying is not allowed'); } $currentStrategy = self::STRATEGY_MIRROR; $allowedStrategies = [self::STRATEGY_MIRROR]; } return [$currentStrategy, $allowedStrategies]; } /** * Returns true if junctions can be created and safely used on Windows * * A PHP bug makes junction detection fragile, leading to possible data loss * when removing a package. See https://bugs.php.net/bug.php?id=77552 * * For safety we require a minimum version of Windows 7, so we can call the * system rmdir which will preserve target content if given a junction. * * The PHP bug was fixed in 7.2.16 and 7.3.3 (requires at least Windows 7). */ private function safeJunctions() : bool { // We need to call mklink, and rmdir on Windows 7 (version 6.1) return \function_exists('proc_open') && (\PHP_WINDOWS_VERSION_MAJOR > 6 || \PHP_WINDOWS_VERSION_MAJOR === 6 && \PHP_WINDOWS_VERSION_MINOR >= 1); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use React\Promise\PromiseInterface; use Composer\Package\PackageInterface; use Composer\Repository\VcsRepository; use Composer\Util\Perforce; /** * @author Matt Whittom */ class PerforceDownloader extends \Composer\Downloader\VcsDownloader { /** @var Perforce|null */ protected $perforce; /** * @inheritDoc */ protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null) : PromiseInterface { return \React\Promise\resolve(null); } /** * @inheritDoc */ public function doInstall(PackageInterface $package, string $path, string $url) : PromiseInterface { $ref = $package->getSourceReference(); $label = $this->getLabelFromSourceReference((string) $ref); $this->io->writeError('Cloning ' . $ref); $this->initPerforce($package, $path, $url); $this->perforce->setStream($ref); $this->perforce->p4Login(); $this->perforce->writeP4ClientSpec(); $this->perforce->connectClient(); $this->perforce->syncCodeBase($label); $this->perforce->cleanupClientSpec(); return \React\Promise\resolve(null); } private function getLabelFromSourceReference(string $ref) : ?string { $pos = \strpos($ref, '@'); if (\false !== $pos) { return \substr($ref, $pos + 1); } return null; } public function initPerforce(PackageInterface $package, string $path, string $url) : void { if (!empty($this->perforce)) { $this->perforce->initializePath($path); return; } $repository = $package->getRepository(); $repoConfig = null; if ($repository instanceof VcsRepository) { $repoConfig = $this->getRepoConfig($repository); } $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io); } /** * @return array */ private function getRepoConfig(VcsRepository $repository) : array { return $repository->getRepoConfig(); } /** * @inheritDoc */ protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url) : PromiseInterface { return $this->doInstall($target, $path, $url); } /** * @inheritDoc */ public function getLocalChanges(PackageInterface $package, string $path) : ?string { $this->io->writeError('Perforce driver does not check for local changes before overriding'); return null; } /** * @inheritDoc */ protected function getCommitLogs(string $fromReference, string $toReference, string $path) : string { return $this->perforce->getCommitLogs($fromReference, $toReference); } public function setPerforce(Perforce $perforce) : void { $this->perforce = $perforce; } /** * @inheritDoc */ protected function hasMetadataRepository(string $path) : bool { return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Config; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Git as GitUtil; use Composer\Util\Url; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Cache; use React\Promise\PromiseInterface; /** * @author Jordi Boggiano */ class GitDownloader extends \Composer\Downloader\VcsDownloader implements \Composer\Downloader\DvcsDownloaderInterface { /** * @var bool[] * @phpstan-var array */ private $hasStashedChanges = []; /** * @var bool[] * @phpstan-var array */ private $hasDiscardedChanges = []; /** * @var GitUtil */ private $gitUtil; /** * @var array * @phpstan-var array> */ private $cachedPackages = []; public function __construct(IOInterface $io, Config $config, ?ProcessExecutor $process = null, ?Filesystem $fs = null) { parent::__construct($io, $config, $process, $fs); $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem); } /** * @inheritDoc */ protected function doDownload(PackageInterface $package, string $path, string $url, ?PackageInterface $prevPackage = null) : PromiseInterface { // Do not create an extra local cache when repository is already local if (Filesystem::isLocalPath($url)) { return \React\Promise\resolve(null); } GitUtil::cleanEnv(); $cachePath = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)) . '/'; $gitVersion = GitUtil::getVersion($this->process); // --dissociate option is only available since git 2.3.0-rc0 if ($gitVersion && \version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) { $this->io->writeError(" - Syncing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ") into cache"); $this->io->writeError(\sprintf(' Cloning to cache at %s', $cachePath), \true, IOInterface::DEBUG); $ref = $package->getSourceReference(); if ($this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref, $package->getPrettyVersion()) && \is_dir($cachePath)) { $this->cachedPackages[$package->getId()][$ref] = \true; } } elseif (null === $gitVersion) { throw new \RuntimeException('git was not found in your PATH, skipping source download'); } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doInstall(PackageInterface $package, string $path, string $url) : PromiseInterface { GitUtil::cleanEnv(); $path = $this->normalizePath($path); $cachePath = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)) . '/'; $ref = $package->getSourceReference(); if (!empty($this->cachedPackages[$package->getId()][$ref])) { $msg = "Cloning " . $this->getShortHash($ref) . ' from cache'; $cloneFlags = ['--dissociate', '--reference', $cachePath]; $transportOptions = $package->getTransportOptions(); if (isset($transportOptions['git']['single_use_clone']) && $transportOptions['git']['single_use_clone']) { $cloneFlags = []; } $commands = [\array_merge(['git', 'clone', '--no-checkout', $cachePath, $path], $cloneFlags), ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%'], ['git', 'remote', 'add', 'composer', '--', '%sanitizedUrl%']]; } else { $msg = "Cloning " . $this->getShortHash($ref); $commands = [\array_merge(['git', 'clone', '--no-checkout', '--', '%url%', $path]), ['git', 'remote', 'add', 'composer', '--', '%url%'], ['git', 'fetch', 'composer'], ['git', 'remote', 'set-url', 'origin', '--', '%sanitizedUrl%'], ['git', 'remote', 'set-url', 'composer', '--', '%sanitizedUrl%']]; if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) { throw new \RuntimeException('The required git reference for ' . $package->getName() . ' is not in cache and network is disabled, aborting'); } } $this->io->writeError($msg); $this->gitUtil->runCommands($commands, $url, $path, \true); $sourceUrl = $package->getSourceUrl(); if ($url !== $sourceUrl && $sourceUrl !== null) { $this->updateOriginUrl($path, $sourceUrl); } else { $this->setPushUrl($path, $url); } if ($newRef = $this->updateToCommit($package, $path, (string) $ref, $package->getPrettyVersion())) { if ($package->getDistReference() === $package->getSourceReference()) { $package->setDistReference($newRef); } $package->setSourceReference($newRef); } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function doUpdate(PackageInterface $initial, PackageInterface $target, string $path, string $url) : PromiseInterface { GitUtil::cleanEnv(); $path = $this->normalizePath($path); if (!$this->hasMetadataRepository($path)) { throw new \RuntimeException('The .git directory is missing from ' . $path . ', see https://getcomposer.org/commit-deps for more information'); } $cachePath = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($url)) . '/'; $ref = $target->getSourceReference(); if (!empty($this->cachedPackages[$target->getId()][$ref])) { $msg = "Checking out " . $this->getShortHash($ref) . ' from cache'; $remoteUrl = $cachePath; } else { $msg = "Checking out " . $this->getShortHash($ref); $remoteUrl = '%url%'; if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) { throw new \RuntimeException('The required git reference for ' . $target->getName() . ' is not in cache and network is disabled, aborting'); } } $this->io->writeError($msg); if (0 !== $this->process->execute(['git', 'rev-parse', '--quiet', '--verify', $ref . '^{commit}'], $output, $path)) { $commands = [['git', 'remote', 'set-url', 'composer', '--', $remoteUrl], ['git', 'fetch', 'composer'], ['git', 'fetch', '--tags', 'composer']]; $this->gitUtil->runCommands($commands, $url, $path); } $command = ['git', 'remote', 'set-url', 'composer', '--', '%sanitizedUrl%']; $this->gitUtil->runCommands([$command], $url, $path); if ($newRef = $this->updateToCommit($target, $path, (string) $ref, $target->getPrettyVersion())) { if ($target->getDistReference() === $target->getSourceReference()) { $target->setDistReference($newRef); } $target->setSourceReference($newRef); } $updateOriginUrl = \false; if (0 === $this->process->execute(['git', 'remote', '-v'], $output, $path) && Preg::isMatch('{^origin\\s+(?P\\S+)}m', $output, $originMatch) && Preg::isMatch('{^composer\\s+(?P\\S+)}m', $output, $composerMatch)) { if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) { $updateOriginUrl = \true; } } if ($updateOriginUrl && $target->getSourceUrl() !== null) { $this->updateOriginUrl($path, $target->getSourceUrl()); } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function getLocalChanges(PackageInterface $package, string $path) : ?string { GitUtil::cleanEnv(); if (!$this->hasMetadataRepository($path)) { return null; } $command = ['git', 'status', '--porcelain', '--untracked-files=no']; if (0 !== $this->process->execute($command, $output, $path)) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } $output = \trim($output); return \strlen($output) > 0 ? $output : null; } public function getUnpushedChanges(PackageInterface $package, string $path) : ?string { GitUtil::cleanEnv(); $path = $this->normalizePath($path); if (!$this->hasMetadataRepository($path)) { return null; } $command = ['git', 'show-ref', '--head', '-d']; if (0 !== $this->process->execute($command, $output, $path)) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } $refs = \trim($output); if (!Preg::isMatchStrictGroups('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) { // could not match the HEAD for some reason return null; } $headRef = $match[1]; if (!Preg::isMatchAllStrictGroups('{^' . \preg_quote($headRef) . ' refs/heads/(.+)$}mi', $refs, $matches)) { // not on a branch, we are either on a not-modified tag or some sort of detached head, so skip this return null; } $candidateBranches = $matches[1]; // use the first match as branch name for now $branch = $candidateBranches[0]; $unpushedChanges = null; $branchNotFoundError = \false; // do two passes, as if we find anything we want to fetch and then re-try for ($i = 0; $i <= 1; $i++) { $remoteBranches = []; // try to find matching branch names in remote repos foreach ($candidateBranches as $candidate) { if (Preg::isMatchAllStrictGroups('{^[a-f0-9]+ refs/remotes/((?:[^/]+)/' . \preg_quote($candidate) . ')$}mi', $refs, $matches)) { foreach ($matches[1] as $match) { $branch = $candidate; $remoteBranches[] = $match; } break; } } // if it doesn't exist, then we assume it is an unpushed branch // this is bad as we have no reference point to do a diff so we just bail listing // the branch as being unpushed if (\count($remoteBranches) === 0) { $unpushedChanges = 'Branch ' . $branch . ' could not be found on any remote and appears to be unpushed'; $branchNotFoundError = \true; } else { // if first iteration found no remote branch but it has now found some, reset $unpushedChanges // so we get the real diff output no matter its length if ($branchNotFoundError) { $unpushedChanges = null; } foreach ($remoteBranches as $remoteBranch) { $command = ['git', 'diff', '--name-status', $remoteBranch . '...' . $branch, '--']; if (0 !== $this->process->execute($command, $output, $path)) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } $output = \trim($output); // keep the shortest diff from all remote branches we compare against if ($unpushedChanges === null || \strlen($output) < \strlen($unpushedChanges)) { $unpushedChanges = $output; } } } // first pass and we found unpushed changes, fetch from all remotes to make sure we have up to date // remotes and then try again as outdated remotes can sometimes cause false-positives if ($unpushedChanges && $i === 0) { $this->process->execute(['git', 'fetch', '--all'], $output, $path); // update list of refs after fetching $command = ['git', 'show-ref', '--head', '-d']; if (0 !== $this->process->execute($command, $output, $path)) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } $refs = \trim($output); } // abort after first pass if we didn't find anything if (!$unpushedChanges) { break; } } return $unpushedChanges; } /** * @inheritDoc */ protected function cleanChanges(PackageInterface $package, string $path, bool $update) : PromiseInterface { GitUtil::cleanEnv(); $path = $this->normalizePath($path); $unpushed = $this->getUnpushedChanges($package, $path); if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== \true)) { throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: ' . "\n" . $unpushed); } if (null === ($changes = $this->getLocalChanges($package, $path))) { return \React\Promise\resolve(null); } if (!$this->io->isInteractive()) { $discardChanges = $this->config->get('discard-changes'); if (\true === $discardChanges) { return $this->discardChanges($path); } if ('stash' === $discardChanges) { if (!$update) { return parent::cleanChanges($package, $path, $update); } return $this->stashChanges($path); } return parent::cleanChanges($package, $path, $update); } $changes = \array_map(static function ($elem) : string { return ' ' . $elem; }, Preg::split('{\\s*\\r?\\n\\s*}', $changes)); $this->io->writeError(' ' . $package->getPrettyName() . ' has modified files:'); $this->io->writeError(\array_slice($changes, 0, 10)); if (\count($changes) > 10) { $this->io->writeError(' ' . (\count($changes) - 10) . ' more files modified, choose "v" to view the full list'); } while (\true) { switch ($this->io->ask(' Discard changes [y,n,v,d,' . ($update ? 's,' : '') . '?]? ', '?')) { case 'y': $this->discardChanges($path); break 2; case 's': if (!$update) { goto help; } $this->stashChanges($path); break 2; case 'n': throw new \RuntimeException('Update aborted'); case 'v': $this->io->writeError($changes); break; case 'd': $this->viewDiff($path); break; case '?': default: help: $this->io->writeError([' y - discard changes and apply the ' . ($update ? 'update' : 'uninstall'), ' n - abort the ' . ($update ? 'update' : 'uninstall') . ' and let you manually clean things up', ' v - view modified files', ' d - view local modifications (diff)']); if ($update) { $this->io->writeError(' s - stash changes and try to reapply them after the update'); } $this->io->writeError(' ? - print help'); break; } } return \React\Promise\resolve(null); } /** * @inheritDoc */ protected function reapplyChanges(string $path) : void { $path = $this->normalizePath($path); if (!empty($this->hasStashedChanges[$path])) { unset($this->hasStashedChanges[$path]); $this->io->writeError(' Re-applying stashed changes'); if (0 !== $this->process->execute(['git', 'stash', 'pop'], $output, $path)) { throw new \RuntimeException("Failed to apply stashed changes:\n\n" . $this->process->getErrorOutput()); } } unset($this->hasDiscardedChanges[$path]); } /** * Updates the given path to the given commit ref * * @throws \RuntimeException * @return null|string if a string is returned, it is the commit reference that was checked out if the original could not be found */ protected function updateToCommit(PackageInterface $package, string $path, string $reference, string $prettyVersion) : ?string { $force = !empty($this->hasDiscardedChanges[$path]) || !empty($this->hasStashedChanges[$path]) ? ['-f'] : []; // This uses the "--" sequence to separate branch from file parameters. // // Otherwise git tries the branch name as well as file name. // If the non-existent branch is actually the name of a file, the file // is checked out. $branch = Preg::replace('{(?:^dev-|(?:\\.x)?-dev$)}i', '', $prettyVersion); /** * @var \Closure(non-empty-list): bool $execute * @phpstan-ignore varTag.nativeType */ $execute = function (array $command) use(&$output, $path) { /** @var non-empty-list $command */ $output = ''; return 0 === $this->process->execute($command, $output, $path); }; $branches = null; if ($execute(['git', 'branch', '-r'])) { $branches = $output; } // check whether non-commitish are branches or tags, and fetch branches with the remote name $gitRef = $reference; if (!Preg::isMatch('{^[a-f0-9]{40}$}', $reference) && null !== $branches && Preg::isMatch('{^\\s+composer/' . \preg_quote($reference) . '$}m', $branches)) { $command1 = \array_merge(['git', 'checkout'], $force, ['-B', $branch, 'composer/' . $reference, '--']); $command2 = ['git', 'reset', '--hard', 'composer/' . $reference, '--']; if ($execute($command1) && $execute($command2)) { return null; } } // try to checkout branch by name and then reset it so it's on the proper branch name if (Preg::isMatch('{^[a-f0-9]{40}$}', $reference)) { // add 'v' in front of the branch if it was stripped when generating the pretty name if (null !== $branches && !Preg::isMatch('{^\\s+composer/' . \preg_quote($branch) . '$}m', $branches) && Preg::isMatch('{^\\s+composer/v' . \preg_quote($branch) . '$}m', $branches)) { $branch = 'v' . $branch; } $command = ['git', 'checkout', $branch, '--']; $fallbackCommand = \array_merge(['git', 'checkout'], $force, ['-B', $branch, 'composer/' . $branch, '--']); $resetCommand = ['git', 'reset', '--hard', $reference, '--']; if (($execute($command) || $execute($fallbackCommand)) && $execute($resetCommand)) { return null; } } $command1 = \array_merge(['git', 'checkout'], $force, [$gitRef, '--']); $command2 = ['git', 'reset', '--hard', $gitRef, '--']; if ($execute($command1) && $execute($command2)) { return null; } $exceptionExtra = ''; // reference was not found (prints "fatal: reference is not a tree: $ref") if (\false !== \strpos($this->process->getErrorOutput(), $reference)) { $this->io->writeError(' ' . $reference . ' is gone (history was rewritten?)'); $exceptionExtra = "\nIt looks like the commit hash is not available in the repository, maybe " . ($package->isDev() ? 'the commit was removed from the branch' : 'the tag was recreated') . '? Run "composer update ' . $package->getPrettyName() . '" to resolve this.'; } $command = \implode(' ', $command1) . ' && ' . \implode(' ', $command2); throw new \RuntimeException(Url::sanitize('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput() . $exceptionExtra)); } protected function updateOriginUrl(string $path, string $url) : void { $this->process->execute(['git', 'remote', 'set-url', 'origin', '--', $url], $output, $path); $this->setPushUrl($path, $url); } protected function setPushUrl(string $path, string $url) : void { // set push url for github projects if (Preg::isMatch('{^(?:https?|git)://' . GitUtil::getGitHubDomainsRegex($this->config) . '/([^/]+)/([^/]+?)(?:\\.git)?$}', $url, $match)) { $protocols = $this->config->get('github-protocols'); $pushUrl = 'git@' . $match[1] . ':' . $match[2] . '/' . $match[3] . '.git'; if (!\in_array('ssh', $protocols, \true)) { $pushUrl = 'https://' . $match[1] . '/' . $match[2] . '/' . $match[3] . '.git'; } $cmd = ['git', 'remote', 'set-url', '--push', 'origin', '--', $pushUrl]; $this->process->execute($cmd, $ignoredOutput, $path); } } /** * @inheritDoc */ protected function getCommitLogs(string $fromReference, string $toReference, string $path) : string { $path = $this->normalizePath($path); $command = \array_merge(['git', 'log', $fromReference . '..' . $toReference, '--pretty=format:%h - %an: %s'], GitUtil::getNoShowSignatureFlags($this->process)); if (0 !== $this->process->execute($command, $output, $path)) { throw new \RuntimeException('Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput()); } return $output; } /** * @phpstan-return PromiseInterface * @throws \RuntimeException */ protected function discardChanges(string $path) : PromiseInterface { $path = $this->normalizePath($path); if (0 !== $this->process->execute(['git', 'clean', '-df'], $output, $path)) { throw new \RuntimeException("Could not reset changes\n\n:" . $output); } if (0 !== $this->process->execute(['git', 'reset', '--hard'], $output, $path)) { throw new \RuntimeException("Could not reset changes\n\n:" . $output); } $this->hasDiscardedChanges[$path] = \true; return \React\Promise\resolve(null); } /** * @phpstan-return PromiseInterface * @throws \RuntimeException */ protected function stashChanges(string $path) : PromiseInterface { $path = $this->normalizePath($path); if (0 !== $this->process->execute(['git', 'stash', '--include-untracked'], $output, $path)) { throw new \RuntimeException("Could not stash changes\n\n:" . $output); } $this->hasStashedChanges[$path] = \true; return \React\Promise\resolve(null); } /** * @throws \RuntimeException */ protected function viewDiff(string $path) : void { $path = $this->normalizePath($path); if (0 !== $this->process->execute(['git', 'diff', 'HEAD'], $output, $path)) { throw new \RuntimeException("Could not view diff\n\n:" . $output); } $this->io->writeError($output); } protected function normalizePath(string $path) : string { if (Platform::isWindows() && \strlen($path) > 0) { $basePath = $path; $removed = []; while (!\is_dir($basePath) && $basePath !== '\\') { \array_unshift($removed, \basename($basePath)); $basePath = \dirname($basePath); } if ($basePath === '\\') { return $path; } $path = \rtrim(\realpath($basePath) . '/' . \implode('/', $removed), '/'); } return $path; } /** * @inheritDoc */ protected function hasMetadataRepository(string $path) : bool { $path = $this->normalizePath($path); return \is_dir($path . '/.git'); } protected function getShortHash(string $reference) : string { if (!$this->io->isVerbose() && Preg::isMatch('{^[0-9a-f]{40}$}', $reference)) { return \substr($reference, 0, 10); } return $reference; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\Pcre\Preg; use Composer\Util\IniHelper; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use _ContaoManager\Symfony\Component\Process\ExecutableFinder; use _ContaoManager\Symfony\Component\Process\Process; use React\Promise\PromiseInterface; use ZipArchive; /** * @author Jordi Boggiano */ class ZipDownloader extends \Composer\Downloader\ArchiveDownloader { /** @var array> */ private static $unzipCommands; /** @var bool */ private static $hasZipArchive; /** @var bool */ private static $isWindows; /** @var ZipArchive|null */ private $zipArchiveObject; // @phpstan-ignore property.onlyRead (helper property that is set via reflection for testing purposes) /** * @inheritDoc */ public function download(PackageInterface $package, string $path, ?PackageInterface $prevPackage = null, bool $output = \true) : PromiseInterface { if (null === self::$unzipCommands) { self::$unzipCommands = []; $finder = new ExecutableFinder(); if (Platform::isWindows() && ($cmd = $finder->find('7z', null, ['C:\\Program Files\\7-Zip']))) { self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%']; } if ($cmd = $finder->find('unzip')) { self::$unzipCommands[] = ['unzip', $cmd, '-qq', '%file%', '-d', '%path%']; } if (!Platform::isWindows() && ($cmd = $finder->find('7z'))) { // 7z linux/macOS support is only used if unzip is not present self::$unzipCommands[] = ['7z', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%']; } if (!Platform::isWindows() && ($cmd = $finder->find('7zz'))) { // 7zz linux/macOS support is only used if unzip is not present self::$unzipCommands[] = ['7zz', $cmd, 'x', '-bb0', '-y', '%file%', '-o%path%']; } } $procOpenMissing = \false; if (!\function_exists('proc_open')) { self::$unzipCommands = []; $procOpenMissing = \true; } if (null === self::$hasZipArchive) { self::$hasZipArchive = \class_exists('ZipArchive'); } if (!self::$hasZipArchive && !self::$unzipCommands) { // php.ini path is added to the error message to help users find the correct file $iniMessage = IniHelper::getMessage(); if ($procOpenMissing) { $error = "The zip extension is missing and unzip/7z commands cannot be called as proc_open is disabled, skipping.\n" . $iniMessage; } else { $error = "The zip extension and unzip/7z commands are both missing, skipping.\n" . $iniMessage; } throw new \RuntimeException($error); } if (null === self::$isWindows) { self::$isWindows = Platform::isWindows(); if (!self::$isWindows && !self::$unzipCommands) { if ($procOpenMissing) { $this->io->writeError("proc_open is disabled so 'unzip' and '7z' commands cannot be used, zip files are being unpacked using the PHP zip extension."); $this->io->writeError("This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost."); $this->io->writeError("Enabling proc_open and installing 'unzip' or '7z' (21.01+) may remediate them."); } else { $this->io->writeError("As there is no 'unzip' nor '7z' command installed zip files are being unpacked using the PHP zip extension."); $this->io->writeError("This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost."); $this->io->writeError("Installing 'unzip' or '7z' (21.01+) may remediate them."); } } } return parent::download($package, $path, $prevPackage, $output); } /** * extract $file to $path with "unzip" command * * @param string $file File to extract * @param string $path Path where to extract file * @phpstan-return PromiseInterface */ private function extractWithSystemUnzip(PackageInterface $package, string $file, string $path) : PromiseInterface { static $warned7ZipLinux = \false; // Force Exception throwing if the other alternative extraction method is not available $isLastChance = !self::$hasZipArchive; if (0 === \count(self::$unzipCommands)) { // This was call as the favorite extract way, but is not available // We switch to the alternative return $this->extractWithZipArchive($package, $file, $path); } $commandSpec = \reset(self::$unzipCommands); $executable = $commandSpec[0]; $command = \array_slice($commandSpec, 1); $map = [ // normalize separators to backslashes to avoid problems with 7-zip on windows // see https://github.com/composer/composer/issues/10058 '%file%' => \strtr($file, '/', \DIRECTORY_SEPARATOR), '%path%' => \strtr($path, '/', \DIRECTORY_SEPARATOR), ]; $command = \array_map(static function ($value) use($map) { return \strtr($value, $map); }, $command); if (!$warned7ZipLinux && !Platform::isWindows() && \in_array($executable, ['7z', '7zz'], \true)) { $warned7ZipLinux = \true; if (0 === $this->process->execute([$commandSpec[1]], $output)) { if (Preg::isMatchStrictGroups('{^\\s*7-Zip(?: \\[64\\])? ([0-9.]+)}', $output, $match) && \version_compare($match[1], '21.01', '<')) { $this->io->writeError(' Unzipping using ' . $executable . ' ' . $match[1] . ' may result in incorrect file permissions. Install ' . $executable . ' 21.01+ or unzip to ensure you get correct permissions.'); } } } $io = $this->io; $tryFallback = function (\Throwable $processError) use($isLastChance, $io, $file, $path, $package, $executable) : \React\Promise\PromiseInterface { if ($isLastChance) { throw $processError; } if (\str_contains($processError->getMessage(), 'zip bomb')) { throw $processError; } if (!\is_file($file)) { $io->writeError(' ' . $processError->getMessage() . ''); $io->writeError(' This most likely is due to a custom installer plugin not handling the returned Promise from the downloader'); $io->writeError(' See https://github.com/composer/installers/commit/5006d0c28730ade233a8f42ec31ac68fb1c5c9bb for an example fix'); } else { $io->writeError(' ' . $processError->getMessage() . ''); $io->writeError(' The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)'); $io->writeError(' Unzip with ' . $executable . ' command failed, falling back to ZipArchive class'); // additional debug data to try to figure out GH actions issues https://github.com/composer/composer/issues/11148 if (Platform::getEnv('GITHUB_ACTIONS') !== \false && Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') === \false) { $io->writeError(' Additional debug info, please report to https://github.com/composer/composer/issues/11148 if you see this:'); $io->writeError('File size: ' . @\filesize($file)); $io->writeError('File SHA1: ' . \hash_file('sha1', $file)); $io->writeError('First 100 bytes (hex): ' . \bin2hex(\substr((string) \file_get_contents($file), 0, 100))); $io->writeError('Last 100 bytes (hex): ' . \bin2hex(\substr((string) \file_get_contents($file), -100))); if (\strlen((string) $package->getDistUrl()) > 0) { $io->writeError('Origin URL: ' . $this->processUrl($package, (string) $package->getDistUrl())); $io->writeError('Response Headers: ' . \json_encode(\Composer\Downloader\FileDownloader::$responseHeaders[$package->getName()] ?? [])); } } } return $this->extractWithZipArchive($package, $file, $path); }; try { $promise = $this->process->executeAsync($command); return $promise->then(function (Process $process) use($tryFallback, $command, $package, $file) { if (!$process->isSuccessful()) { if (isset($this->cleanupExecuted[$package->getName()])) { throw new \RuntimeException('Failed to extract ' . $package->getName() . ' as the installation was aborted by another package operation.'); } $output = $process->getErrorOutput(); $output = \str_replace(', ' . $file . '.zip or ' . $file . '.ZIP', '', $output); return $tryFallback(new \RuntimeException('Failed to extract ' . $package->getName() . ': (' . $process->getExitCode() . ') ' . \implode(' ', $command) . "\n\n" . $output)); } }); } catch (\Throwable $e) { return $tryFallback($e); } } /** * extract $file to $path with ZipArchive * * @param string $file File to extract * @param string $path Path where to extract file * @phpstan-return PromiseInterface */ private function extractWithZipArchive(PackageInterface $package, string $file, string $path) : PromiseInterface { $processError = null; $zipArchive = $this->zipArchiveObject ?: new ZipArchive(); try { if (!\file_exists($file) || ($filesize = \filesize($file)) === \false || $filesize === 0) { $retval = -1; } else { $retval = $zipArchive->open($file); } if (\true === $retval) { $totalSize = 0; $archiveSize = \filesize($file); $totalFiles = $zipArchive->count(); if ($totalFiles > 0) { for ($i = 0; $i < \min($totalFiles, 5); $i++) { $stat = $zipArchive->statIndex(\random_int(0, $totalFiles - 1)); if ($stat === \false) { continue; } $totalSize += $stat['size']; if ($stat['size'] > $stat['comp_size'] * 200) { throw new \RuntimeException('Invalid zip file with compression ratio >99% (possible zip bomb)'); } } if ($archiveSize !== \false && $totalSize > $archiveSize * 100 && $totalSize > 50 * 1024 * 1024) { throw new \RuntimeException('Invalid zip file with compression ratio >99% (possible zip bomb)'); } } $extractResult = $zipArchive->extractTo($path); if (\true === $extractResult) { $zipArchive->close(); return \React\Promise\resolve(null); } $processError = new \RuntimeException(\rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n")); } else { $processError = new \UnexpectedValueException(\rtrim($this->getErrorMessage($retval, $file) . "\n"), $retval); } } catch (\ErrorException $e) { $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): ' . $e->getMessage(), 0, $e); } catch (\Throwable $e) { $processError = $e; } throw $processError; } /** * extract $file to $path * * @param string $file File to extract * @param string $path Path where to extract file */ protected function extract(PackageInterface $package, string $file, string $path) : PromiseInterface { return $this->extractWithSystemUnzip($package, $file, $path); } /** * Give a meaningful error message to the user. */ protected function getErrorMessage(int $retval, string $file) : string { switch ($retval) { case ZipArchive::ER_EXISTS: return \sprintf("File '%s' already exists.", $file); case ZipArchive::ER_INCONS: return \sprintf("Zip archive '%s' is inconsistent.", $file); case ZipArchive::ER_INVAL: return \sprintf("Invalid argument (%s)", $file); case ZipArchive::ER_MEMORY: return \sprintf("Malloc failure (%s)", $file); case ZipArchive::ER_NOENT: return \sprintf("No such zip file: '%s'", $file); case ZipArchive::ER_NOZIP: return \sprintf("'%s' is not a zip archive.", $file); case ZipArchive::ER_OPEN: return \sprintf("Can't open zip file: %s", $file); case ZipArchive::ER_READ: return \sprintf("Zip read error (%s)", $file); case ZipArchive::ER_SEEK: return \sprintf("Zip seek error (%s)", $file); case -1: return \sprintf("'%s' is a corrupted zip archive (0 bytes), try again.", $file); default: return \sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Downloader; use React\Promise\PromiseInterface; use Composer\Package\PackageInterface; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; /** * GZip archive downloader. * * @author Pavel Puchkin */ class GzipDownloader extends \Composer\Downloader\ArchiveDownloader { protected function extract(PackageInterface $package, string $file, string $path) : PromiseInterface { $filename = \pathinfo(\parse_url(\strtr((string) $package->getDistUrl(), '\\', '/'), \PHP_URL_PATH), \PATHINFO_FILENAME); $targetFilepath = $path . \DIRECTORY_SEPARATOR . $filename; // Try to use gunzip on *nix if (!Platform::isWindows()) { $command = ['sh', '-c', 'gzip -cd -- "$0" > "$1"', $file, $targetFilepath]; if (0 === $this->process->execute($command, $ignoredOutput)) { return \React\Promise\resolve(null); } if (\extension_loaded('zlib')) { // Fallback to using the PHP extension. $this->extractUsingExt($file, $targetFilepath); return \React\Promise\resolve(null); } $processError = 'Failed to execute ' . \implode(' ', $command) . "\n\n" . $this->process->getErrorOutput(); throw new \RuntimeException($processError); } // Windows version of PHP has built-in support of gzip functions $this->extractUsingExt($file, $targetFilepath); return \React\Promise\resolve(null); } private function extractUsingExt(string $file, string $targetFilepath) : void { $archiveFile = \gzopen($file, 'rb'); $targetFile = \fopen($targetFilepath, 'wb'); while ($string = \gzread($archiveFile, 4096)) { \fwrite($targetFile, $string, Platform::strlen($string)); } \gzclose($archiveFile); \fclose($targetFile); } } * 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\Advisory\Auditor; use Composer\Config\ConfigSourceInterface; use Composer\Downloader\TransportException; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; /** * @author Jordi Boggiano */ class Config { public const SOURCE_DEFAULT = 'default'; public const SOURCE_COMMAND = 'command'; public const SOURCE_UNKNOWN = 'unknown'; public const RELATIVE_PATHS = 1; /** @var array */ public static $defaultConfig = [ 'process-timeout' => 300, 'use-include-path' => \false, 'allow-plugins' => [], 'use-parent-dir' => 'prompt', 'preferred-install' => 'dist', 'audit' => ['ignore' => [], 'abandoned' => Auditor::ABANDONED_FAIL], 'notify-on-install' => \true, 'github-protocols' => ['https', 'ssh', 'git'], 'gitlab-protocol' => null, 'vendor-dir' => 'vendor', 'bin-dir' => '{$vendor-dir}/bin', 'cache-dir' => '{$home}/cache', 'data-dir' => '{$home}', 'cache-files-dir' => '{$cache-dir}/files', 'cache-repo-dir' => '{$cache-dir}/repo', 'cache-vcs-dir' => '{$cache-dir}/vcs', 'cache-ttl' => 15552000, // 6 months 'cache-files-ttl' => null, // fallback to cache-ttl 'cache-files-maxsize' => '300MiB', 'cache-read-only' => \false, 'bin-compat' => 'auto', 'discard-changes' => \false, 'autoloader-suffix' => null, 'sort-packages' => \false, 'optimize-autoloader' => \false, 'classmap-authoritative' => \false, 'apcu-autoloader' => \false, 'prepend-autoloader' => \true, 'github-domains' => ['github.com'], 'bitbucket-expose-hostname' => \true, 'disable-tls' => \false, 'secure-http' => \true, 'secure-svn-domains' => [], 'cafile' => null, 'capath' => null, 'github-expose-hostname' => \true, 'gitlab-domains' => ['gitlab.com'], 'store-auths' => 'prompt', 'platform' => [], 'archive-format' => 'tar', 'archive-dir' => '.', 'htaccess-protect' => \true, 'use-github-api' => \true, 'lock' => \true, 'platform-check' => 'php-only', 'bitbucket-oauth' => [], 'github-oauth' => [], 'gitlab-oauth' => [], 'gitlab-token' => [], 'http-basic' => [], 'bearer' => [], 'bump-after-update' => \false, 'allow-missing-requirements' => \false, ]; /** @var array */ public static $defaultRepositories = ['packagist.org' => ['type' => 'composer', 'url' => 'https://repo.packagist.org']]; /** @var array */ private $config; /** @var ?non-empty-string */ private $baseDir; /** @var array */ private $repositories; /** @var ConfigSourceInterface */ private $configSource; /** @var ConfigSourceInterface */ private $authConfigSource; /** @var ConfigSourceInterface|null */ private $localAuthConfigSource = null; /** @var bool */ private $useEnvironment; /** @var array */ private $warnedHosts = []; /** @var array */ private $sslVerifyWarnedHosts = []; /** @var array */ private $sourceOfConfigValue = []; /** * @param bool $useEnvironment Use COMPOSER_ environment variables to replace config settings * @param ?string $baseDir Optional base directory of the config */ public function __construct(bool $useEnvironment = \true, ?string $baseDir = null) { // load defaults $this->config = static::$defaultConfig; $this->repositories = static::$defaultRepositories; $this->useEnvironment = $useEnvironment; $this->baseDir = \is_string($baseDir) && '' !== $baseDir ? $baseDir : null; foreach ($this->config as $configKey => $configValue) { $this->setSourceOfConfigValue($configValue, $configKey, self::SOURCE_DEFAULT); } foreach ($this->repositories as $configKey => $configValue) { $this->setSourceOfConfigValue($configValue, 'repositories.' . $configKey, self::SOURCE_DEFAULT); } } /** * Changing this can break path resolution for relative config paths so do not call this without knowing what you are doing * * The $baseDir should be an absolute path and without trailing slash * * @param non-empty-string|null $baseDir */ public function setBaseDir(?string $baseDir) : void { $this->baseDir = $baseDir; } public function setConfigSource(ConfigSourceInterface $source) : void { $this->configSource = $source; } public function getConfigSource() : ConfigSourceInterface { return $this->configSource; } public function setAuthConfigSource(ConfigSourceInterface $source) : void { $this->authConfigSource = $source; } public function getAuthConfigSource() : ConfigSourceInterface { return $this->authConfigSource; } public function setLocalAuthConfigSource(ConfigSourceInterface $source) : void { $this->localAuthConfigSource = $source; } public function getLocalAuthConfigSource() : ?ConfigSourceInterface { return $this->localAuthConfigSource; } /** * Merges new config values with the existing ones (overriding) * * @param array{config?: array, repositories?: array} $config */ public function merge(array $config, string $source = self::SOURCE_UNKNOWN) : void { // override defaults with given config if (!empty($config['config']) && \is_array($config['config'])) { foreach ($config['config'] as $key => $val) { if (\in_array($key, ['bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic', 'bearer'], \true) && isset($this->config[$key])) { $this->config[$key] = \array_merge($this->config[$key], $val); $this->setSourceOfConfigValue($val, $key, $source); } elseif (\in_array($key, ['allow-plugins'], \true) && isset($this->config[$key]) && \is_array($this->config[$key]) && \is_array($val)) { // merging $val first to get the local config on top of the global one, then appending the global config, // then merging local one again to make sure the values from local win over global ones for keys present in both $this->config[$key] = \array_merge($val, $this->config[$key], $val); $this->setSourceOfConfigValue($val, $key, $source); } elseif (\in_array($key, ['gitlab-domains', 'github-domains'], \true) && isset($this->config[$key])) { $this->config[$key] = \array_unique(\array_merge($this->config[$key], $val)); $this->setSourceOfConfigValue($val, $key, $source); } elseif ('preferred-install' === $key && isset($this->config[$key])) { if (\is_array($val) || \is_array($this->config[$key])) { if (\is_string($val)) { $val = ['*' => $val]; } if (\is_string($this->config[$key])) { $this->config[$key] = ['*' => $this->config[$key]]; $this->sourceOfConfigValue[$key . '*'] = $source; } $this->config[$key] = \array_merge($this->config[$key], $val); $this->setSourceOfConfigValue($val, $key, $source); // the full match pattern needs to be last if (isset($this->config[$key]['*'])) { $wildcard = $this->config[$key]['*']; unset($this->config[$key]['*']); $this->config[$key]['*'] = $wildcard; } } else { $this->config[$key] = $val; $this->setSourceOfConfigValue($val, $key, $source); } } elseif ('audit' === $key) { $currentIgnores = $this->config['audit']['ignore']; $this->config[$key] = \array_merge($this->config['audit'], $val); $this->setSourceOfConfigValue($val, $key, $source); $this->config['audit']['ignore'] = \array_merge($currentIgnores, $val['ignore'] ?? []); } else { $this->config[$key] = $val; $this->setSourceOfConfigValue($val, $key, $source); } } } if (!empty($config['repositories']) && \is_array($config['repositories'])) { $this->repositories = \array_reverse($this->repositories, \true); $newRepos = \array_reverse($config['repositories'], \true); foreach ($newRepos as $name => $repository) { // disable a repository by name if (\false === $repository) { $this->disableRepoByName((string) $name); continue; } // disable a repository with an anonymous {"name": false} repo if (\is_array($repository) && 1 === \count($repository) && \false === \current($repository)) { $this->disableRepoByName((string) \key($repository)); continue; } // auto-deactivate the default packagist.org repo if it gets redefined if (isset($repository['type'], $repository['url']) && $repository['type'] === 'composer' && Preg::isMatch('{^https?://(?:[a-z0-9-.]+\\.)?packagist.org(/|$)}', $repository['url'])) { $this->disableRepoByName('packagist.org'); } // store repo if (\is_int($name)) { $this->repositories[] = $repository; $this->setSourceOfConfigValue($repository, 'repositories.' . \array_search($repository, $this->repositories, \true), $source); } else { if ($name === 'packagist') { // BC support for default "packagist" named repo $this->repositories[$name . '.org'] = $repository; $this->setSourceOfConfigValue($repository, 'repositories.' . $name . '.org', $source); } else { $this->repositories[$name] = $repository; $this->setSourceOfConfigValue($repository, 'repositories.' . $name, $source); } } } $this->repositories = \array_reverse($this->repositories, \true); } } /** * @return array */ public function getRepositories() : array { return $this->repositories; } /** * Returns a setting * * @param int $flags Options (see class constants) * @throws \RuntimeException * * @return mixed */ public function get(string $key, int $flags = 0) { switch ($key) { // strings/paths with env var and {$refs} support case 'vendor-dir': case 'bin-dir': case 'process-timeout': case 'data-dir': case 'cache-dir': case 'cache-files-dir': case 'cache-repo-dir': case 'cache-vcs-dir': case 'cafile': case 'capath': // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config $env = 'COMPOSER_' . \strtoupper(\strtr($key, '-', '_')); $val = $this->getComposerEnv($env); if ($val !== \false) { $this->setSourceOfConfigValue($val, $key, $env); } if ($key === 'process-timeout') { return \max(0, \false !== $val ? (int) $val : $this->config[$key]); } $val = \rtrim((string) $this->process(\false !== $val ? $val : $this->config[$key], $flags), '/\\'); $val = Platform::expandPath($val); if (\substr($key, -4) !== '-dir') { return $val; } return ($flags & self::RELATIVE_PATHS) === self::RELATIVE_PATHS ? $val : $this->realpath($val); // booleans with env var support case 'cache-read-only': case 'htaccess-protect': // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config $env = 'COMPOSER_' . \strtoupper(\strtr($key, '-', '_')); $val = $this->getComposerEnv($env); if (\false === $val) { $val = $this->config[$key]; } else { $this->setSourceOfConfigValue($val, $key, $env); } return $val !== 'false' && (bool) $val; // booleans without env var support case 'disable-tls': case 'secure-http': case 'use-github-api': case 'lock': // special case for secure-http if ($key === 'secure-http' && $this->get('disable-tls') === \true) { return \false; } return $this->config[$key] !== 'false' && (bool) $this->config[$key]; // ints without env var support case 'cache-ttl': return \max(0, (int) $this->config[$key]); // numbers with kb/mb/gb support, without env var support case 'cache-files-maxsize': if (!Preg::isMatch('/^\\s*([0-9.]+)\\s*(?:([kmg])(?:i?b)?)?\\s*$/i', (string) $this->config[$key], $matches)) { throw new \RuntimeException("Could not parse the value of '{$key}': {$this->config[$key]}"); } $size = (float) $matches[1]; if (isset($matches[2])) { switch (\strtolower($matches[2])) { case 'g': $size *= 1024; // intentional fallthrough // no break case 'm': $size *= 1024; // intentional fallthrough // no break case 'k': $size *= 1024; break; } } return \max(0, (int) $size); // special cases below case 'cache-files-ttl': if (isset($this->config[$key])) { return \max(0, (int) $this->config[$key]); } return $this->get('cache-ttl'); case 'home': return \rtrim($this->process(Platform::expandPath($this->config[$key]), $flags), '/\\'); case 'bin-compat': $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key]; if (!\in_array($value, ['auto', 'full', 'proxy', 'symlink'])) { throw new \RuntimeException("Invalid value for 'bin-compat': {$value}. Expected auto, full or proxy"); } if ($value === 'symlink') { \trigger_error('config.bin-compat "symlink" is deprecated since Composer 2.2, use auto, full (for Windows compatibility) or proxy instead.', \E_USER_DEPRECATED); } return $value; case 'discard-changes': $env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES'); if ($env !== \false) { if (!\in_array($env, ['stash', 'true', 'false', '1', '0'], \true)) { throw new \RuntimeException("Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"); } if ('stash' === $env) { return 'stash'; } // convert string value to bool return $env !== 'false' && (bool) $env; } if (!\in_array($this->config[$key], [\true, \false, 'stash'], \true)) { throw new \RuntimeException("Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"); } return $this->config[$key]; case 'github-protocols': $protos = $this->config['github-protocols']; if ($this->config['secure-http'] && \false !== ($index = \array_search('git', $protos))) { unset($protos[$index]); } if (\reset($protos) === 'http') { throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"'); } return $protos; case 'autoloader-suffix': if ($this->config[$key] === '') { // we need to guarantee null or non-empty-string return null; } return $this->process($this->config[$key], $flags); case 'audit': $result = $this->config[$key]; $abandonedEnv = $this->getComposerEnv('COMPOSER_AUDIT_ABANDONED'); if (\false !== $abandonedEnv) { if (!\in_array($abandonedEnv, $validChoices = Auditor::ABANDONEDS, \true)) { throw new \RuntimeException("Invalid value for COMPOSER_AUDIT_ABANDONED: {$abandonedEnv}. Expected one of " . \implode(', ', Auditor::ABANDONEDS) . "."); } $result['abandoned'] = $abandonedEnv; } return $result; default: if (!isset($this->config[$key])) { return null; } return $this->process($this->config[$key], $flags); } } /** * @return array */ public function all(int $flags = 0) : array { $all = ['repositories' => $this->getRepositories()]; foreach (\array_keys($this->config) as $key) { $all['config'][$key] = $this->get($key, $flags); } return $all; } public function getSourceOfValue(string $key) : string { $this->get($key); return $this->sourceOfConfigValue[$key] ?? self::SOURCE_UNKNOWN; } /** * @param mixed $configValue */ private function setSourceOfConfigValue($configValue, string $path, string $source) : void { $this->sourceOfConfigValue[$path] = $source; if (\is_array($configValue)) { foreach ($configValue as $key => $value) { $this->setSourceOfConfigValue($value, $path . '.' . $key, $source); } } } /** * @return array */ public function raw() : array { return ['repositories' => $this->getRepositories(), 'config' => $this->config]; } /** * Checks whether a setting exists */ public function has(string $key) : bool { return \array_key_exists($key, $this->config); } /** * Replaces {$refs} inside a config string * * @param string|mixed $value a config string that can contain {$refs-to-other-config} * @param int $flags Options (see class constants) * * @return string|mixed */ private function process($value, int $flags) { if (!\is_string($value)) { return $value; } return Preg::replaceCallback('#\\{\\$(.+)\\}#', function ($match) use($flags) { return $this->get($match[1], $flags); }, $value); } /** * Turns relative paths in absolute paths without realpath() * * Since the dirs might not exist yet we can not call realpath or it will fail. */ private function realpath(string $path) : string { if (Preg::isMatch('{^(?:/|[a-z]:|[a-z0-9.]+://|\\\\\\\\)}i', $path)) { return $path; } return $this->baseDir !== null ? $this->baseDir . '/' . $path : $path; } /** * Reads the value of a Composer environment variable * * This should be used to read COMPOSER_ environment variables * that overload config values. * * @param non-empty-string $var * * @return string|false */ private function getComposerEnv(string $var) { if ($this->useEnvironment) { return Platform::getEnv($var); } return \false; } private function disableRepoByName(string $name) : void { if (isset($this->repositories[$name])) { unset($this->repositories[$name]); } elseif ($name === 'packagist') { // BC support for default "packagist" named repo unset($this->repositories['packagist.org']); } } /** * Validates that the passed URL is allowed to be used by current config, or throws an exception. * * @param IOInterface $io * @param mixed[] $repoOptions */ public function prohibitUrlByConfig(string $url, ?IOInterface $io = null, array $repoOptions = []) : void { // Return right away if the URL is malformed or custom (see issue #5173), but only for non-HTTP(S) URLs if (\false === \filter_var($url, \FILTER_VALIDATE_URL) && !Preg::isMatch('{^https?://}', $url)) { return; } // Extract scheme and throw exception on known insecure protocols $scheme = \parse_url($url, \PHP_URL_SCHEME); $hostname = \parse_url($url, \PHP_URL_HOST); if (\in_array($scheme, ['http', 'git', 'ftp', 'svn'])) { if ($this->get('secure-http')) { if ($scheme === 'svn') { if (\in_array($hostname, $this->get('secure-svn-domains'), \true)) { return; } throw new TransportException("Your configuration does not allow connections to {$url}. See https://getcomposer.org/doc/06-config.md#secure-svn-domains for details."); } throw new TransportException("Your configuration does not allow connections to {$url}. See https://getcomposer.org/doc/06-config.md#secure-http for details."); } if ($io !== null) { if (\is_string($hostname)) { if (!isset($this->warnedHosts[$hostname])) { $io->writeError("Warning: Accessing {$hostname} over {$scheme} which is an insecure protocol."); } $this->warnedHosts[$hostname] = \true; } } } if ($io !== null && \is_string($hostname) && !isset($this->sslVerifyWarnedHosts[$hostname])) { $warning = null; if (isset($repoOptions['ssl']['verify_peer']) && !(bool) $repoOptions['ssl']['verify_peer']) { $warning = 'verify_peer'; } if (isset($repoOptions['ssl']['verify_peer_name']) && !(bool) $repoOptions['ssl']['verify_peer_name']) { $warning = $warning === null ? 'verify_peer_name' : $warning . ' and verify_peer_name'; } if ($warning !== null) { $io->writeError("Warning: Accessing {$hostname} with {$warning} disabled."); $this->sslVerifyWarnedHosts[$hostname] = \true; } } } /** * Used by long-running custom scripts in composer.json * * "scripts": { * "watch": [ * "Composer\\Config::disableProcessTimeout", * "vendor/bin/long-running-script --watch" * ] * } */ public static function disableProcessTimeout() : void { // Override global timeout set earlier by environment or config ProcessExecutor::setTimeout(0); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Script; use Composer\Composer; use Composer\IO\IOInterface; use Composer\EventDispatcher\Event as BaseEvent; /** * The script event class * * @author François Pluchino * @author Nils Adermann */ class Event extends BaseEvent { /** * @var Composer The composer instance */ private $composer; /** * @var IOInterface The IO instance */ private $io; /** * @var bool Dev mode flag */ private $devMode; /** * @var BaseEvent|null */ private $originatingEvent; /** * Constructor. * * @param string $name The event name * @param Composer $composer The composer object * @param IOInterface $io The IOInterface object * @param bool $devMode Whether or not we are in dev mode * @param array $args Arguments passed by the user * @param mixed[] $flags Optional flags to pass data not as argument */ public function __construct(string $name, Composer $composer, IOInterface $io, bool $devMode = \false, array $args = [], array $flags = []) { parent::__construct($name, $args, $flags); $this->composer = $composer; $this->io = $io; $this->devMode = $devMode; } /** * Returns the composer instance. */ public function getComposer() : Composer { return $this->composer; } /** * Returns the IO instance. */ public function getIO() : IOInterface { return $this->io; } /** * Return the dev mode flag */ public function isDevMode() : bool { return $this->devMode; } /** * Set the originating event. * * @return ?BaseEvent */ public function getOriginatingEvent() : ?BaseEvent { return $this->originatingEvent; } /** * Set the originating event. * * @return $this */ public function setOriginatingEvent(BaseEvent $event) : self { $this->originatingEvent = $this->calculateOriginatingEvent($event); return $this; } /** * Returns the upper-most event in chain. */ private function calculateOriginatingEvent(BaseEvent $event) : BaseEvent { if ($event instanceof \Composer\Script\Event && $event->getOriginatingEvent()) { return $this->calculateOriginatingEvent($event->getOriginatingEvent()); } return $event; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Script; /** * The Script Events. * * @author François Pluchino * @author Jordi Boggiano */ class ScriptEvents { /** * The PRE_INSTALL_CMD event occurs before the install command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const PRE_INSTALL_CMD = 'pre-install-cmd'; /** * The POST_INSTALL_CMD event occurs after the install command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const POST_INSTALL_CMD = 'post-install-cmd'; /** * The PRE_UPDATE_CMD event occurs before the update command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const PRE_UPDATE_CMD = 'pre-update-cmd'; /** * The POST_UPDATE_CMD event occurs after the update command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const POST_UPDATE_CMD = 'post-update-cmd'; /** * The PRE_STATUS_CMD event occurs before the status command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const PRE_STATUS_CMD = 'pre-status-cmd'; /** * The POST_STATUS_CMD event occurs after the status command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const POST_STATUS_CMD = 'post-status-cmd'; /** * The PRE_AUTOLOAD_DUMP event occurs before the autoload file is generated. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump'; /** * The POST_AUTOLOAD_DUMP event occurs after the autoload file has been generated. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const POST_AUTOLOAD_DUMP = 'post-autoload-dump'; /** * The POST_ROOT_PACKAGE_INSTALL event occurs after the root package has been installed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install'; /** * The POST_CREATE_PROJECT event occurs after the create-project command has been executed. * Note: Event occurs after POST_INSTALL_CMD * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd'; /** * The PRE_ARCHIVE_CMD event occurs before the update command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const PRE_ARCHIVE_CMD = 'pre-archive-cmd'; /** * The POST_ARCHIVE_CMD event occurs after the status command is executed. * * The event listener method receives a Composer\Script\Event instance. * * @var string */ public const POST_ARCHIVE_CMD = 'post-archive-cmd'; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Question; use Composer\Pcre\Preg; use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException; use _ContaoManager\Symfony\Component\Console\Question\Question; /** * Represents a yes/no question * Enforces strict responses rather than non-standard answers counting as default * Based on Symfony\Component\Console\Question\ConfirmationQuestion * * @author Theo Tonge */ class StrictConfirmationQuestion extends Question { /** @var non-empty-string */ private $trueAnswerRegex; /** @var non-empty-string */ private $falseAnswerRegex; /** * Constructor.s * * @param string $question The question to ask to the user * @param bool $default The default answer to return, true or false * @param non-empty-string $trueAnswerRegex A regex to match the "yes" answer * @param non-empty-string $falseAnswerRegex A regex to match the "no" answer */ public function __construct(string $question, bool $default = \true, string $trueAnswerRegex = '/^y(?:es)?$/i', string $falseAnswerRegex = '/^no?$/i') { parent::__construct($question, $default); $this->trueAnswerRegex = $trueAnswerRegex; $this->falseAnswerRegex = $falseAnswerRegex; $this->setNormalizer($this->getDefaultNormalizer()); $this->setValidator($this->getDefaultValidator()); } /** * Returns the default answer normalizer. */ private function getDefaultNormalizer() : callable { $default = $this->getDefault(); $trueRegex = $this->trueAnswerRegex; $falseRegex = $this->falseAnswerRegex; return static function ($answer) use($default, $trueRegex, $falseRegex) { if (\is_bool($answer)) { return $answer; } if (empty($answer) && !empty($default)) { return $default; } if (Preg::isMatch($trueRegex, $answer)) { return \true; } if (Preg::isMatch($falseRegex, $answer)) { return \false; } return null; }; } /** * Returns the default answer validator. */ private function getDefaultValidator() : callable { return static function ($answer) : bool { if (!\is_bool($answer)) { throw new InvalidArgumentException('Please answer yes, y, no, or n.'); } return $answer; }; } } * 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\Package\Locker; use Composer\Pcre\Preg; use Composer\Plugin\PluginManager; use Composer\Downloader\DownloadManager; use Composer\Autoload\AutoloadGenerator; use Composer\Package\Archiver\ArchiveManager; /** * @author Jordi Boggiano * @author Konstantin Kudryashiv * @author Nils Adermann */ class Composer extends \Composer\PartialComposer { /* * Examples of the following constants in the various configurations they can be in * * You are probably better off using Composer::getVersion() though as that will always return something usable * * releases (phar): * const VERSION = '1.8.2'; * const BRANCH_ALIAS_VERSION = ''; * const RELEASE_DATE = '2019-01-29 15:00:53'; * const SOURCE_VERSION = ''; * * snapshot builds (phar): * const VERSION = 'd3873a05650e168251067d9648845c220c50e2d7'; * const BRANCH_ALIAS_VERSION = '1.9-dev'; * const RELEASE_DATE = '2019-02-20 07:43:56'; * const SOURCE_VERSION = ''; * * source (git clone): * const VERSION = '@package_version@'; * const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@'; * const RELEASE_DATE = '@release_date@'; * const SOURCE_VERSION = '1.8-dev+source'; * * @see getVersion() */ public const VERSION = '2.8.5'; public const BRANCH_ALIAS_VERSION = ''; public const RELEASE_DATE = '2025-01-21 15:23:40'; public const SOURCE_VERSION = ''; /** * Version number of the internal composer-runtime-api package * * This is used to version features available to projects at runtime * like the platform-check file, the Composer\InstalledVersions class * and possibly others in the future. * * @var string */ public const RUNTIME_API_VERSION = '2.2.2'; public static function getVersion() : string { // no replacement done, this must be a source checkout if (self::VERSION === '@package_version' . '@') { return self::SOURCE_VERSION; } // we have a branch alias and version is a commit id, this must be a snapshot build if (self::BRANCH_ALIAS_VERSION !== '' && Preg::isMatch('{^[a-f0-9]{40}$}', self::VERSION)) { return self::BRANCH_ALIAS_VERSION . '+' . self::VERSION; } return self::VERSION; } /** * @var Locker */ private $locker; /** * @var Downloader\DownloadManager */ private $downloadManager; /** * @var Plugin\PluginManager */ private $pluginManager; /** * @var Autoload\AutoloadGenerator */ private $autoloadGenerator; /** * @var ArchiveManager */ private $archiveManager; public function setLocker(Locker $locker) : void { $this->locker = $locker; } public function getLocker() : Locker { return $this->locker; } public function setDownloadManager(DownloadManager $manager) : void { $this->downloadManager = $manager; } public function getDownloadManager() : DownloadManager { return $this->downloadManager; } public function setArchiveManager(ArchiveManager $manager) : void { $this->archiveManager = $manager; } public function getArchiveManager() : ArchiveManager { return $this->archiveManager; } public function setPluginManager(PluginManager $manager) : void { $this->pluginManager = $manager; } public function getPluginManager() : PluginManager { return $this->pluginManager; } public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator) : void { $this->autoloadGenerator = $autoloadGenerator; } public function getAutoloadGenerator() : AutoloadGenerator { return $this->autoloadGenerator; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Json; use Exception; /** * @author Jordi Boggiano */ class JsonValidationException extends Exception { /** * @var string[] */ protected $errors; /** * @param string[] $errors */ public function __construct(string $message, array $errors = [], ?Exception $previous = null) { $this->errors = $errors; parent::__construct((string) $message, 0, $previous); } /** * @return string[] */ public function getErrors() : array { return $this->errors; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Json; use Composer\Pcre\Preg; /** * Formats json strings used for php < 5.4 because the json_encode doesn't * supports the flags JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE * in these versions * * @author Konstantin Kudryashiv * @author Jordi Boggiano * * @deprecated Use json_encode or JsonFile::encode() with modern JSON_* flags to configure formatting - this class will be removed in 3.0 */ class JsonFormatter { /** * This code is based on the function found at: * http://recursive-design.com/blog/2008/03/11/format-json-with-php/ * * Originally licensed under MIT by Dave Perrett * * @param bool $unescapeUnicode Un escape unicode * @param bool $unescapeSlashes Un escape slashes */ public static function format(string $json, bool $unescapeUnicode, bool $unescapeSlashes) : string { $result = ''; $pos = 0; $strLen = \strlen($json); $indentStr = ' '; $newLine = "\n"; $outOfQuotes = \true; $buffer = ''; $noescape = \true; for ($i = 0; $i < $strLen; $i++) { // Grab the next character in the string $char = \substr($json, $i, 1); // Are we inside a quoted string? if ('"' === $char && $noescape) { $outOfQuotes = !$outOfQuotes; } if (!$outOfQuotes) { $buffer .= $char; $noescape = '\\' === $char ? !$noescape : \true; continue; } if ('' !== $buffer) { if ($unescapeSlashes) { $buffer = \str_replace('\\/', '/', $buffer); } if ($unescapeUnicode && \function_exists('mb_convert_encoding')) { // https://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha $buffer = Preg::replaceCallback('/(\\\\+)u([0-9a-f]{4})/i', static function ($match) : string { $l = \strlen($match[1]); if ($l % 2) { $code = \hexdec($match[2]); // 0xD800..0xDFFF denotes UTF-16 surrogate pair which won't be unescaped // see https://github.com/composer/composer/issues/7510 if (0xd800 <= $code && 0xdfff >= $code) { return $match[0]; } return \str_repeat('\\', $l - 1) . \mb_convert_encoding(\pack('H*', $match[2]), 'UTF-8', 'UCS-2BE'); } return $match[0]; }, $buffer); } $result .= $buffer . $char; $buffer = ''; continue; } if (':' === $char) { // Add a space after the : character $char .= ' '; } elseif ('}' === $char || ']' === $char) { $pos--; $prevChar = \substr($json, $i - 1, 1); if ('{' !== $prevChar && '[' !== $prevChar) { // If this character is the end of an element, // output a new line and indent the next line $result .= $newLine; $result .= \str_repeat($indentStr, $pos); } else { // Collapse empty {} and [] $result = \rtrim($result); } } $result .= $char; // If the last character was the beginning of an element, // output a new line and indent the next line if (',' === $char || '{' === $char || '[' === $char) { $result .= $newLine; if ('{' === $char || '[' === $char) { $pos++; } $result .= \str_repeat($indentStr, $pos); } } return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Json; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use _ContaoManager\JsonSchema\Validator; use _ContaoManager\Seld\JsonLint\JsonParser; use _ContaoManager\Seld\JsonLint\ParsingException; use Composer\Util\HttpDownloader; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; /** * Reads/writes json files. * * @author Konstantin Kudryashiv * @author Jordi Boggiano */ class JsonFile { public const LAX_SCHEMA = 1; public const STRICT_SCHEMA = 2; public const AUTH_SCHEMA = 3; public const LOCK_SCHEMA = 4; /** @deprecated Use \JSON_UNESCAPED_SLASHES */ public const JSON_UNESCAPED_SLASHES = 64; /** @deprecated Use \JSON_PRETTY_PRINT */ public const JSON_PRETTY_PRINT = 128; /** @deprecated Use \JSON_UNESCAPED_UNICODE */ public const JSON_UNESCAPED_UNICODE = 256; public const COMPOSER_SCHEMA_PATH = __DIR__ . '/../../../res/composer-schema.json'; public const LOCK_SCHEMA_PATH = __DIR__ . '/../../../res/composer-lock-schema.json'; public const INDENT_DEFAULT = ' '; /** @var string */ private $path; /** @var ?HttpDownloader */ private $httpDownloader; /** @var ?IOInterface */ private $io; /** @var string */ private $indent = self::INDENT_DEFAULT; /** * Initializes json file reader/parser. * * @param string $path path to a lockfile * @param ?HttpDownloader $httpDownloader required for loading http/https json files * @param ?IOInterface $io * @throws \InvalidArgumentException */ public function __construct(string $path, ?HttpDownloader $httpDownloader = null, ?IOInterface $io = null) { $this->path = $path; if (null === $httpDownloader && Preg::isMatch('{^https?://}i', $path)) { throw new \InvalidArgumentException('http urls require a HttpDownloader instance to be passed'); } $this->httpDownloader = $httpDownloader; $this->io = $io; } public function getPath() : string { return $this->path; } /** * Checks whether json file exists. */ public function exists() : bool { return \is_file($this->path); } /** * Reads json file. * * @throws ParsingException * @throws \RuntimeException * @return mixed */ public function read() { try { if ($this->httpDownloader) { $json = $this->httpDownloader->get($this->path)->getBody(); } else { if (!Filesystem::isReadable($this->path)) { throw new \RuntimeException('The file "' . $this->path . '" is not readable.'); } if ($this->io && $this->io->isDebug()) { $realpathInfo = ''; $realpath = \realpath($this->path); if (\false !== $realpath && $realpath !== $this->path) { $realpathInfo = ' (' . $realpath . ')'; } $this->io->writeError('Reading ' . $this->path . $realpathInfo); } $json = \file_get_contents($this->path); } } catch (TransportException $e) { throw new \RuntimeException($e->getMessage(), 0, $e); } catch (\Exception $e) { throw new \RuntimeException('Could not read ' . $this->path . "\n\n" . $e->getMessage()); } if ($json === \false) { throw new \RuntimeException('Could not read ' . $this->path); } $this->indent = self::detectIndenting($json); return static::parseJson($json, $this->path); } /** * Writes json file. * * @param mixed[] $hash writes hash into json file * @param int $options json_encode options * @throws \UnexpectedValueException|\Exception * @return void */ public function write(array $hash, int $options = \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE) { if ($this->path === 'php://memory') { \file_put_contents($this->path, static::encode($hash, $options, $this->indent)); return; } $dir = \dirname($this->path); if (!\is_dir($dir)) { if (\file_exists($dir)) { throw new \UnexpectedValueException(\realpath($dir) . ' exists and is not a directory.'); } if (!@\mkdir($dir, 0777, \true)) { throw new \UnexpectedValueException($dir . ' does not exist and could not be created.'); } } $retries = 3; while ($retries--) { try { $this->filePutContentsIfModified($this->path, static::encode($hash, $options, $this->indent) . ($options & \JSON_PRETTY_PRINT ? "\n" : '')); break; } catch (\Exception $e) { if ($retries > 0) { \usleep(500000); continue; } throw $e; } } } /** * Modify file properties only if content modified * * @return int|false */ private function filePutContentsIfModified(string $path, string $content) { $currentContent = @\file_get_contents($path); if (\false === $currentContent || $currentContent !== $content) { return \file_put_contents($path, $content); } return 0; } /** * Validates the schema of the current json file according to composer-schema.json rules * * @param int $schema a JsonFile::*_SCHEMA constant * @param string|null $schemaFile a path to the schema file * @throws JsonValidationException * @throws ParsingException * @return true true on success * * @phpstan-param self::*_SCHEMA $schema */ public function validateSchema(int $schema = self::STRICT_SCHEMA, ?string $schemaFile = null) : bool { if (!Filesystem::isReadable($this->path)) { throw new \RuntimeException('The file "' . $this->path . '" is not readable.'); } $content = \file_get_contents($this->path); $data = \json_decode($content); if (null === $data && 'null' !== $content) { self::validateSyntax($content, $this->path); } return self::validateJsonSchema($this->path, $data, $schema, $schemaFile); } /** * Validates the schema of the current json file according to composer-schema.json rules * * @param mixed $data Decoded JSON data to validate * @param int $schema a JsonFile::*_SCHEMA constant * @param string|null $schemaFile a path to the schema file * @throws JsonValidationException * @return true true on success * * @phpstan-param self::*_SCHEMA $schema */ public static function validateJsonSchema(string $source, $data, int $schema, ?string $schemaFile = null) : bool { $isComposerSchemaFile = \false; if (null === $schemaFile) { if ($schema === self::LOCK_SCHEMA) { $schemaFile = self::LOCK_SCHEMA_PATH; } else { $isComposerSchemaFile = \true; $schemaFile = self::COMPOSER_SCHEMA_PATH; } } // Prepend with file:// only when not using a special schema already (e.g. in the phar) if (\false === \strpos($schemaFile, '://')) { $schemaFile = 'file://' . $schemaFile; } $schemaData = (object) ['$ref' => $schemaFile]; if ($schema === self::LAX_SCHEMA) { $schemaData->additionalProperties = \true; $schemaData->required = []; } elseif ($schema === self::STRICT_SCHEMA && $isComposerSchemaFile) { $schemaData->additionalProperties = \false; $schemaData->required = ['name', 'description']; } elseif ($schema === self::AUTH_SCHEMA && $isComposerSchemaFile) { $schemaData = (object) ['$ref' => $schemaFile . '#/properties/config', '$schema' => "https://json-schema.org/draft-04/schema#"]; } $validator = new Validator(); $validator->check($data, $schemaData); if (!$validator->isValid()) { $errors = []; foreach ((array) $validator->getErrors() as $error) { $errors[] = ($error['property'] ? $error['property'] . ' : ' : '') . $error['message']; } throw new \Composer\Json\JsonValidationException('"' . $source . '" does not match the expected JSON schema', $errors); } return \true; } /** * Encodes an array into (optionally pretty-printed) JSON * * @param mixed $data Data to encode into a formatted JSON string * @param int $options json_encode options (defaults to JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) * @param string $indent Indentation string * @return string Encoded json */ public static function encode($data, int $options = 448, string $indent = self::INDENT_DEFAULT) : string { $json = \json_encode($data, $options); if (\false === $json) { self::throwEncodeError(\json_last_error()); } if (($options & \JSON_PRETTY_PRINT) > 0 && $indent !== self::INDENT_DEFAULT) { // Pretty printing and not using default indentation return Preg::replaceCallback('#^ {4,}#m', static function ($match) use($indent) : string { return \str_repeat($indent, (int) (\strlen($match[0]) / 4)); }, $json); } return $json; } /** * Throws an exception according to a given code with a customized message * * @param int $code return code of json_last_error function * @throws \RuntimeException * @return never */ private static function throwEncodeError(int $code) : void { switch ($code) { case \JSON_ERROR_DEPTH: $msg = 'Maximum stack depth exceeded'; break; case \JSON_ERROR_STATE_MISMATCH: $msg = 'Underflow or the modes mismatch'; break; case \JSON_ERROR_CTRL_CHAR: $msg = 'Unexpected control character found'; break; case \JSON_ERROR_UTF8: $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; break; default: $msg = 'Unknown error'; } throw new \RuntimeException('JSON encoding failed: ' . $msg); } /** * Parses json string and returns hash. * * @param null|string $json json string * @param string $file the json file * * @throws ParsingException * @return mixed */ public static function parseJson(?string $json, ?string $file = null) { if (null === $json) { return null; } $data = \json_decode($json, \true); if (null === $data && \JSON_ERROR_NONE !== \json_last_error()) { self::validateSyntax($json, $file); } return $data; } /** * Validates the syntax of a JSON string * * @param string $file * @throws \UnexpectedValueException * @throws ParsingException * @return bool true on success */ protected static function validateSyntax(string $json, ?string $file = null) : bool { $parser = new JsonParser(); $result = $parser->lint($json); if (null === $result) { if (\defined('JSON_ERROR_UTF8') && \JSON_ERROR_UTF8 === \json_last_error()) { if ($file === null) { throw new \UnexpectedValueException('The input is not UTF-8, could not parse as JSON'); } else { throw new \UnexpectedValueException('"' . $file . '" is not UTF-8, could not parse as JSON'); } } return \true; } if ($file === null) { throw new ParsingException('The input does not contain valid JSON' . "\n" . $result->getMessage(), $result->getDetails()); } else { throw new ParsingException('"' . $file . '" does not contain valid JSON' . "\n" . $result->getMessage(), $result->getDetails()); } } public static function detectIndenting(?string $json) : string { if (Preg::isMatchStrictGroups('#^([ \\t]+)"#m', $json ?? '', $match)) { return $match[1]; } return self::INDENT_DEFAULT; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Json; use Composer\Pcre\Preg; use Composer\Repository\PlatformRepository; /** * @author Jordi Boggiano */ class JsonManipulator { /** @var string */ private const DEFINES = '(?(DEFINE) (? -? (?= [1-9]|0(?!\\d) ) \\d++ (?:\\.\\d++)? (?:[eE] [+-]?+ \\d++)? ) (? true | false | null ) (? " (?:[^"\\\\]*+ | \\\\ ["\\\\bfnrt\\/] | \\\\ u [0-9A-Fa-f]{4} )* " ) (? \\[ (?: (?&json) \\s*+ (?: , (?&json) \\s*+ )*+ )?+ \\s*+ \\] ) (? \\s*+ (?&string) \\s*+ : (?&json) \\s*+ ) (? \\{ (?: (?&pair) (?: , (?&pair) )*+ )?+ \\s*+ \\} ) (? \\s*+ (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) ) )'; /** @var string */ private $contents; /** @var string */ private $newline; /** @var string */ private $indent; public function __construct(string $contents) { $contents = \trim($contents); if ($contents === '') { $contents = '{}'; } if (!Preg::isMatch('#^\\{(.*)\\}$#s', $contents)) { throw new \InvalidArgumentException('The json file must be an object ({})'); } $this->newline = \false !== \strpos($contents, "\r\n") ? "\r\n" : "\n"; $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents; $this->detectIndenting(); } public function getContents() : string { return $this->contents . $this->newline; } public function addLink(string $type, string $package, string $constraint, bool $sortPackages = \false) : bool { $decoded = \Composer\Json\JsonFile::parseJson($this->contents); // no link of that type yet if (!isset($decoded[$type])) { return $this->addMainKey($type, [$package => $constraint]); } $regex = '{' . self::DEFINES . '^(?P\\s*\\{\\s*(?:(?&string)\\s*:\\s*(?&json)\\s*,\\s*)*?)' . '(?P' . \preg_quote(\Composer\Json\JsonFile::encode($type)) . '\\s*:\\s*)(?P(?&json))(?P.*)}sx'; if (!Preg::isMatch($regex, $this->contents, $matches)) { return \false; } \assert(\is_string($matches['start'])); \assert(\is_string($matches['value'])); \assert(\is_string($matches['end'])); $links = $matches['value']; // try to find existing link $packageRegex = \str_replace('/', '\\\\?/', \preg_quote($package)); $regex = '{' . self::DEFINES . '"(?P' . $packageRegex . ')"(\\s*:\\s*)(?&string)}ix'; if (Preg::isMatch($regex, $links, $packageMatches)) { \assert(\is_string($packageMatches['package'])); // update existing link $existingPackage = $packageMatches['package']; $packageRegex = \str_replace('/', '\\\\?/', \preg_quote($existingPackage)); $links = Preg::replaceCallback('{' . self::DEFINES . '"' . $packageRegex . '"(?P\\s*:\\s*)(?&string)}ix', static function ($m) use($existingPackage, $constraint) : string { return \Composer\Json\JsonFile::encode(\str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"'; }, $links); } else { if (Preg::isMatchStrictGroups('#^\\s*\\{\\s*\\S+.*?(\\s*\\}\\s*)$#s', $links, $match)) { // link missing but non empty links $links = Preg::replace( '{' . \preg_quote($match[1]) . '$}', // addcslashes is used to double up backslashes/$ since preg_replace resolves them as back references otherwise, see #1588 \addcslashes(',' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($package) . ': ' . \Composer\Json\JsonFile::encode($constraint) . $match[1], '\\$'), $links ); } else { // links empty $links = '{' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($package) . ': ' . \Composer\Json\JsonFile::encode($constraint) . $this->newline . $this->indent . '}'; } } if (\true === $sortPackages) { $requirements = \json_decode($links, \true); $this->sortPackages($requirements); $links = $this->format($requirements); } $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end']; return \true; } /** * Sorts packages by importance (platform packages first, then PHP dependencies) and alphabetically. * * @link https://getcomposer.org/doc/02-libraries.md#platform-packages * * @param array $packages */ private function sortPackages(array &$packages = []) : void { $prefix = static function ($requirement) : string { if (PlatformRepository::isPlatformPackage($requirement)) { return Preg::replace(['/^php/', '/^hhvm/', '/^ext/', '/^lib/', '/^\\D/'], ['0-$0', '1-$0', '2-$0', '3-$0', '4-$0'], $requirement); } return '5-' . $requirement; }; \uksort($packages, static function ($a, $b) use($prefix) : int { return \strnatcmp($prefix($a), $prefix($b)); }); } /** * @param array|false $config */ public function addRepository(string $name, $config, bool $append = \true) : bool { return $this->addSubNode('repositories', $name, $config, $append); } public function removeRepository(string $name) : bool { return $this->removeSubNode('repositories', $name); } /** * @param mixed $value */ public function addConfigSetting(string $name, $value) : bool { return $this->addSubNode('config', $name, $value); } public function removeConfigSetting(string $name) : bool { return $this->removeSubNode('config', $name); } /** * @param mixed $value */ public function addProperty(string $name, $value) : bool { if (\strpos($name, 'suggest.') === 0) { return $this->addSubNode('suggest', \substr($name, 8), $value); } if (\strpos($name, 'extra.') === 0) { return $this->addSubNode('extra', \substr($name, 6), $value); } if (\strpos($name, 'scripts.') === 0) { return $this->addSubNode('scripts', \substr($name, 8), $value); } return $this->addMainKey($name, $value); } public function removeProperty(string $name) : bool { if (\strpos($name, 'suggest.') === 0) { return $this->removeSubNode('suggest', \substr($name, 8)); } if (\strpos($name, 'extra.') === 0) { return $this->removeSubNode('extra', \substr($name, 6)); } if (\strpos($name, 'scripts.') === 0) { return $this->removeSubNode('scripts', \substr($name, 8)); } if (\strpos($name, 'autoload.') === 0) { return $this->removeSubNode('autoload', \substr($name, 9)); } if (\strpos($name, 'autoload-dev.') === 0) { return $this->removeSubNode('autoload-dev', \substr($name, 13)); } return $this->removeMainKey($name); } /** * @param mixed $value */ public function addSubNode(string $mainNode, string $name, $value, bool $append = \true) : bool { $decoded = \Composer\Json\JsonFile::parseJson($this->contents); $subName = null; if (\in_array($mainNode, ['config', 'extra', 'scripts']) && \false !== \strpos($name, '.')) { [$name, $subName] = \explode('.', $name, 2); } // no main node yet if (!isset($decoded[$mainNode])) { if ($subName !== null) { $this->addMainKey($mainNode, [$name => [$subName => $value]]); } else { $this->addMainKey($mainNode, [$name => $value]); } return \true; } // main node content not match-able $nodeRegex = '{' . self::DEFINES . '^(?P \\s* \\{ \\s* (?: (?&string) \\s* : (?&json) \\s* , \\s* )*?' . \preg_quote(\Composer\Json\JsonFile::encode($mainNode)) . '\\s*:\\s*)(?P(?&object))(?P.*)}sx'; try { if (!Preg::isMatch($nodeRegex, $this->contents, $match)) { return \false; } } catch (\RuntimeException $e) { if ($e->getCode() === \PREG_BACKTRACK_LIMIT_ERROR) { return \false; } throw $e; } \assert(\is_string($match['start'])); \assert(\is_string($match['content'])); \assert(\is_string($match['end'])); $children = $match['content']; // invalid match due to un-regexable content, abort if (!@\json_decode($children)) { return \false; } // child exists $childRegex = '{' . self::DEFINES . '(?P"' . \preg_quote($name) . '"\\s*:\\s*)(?P(?&json))(?P,?)}x'; if (Preg::isMatch($childRegex, $children, $matches)) { $children = Preg::replaceCallback($childRegex, function ($matches) use($subName, $value) : string { if ($subName !== null && \is_string($matches['content'])) { $curVal = \json_decode($matches['content'], \true); if (!\is_array($curVal)) { $curVal = []; } $curVal[$subName] = $value; $value = $curVal; } return $matches['start'] . $this->format($value, 1) . $matches['end']; }, $children); } else { Preg::match('#^{ (?P\\s*?) (?P\\S+.*?)? (?P\\s*) }$#sx', $children, $match); $whitespace = ''; if (!empty($match['trailingspace'])) { $whitespace = $match['trailingspace']; } if (!empty($match['content'])) { if ($subName !== null) { $value = [$subName => $value]; } // child missing but non empty children if ($append) { $children = Preg::replace('#' . $whitespace . '}$#', \addcslashes(',' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($name) . ': ' . $this->format($value, 1) . $whitespace . '}', '\\$'), $children); } else { $whitespace = ''; if (!empty($match['leadingspace'])) { $whitespace = $match['leadingspace']; } $children = Preg::replace('#^{' . $whitespace . '#', \addcslashes('{' . $whitespace . \Composer\Json\JsonFile::encode($name) . ': ' . $this->format($value, 1) . ',' . $this->newline . $this->indent . $this->indent, '\\$'), $children); } } else { if ($subName !== null) { $value = [$subName => $value]; } // children present but empty $children = '{' . $this->newline . $this->indent . $this->indent . \Composer\Json\JsonFile::encode($name) . ': ' . $this->format($value, 1) . $whitespace . '}'; } } $this->contents = Preg::replaceCallback($nodeRegex, static function ($m) use($children) : string { return $m['start'] . $children . $m['end']; }, $this->contents); return \true; } public function removeSubNode(string $mainNode, string $name) : bool { $decoded = \Composer\Json\JsonFile::parseJson($this->contents); // no node or empty node if (empty($decoded[$mainNode])) { return \true; } // no node content match-able $nodeRegex = '{' . self::DEFINES . '^(?P \\s* \\{ \\s* (?: (?&string) \\s* : (?&json) \\s* , \\s* )*?' . \preg_quote(\Composer\Json\JsonFile::encode($mainNode)) . '\\s*:\\s*)(?P(?&object))(?P.*)}sx'; try { if (!Preg::isMatch($nodeRegex, $this->contents, $match)) { return \false; } } catch (\RuntimeException $e) { if ($e->getCode() === \PREG_BACKTRACK_LIMIT_ERROR) { return \false; } throw $e; } \assert(\is_string($match['start'])); \assert(\is_string($match['content'])); \assert(\is_string($match['end'])); $children = $match['content']; // invalid match due to un-regexable content, abort if (!@\json_decode($children, \true)) { return \false; } $subName = null; if (\in_array($mainNode, ['config', 'extra', 'scripts']) && \false !== \strpos($name, '.')) { [$name, $subName] = \explode('.', $name, 2); } // no node to remove if (!isset($decoded[$mainNode][$name]) || $subName && !isset($decoded[$mainNode][$name][$subName])) { return \true; } // try and find a match for the subkey $keyRegex = \str_replace('/', '\\\\?/', \preg_quote($name)); if (Preg::isMatch('{"' . $keyRegex . '"\\s*:}i', $children)) { // find best match for the value of "name" if (Preg::isMatchAll('{' . self::DEFINES . '"' . $keyRegex . '"\\s*:\\s*(?:(?&json))}x', $children, $matches)) { $bestMatch = ''; foreach ($matches[0] as $match) { \assert(\is_string($match)); if (\strlen($bestMatch) < \strlen($match)) { $bestMatch = $match; } } $childrenClean = Preg::replace('{,\\s*' . \preg_quote($bestMatch) . '}i', '', $children, -1, $count); if (1 !== $count) { $childrenClean = Preg::replace('{' . \preg_quote($bestMatch) . '\\s*,?\\s*}i', '', $childrenClean, -1, $count); if (1 !== $count) { return \false; } } } } else { $childrenClean = $children; } if (!isset($childrenClean)) { throw new \InvalidArgumentException("JsonManipulator: \$childrenClean is not defined. Please report at https://github.com/composer/composer/issues/new."); } // no child data left, $name was the only key in unset($match); Preg::match('#^{ \\s*? (?P\\S+.*?)? (?P\\s*) }$#sx', $childrenClean, $match); if (empty($match['content'])) { $newline = $this->newline; $indent = $this->indent; $this->contents = Preg::replaceCallback($nodeRegex, static function ($matches) use($indent, $newline) : string { return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end']; }, $this->contents); // we have a subname, so we restore the rest of $name if ($subName !== null) { $curVal = \json_decode($children, \true); unset($curVal[$name][$subName]); if ($curVal[$name] === []) { $curVal[$name] = new \ArrayObject(); } $this->addSubNode($mainNode, $name, $curVal[$name]); } return \true; } $this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use($name, $subName, $childrenClean) : string { \assert(\is_string($matches['content'])); if ($subName !== null) { $curVal = \json_decode($matches['content'], \true); unset($curVal[$name][$subName]); if ($curVal[$name] === []) { $curVal[$name] = new \ArrayObject(); } $childrenClean = $this->format($curVal, 0, \true); } return $matches['start'] . $childrenClean . $matches['end']; }, $this->contents); return \true; } /** * @param mixed $content */ public function addMainKey(string $key, $content) : bool { $decoded = \Composer\Json\JsonFile::parseJson($this->contents); $content = $this->format($content); // key exists already $regex = '{' . self::DEFINES . '^(?P\\s*\\{\\s*(?:(?&string)\\s*:\\s*(?&json)\\s*,\\s*)*?)' . '(?P' . \preg_quote(\Composer\Json\JsonFile::encode($key)) . '\\s*:\\s*(?&json))(?P.*)}sx'; if (isset($decoded[$key]) && Preg::isMatch($regex, $this->contents, $matches)) { // invalid match due to un-regexable content, abort if (!@\json_decode('{' . $matches['key'] . '}')) { return \false; } $this->contents = $matches['start'] . \Composer\Json\JsonFile::encode($key) . ': ' . $content . $matches['end']; return \true; } // append at the end of the file and keep whitespace if (Preg::isMatch('#[^{\\s](\\s*)\\}$#', $this->contents, $match)) { $this->contents = Preg::replace('#' . $match[1] . '\\}$#', \addcslashes(',' . $this->newline . $this->indent . \Composer\Json\JsonFile::encode($key) . ': ' . $content . $this->newline . '}', '\\$'), $this->contents); return \true; } // append at the end of the file $this->contents = Preg::replace('#\\}$#', \addcslashes($this->indent . \Composer\Json\JsonFile::encode($key) . ': ' . $content . $this->newline . '}', '\\$'), $this->contents); return \true; } public function removeMainKey(string $key) : bool { $decoded = \Composer\Json\JsonFile::parseJson($this->contents); if (!\array_key_exists($key, $decoded)) { return \true; } // key exists already $regex = '{' . self::DEFINES . '^(?P\\s*\\{\\s*(?:(?&string)\\s*:\\s*(?&json)\\s*,\\s*)*?)' . '(?P' . \preg_quote(\Composer\Json\JsonFile::encode($key)) . '\\s*:\\s*(?&json))\\s*,?\\s*(?P.*)}sx'; if (Preg::isMatch($regex, $this->contents, $matches)) { \assert(\is_string($matches['start'])); \assert(\is_string($matches['removal'])); \assert(\is_string($matches['end'])); // invalid match due to un-regexable content, abort if (!@\json_decode('{' . $matches['removal'] . '}')) { return \false; } // check that we are not leaving a dangling comma on the previous line if the last line was removed if (Preg::isMatchStrictGroups('#,\\s*$#', $matches['start']) && Preg::isMatch('#^\\}$#', $matches['end'])) { $matches['start'] = \rtrim(Preg::replace('#,(\\s*)$#', '$1', $matches['start']), $this->indent); } $this->contents = $matches['start'] . $matches['end']; if (Preg::isMatch('#^\\{\\s*\\}\\s*$#', $this->contents)) { $this->contents = "{\n}"; } return \true; } return \false; } public function removeMainKeyIfEmpty(string $key) : bool { $decoded = \Composer\Json\JsonFile::parseJson($this->contents); if (!\array_key_exists($key, $decoded)) { return \true; } if (\is_array($decoded[$key]) && \count($decoded[$key]) === 0) { return $this->removeMainKey($key); } return \true; } /** * @param mixed $data */ public function format($data, int $depth = 0, bool $wasObject = \false) : string { if ($data instanceof \stdClass || $data instanceof \ArrayObject) { $data = (array) $data; $wasObject = \true; } if (\is_array($data)) { if (\count($data) === 0) { return $wasObject ? '{' . $this->newline . \str_repeat($this->indent, $depth + 1) . '}' : '[]'; } if (\array_is_list($data)) { foreach ($data as $key => $val) { $data[$key] = $this->format($val, $depth + 1); } return '[' . \implode(', ', $data) . ']'; } $out = '{' . $this->newline; $elems = []; foreach ($data as $key => $val) { $elems[] = \str_repeat($this->indent, $depth + 2) . \Composer\Json\JsonFile::encode((string) $key) . ': ' . $this->format($val, $depth + 1); } return $out . \implode(',' . $this->newline, $elems) . $this->newline . \str_repeat($this->indent, $depth + 1) . '}'; } return \Composer\Json\JsonFile::encode($data); } protected function detectIndenting() : void { $this->indent = \Composer\Json\JsonFile::detectIndenting($this->contents); } } * 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 */ private static $installedIsLocalDir; /** * @var bool|null */ private static $canGetVendors; /** * @var array[] * @psalm-var array}> */ private static $installedByVendor = array(); /** * Returns a list of all package names which are present, either by being installed, replaced or provided * * @return string[] * @psalm-return list */ public static function getInstalledPackages() { $packages = array(); foreach (self::getInstalled() as $installed) { $packages[] = \array_keys($installed['versions']); } if (1 === \count($packages)) { return $packages[0]; } return \array_keys(\array_flip(\call_user_func_array('array_merge', $packages))); } /** * Returns a list of all package names with a specific type e.g. 'library' * * @param string $type * @return string[] * @psalm-return list */ public static function getInstalledPackagesByType($type) { $packagesByType = array(); foreach (self::getInstalled() as $installed) { foreach ($installed['versions'] as $name => $package) { if (isset($package['type']) && $package['type'] === $type) { $packagesByType[] = $name; } } } return $packagesByType; } /** * Checks whether the given package is installed * * This also returns true if the package name is provided or replaced by another package * * @param string $packageName * @param bool $includeDevRequirements * @return bool */ public static function isInstalled($packageName, $includeDevRequirements = \true) { foreach (self::getInstalled() as $installed) { if (isset($installed['versions'][$packageName])) { return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === \false; } } return \false; } /** * Checks whether the given package satisfies a version constraint * * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: * * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') * * @param VersionParser $parser Install composer/semver to have access to this class and functionality * @param string $packageName * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package * @return bool */ public static function satisfies(VersionParser $parser, $packageName, $constraint) { $constraint = $parser->parseConstraints((string) $constraint); $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); return $provided->matches($constraint); } /** * Returns a version constraint representing all the range(s) which are installed for a given package * * It is easier to use this via isInstalled() with the $constraint argument if you need to check * whether a given version of a package is installed, and not just whether it exists * * @param string $packageName * @return string Version constraint usable with composer/semver */ public static function getVersionRanges($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } $ranges = array(); if (isset($installed['versions'][$packageName]['pretty_version'])) { $ranges[] = $installed['versions'][$packageName]['pretty_version']; } if (\array_key_exists('aliases', $installed['versions'][$packageName])) { $ranges = \array_merge($ranges, $installed['versions'][$packageName]['aliases']); } if (\array_key_exists('replaced', $installed['versions'][$packageName])) { $ranges = \array_merge($ranges, $installed['versions'][$packageName]['replaced']); } if (\array_key_exists('provided', $installed['versions'][$packageName])) { $ranges = \array_merge($ranges, $installed['versions'][$packageName]['provided']); } return \implode(' || ', $ranges); } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present */ public static function getVersion($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } if (!isset($installed['versions'][$packageName]['version'])) { return null; } return $installed['versions'][$packageName]['version']; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present */ public static function getPrettyVersion($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } if (!isset($installed['versions'][$packageName]['pretty_version'])) { return null; } return $installed['versions'][$packageName]['pretty_version']; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference */ public static function getReference($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } if (!isset($installed['versions'][$packageName]['reference'])) { return null; } return $installed['versions'][$packageName]['reference']; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. */ public static function getInstallPath($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @return array * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} */ public static function getRootPackage() { $installed = self::getInstalled(); return $installed[0]['root']; } /** * Returns the raw installed.php data for custom implementations * * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. * @return array[] * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} */ public static function getRawData() { @\trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', \E_USER_DEPRECATED); if (null === self::$installed) { // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 if (\substr(__DIR__, -8, 1) !== 'C') { self::$installed = (include __DIR__ . '/installed.php'); } else { self::$installed = array(); } } return self::$installed; } /** * Returns the raw data of all installed.php which are currently loaded for custom implementations * * @return array[] * @psalm-return list}> */ public static function getAllRawData() { return self::getInstalled(); } /** * Lets you reload the static array from another file * * This is only useful for complex integrations in which a project needs to use * this class but then also needs to execute another project's autoloader in process, * and wants to ensure both projects have access to their version of installed.php. * * A typical case would be PHPUnit, where it would need to make sure it reads all * the data it needs from this class, then call reload() with * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure * the project in which it runs can then also use this class safely, without * interference between PHPUnit's dependencies and the project's dependencies. * * @param array[] $data A vendor/composer/installed.php data set * @return void * * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data */ public static function reload($data) { self::$installed = $data; self::$installedByVendor = array(); // when using reload, we disable the duplicate protection to ensure that self::$installed data is // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, // so we have to assume it does not, and that may result in duplicate data being returned when listing // all installed packages for example self::$installedIsLocalDir = \false; } /** * @return array[] * @psalm-return list}> */ private static function getInstalled() { if (null === self::$canGetVendors) { self::$canGetVendors = \method_exists('Composer\\Autoload\\ClassLoader', 'getRegisteredLoaders'); } $installed = array(); $copiedLocalDir = \false; if (self::$canGetVendors) { $selfDir = \strtr(__DIR__, '\\', '/'); foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { $vendorDir = \strtr($vendorDir, '\\', '/'); if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (\is_file($vendorDir . '/composer/installed.php')) { /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ $required = (require $vendorDir . '/composer/installed.php'); self::$installedByVendor[$vendorDir] = $required; $installed[] = $required; if (self::$installed === null && $vendorDir . '/composer' === $selfDir) { self::$installed = $required; self::$installedIsLocalDir = \true; } } if (self::$installedIsLocalDir && $vendorDir . '/composer' === $selfDir) { $copiedLocalDir = \true; } } } if (null === self::$installed) { // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 if (\substr(__DIR__, -8, 1) !== 'C') { /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ $required = (require __DIR__ . '/installed.php'); self::$installed = $required; } else { self::$installed = array(); } } if (self::$installed !== array() && !$copiedLocalDir) { $installed[] = self::$installed; } return $installed; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver\Operation; use Composer\Package\PackageInterface; /** * Solver install operation. * * @author Konstantin Kudryashov */ class InstallOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface { protected const TYPE = 'install'; /** * @var PackageInterface */ protected $package; public function __construct(PackageInterface $package) { $this->package = $package; } /** * Returns package instance. */ public function getPackage() : PackageInterface { return $this->package; } /** * @inheritDoc */ public function show($lock) : string { return self::format($this->package, $lock); } public static function format(PackageInterface $package, bool $lock = \false) : string { return ($lock ? 'Locking ' : 'Installing ') . '' . $package->getPrettyName() . ' (' . $package->getFullPrettyVersion() . ')'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver\Operation; use Composer\Package\AliasPackage; /** * Solver install operation. * * @author Nils Adermann */ class MarkAliasInstalledOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface { protected const TYPE = 'markAliasInstalled'; /** * @var AliasPackage */ protected $package; public function __construct(AliasPackage $package) { $this->package = $package; } /** * Returns package instance. */ public function getPackage() : AliasPackage { return $this->package; } /** * @inheritDoc */ public function show($lock) : string { return 'Marking ' . $this->package->getPrettyName() . ' (' . $this->package->getFullPrettyVersion() . ') as installed, alias of ' . $this->package->getAliasOf()->getPrettyName() . ' (' . $this->package->getAliasOf()->getFullPrettyVersion() . ')'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver\Operation; /** * Solver operation interface. * * @author Konstantin Kudryashov */ interface OperationInterface { /** * Returns operation type. * * @return string */ public function getOperationType(); /** * Serializes the operation in a human readable format * * @param bool $lock Whether this is an operation on the lock file * @return string */ public function show(bool $lock); /** * Serializes the operation in a human readable format * * @return string */ public function __toString(); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver\Operation; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; /** * Solver update operation. * * @author Konstantin Kudryashov */ class UpdateOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface { protected const TYPE = 'update'; /** * @var PackageInterface */ protected $initialPackage; /** * @var PackageInterface */ protected $targetPackage; /** * @param PackageInterface $initial initial package * @param PackageInterface $target target package (updated) */ public function __construct(PackageInterface $initial, PackageInterface $target) { $this->initialPackage = $initial; $this->targetPackage = $target; } /** * Returns initial package. */ public function getInitialPackage() : PackageInterface { return $this->initialPackage; } /** * Returns target package. */ public function getTargetPackage() : PackageInterface { return $this->targetPackage; } /** * @inheritDoc */ public function show($lock) : string { return self::format($this->initialPackage, $this->targetPackage, $lock); } public static function format(PackageInterface $initialPackage, PackageInterface $targetPackage, bool $lock = \false) : string { $fromVersion = $initialPackage->getFullPrettyVersion(); $toVersion = $targetPackage->getFullPrettyVersion(); if ($fromVersion === $toVersion && $initialPackage->getSourceReference() !== $targetPackage->getSourceReference()) { $fromVersion = $initialPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_SOURCE_REF); $toVersion = $targetPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_SOURCE_REF); } elseif ($fromVersion === $toVersion && $initialPackage->getDistReference() !== $targetPackage->getDistReference()) { $fromVersion = $initialPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_DIST_REF); $toVersion = $targetPackage->getFullPrettyVersion(\true, PackageInterface::DISPLAY_DIST_REF); } $actionName = VersionParser::isUpgrade($initialPackage->getVersion(), $targetPackage->getVersion()) ? 'Upgrading' : 'Downgrading'; return $actionName . ' ' . $initialPackage->getPrettyName() . ' (' . $fromVersion . ' => ' . $toVersion . ')'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver\Operation; /** * Abstract operation class. * * @author Aleksandr Bezpiatov */ abstract class SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface { /** * @abstract must be redefined by extending classes */ protected const TYPE = ''; /** * Returns operation type. */ public function getOperationType() : string { return static::TYPE; } /** * @inheritDoc */ public function __toString() { return $this->show(\false); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver\Operation; use Composer\Package\PackageInterface; /** * Solver uninstall operation. * * @author Konstantin Kudryashov */ class UninstallOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface { protected const TYPE = 'uninstall'; /** * @var PackageInterface */ protected $package; public function __construct(PackageInterface $package) { $this->package = $package; } /** * Returns package instance. */ public function getPackage() : PackageInterface { return $this->package; } /** * @inheritDoc */ public function show($lock) : string { return self::format($this->package, $lock); } public static function format(PackageInterface $package, bool $lock = \false) : string { return 'Removing ' . $package->getPrettyName() . ' (' . $package->getFullPrettyVersion() . ')'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver\Operation; use Composer\Package\AliasPackage; /** * Solver install operation. * * @author Nils Adermann */ class MarkAliasUninstalledOperation extends \Composer\DependencyResolver\Operation\SolverOperation implements \Composer\DependencyResolver\Operation\OperationInterface { protected const TYPE = 'markAliasUninstalled'; /** * @var AliasPackage */ protected $package; public function __construct(AliasPackage $package) { $this->package = $package; } /** * Returns package instance. */ public function getPackage() : AliasPackage { return $this->package; } /** * @inheritDoc */ public function show($lock) : string { return 'Marking ' . $this->package->getPrettyName() . ' (' . $this->package->getFullPrettyVersion() . ') as uninstalled, alias of ' . $this->package->getAliasOf()->getPrettyName() . ' (' . $this->package->getAliasOf()->getFullPrettyVersion() . ')'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\AliasPackage; use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Repository\PlatformRepository; use Composer\DependencyResolver\Operation\OperationInterface; /** * @author Nils Adermann * @internal */ class Transaction { /** * @var OperationInterface[] */ protected $operations; /** * Packages present at the beginning of the transaction * @var PackageInterface[] */ protected $presentPackages; /** * Package set resulting from this transaction * @var array */ protected $resultPackageMap; /** * @var array */ protected $resultPackagesByName = []; /** * @param PackageInterface[] $presentPackages * @param PackageInterface[] $resultPackages */ public function __construct(array $presentPackages, array $resultPackages) { $this->presentPackages = $presentPackages; $this->setResultPackageMaps($resultPackages); $this->operations = $this->calculateOperations(); } /** * @return OperationInterface[] */ public function getOperations() : array { return $this->operations; } /** * @param PackageInterface[] $resultPackages */ private function setResultPackageMaps(array $resultPackages) : void { $packageSort = static function (PackageInterface $a, PackageInterface $b) : int { // sort alias packages by the same name behind their non alias version if ($a->getName() === $b->getName()) { if ($a instanceof AliasPackage !== $b instanceof AliasPackage) { return $a instanceof AliasPackage ? -1 : 1; } // if names are the same, compare version, e.g. to sort aliases reliably, actual order does not matter return \strcmp($b->getVersion(), $a->getVersion()); } return \strcmp($b->getName(), $a->getName()); }; $this->resultPackageMap = []; foreach ($resultPackages as $package) { $this->resultPackageMap[\spl_object_hash($package)] = $package; foreach ($package->getNames() as $name) { $this->resultPackagesByName[$name][] = $package; } } \uasort($this->resultPackageMap, $packageSort); foreach ($this->resultPackagesByName as $name => $packages) { \uasort($this->resultPackagesByName[$name], $packageSort); } } /** * @return OperationInterface[] */ protected function calculateOperations() : array { $operations = []; $presentPackageMap = []; $removeMap = []; $presentAliasMap = []; $removeAliasMap = []; foreach ($this->presentPackages as $package) { if ($package instanceof AliasPackage) { $presentAliasMap[$package->getName() . '::' . $package->getVersion()] = $package; $removeAliasMap[$package->getName() . '::' . $package->getVersion()] = $package; } else { $presentPackageMap[$package->getName()] = $package; $removeMap[$package->getName()] = $package; } } $stack = $this->getRootPackages(); $visited = []; $processed = []; while (\count($stack) > 0) { $package = \array_pop($stack); if (isset($processed[\spl_object_hash($package)])) { continue; } if (!isset($visited[\spl_object_hash($package)])) { $visited[\spl_object_hash($package)] = \true; $stack[] = $package; if ($package instanceof AliasPackage) { $stack[] = $package->getAliasOf(); } else { foreach ($package->getRequires() as $link) { $possibleRequires = $this->getProvidersInResult($link); foreach ($possibleRequires as $require) { $stack[] = $require; } } } } elseif (!isset($processed[\spl_object_hash($package)])) { $processed[\spl_object_hash($package)] = \true; if ($package instanceof AliasPackage) { $aliasKey = $package->getName() . '::' . $package->getVersion(); if (isset($presentAliasMap[$aliasKey])) { unset($removeAliasMap[$aliasKey]); } else { $operations[] = new \Composer\DependencyResolver\Operation\MarkAliasInstalledOperation($package); } } else { if (isset($presentPackageMap[$package->getName()])) { $source = $presentPackageMap[$package->getName()]; // do we need to update? // TODO different for lock? if ($package->getVersion() !== $presentPackageMap[$package->getName()]->getVersion() || $package->getDistReference() !== $presentPackageMap[$package->getName()]->getDistReference() || $package->getSourceReference() !== $presentPackageMap[$package->getName()]->getSourceReference()) { $operations[] = new \Composer\DependencyResolver\Operation\UpdateOperation($source, $package); } unset($removeMap[$package->getName()]); } else { $operations[] = new \Composer\DependencyResolver\Operation\InstallOperation($package); unset($removeMap[$package->getName()]); } } } } foreach ($removeMap as $name => $package) { \array_unshift($operations, new \Composer\DependencyResolver\Operation\UninstallOperation($package)); } foreach ($removeAliasMap as $nameVersion => $package) { $operations[] = new \Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation($package); } $operations = $this->movePluginsToFront($operations); // TODO fix this: // we have to do this again here even though the above stack code did it because moving plugins moves them before uninstalls $operations = $this->moveUninstallsToFront($operations); // TODO skip updates which don't update? is this needed? we shouldn't schedule this update in the first place? /* if ('update' === $opType) { $targetPackage = $operation->getTargetPackage(); if ($targetPackage->isDev()) { $initialPackage = $operation->getInitialPackage(); if ($targetPackage->getVersion() === $initialPackage->getVersion() && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference()) && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference()) ) { $this->io->writeError(' - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG); $this->io->writeError('', true, IOInterface::DEBUG); continue; } } }*/ return $this->operations = $operations; } /** * Determine which packages in the result are not required by any other packages in it. * * These serve as a starting point to enumerate packages in a topological order despite potential cycles. * If there are packages with a cycle on the top level the package with the lowest name gets picked * * @return array */ protected function getRootPackages() : array { $roots = $this->resultPackageMap; foreach ($this->resultPackageMap as $packageHash => $package) { if (!isset($roots[$packageHash])) { continue; } foreach ($package->getRequires() as $link) { $possibleRequires = $this->getProvidersInResult($link); foreach ($possibleRequires as $require) { if ($require !== $package) { unset($roots[\spl_object_hash($require)]); } } } } return $roots; } /** * @return PackageInterface[] */ protected function getProvidersInResult(Link $link) : array { if (!isset($this->resultPackagesByName[$link->getTarget()])) { return []; } return $this->resultPackagesByName[$link->getTarget()]; } /** * Workaround: if your packages depend on plugins, we must be sure * that those are installed / updated first; else it would lead to packages * being installed multiple times in different folders, when running Composer * twice. * * While this does not fix the root-causes of https://github.com/composer/composer/issues/1147, * it at least fixes the symptoms and makes usage of composer possible (again) * in such scenarios. * * @param OperationInterface[] $operations * @return OperationInterface[] reordered operation list */ private function movePluginsToFront(array $operations) : array { $dlModifyingPluginsNoDeps = []; $dlModifyingPluginsWithDeps = []; $dlModifyingPluginRequires = []; $pluginsNoDeps = []; $pluginsWithDeps = []; $pluginRequires = []; foreach (\array_reverse($operations, \true) as $idx => $op) { if ($op instanceof \Composer\DependencyResolver\Operation\InstallOperation) { $package = $op->getPackage(); } elseif ($op instanceof \Composer\DependencyResolver\Operation\UpdateOperation) { $package = $op->getTargetPackage(); } else { continue; } $extra = $package->getExtra(); $isDownloadsModifyingPlugin = $package->getType() === 'composer-plugin' && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === \true; // is this a downloads modifying plugin or a dependency of one? if ($isDownloadsModifyingPlugin || \count(\array_intersect($package->getNames(), $dlModifyingPluginRequires)) > 0) { // get the package's requires, but filter out any platform requirements $requires = \array_filter(\array_keys($package->getRequires()), static function ($req) : bool { return !PlatformRepository::isPlatformPackage($req); }); // is this a plugin with no meaningful dependencies? if ($isDownloadsModifyingPlugin && 0 === \count($requires)) { // plugins with no dependencies go to the very front \array_unshift($dlModifyingPluginsNoDeps, $op); } else { // capture the requirements for this package so those packages will be moved up as well $dlModifyingPluginRequires = \array_merge($dlModifyingPluginRequires, $requires); // move the operation to the front \array_unshift($dlModifyingPluginsWithDeps, $op); } unset($operations[$idx]); continue; } // is this package a plugin? $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer'; // is this a plugin or a dependency of a plugin? if ($isPlugin || \count(\array_intersect($package->getNames(), $pluginRequires)) > 0) { // get the package's requires, but filter out any platform requirements $requires = \array_filter(\array_keys($package->getRequires()), static function ($req) : bool { return !PlatformRepository::isPlatformPackage($req); }); // is this a plugin with no meaningful dependencies? if ($isPlugin && 0 === \count($requires)) { // plugins with no dependencies go to the very front \array_unshift($pluginsNoDeps, $op); } else { // capture the requirements for this package so those packages will be moved up as well $pluginRequires = \array_merge($pluginRequires, $requires); // move the operation to the front \array_unshift($pluginsWithDeps, $op); } unset($operations[$idx]); } } return \array_merge($dlModifyingPluginsNoDeps, $dlModifyingPluginsWithDeps, $pluginsNoDeps, $pluginsWithDeps, $operations); } /** * Removals of packages should be executed before installations in * case two packages resolve to the same path (due to custom installers) * * @param OperationInterface[] $operations * @return OperationInterface[] reordered operation list */ private function moveUninstallsToFront(array $operations) : array { $uninstOps = []; foreach ($operations as $idx => $op) { if ($op instanceof \Composer\DependencyResolver\Operation\UninstallOperation || $op instanceof \Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation) { $uninstOps[] = $op; unset($operations[$idx]); } } return \array_merge($uninstOps, $operations); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\PackageInterface; use Composer\Semver\Constraint\Constraint; /** * @author Nils Adermann */ interface PolicyInterface { /** * @phpstan-param Constraint::STR_OP_* $operator */ public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator) : bool; /** * @param non-empty-list $literals * @return non-empty-list */ public function selectPreferredPackages(\Composer\DependencyResolver\Pool $pool, array $literals, ?string $requiredPackage = null) : array; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\RepositoryInterface; /** * @author Nils Adermann * @internal */ class LocalRepoTransaction extends \Composer\DependencyResolver\Transaction { public function __construct(RepositoryInterface $lockedRepository, InstalledRepositoryInterface $localRepository) { parent::__construct($localRepository->getPackages(), $lockedRepository->getPackages()); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * The RuleWatchGraph efficiently propagates decisions to other rules * * All rules generated for solving a SAT problem should be inserted into the * graph. When a decision on a literal is made, the graph can be used to * propagate the decision to all other rules involving the literal, leading to * other trivial decisions resulting from unit clauses. * * @author Nils Adermann */ class RuleWatchGraph { /** @var array */ protected $watchChains = []; /** * Inserts a rule node into the appropriate chains within the graph * * The node is prepended to the watch chains for each of the two literals it * watches. * * Assertions are skipped because they only depend on a single package and * have no alternative literal that could be true, so there is no need to * watch changes in any literals. * * @param RuleWatchNode $node The rule node to be inserted into the graph */ public function insert(\Composer\DependencyResolver\RuleWatchNode $node) : void { if ($node->getRule()->isAssertion()) { return; } if (!$node->getRule() instanceof \Composer\DependencyResolver\MultiConflictRule) { foreach ([$node->watch1, $node->watch2] as $literal) { if (!isset($this->watchChains[$literal])) { $this->watchChains[$literal] = new \Composer\DependencyResolver\RuleWatchChain(); } $this->watchChains[$literal]->unshift($node); } } else { foreach ($node->getRule()->getLiterals() as $literal) { if (!isset($this->watchChains[$literal])) { $this->watchChains[$literal] = new \Composer\DependencyResolver\RuleWatchChain(); } $this->watchChains[$literal]->unshift($node); } } } /** * Propagates a decision on a literal to all rules watching the literal * * If a decision, e.g. +A has been made, then all rules containing -A, e.g. * (-A|+B|+C) now need to satisfy at least one of the other literals, so * that the rule as a whole becomes true, since with +A applied the rule * is now (false|+B|+C) so essentially (+B|+C). * * This means that all rules watching the literal -A need to be updated to * watch 2 other literals which can still be satisfied instead. So literals * that conflict with previously made decisions are not an option. * * Alternatively it can occur that a unit clause results: e.g. if in the * above example the rule was (-A|+B), then A turning true means that * B must now be decided true as well. * * @param int $decidedLiteral The literal which was decided (A in our example) * @param int $level The level at which the decision took place and at which * all resulting decisions should be made. * @param Decisions $decisions Used to check previous decisions and to * register decisions resulting from propagation * @return Rule|null If a conflict is found the conflicting rule is returned */ public function propagateLiteral(int $decidedLiteral, int $level, \Composer\DependencyResolver\Decisions $decisions) : ?\Composer\DependencyResolver\Rule { // we invert the decided literal here, example: // A was decided => (-A|B) now requires B to be true, so we look for // rules which are fulfilled by -A, rather than A. $literal = -$decidedLiteral; if (!isset($this->watchChains[$literal])) { return null; } $chain = $this->watchChains[$literal]; $chain->rewind(); while ($chain->valid()) { $node = $chain->current(); if (!$node->getRule() instanceof \Composer\DependencyResolver\MultiConflictRule) { $otherWatch = $node->getOtherWatch($literal); if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) { $ruleLiterals = $node->getRule()->getLiterals(); $alternativeLiterals = \array_filter($ruleLiterals, static function ($ruleLiteral) use($literal, $otherWatch, $decisions) : bool { return $literal !== $ruleLiteral && $otherWatch !== $ruleLiteral && !$decisions->conflict($ruleLiteral); }); if (\count($alternativeLiterals) > 0) { \reset($alternativeLiterals); $this->moveWatch($literal, \current($alternativeLiterals), $node); continue; } if ($decisions->conflict($otherWatch)) { return $node->getRule(); } $decisions->decide($otherWatch, $level, $node->getRule()); } } else { foreach ($node->getRule()->getLiterals() as $otherLiteral) { if ($literal !== $otherLiteral && !$decisions->satisfy($otherLiteral)) { if ($decisions->conflict($otherLiteral)) { return $node->getRule(); } $decisions->decide($otherLiteral, $level, $node->getRule()); } } } $chain->next(); } return null; } /** * Moves a rule node from one watch chain to another * * The rule node's watched literals are updated accordingly. * * @param int $fromLiteral A literal the node used to watch * @param int $toLiteral A literal the node should watch now * @param RuleWatchNode $node The rule node to be moved */ protected function moveWatch(int $fromLiteral, int $toLiteral, \Composer\DependencyResolver\RuleWatchNode $node) : void { if (!isset($this->watchChains[$toLiteral])) { $this->watchChains[$toLiteral] = new \Composer\DependencyResolver\RuleWatchChain(); } $node->moveWatch($fromLiteral, $toLiteral); $this->watchChains[$fromLiteral]->remove(); $this->watchChains[$toLiteral]->unshift($node); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * @author Nils Adermann */ class GenericRule extends \Composer\DependencyResolver\Rule { /** @var list */ protected $literals; /** * @param list $literals */ public function __construct(array $literals, $reason, $reasonData) { parent::__construct($reason, $reasonData); // sort all packages ascending by id \sort($literals); $this->literals = $literals; } /** * @return list */ public function getLiterals() : array { return $this->literals; } /** * @inheritDoc */ public function getHash() { $data = \unpack('ihash', (string) \hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', \implode(',', $this->literals), \true)); if (\false === $data) { throw new \RuntimeException('Failed unpacking: ' . \implode(', ', $this->literals)); } return $data['hash']; } /** * Checks if this rule is equal to another one * * Ignores whether either of the rules is disabled. * * @param Rule $rule The rule to check against * @return bool Whether the rules are equal */ public function equals(\Composer\DependencyResolver\Rule $rule) : bool { return $this->literals === $rule->getLiterals(); } public function isAssertion() : bool { return 1 === \count($this->literals); } /** * Formats a rule as a string of the format (Literal1|Literal2|...) */ public function __toString() : string { $result = $this->isDisabled() ? 'disabled(' : '('; foreach ($this->literals as $i => $literal) { if ($i !== 0) { $result .= '|'; } $result .= $literal; } $result .= ')'; return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Package; use Composer\Pcre\Preg; /** * @author Nils Adermann * @internal */ class LockTransaction extends \Composer\DependencyResolver\Transaction { /** * packages in current lock file, platform repo or otherwise present * * Indexed by spl_object_hash * * @var array */ protected $presentMap; /** * Packages which cannot be mapped, platform repo, root package, other fixed repos * * Indexed by package id * * @var array */ protected $unlockableMap; /** * @var array{dev: BasePackage[], non-dev: BasePackage[], all: BasePackage[]} */ protected $resultPackages; /** * @param array $presentMap * @param array $unlockableMap */ public function __construct(\Composer\DependencyResolver\Pool $pool, array $presentMap, array $unlockableMap, \Composer\DependencyResolver\Decisions $decisions) { $this->presentMap = $presentMap; $this->unlockableMap = $unlockableMap; $this->setResultPackages($pool, $decisions); parent::__construct($this->presentMap, $this->resultPackages['all']); } // TODO make this a bit prettier instead of the two text indexes? public function setResultPackages(\Composer\DependencyResolver\Pool $pool, \Composer\DependencyResolver\Decisions $decisions) : void { $this->resultPackages = ['all' => [], 'non-dev' => [], 'dev' => []]; foreach ($decisions as $i => $decision) { $literal = $decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL]; if ($literal > 0) { $package = $pool->literalToPackage($literal); $this->resultPackages['all'][] = $package; if (!isset($this->unlockableMap[$package->id])) { $this->resultPackages['non-dev'][] = $package; } } } } public function setNonDevPackages(\Composer\DependencyResolver\LockTransaction $extractionResult) : void { $packages = $extractionResult->getNewLockPackages(\false); $this->resultPackages['dev'] = $this->resultPackages['non-dev']; $this->resultPackages['non-dev'] = []; foreach ($packages as $package) { foreach ($this->resultPackages['dev'] as $i => $resultPackage) { // TODO this comparison is probably insufficient, aliases, what about modified versions? I guess they aren't possible? if ($package->getName() === $resultPackage->getName()) { $this->resultPackages['non-dev'][] = $resultPackage; unset($this->resultPackages['dev'][$i]); } } } } // TODO additionalFixedRepository needs to be looked at here as well? /** * @return BasePackage[] */ public function getNewLockPackages(bool $devMode, bool $updateMirrors = \false) : array { $packages = []; foreach ($this->resultPackages[$devMode ? 'dev' : 'non-dev'] as $package) { if ($package instanceof AliasPackage) { continue; } // if we're just updating mirrors we need to reset everything to the same as currently "present" packages' references to keep the lock file as-is if ($updateMirrors === \true && !\array_key_exists(\spl_object_hash($package), $this->presentMap)) { $package = $this->updateMirrorAndUrls($package); } $packages[] = $package; } return $packages; } /** * Try to return the original package from presentMap with updated URLs/mirrors * * If the type of source/dist changed, then we do not update those and keep them as they were */ private function updateMirrorAndUrls(BasePackage $package) : BasePackage { foreach ($this->presentMap as $presentPackage) { if ($package->getName() !== $presentPackage->getName()) { continue; } if ($package->getVersion() !== $presentPackage->getVersion()) { continue; } if ($presentPackage->getSourceReference() === null) { continue; } if ($presentPackage->getSourceType() !== $package->getSourceType()) { continue; } if ($presentPackage instanceof Package) { $presentPackage->setSourceUrl($package->getSourceUrl()); $presentPackage->setSourceMirrors($package->getSourceMirrors()); } // if the dist type changed, we only update the source url/mirrors if ($presentPackage->getDistType() !== $package->getDistType()) { return $presentPackage; } // update dist url if it is in a known format if ($package->getDistUrl() !== null && $presentPackage->getDistReference() !== null && Preg::isMatch('{^https?://(?:(?:www\\.)?bitbucket\\.org|(api\\.)?github\\.com|(?:www\\.)?gitlab\\.com)/}i', $package->getDistUrl())) { $presentPackage->setDistUrl(Preg::replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $presentPackage->getDistReference(), $package->getDistUrl())); } $presentPackage->setDistMirrors($package->getDistMirrors()); return $presentPackage; } return $package; } /** * Checks which of the given aliases from composer.json are actually in use for the lock file * @param list $aliases * @return list */ public function getAliases(array $aliases) : array { $usedAliases = []; foreach ($this->resultPackages['all'] as $package) { if ($package instanceof AliasPackage) { foreach ($aliases as $index => $alias) { if ($alias['package'] === $package->getName()) { $usedAliases[] = $alias; unset($aliases[$index]); } } } } \usort($usedAliases, static function ($a, $b) : int { return \strcmp($a['package'], $b['package']); }); return $usedAliases; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\IO\IOInterface; use Composer\Package\BasePackage; /** * @author Nils Adermann */ class Solver { private const BRANCH_LITERALS = 0; private const BRANCH_LEVEL = 1; /** @var PolicyInterface */ protected $policy; /** @var Pool */ protected $pool; /** @var RuleSet */ protected $rules; /** @var RuleWatchGraph */ protected $watchGraph; /** @var Decisions */ protected $decisions; /** @var BasePackage[] */ protected $fixedMap; /** @var int */ protected $propagateIndex; /** @var array, int}> */ protected $branches = []; /** @var Problem[] */ protected $problems = []; /** @var array */ protected $learnedPool = []; /** @var array */ protected $learnedWhy = []; /** @var bool */ public $testFlagLearnedPositiveLiteral = \false; /** @var IOInterface */ protected $io; public function __construct(\Composer\DependencyResolver\PolicyInterface $policy, \Composer\DependencyResolver\Pool $pool, IOInterface $io) { $this->io = $io; $this->policy = $policy; $this->pool = $pool; } public function getRuleSetSize() : int { return \count($this->rules); } public function getPool() : \Composer\DependencyResolver\Pool { return $this->pool; } // aka solver_makeruledecisions private function makeAssertionRuleDecisions() : void { $decisionStart = \count($this->decisions) - 1; $rulesCount = \count($this->rules); for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) { $rule = $this->rules->ruleById[$ruleIndex]; if (!$rule->isAssertion() || $rule->isDisabled()) { continue; } $literals = $rule->getLiterals(); $literal = $literals[0]; if (!$this->decisions->decided($literal)) { $this->decisions->decide($literal, 1, $rule); continue; } if ($this->decisions->satisfy($literal)) { continue; } // found a conflict if (\Composer\DependencyResolver\RuleSet::TYPE_LEARNED === $rule->getType()) { $rule->disable(); continue; } $conflict = $this->decisions->decisionRule($literal); if (\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE === $conflict->getType()) { $problem = new \Composer\DependencyResolver\Problem(); $problem->addRule($rule); $problem->addRule($conflict); $rule->disable(); $this->problems[] = $problem; continue; } // conflict with another root require/fixed package $problem = new \Composer\DependencyResolver\Problem(); $problem->addRule($rule); $problem->addRule($conflict); // push all of our rules (can only be root require/fixed package rules) // asserting this literal on the problem stack foreach ($this->rules->getIteratorFor(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST) as $assertRule) { if ($assertRule->isDisabled() || !$assertRule->isAssertion()) { continue; } $assertRuleLiterals = $assertRule->getLiterals(); $assertRuleLiteral = $assertRuleLiterals[0]; if (\abs($literal) !== \abs($assertRuleLiteral)) { continue; } $problem->addRule($assertRule); $assertRule->disable(); } $this->problems[] = $problem; $this->decisions->resetToOffset($decisionStart); $ruleIndex = -1; } } protected function setupFixedMap(\Composer\DependencyResolver\Request $request) : void { $this->fixedMap = []; foreach ($request->getFixedPackages() as $package) { $this->fixedMap[$package->id] = $package; } } protected function checkForRootRequireProblems(\Composer\DependencyResolver\Request $request, PlatformRequirementFilterInterface $platformRequirementFilter) : void { foreach ($request->getRequires() as $packageName => $constraint) { if ($platformRequirementFilter->isIgnored($packageName)) { continue; } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) { $constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint); } if (0 === \count($this->pool->whatProvides($packageName, $constraint))) { $problem = new \Composer\DependencyResolver\Problem(); $problem->addRule(new \Composer\DependencyResolver\GenericRule([], \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint])); $this->problems[] = $problem; } } } public function solve(\Composer\DependencyResolver\Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null) : \Composer\DependencyResolver\LockTransaction { $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing(); $this->setupFixedMap($request); $this->io->writeError('Generating rules', \true, IOInterface::DEBUG); $ruleSetGenerator = new \Composer\DependencyResolver\RuleSetGenerator($this->policy, $this->pool); $this->rules = $ruleSetGenerator->getRulesFor($request, $platformRequirementFilter); unset($ruleSetGenerator); $this->checkForRootRequireProblems($request, $platformRequirementFilter); $this->decisions = new \Composer\DependencyResolver\Decisions($this->pool); $this->watchGraph = new \Composer\DependencyResolver\RuleWatchGraph(); foreach ($this->rules as $rule) { $this->watchGraph->insert(new \Composer\DependencyResolver\RuleWatchNode($rule)); } /* make decisions based on root require/fix assertions */ $this->makeAssertionRuleDecisions(); $this->io->writeError('Resolving dependencies through SAT', \true, IOInterface::DEBUG); $before = \microtime(\true); $this->runSat(); $this->io->writeError('', \true, IOInterface::DEBUG); $this->io->writeError(\sprintf('Dependency resolution completed in %.3f seconds', \microtime(\true) - $before), \true, IOInterface::VERBOSE); if (\count($this->problems) > 0) { throw new \Composer\DependencyResolver\SolverProblemsException($this->problems, $this->learnedPool); } return new \Composer\DependencyResolver\LockTransaction($this->pool, $request->getPresentMap(), $request->getFixedPackagesMap(), $this->decisions); } /** * Makes a decision and propagates it to all rules. * * Evaluates each term affected by the decision (linked through watches) * If we find unit rules we make new decisions based on them * * @return Rule|null A rule on conflict, otherwise null. */ protected function propagate(int $level) : ?\Composer\DependencyResolver\Rule { while ($this->decisions->validOffset($this->propagateIndex)) { $decision = $this->decisions->atOffset($this->propagateIndex); $conflict = $this->watchGraph->propagateLiteral($decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL], $level, $this->decisions); $this->propagateIndex++; if ($conflict !== null) { return $conflict; } } return null; } /** * Reverts a decision at the given level. */ private function revert(int $level) : void { while (!$this->decisions->isEmpty()) { $literal = $this->decisions->lastLiteral(); if ($this->decisions->undecided($literal)) { break; } $decisionLevel = $this->decisions->decisionLevel($literal); if ($decisionLevel <= $level) { break; } $this->decisions->revertLast(); $this->propagateIndex = \count($this->decisions); } while (\count($this->branches) > 0 && $this->branches[\count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) { \array_pop($this->branches); } } /** * setpropagatelearn * * add free decision (a positive literal) to decision queue * increase level and propagate decision * return if no conflict. * * in conflict case, analyze conflict rule, add resulting * rule to learnt rule set, make decision from learnt * rule (always unit) and re-propagate. * * returns the new solver level or 0 if unsolvable */ private function setPropagateLearn(int $level, int $literal, \Composer\DependencyResolver\Rule $rule) : int { $level++; $this->decisions->decide($literal, $level, $rule); while (\true) { $rule = $this->propagate($level); if (null === $rule) { break; } if ($level === 1) { $this->analyzeUnsolvable($rule); return 0; } // conflict [$learnLiteral, $newLevel, $newRule, $why] = $this->analyze($level, $rule); if ($newLevel <= 0 || $newLevel >= $level) { throw new \Composer\DependencyResolver\SolverBugException("Trying to revert to invalid level " . $newLevel . " from level " . $level . "."); } $level = $newLevel; $this->revert($level); $this->rules->add($newRule, \Composer\DependencyResolver\RuleSet::TYPE_LEARNED); $this->learnedWhy[\spl_object_hash($newRule)] = $why; $ruleNode = new \Composer\DependencyResolver\RuleWatchNode($newRule); $ruleNode->watch2OnHighest($this->decisions); $this->watchGraph->insert($ruleNode); $this->decisions->decide($learnLiteral, $level, $newRule); } return $level; } /** * @param non-empty-list $decisionQueue */ private function selectAndInstall(int $level, array $decisionQueue, \Composer\DependencyResolver\Rule $rule) : int { // choose best package to install from decisionQueue $literals = $this->policy->selectPreferredPackages($this->pool, $decisionQueue, $rule->getRequiredPackage()); $selectedLiteral = \array_shift($literals); // if there are multiple candidates, then branch if (\count($literals) > 0) { $this->branches[] = [$literals, $level]; } return $this->setPropagateLearn($level, $selectedLiteral, $rule); } /** * @return array{int, int, GenericRule, int} */ protected function analyze(int $level, \Composer\DependencyResolver\Rule $rule) : array { $analyzedRule = $rule; $ruleLevel = 1; $num = 0; $l1num = 0; $seen = []; $learnedLiteral = null; $otherLearnedLiterals = []; $decisionId = \count($this->decisions); $this->learnedPool[] = []; while (\true) { $this->learnedPool[\count($this->learnedPool) - 1][] = $rule; foreach ($rule->getLiterals() as $literal) { // multiconflictrule is really a bunch of rules in one, so some may not have finished propagating yet if ($rule instanceof \Composer\DependencyResolver\MultiConflictRule && !$this->decisions->decided($literal)) { continue; } // skip the one true literal if ($this->decisions->satisfy($literal)) { continue; } if (isset($seen[\abs($literal)])) { continue; } $seen[\abs($literal)] = \true; $l = $this->decisions->decisionLevel($literal); if (1 === $l) { $l1num++; } elseif ($level === $l) { $num++; } else { // not level1 or conflict level, add to new rule $otherLearnedLiterals[] = $literal; if ($l > $ruleLevel) { $ruleLevel = $l; } } } unset($literal); $l1retry = \true; while ($l1retry) { $l1retry = \false; if (0 === $num && 0 === --$l1num) { // all level 1 literals done break 2; } while (\true) { if ($decisionId <= 0) { throw new \Composer\DependencyResolver\SolverBugException("Reached invalid decision id {$decisionId} while looking through {$rule} for a literal present in the analyzed rule {$analyzedRule}."); } $decisionId--; $decision = $this->decisions->atOffset($decisionId); $literal = $decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL]; if (isset($seen[\abs($literal)])) { break; } } unset($seen[\abs($literal)]); if (0 !== $num && 0 === --$num) { if ($literal < 0) { $this->testFlagLearnedPositiveLiteral = \true; } $learnedLiteral = -$literal; if (0 === $l1num) { break 2; } foreach ($otherLearnedLiterals as $otherLiteral) { unset($seen[\abs($otherLiteral)]); } // only level 1 marks left $l1num++; $l1retry = \true; } else { $decision = $this->decisions->atOffset($decisionId); $rule = $decision[\Composer\DependencyResolver\Decisions::DECISION_REASON]; if ($rule instanceof \Composer\DependencyResolver\MultiConflictRule) { // there is only ever exactly one positive decision in a MultiConflictRule foreach ($rule->getLiterals() as $ruleLiteral) { if (!isset($seen[\abs($ruleLiteral)]) && $this->decisions->satisfy(-$ruleLiteral)) { $this->learnedPool[\count($this->learnedPool) - 1][] = $rule; $l = $this->decisions->decisionLevel($ruleLiteral); if (1 === $l) { $l1num++; } elseif ($level === $l) { $num++; } else { // not level1 or conflict level, add to new rule $otherLearnedLiterals[] = $ruleLiteral; if ($l > $ruleLevel) { $ruleLevel = $l; } } $seen[\abs($ruleLiteral)] = \true; break; } } $l1retry = \true; } } } $decision = $this->decisions->atOffset($decisionId); $rule = $decision[\Composer\DependencyResolver\Decisions::DECISION_REASON]; } $why = \count($this->learnedPool) - 1; if (null === $learnedLiteral) { throw new \Composer\DependencyResolver\SolverBugException("Did not find a learnable literal in analyzed rule {$analyzedRule}."); } \array_unshift($otherLearnedLiterals, $learnedLiteral); $newRule = new \Composer\DependencyResolver\GenericRule($otherLearnedLiterals, \Composer\DependencyResolver\Rule::RULE_LEARNED, $why); return [$learnedLiteral, $ruleLevel, $newRule, $why]; } /** * @param array $ruleSeen */ private function analyzeUnsolvableRule(\Composer\DependencyResolver\Problem $problem, \Composer\DependencyResolver\Rule $conflictRule, array &$ruleSeen) : void { $why = \spl_object_hash($conflictRule); $ruleSeen[$why] = \true; if ($conflictRule->getType() === \Composer\DependencyResolver\RuleSet::TYPE_LEARNED) { $learnedWhy = $this->learnedWhy[$why]; $problemRules = $this->learnedPool[$learnedWhy]; foreach ($problemRules as $problemRule) { if (!isset($ruleSeen[\spl_object_hash($problemRule)])) { $this->analyzeUnsolvableRule($problem, $problemRule, $ruleSeen); } } return; } if ($conflictRule->getType() === \Composer\DependencyResolver\RuleSet::TYPE_PACKAGE) { // package rules cannot be part of a problem return; } $problem->nextSection(); $problem->addRule($conflictRule); } private function analyzeUnsolvable(\Composer\DependencyResolver\Rule $conflictRule) : void { $problem = new \Composer\DependencyResolver\Problem(); $problem->addRule($conflictRule); $ruleSeen = []; $this->analyzeUnsolvableRule($problem, $conflictRule, $ruleSeen); $this->problems[] = $problem; $seen = []; $literals = $conflictRule->getLiterals(); foreach ($literals as $literal) { // skip the one true literal if ($this->decisions->satisfy($literal)) { continue; } $seen[\abs($literal)] = \true; } foreach ($this->decisions as $decision) { $decisionLiteral = $decision[\Composer\DependencyResolver\Decisions::DECISION_LITERAL]; // skip literals that are not in this rule if (!isset($seen[\abs($decisionLiteral)])) { continue; } $why = $decision[\Composer\DependencyResolver\Decisions::DECISION_REASON]; $problem->addRule($why); $this->analyzeUnsolvableRule($problem, $why, $ruleSeen); $literals = $why->getLiterals(); foreach ($literals as $literal) { // skip the one true literal if ($this->decisions->satisfy($literal)) { continue; } $seen[\abs($literal)] = \true; } } } private function runSat() : void { $this->propagateIndex = 0; /* * here's the main loop: * 1) propagate new decisions (only needed once) * 2) fulfill root requires/fixed packages * 3) fulfill all unresolved rules * 4) minimalize solution if we had choices * if we encounter a problem, we rewind to a safe level and restart * with step 1 */ $level = 1; $systemLevel = $level + 1; while (\true) { if (1 === $level) { $conflictRule = $this->propagate($level); if (null !== $conflictRule) { $this->analyzeUnsolvable($conflictRule); return; } } // handle root require/fixed package rules if ($level < $systemLevel) { $iterator = $this->rules->getIteratorFor(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST); foreach ($iterator as $rule) { if ($rule->isEnabled()) { $decisionQueue = []; $noneSatisfied = \true; foreach ($rule->getLiterals() as $literal) { if ($this->decisions->satisfy($literal)) { $noneSatisfied = \false; break; } if ($literal > 0 && $this->decisions->undecided($literal)) { $decisionQueue[] = $literal; } } if ($noneSatisfied && \count($decisionQueue) > 0) { // if any of the options in the decision queue are fixed, only use those $prunedQueue = []; foreach ($decisionQueue as $literal) { if (isset($this->fixedMap[\abs($literal)])) { $prunedQueue[] = $literal; } } if (\count($prunedQueue) > 0) { $decisionQueue = $prunedQueue; } } if ($noneSatisfied && \count($decisionQueue) > 0) { $oLevel = $level; $level = $this->selectAndInstall($level, $decisionQueue, $rule); if (0 === $level) { return; } if ($level <= $oLevel) { break; } } } } $systemLevel = $level + 1; // root requires/fixed packages left $iterator->next(); if ($iterator->valid()) { continue; } } if ($level < $systemLevel) { $systemLevel = $level; } $rulesCount = \count($this->rules); $pass = 1; $this->io->writeError('Looking at all rules.', \true, IOInterface::DEBUG); for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) { if ($i === $rulesCount) { if (1 === $pass) { $this->io->writeError("Something's changed, looking at all rules again (pass #{$pass})", \false, IOInterface::DEBUG); } else { $this->io->overwriteError("Something's changed, looking at all rules again (pass #{$pass})", \false, null, IOInterface::DEBUG); } $i = 0; $pass++; } $rule = $this->rules->ruleById[$i]; $literals = $rule->getLiterals(); if ($rule->isDisabled()) { continue; } $decisionQueue = []; // make sure that // * all negative literals are installed // * no positive literal is installed // i.e. the rule is not fulfilled and we // just need to decide on the positive literals // foreach ($literals as $literal) { if ($literal <= 0) { if (!$this->decisions->decidedInstall($literal)) { continue 2; // next rule } } else { if ($this->decisions->decidedInstall($literal)) { continue 2; // next rule } if ($this->decisions->undecided($literal)) { $decisionQueue[] = $literal; } } } // need to have at least 2 item to pick from if (\count($decisionQueue) < 2) { continue; } $level = $this->selectAndInstall($level, $decisionQueue, $rule); if (0 === $level) { return; } // something changed, so look at all rules again $rulesCount = \count($this->rules); $n = -1; } if ($level < $systemLevel) { continue; } // minimization step if (\count($this->branches) > 0) { $lastLiteral = null; $lastLevel = null; $lastBranchIndex = 0; $lastBranchOffset = 0; for ($i = \count($this->branches) - 1; $i >= 0; $i--) { [$literals, $l] = $this->branches[$i]; foreach ($literals as $offset => $literal) { if ($literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) { $lastLiteral = $literal; $lastBranchIndex = $i; $lastBranchOffset = $offset; $lastLevel = $l; } } } if ($lastLiteral !== null) { \assert($lastLevel !== null); unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]); $level = $lastLevel; $this->revert($level); $why = $this->decisions->lastReason(); $level = $this->setPropagateLearn($level, $lastLiteral, $why); if ($level === 0) { return; } continue; } } break; } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Link; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositorySet; use Composer\Package\Version\VersionParser; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; /** * @author Nils Adermann * @author Ruben Gonzalez * @phpstan-type ReasonData Link|BasePackage|string|int|array{packageName: string, constraint: ConstraintInterface}|array{package: BasePackage} */ abstract class Rule { // reason constants and // their reason data contents public const RULE_ROOT_REQUIRE = 2; // array{packageName: string, constraint: ConstraintInterface} public const RULE_FIXED = 3; // array{package: BasePackage} public const RULE_PACKAGE_CONFLICT = 6; // Link public const RULE_PACKAGE_REQUIRES = 7; // Link public const RULE_PACKAGE_SAME_NAME = 10; // string (package name) public const RULE_LEARNED = 12; // int (rule id) public const RULE_PACKAGE_ALIAS = 13; // BasePackage public const RULE_PACKAGE_INVERSE_ALIAS = 14; // BasePackage // bitfield defs private const BITFIELD_TYPE = 0; private const BITFIELD_REASON = 8; private const BITFIELD_DISABLED = 16; /** @var int */ protected $bitfield; /** @var Request */ protected $request; /** * @var Link|BasePackage|ConstraintInterface|string * @phpstan-var ReasonData */ protected $reasonData; /** * @param self::RULE_* $reason A RULE_* constant describing the reason for generating this rule * @param mixed $reasonData * * @phpstan-param ReasonData $reasonData */ public function __construct($reason, $reasonData) { $this->reasonData = $reasonData; $this->bitfield = 0 << self::BITFIELD_DISABLED | $reason << self::BITFIELD_REASON | 255 << self::BITFIELD_TYPE; } /** * @return list */ public abstract function getLiterals() : array; /** * @return int|string */ public abstract function getHash(); public abstract function __toString() : string; public abstract function equals(\Composer\DependencyResolver\Rule $rule) : bool; /** * @return self::RULE_* */ public function getReason() : int { return ($this->bitfield & 255 << self::BITFIELD_REASON) >> self::BITFIELD_REASON; } /** * @phpstan-return ReasonData */ public function getReasonData() { return $this->reasonData; } public function getRequiredPackage() : ?string { switch ($this->getReason()) { case self::RULE_ROOT_REQUIRE: return $this->getReasonData()['packageName']; case self::RULE_FIXED: return $this->getReasonData()['package']->getName(); case self::RULE_PACKAGE_REQUIRES: return $this->getReasonData()->getTarget(); } return null; } /** * @param RuleSet::TYPE_* $type */ public function setType($type) : void { $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_TYPE) | (255 & $type) << self::BITFIELD_TYPE; } public function getType() : int { return ($this->bitfield & 255 << self::BITFIELD_TYPE) >> self::BITFIELD_TYPE; } public function disable() : void { $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED) | 1 << self::BITFIELD_DISABLED; } public function enable() : void { $this->bitfield &= ~(255 << self::BITFIELD_DISABLED); } public function isDisabled() : bool { return 0 !== ($this->bitfield & 255 << self::BITFIELD_DISABLED) >> self::BITFIELD_DISABLED; } public function isEnabled() : bool { return 0 === ($this->bitfield & 255 << self::BITFIELD_DISABLED) >> self::BITFIELD_DISABLED; } public abstract function isAssertion() : bool; public function isCausedByLock(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool) : bool { if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) { if (PlatformRepository::isPlatformPackage($this->getReasonData()->getTarget())) { return \false; } if ($request->getLockedRepository() !== null) { foreach ($request->getLockedRepository()->getPackages() as $package) { if ($package->getName() === $this->getReasonData()->getTarget()) { if ($pool->isUnacceptableFixedOrLockedPackage($package)) { return \true; } if (!$this->getReasonData()->getConstraint()->matches(new Constraint('=', $package->getVersion()))) { return \true; } // required package was locked but has been unlocked and still matches if (!$request->isLockedPackage($package)) { return \true; } break; } } } } if ($this->getReason() === self::RULE_ROOT_REQUIRE) { if (PlatformRepository::isPlatformPackage($this->getReasonData()['packageName'])) { return \false; } if ($request->getLockedRepository() !== null) { foreach ($request->getLockedRepository()->getPackages() as $package) { if ($package->getName() === $this->getReasonData()['packageName']) { if ($pool->isUnacceptableFixedOrLockedPackage($package)) { return \true; } if (!$this->getReasonData()['constraint']->matches(new Constraint('=', $package->getVersion()))) { return \true; } break; } } } } return \false; } /** * @internal */ public function getSourcePackage(\Composer\DependencyResolver\Pool $pool) : BasePackage { $literals = $this->getLiterals(); switch ($this->getReason()) { case self::RULE_PACKAGE_CONFLICT: $package1 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0])); $package2 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1])); $reasonData = $this->getReasonData(); // swap literals if they are not in the right order with package2 being the conflicter if ($reasonData->getSource() === $package1->getName()) { [$package2, $package1] = [$package1, $package2]; } return $package2; case self::RULE_PACKAGE_REQUIRES: $sourceLiteral = $literals[0]; $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral)); return $sourcePackage; default: throw new \LogicException('Not implemented'); } } /** * @param BasePackage[] $installedMap * @param array $learnedPool */ public function getPrettyString(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, array $installedMap = [], array $learnedPool = []) : string { $literals = $this->getLiterals(); switch ($this->getReason()) { case self::RULE_ROOT_REQUIRE: $reasonData = $this->getReasonData(); $packageName = $reasonData['packageName']; $constraint = $reasonData['constraint']; $packages = $pool->whatProvides($packageName, $constraint); if (0 === \count($packages)) { return 'No package found to satisfy root composer.json require ' . $packageName . ' ' . $constraint->getPrettyString(); } $packagesNonAlias = \array_values(\array_filter($packages, static function ($p) : bool { return !$p instanceof AliasPackage; })); if (\count($packagesNonAlias) === 1) { $package = $packagesNonAlias[0]; if ($request->isLockedPackage($package)) { return $package->getPrettyName() . ' is locked to version ' . $package->getPrettyVersion() . " and an update of this package was not requested."; } } return 'Root composer.json requires ' . $packageName . ' ' . $constraint->getPrettyString() . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $packages, $isVerbose, $constraint) . '.'; case self::RULE_FIXED: $package = $this->deduplicateDefaultBranchAlias($this->getReasonData()['package']); if ($request->isLockedPackage($package)) { return $package->getPrettyName() . ' is locked to version ' . $package->getPrettyVersion() . ' and an update of this package was not requested.'; } return $package->getPrettyName() . ' is present at version ' . $package->getPrettyVersion() . ' and cannot be modified by Composer'; case self::RULE_PACKAGE_CONFLICT: $package1 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0])); $package2 = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1])); $conflictTarget = $package1->getPrettyString(); $reasonData = $this->getReasonData(); // swap literals if they are not in the right order with package2 being the conflicter if ($reasonData->getSource() === $package1->getName()) { [$package2, $package1] = [$package1, $package2]; $conflictTarget = $package1->getPrettyName() . ' ' . $reasonData->getPrettyConstraint(); } // if the conflict is not directly against the package but something it provides/replaces, // we try to find that link to display a better message if ($reasonData->getTarget() !== $package1->getName()) { $provideType = null; $provided = null; foreach ($package1->getProvides() as $provide) { if ($provide->getTarget() === $reasonData->getTarget()) { $provideType = 'provides'; $provided = $provide->getPrettyConstraint(); break; } } foreach ($package1->getReplaces() as $replace) { if ($replace->getTarget() === $reasonData->getTarget()) { $provideType = 'replaces'; $provided = $replace->getPrettyConstraint(); break; } } if (null !== $provideType) { $conflictTarget = $reasonData->getTarget() . ' ' . $reasonData->getPrettyConstraint() . ' (' . $package1->getPrettyString() . ' ' . $provideType . ' ' . $reasonData->getTarget() . ' ' . $provided . ')'; } } return $package2->getPrettyString() . ' conflicts with ' . $conflictTarget . '.'; case self::RULE_PACKAGE_REQUIRES: \assert(\count($literals) > 0); $sourceLiteral = \array_shift($literals); $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral)); $reasonData = $this->getReasonData(); $requires = []; foreach ($literals as $literal) { $requires[] = $pool->literalToPackage($literal); } $text = $reasonData->getPrettyString($sourcePackage); if (\count($requires) > 0) { $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose, $reasonData->getConstraint()) . '.'; } else { $targetName = $reasonData->getTarget(); $reason = \Composer\DependencyResolver\Problem::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $targetName, $reasonData->getConstraint()); return $text . ' -> ' . $reason[1]; } return $text; case self::RULE_PACKAGE_SAME_NAME: $packageNames = []; foreach ($literals as $literal) { $package = $pool->literalToPackage($literal); $packageNames[$package->getName()] = \true; } unset($literal); $replacedName = $this->getReasonData(); if (\count($packageNames) > 1) { if (!isset($packageNames[$replacedName])) { $reason = 'They ' . (\count($literals) === 2 ? 'both' : 'all') . ' replace ' . $replacedName . ' and thus cannot coexist.'; } else { $replacerNames = $packageNames; unset($replacerNames[$replacedName]); $replacerNames = \array_keys($replacerNames); if (\count($replacerNames) === 1) { $reason = $replacerNames[0] . ' replaces '; } else { $reason = '[' . \implode(', ', $replacerNames) . '] replace '; } $reason .= $replacedName . ' and thus cannot coexist with it.'; } $installedPackages = []; $removablePackages = []; foreach ($literals as $literal) { if (isset($installedMap[\abs($literal)])) { $installedPackages[] = $pool->literalToPackage($literal); } else { $removablePackages[] = $pool->literalToPackage($literal); } } if (\count($installedPackages) > 0 && \count($removablePackages) > 0) { return $this->formatPackagesUnique($pool, $removablePackages, $isVerbose, null, \true) . ' cannot be installed as that would require removing ' . $this->formatPackagesUnique($pool, $installedPackages, $isVerbose, null, \true) . '. ' . $reason; } return 'Only one of these can be installed: ' . $this->formatPackagesUnique($pool, $literals, $isVerbose, null, \true) . '. ' . $reason; } return 'You can only install one version of a package, so only one of these can be installed: ' . $this->formatPackagesUnique($pool, $literals, $isVerbose, null, \true) . '.'; case self::RULE_LEARNED: /** @TODO currently still generates way too much output to be helpful, and in some cases can even lead to endless recursion */ // if (isset($learnedPool[$this->getReasonData()])) { // echo $this->getReasonData()."\n"; // $learnedString = ', learned rules:' . Problem::formatDeduplicatedRules($learnedPool[$this->getReasonData()], ' ', $repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool); // } else { // $learnedString = ' (reasoning unavailable)'; // } $learnedString = ' (conflict analysis result)'; if (\count($literals) === 1) { $ruleText = $pool->literalToPrettyString($literals[0], $installedMap); } else { $groups = []; foreach ($literals as $literal) { $package = $pool->literalToPackage($literal); if (isset($installedMap[$package->id])) { $group = $literal > 0 ? 'keep' : 'remove'; } else { $group = $literal > 0 ? 'install' : 'don\'t install'; } $groups[$group][] = $this->deduplicateDefaultBranchAlias($package); } $ruleTexts = []; foreach ($groups as $group => $packages) { $ruleTexts[] = $group . (\count($packages) > 1 ? ' one of' : '') . ' ' . $this->formatPackagesUnique($pool, $packages, $isVerbose); } $ruleText = \implode(' | ', $ruleTexts); } return 'Conclusion: ' . $ruleText . $learnedString; case self::RULE_PACKAGE_ALIAS: $aliasPackage = $pool->literalToPackage($literals[0]); // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless if ($aliasPackage->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { return ''; } $package = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[1])); return $aliasPackage->getPrettyString() . ' is an alias of ' . $package->getPrettyString() . ' and thus requires it to be installed too.'; case self::RULE_PACKAGE_INVERSE_ALIAS: // inverse alias rules work the other way around than above $aliasPackage = $pool->literalToPackage($literals[1]); // avoid returning content like "9999999-dev is an alias of dev-master" as it is useless if ($aliasPackage->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { return ''; } $package = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($literals[0])); return $aliasPackage->getPrettyString() . ' is an alias of ' . $package->getPrettyString() . ' and must be installed with it.'; default: $ruleText = ''; foreach ($literals as $i => $literal) { if ($i !== 0) { $ruleText .= '|'; } $ruleText .= $pool->literalToPrettyString($literal, $installedMap); } return '(' . $ruleText . ')'; } } /** * @param array $literalsOrPackages An array containing packages or literals */ protected function formatPackagesUnique(\Composer\DependencyResolver\Pool $pool, array $literalsOrPackages, bool $isVerbose, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = \false) : string { $packages = []; foreach ($literalsOrPackages as $package) { $packages[] = \is_object($package) ? $package : $pool->literalToPackage($package); } return \Composer\DependencyResolver\Problem::getPackageList($packages, $isVerbose, $pool, $constraint, $useRemovedVersionGroup); } private function deduplicateDefaultBranchAlias(BasePackage $package) : BasePackage { if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { $package = $package->getAliasOf(); } return $package; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * @author Nils Adermann * @phpstan-import-type ReasonData from Rule */ class Rule2Literals extends \Composer\DependencyResolver\Rule { /** @var int */ protected $literal1; /** @var int */ protected $literal2; /** * @param Rule::RULE_* $reason A RULE_* constant * @param mixed $reasonData * * @phpstan-param ReasonData $reasonData */ public function __construct(int $literal1, int $literal2, $reason, $reasonData) { parent::__construct($reason, $reasonData); if ($literal1 < $literal2) { $this->literal1 = $literal1; $this->literal2 = $literal2; } else { $this->literal1 = $literal2; $this->literal2 = $literal1; } } /** * @return non-empty-list */ public function getLiterals() : array { return [$this->literal1, $this->literal2]; } /** * @inheritDoc */ public function getHash() { return $this->literal1 . ',' . $this->literal2; } /** * Checks if this rule is equal to another one * * Ignores whether either of the rules is disabled. * * @param Rule $rule The rule to check against * @return bool Whether the rules are equal */ public function equals(\Composer\DependencyResolver\Rule $rule) : bool { // specialized fast-case if ($rule instanceof self) { if ($this->literal1 !== $rule->literal1) { return \false; } if ($this->literal2 !== $rule->literal2) { return \false; } return \true; } $literals = $rule->getLiterals(); if (2 !== \count($literals)) { return \false; } if ($this->literal1 !== $literals[0]) { return \false; } if ($this->literal2 !== $literals[1]) { return \false; } return \true; } /** @return false */ public function isAssertion() : bool { return \false; } /** * Formats a rule as a string of the format (Literal1|Literal2|...) */ public function __toString() : string { $result = $this->isDisabled() ? 'disabled(' : '('; $result .= $this->literal1 . '|' . $this->literal2 . ')'; return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Util\IniHelper; use Composer\Repository\RepositorySet; /** * @author Nils Adermann * * @method self::ERROR_DEPENDENCY_RESOLUTION_FAILED getCode() */ class SolverProblemsException extends \RuntimeException { public const ERROR_DEPENDENCY_RESOLUTION_FAILED = 2; /** @var Problem[] */ protected $problems; /** @var array */ protected $learnedPool; /** * @param Problem[] $problems * @param array $learnedPool */ public function __construct(array $problems, array $learnedPool) { $this->problems = $problems; $this->learnedPool = $learnedPool; parent::__construct('Failed resolving dependencies with ' . \count($problems) . ' problems, call getPrettyString to get formatted details', self::ERROR_DEPENDENCY_RESOLUTION_FAILED); } public function getPrettyString(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, bool $isDevExtraction = \false) : string { $installedMap = $request->getPresentMap(\true); $missingExtensions = []; $isCausedByLock = \false; $problems = []; foreach ($this->problems as $problem) { $problems[] = $problem->getPrettyString($repositorySet, $request, $pool, $isVerbose, $installedMap, $this->learnedPool) . "\n"; $missingExtensions = \array_merge($missingExtensions, $this->getExtensionProblems($problem->getReasons())); $isCausedByLock = $isCausedByLock || $problem->isCausedByLock($repositorySet, $request, $pool); } $i = 1; $text = "\n"; foreach (\array_unique($problems) as $problem) { $text .= " Problem " . $i++ . $problem; } $hints = []; if (!$isDevExtraction && (\str_contains($text, 'could not be found') || \str_contains($text, 'no matching package found'))) { $hints[] = "Potential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead for further common problems."; } if (\count($missingExtensions) > 0) { $hints[] = $this->createExtensionHint($missingExtensions); } if ($isCausedByLock && !$isDevExtraction && !$request->getUpdateAllowTransitiveRootDependencies()) { $hints[] = "Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions."; } if (\str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match') && \str_contains($text, '- ocramius/package-versions')) { $hints[] = "ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.\nIf you can not upgrade PHP you can require composer/package-versions-deprecated to resolve this with PHP 7.0+."; } if (!\class_exists('_ContaoManager\\PHPUnit\\Framework\\TestCase', \false)) { if (\str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match')) { $hints[] = "You are using Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report a plugin-issue to ask them to support Composer 2."; } } if (\count($hints) > 0) { $text .= "\n" . \implode("\n\n", $hints); } return $text; } /** * @return Problem[] */ public function getProblems() : array { return $this->problems; } /** * @param string[] $missingExtensions */ private function createExtensionHint(array $missingExtensions) : string { $paths = IniHelper::getAll(); if ('' === $paths[0]) { if (\count($paths) === 1) { return ''; } \array_shift($paths); } $ignoreExtensionsArguments = \implode(" ", \array_map(static function ($extension) { return "--ignore-platform-req={$extension}"; }, \array_unique($missingExtensions))); $text = "To enable extensions, verify that they are enabled in your .ini files:\n - "; $text .= \implode("\n - ", $paths); $text .= "\nYou can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode."; $text .= "\nAlternatively, you can run Composer with `{$ignoreExtensionsArguments}` to temporarily ignore these required extensions."; return $text; } /** * @param Rule[][] $reasonSets * @return string[] */ private function getExtensionProblems(array $reasonSets) : array { $missingExtensions = []; foreach ($reasonSets as $reasonSet) { foreach ($reasonSet as $rule) { $required = $rule->getRequiredPackage(); if (null !== $required && 0 === \strpos($required, 'ext-')) { $missingExtensions[$required] = 1; } } } return \array_keys($missingExtensions); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * @author Nils Adermann */ class SolverBugException extends \RuntimeException { public function __construct(string $message) { parent::__construct($message . "\nThis exception was most likely caused by a bug in Composer.\n" . "Please report the command you ran, the exact error you received, and your composer.json on https://github.com/composer/composer/issues - thank you!\n"); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Semver\CompilingMatcher; use Composer\Semver\Constraint\Constraint; /** * @author Nils Adermann * @author Jordi Boggiano */ class DefaultPolicy implements \Composer\DependencyResolver\PolicyInterface { /** @var bool */ private $preferStable; /** @var bool */ private $preferLowest; /** @var array|null */ private $preferredVersions; /** @var array>> */ private $preferredPackageResultCachePerPool; /** @var array> */ private $sortingCachePerPool; /** * @param array|null $preferredVersions Must be an array of package name => normalized version */ public function __construct(bool $preferStable = \false, bool $preferLowest = \false, ?array $preferredVersions = null) { $this->preferStable = $preferStable; $this->preferLowest = $preferLowest; $this->preferredVersions = $preferredVersions; } /** * @param string $operator One of Constraint::STR_OP_* * * @phpstan-param Constraint::STR_OP_* $operator */ public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator) : bool { if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) { return BasePackage::STABILITIES[$stabA] < BasePackage::STABILITIES[$stabB]; } // dev versions need to be compared as branches via matchSpecific's special treatment, the rest can be optimized with compiling matcher if ($a->isDev() && \str_starts_with($a->getVersion(), 'dev-') || $b->isDev() && \str_starts_with($b->getVersion(), 'dev-')) { $constraint = new Constraint($operator, $b->getVersion()); $version = new Constraint('==', $a->getVersion()); return $constraint->matchSpecific($version, \true); } return CompilingMatcher::match(new Constraint($operator, $b->getVersion()), Constraint::OP_EQ, $a->getVersion()); } /** * @param non-empty-list $literals * @return non-empty-list */ public function selectPreferredPackages(\Composer\DependencyResolver\Pool $pool, array $literals, ?string $requiredPackage = null) : array { \sort($literals); $resultCacheKey = \implode(',', $literals) . $requiredPackage; $poolId = \spl_object_id($pool); if (isset($this->preferredPackageResultCachePerPool[$poolId][$resultCacheKey])) { return $this->preferredPackageResultCachePerPool[$poolId][$resultCacheKey]; } $packages = $this->groupLiteralsByName($pool, $literals); foreach ($packages as &$nameLiterals) { \usort($nameLiterals, function ($a, $b) use($pool, $requiredPackage, $poolId) : int { $cacheKey = 'i' . $a . '.' . $b . $requiredPackage; // i prefix -> ignoreReplace = true if (isset($this->sortingCachePerPool[$poolId][$cacheKey])) { return $this->sortingCachePerPool[$poolId][$cacheKey]; } return $this->sortingCachePerPool[$poolId][$cacheKey] = $this->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, \true); }); } foreach ($packages as &$sortedLiterals) { $sortedLiterals = $this->pruneToBestVersion($pool, $sortedLiterals); $sortedLiterals = $this->pruneRemoteAliases($pool, $sortedLiterals); } $selected = \array_merge(...\array_values($packages)); // now sort the result across all packages to respect replaces across packages \usort($selected, function ($a, $b) use($pool, $requiredPackage, $poolId) : int { $cacheKey = $a . '.' . $b . $requiredPackage; // no i prefix -> ignoreReplace = false if (isset($this->sortingCachePerPool[$poolId][$cacheKey])) { return $this->sortingCachePerPool[$poolId][$cacheKey]; } return $this->sortingCachePerPool[$poolId][$cacheKey] = $this->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage); }); return $this->preferredPackageResultCachePerPool[$poolId][$resultCacheKey] = $selected; } /** * @param non-empty-list $literals * @return non-empty-array> */ protected function groupLiteralsByName(\Composer\DependencyResolver\Pool $pool, array $literals) : array { $packages = []; foreach ($literals as $literal) { $packageName = $pool->literalToPackage($literal)->getName(); if (!isset($packages[$packageName])) { $packages[$packageName] = []; } $packages[$packageName][] = $literal; } return $packages; } /** * @protected */ public function compareByPriority(\Composer\DependencyResolver\Pool $pool, BasePackage $a, BasePackage $b, ?string $requiredPackage = null, bool $ignoreReplace = \false) : int { // prefer aliases to the original package if ($a->getName() === $b->getName()) { $aAliased = $a instanceof AliasPackage; $bAliased = $b instanceof AliasPackage; if ($aAliased && !$bAliased) { return -1; // use a } if (!$aAliased && $bAliased) { return 1; // use b } } if (!$ignoreReplace) { // return original, not replaced if ($this->replaces($a, $b)) { return 1; // use b } if ($this->replaces($b, $a)) { return -1; // use a } // for replacers not replacing each other, put a higher prio on replacing // packages with the same vendor as the required package if ($requiredPackage !== null && \false !== ($pos = \strpos($requiredPackage, '/'))) { $requiredVendor = \substr($requiredPackage, 0, $pos); $aIsSameVendor = \strpos($a->getName(), $requiredVendor) === 0; $bIsSameVendor = \strpos($b->getName(), $requiredVendor) === 0; if ($bIsSameVendor !== $aIsSameVendor) { return $aIsSameVendor ? -1 : 1; } } } // priority equal, sort by package id to make reproducible if ($a->id === $b->id) { return 0; } return $a->id < $b->id ? -1 : 1; } /** * Checks if source replaces a package with the same name as target. * * Replace constraints are ignored. This method should only be used for * prioritisation, not for actual constraint verification. */ protected function replaces(BasePackage $source, BasePackage $target) : bool { foreach ($source->getReplaces() as $link) { if ($link->getTarget() === $target->getName()) { return \true; } } return \false; } /** * @param list $literals * @return list */ protected function pruneToBestVersion(\Composer\DependencyResolver\Pool $pool, array $literals) : array { if ($this->preferredVersions !== null) { $name = $pool->literalToPackage($literals[0])->getName(); if (isset($this->preferredVersions[$name])) { $preferredVersion = $this->preferredVersions[$name]; $bestLiterals = []; foreach ($literals as $literal) { if ($pool->literalToPackage($literal)->getVersion() === $preferredVersion) { $bestLiterals[] = $literal; } } if (\count($bestLiterals) > 0) { return $bestLiterals; } } } $operator = $this->preferLowest ? '<' : '>'; $bestLiterals = [$literals[0]]; $bestPackage = $pool->literalToPackage($literals[0]); foreach ($literals as $i => $literal) { if (0 === $i) { continue; } $package = $pool->literalToPackage($literal); if ($this->versionCompare($package, $bestPackage, $operator)) { $bestPackage = $package; $bestLiterals = [$literal]; } elseif ($this->versionCompare($package, $bestPackage, '==')) { $bestLiterals[] = $literal; } } return $bestLiterals; } /** * Assumes that locally aliased (in root package requires) packages take priority over branch-alias ones * * If no package is a local alias, nothing happens * * @param list $literals * @return list */ protected function pruneRemoteAliases(\Composer\DependencyResolver\Pool $pool, array $literals) : array { $hasLocalAlias = \false; foreach ($literals as $literal) { $package = $pool->literalToPackage($literal); if ($package instanceof AliasPackage && $package->isRootPackageAlias()) { $hasLocalAlias = \true; break; } } if (!$hasLocalAlias) { return $literals; } $selected = []; foreach ($literals as $literal) { $package = $pool->literalToPackage($literal); if ($package instanceof AliasPackage && $package->isRootPackageAlias()) { $selected[] = $literal; } } return $selected; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * Wrapper around a Rule which keeps track of the two literals it watches * * Used by RuleWatchGraph to store rules in two RuleWatchChains. * * @author Nils Adermann */ class RuleWatchNode { /** @var int */ public $watch1; /** @var int */ public $watch2; /** @var Rule */ protected $rule; /** * Creates a new node watching the first and second literals of the rule. * * @param Rule $rule The rule to wrap */ public function __construct(\Composer\DependencyResolver\Rule $rule) { $this->rule = $rule; $literals = $rule->getLiterals(); $literalCount = \count($literals); $this->watch1 = $literalCount > 0 ? $literals[0] : 0; $this->watch2 = $literalCount > 1 ? $literals[1] : 0; } /** * Places the second watch on the rule's literal, decided at the highest level * * Useful for learned rules where the literal for the highest rule is most * likely to quickly lead to further decisions. * * @param Decisions $decisions The decisions made so far by the solver */ public function watch2OnHighest(\Composer\DependencyResolver\Decisions $decisions) : void { $literals = $this->rule->getLiterals(); // if there are only 2 elements, both are being watched anyway if (\count($literals) < 3 || $this->rule instanceof \Composer\DependencyResolver\MultiConflictRule) { return; } $watchLevel = 0; foreach ($literals as $literal) { $level = $decisions->decisionLevel($literal); if ($level > $watchLevel) { $this->watch2 = $literal; $watchLevel = $level; } } } /** * Returns the rule this node wraps */ public function getRule() : \Composer\DependencyResolver\Rule { return $this->rule; } /** * Given one watched literal, this method returns the other watched literal * * @param int $literal The watched literal that should not be returned * @return int A literal */ public function getOtherWatch(int $literal) : int { if ($this->watch1 === $literal) { return $this->watch2; } return $this->watch1; } /** * Moves a watch from one literal to another * * @param int $from The previously watched literal * @param int $to The literal to be watched now */ public function moveWatch(int $from, int $to) : void { if ($this->watch1 === $from) { $this->watch1 = $to; } else { $this->watch2 = $to; } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Repository\RepositorySet; /** * @author Nils Adermann * @implements \IteratorAggregate * @internal * @final */ class RuleSet implements \IteratorAggregate, \Countable { // highest priority => lowest number public const TYPE_PACKAGE = 0; public const TYPE_REQUEST = 1; public const TYPE_LEARNED = 4; /** * READ-ONLY: Lookup table for rule id to rule object * * @var array */ public $ruleById = []; const TYPES = [self::TYPE_PACKAGE => 'PACKAGE', self::TYPE_REQUEST => 'REQUEST', self::TYPE_LEARNED => 'LEARNED']; /** @var array */ protected $rules; /** @var 0|positive-int */ protected $nextRuleId = 0; /** @var array */ protected $rulesByHash = []; public function __construct() { foreach ($this->getTypes() as $type) { $this->rules[$type] = []; } } /** * @param self::TYPE_* $type */ public function add(\Composer\DependencyResolver\Rule $rule, $type) : void { if (!isset(self::TYPES[$type])) { throw new \OutOfBoundsException('Unknown rule type: ' . $type); } $hash = $rule->getHash(); // Do not add if rule already exists if (isset($this->rulesByHash[$hash])) { $potentialDuplicates = $this->rulesByHash[$hash]; if (\is_array($potentialDuplicates)) { foreach ($potentialDuplicates as $potentialDuplicate) { if ($rule->equals($potentialDuplicate)) { return; } } } else { if ($rule->equals($potentialDuplicates)) { return; } } } if (!isset($this->rules[$type])) { $this->rules[$type] = []; } $this->rules[$type][] = $rule; $this->ruleById[$this->nextRuleId] = $rule; $rule->setType($type); $this->nextRuleId++; if (!isset($this->rulesByHash[$hash])) { $this->rulesByHash[$hash] = $rule; } elseif (\is_array($this->rulesByHash[$hash])) { $this->rulesByHash[$hash][] = $rule; } else { $originalRule = $this->rulesByHash[$hash]; $this->rulesByHash[$hash] = [$originalRule, $rule]; } } public function count() : int { return $this->nextRuleId; } public function ruleById(int $id) : \Composer\DependencyResolver\Rule { return $this->ruleById[$id]; } /** @return array */ public function getRules() : array { return $this->rules; } public function getIterator() : \Composer\DependencyResolver\RuleSetIterator { return new \Composer\DependencyResolver\RuleSetIterator($this->getRules()); } /** * @param self::TYPE_*|array $types */ public function getIteratorFor($types) : \Composer\DependencyResolver\RuleSetIterator { if (!\is_array($types)) { $types = [$types]; } $allRules = $this->getRules(); /** @var array $rules */ $rules = []; foreach ($types as $type) { $rules[$type] = $allRules[$type]; } return new \Composer\DependencyResolver\RuleSetIterator($rules); } /** * @param array|self::TYPE_* $types */ public function getIteratorWithout($types) : \Composer\DependencyResolver\RuleSetIterator { if (!\is_array($types)) { $types = [$types]; } $rules = $this->getRules(); foreach ($types as $type) { unset($rules[$type]); } return new \Composer\DependencyResolver\RuleSetIterator($rules); } /** * @return array{self::TYPE_PACKAGE, self::TYPE_REQUEST, self::TYPE_LEARNED} */ public function getTypes() : array { $types = self::TYPES; return \array_keys($types); } public function getPrettyString(?RepositorySet $repositorySet = null, ?\Composer\DependencyResolver\Request $request = null, ?\Composer\DependencyResolver\Pool $pool = null, bool $isVerbose = \false) : string { $string = "\n"; foreach ($this->rules as $type => $rules) { $string .= \str_pad(self::TYPES[$type], 8, ' ') . ": "; foreach ($rules as $rule) { $string .= ($repositorySet !== null && $request !== null && $pool !== null ? $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose) : $rule) . "\n"; } $string .= "\n\n"; } return $string; } public function __toString() : string { return $this->getPrettyString(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\BasePackage; use Composer\Package\Version\VersionParser; use Composer\Semver\CompilingMatcher; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\Constraint; /** * A package pool contains all packages for dependency resolution * * @author Nils Adermann * @author Jordi Boggiano */ class Pool implements \Countable { /** @var BasePackage[] */ protected $packages = []; /** @var array */ protected $packageByName = []; /** @var VersionParser */ protected $versionParser; /** @var array> */ protected $providerCache = []; /** @var BasePackage[] */ protected $unacceptableFixedOrLockedPackages; /** @var array> Map of package name => normalized version => pretty version */ protected $removedVersions = []; /** @var array> Map of package object hash => removed normalized versions => removed pretty version */ protected $removedVersionsByPackage = []; /** * @param BasePackage[] $packages * @param BasePackage[] $unacceptableFixedOrLockedPackages * @param array> $removedVersions * @param array> $removedVersionsByPackage */ public function __construct(array $packages = [], array $unacceptableFixedOrLockedPackages = [], array $removedVersions = [], array $removedVersionsByPackage = []) { $this->versionParser = new VersionParser(); $this->setPackages($packages); $this->unacceptableFixedOrLockedPackages = $unacceptableFixedOrLockedPackages; $this->removedVersions = $removedVersions; $this->removedVersionsByPackage = $removedVersionsByPackage; } /** * @return array */ public function getRemovedVersions(string $name, ConstraintInterface $constraint) : array { if (!isset($this->removedVersions[$name])) { return []; } $result = []; foreach ($this->removedVersions[$name] as $version => $prettyVersion) { if ($constraint->matches(new Constraint('==', $version))) { $result[$version] = $prettyVersion; } } return $result; } /** * @return array */ public function getRemovedVersionsByPackage(string $objectHash) : array { if (!isset($this->removedVersionsByPackage[$objectHash])) { return []; } return $this->removedVersionsByPackage[$objectHash]; } /** * @param BasePackage[] $packages */ private function setPackages(array $packages) : void { $id = 1; foreach ($packages as $package) { $this->packages[] = $package; $package->id = $id++; foreach ($package->getNames() as $provided) { $this->packageByName[$provided][] = $package; } } } /** * @return BasePackage[] */ public function getPackages() : array { return $this->packages; } /** * Retrieves the package object for a given package id. */ public function packageById(int $id) : BasePackage { return $this->packages[$id - 1]; } /** * Returns how many packages have been loaded into the pool */ public function count() : int { return \count($this->packages); } /** * Searches all packages providing the given package name and match the constraint * * @param string $name The package name to be searched for * @param ?ConstraintInterface $constraint A constraint that all returned * packages must match or null to return all * @return BasePackage[] A set of packages */ public function whatProvides(string $name, ?ConstraintInterface $constraint = null) : array { $key = (string) $constraint; if (isset($this->providerCache[$name][$key])) { return $this->providerCache[$name][$key]; } return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint); } /** * @param string $name The package name to be searched for * @param ?ConstraintInterface $constraint A constraint that all returned * packages must match or null to return all * @return BasePackage[] */ private function computeWhatProvides(string $name, ?ConstraintInterface $constraint = null) : array { if (!isset($this->packageByName[$name])) { return []; } $matches = []; foreach ($this->packageByName[$name] as $candidate) { if ($this->match($candidate, $name, $constraint)) { $matches[] = $candidate; } } return $matches; } public function literalToPackage(int $literal) : BasePackage { $packageId = \abs($literal); return $this->packageById($packageId); } /** * @param array $installedMap */ public function literalToPrettyString(int $literal, array $installedMap) : string { $package = $this->literalToPackage($literal); if (isset($installedMap[$package->id])) { $prefix = $literal > 0 ? 'keep' : 'remove'; } else { $prefix = $literal > 0 ? 'install' : 'don\'t install'; } return $prefix . ' ' . $package->getPrettyString(); } /** * Checks if the package matches the given constraint directly or through * provided or replaced packages * * @param string $name Name of the package to be matched */ public function match(BasePackage $candidate, string $name, ?ConstraintInterface $constraint = null) : bool { $candidateName = $candidate->getName(); $candidateVersion = $candidate->getVersion(); if ($candidateName === $name) { return $constraint === null || CompilingMatcher::match($constraint, Constraint::OP_EQ, $candidateVersion); } $provides = $candidate->getProvides(); $replaces = $candidate->getReplaces(); // aliases create multiple replaces/provides for one target so they can not use the shortcut below if (isset($replaces[0]) || isset($provides[0])) { foreach ($provides as $link) { if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) { return \true; } } foreach ($replaces as $link) { if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) { return \true; } } return \false; } if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) { return \true; } if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) { return \true; } return \false; } public function isUnacceptableFixedOrLockedPackage(BasePackage $package) : bool { return \in_array($package, $this->unacceptableFixedOrLockedPackages, \true); } /** * @return BasePackage[] */ public function getUnacceptableFixedOrLockedPackages() : array { return $this->unacceptableFixedOrLockedPackages; } public function __toString() : string { $str = "Pool:\n"; foreach ($this->packages as $package) { $str .= '- ' . \str_pad((string) $package->id, 6, ' ', \STR_PAD_LEFT) . ': ' . $package->getName() . "\n"; } return $str; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * @author Nils Adermann * * MultiConflictRule([A, B, C]) acts as Rule([-A, -B]), Rule([-A, -C]), Rule([-B, -C]) */ class MultiConflictRule extends \Composer\DependencyResolver\Rule { /** @var non-empty-list */ protected $literals; /** * @param non-empty-list $literals */ public function __construct(array $literals, $reason, $reasonData) { parent::__construct($reason, $reasonData); if (\count($literals) < 3) { throw new \RuntimeException("multi conflict rule requires at least 3 literals"); } // sort all packages ascending by id \sort($literals); $this->literals = $literals; } /** * @return non-empty-list */ public function getLiterals() : array { return $this->literals; } /** * @inheritDoc */ public function getHash() { $data = \unpack('ihash', (string) \hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', 'c:' . \implode(',', $this->literals), \true)); if (\false === $data) { throw new \RuntimeException('Failed unpacking: ' . \implode(', ', $this->literals)); } return $data['hash']; } /** * Checks if this rule is equal to another one * * Ignores whether either of the rules is disabled. * * @param Rule $rule The rule to check against * @return bool Whether the rules are equal */ public function equals(\Composer\DependencyResolver\Rule $rule) : bool { if ($rule instanceof \Composer\DependencyResolver\MultiConflictRule) { return $this->literals === $rule->getLiterals(); } return \false; } public function isAssertion() : bool { return \false; } /** * @return never * @throws \RuntimeException */ public function disable() : void { throw new \RuntimeException("Disabling multi conflict rules is not possible. Please contact composer at https://github.com/composer/composer to let us debug what lead to this situation."); } /** * Formats a rule as a string of the format (Literal1|Literal2|...) */ public function __toString() : string { // TODO multi conflict? $result = $this->isDisabled() ? 'disabled(multi(' : '(multi('; foreach ($this->literals as $i => $literal) { if ($i !== 0) { $result .= '|'; } $result .= $literal; } $result .= '))'; return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Repository\LockArrayRepository; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\MatchAllConstraint; /** * @author Nils Adermann */ class Request { /** * Identifies a partial update for listed packages only, all dependencies will remain at locked versions */ public const UPDATE_ONLY_LISTED = 0; /** * Identifies a partial update for listed packages and recursively all their dependencies, however dependencies * also directly required by the root composer.json and their dependencies will remain at the locked version. */ public const UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE = 1; /** * Identifies a partial update for listed packages and recursively all their dependencies, even dependencies * also directly required by the root composer.json will be updated. */ public const UPDATE_LISTED_WITH_TRANSITIVE_DEPS = 2; /** @var ?LockArrayRepository */ protected $lockedRepository; /** @var array */ protected $requires = []; /** @var array */ protected $fixedPackages = []; /** @var array */ protected $lockedPackages = []; /** @var array */ protected $fixedLockedPackages = []; /** @var array */ protected $updateAllowList = []; /** @var false|self::UPDATE_* */ protected $updateAllowTransitiveDependencies = \false; /** @var non-empty-list|null */ private $restrictedPackages = null; public function __construct(?LockArrayRepository $lockedRepository = null) { $this->lockedRepository = $lockedRepository; } public function requireName(string $packageName, ?ConstraintInterface $constraint = null) : void { $packageName = \strtolower($packageName); if ($constraint === null) { $constraint = new MatchAllConstraint(); } if (isset($this->requires[$packageName])) { throw new \LogicException('Overwriting requires seems like a bug (' . $packageName . ' ' . $this->requires[$packageName]->getPrettyString() . ' => ' . $constraint->getPrettyString() . ', check why it is happening, might be a root alias'); } $this->requires[$packageName] = $constraint; } /** * Mark a package as currently present and having to remain installed * * This is used for platform packages which cannot be modified by Composer. A rule enforcing their installation is * generated for dependency resolution. Partial updates with dependencies cannot in any way modify these packages. */ public function fixPackage(BasePackage $package) : void { $this->fixedPackages[\spl_object_hash($package)] = $package; } /** * Mark a package as locked to a specific version but removable * * This is used for lock file packages which need to be treated similar to fixed packages by the pool builder in * that by default they should really only have the currently present version loaded and no remote alternatives. * * However unlike fixed packages there will not be a special rule enforcing their installation for the solver, so * if nothing requires these packages they will be removed. Additionally in a partial update these packages can be * unlocked, meaning other versions can be installed if explicitly requested as part of the update. */ public function lockPackage(BasePackage $package) : void { $this->lockedPackages[\spl_object_hash($package)] = $package; } /** * Marks a locked package fixed. So it's treated irremovable like a platform package. * * This is necessary for the composer install step which verifies the lock file integrity and should not allow * removal of any packages. At the same time lock packages there cannot simply be marked fixed, as error reporting * would then report them as platform packages, so this still marks them as locked packages at the same time. */ public function fixLockedPackage(BasePackage $package) : void { $this->fixedPackages[\spl_object_hash($package)] = $package; $this->fixedLockedPackages[\spl_object_hash($package)] = $package; } public function unlockPackage(BasePackage $package) : void { unset($this->lockedPackages[\spl_object_hash($package)]); } /** * @param array $updateAllowList * @param false|self::UPDATE_* $updateAllowTransitiveDependencies */ public function setUpdateAllowList(array $updateAllowList, $updateAllowTransitiveDependencies) : void { $this->updateAllowList = $updateAllowList; $this->updateAllowTransitiveDependencies = $updateAllowTransitiveDependencies; } /** * @return array */ public function getUpdateAllowList() : array { return $this->updateAllowList; } public function getUpdateAllowTransitiveDependencies() : bool { return $this->updateAllowTransitiveDependencies !== self::UPDATE_ONLY_LISTED; } public function getUpdateAllowTransitiveRootDependencies() : bool { return $this->updateAllowTransitiveDependencies === self::UPDATE_LISTED_WITH_TRANSITIVE_DEPS; } /** * @return array */ public function getRequires() : array { return $this->requires; } /** * @return array */ public function getFixedPackages() : array { return $this->fixedPackages; } public function isFixedPackage(BasePackage $package) : bool { return isset($this->fixedPackages[\spl_object_hash($package)]); } /** * @return array */ public function getLockedPackages() : array { return $this->lockedPackages; } public function isLockedPackage(PackageInterface $package) : bool { return isset($this->lockedPackages[\spl_object_hash($package)]) || isset($this->fixedLockedPackages[\spl_object_hash($package)]); } /** * @return array */ public function getFixedOrLockedPackages() : array { return \array_merge($this->fixedPackages, $this->lockedPackages); } /** * @return ($packageIds is true ? array : array) * * @TODO look into removing the packageIds option, the only place true is used * is for the installed map in the solver problems. * Some locked packages may not be in the pool, * so they have a package->id of -1 */ public function getPresentMap(bool $packageIds = \false) : array { $presentMap = []; if ($this->lockedRepository !== null) { foreach ($this->lockedRepository->getPackages() as $package) { $presentMap[$packageIds ? $package->getId() : \spl_object_hash($package)] = $package; } } foreach ($this->fixedPackages as $package) { $presentMap[$packageIds ? $package->getId() : \spl_object_hash($package)] = $package; } return $presentMap; } /** * @return array */ public function getFixedPackagesMap() : array { $fixedPackagesMap = []; foreach ($this->fixedPackages as $package) { $fixedPackagesMap[$package->getId()] = $package; } return $fixedPackagesMap; } /** * @return ?LockArrayRepository */ public function getLockedRepository() : ?LockArrayRepository { return $this->lockedRepository; } /** * Restricts the pool builder from loading other packages than those listed here * * @param non-empty-list $names */ public function restrictPackages(array $names) : void { $this->restrictedPackages = $names; } /** * @return list */ public function getRestrictedPackages() : ?array { return $this->restrictedPackages; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Version\VersionParser; use Composer\Semver\CompilingMatcher; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\MultiConstraint; use Composer\Semver\Intervals; /** * Optimizes a given pool * * @author Yanick Witschi */ class PoolOptimizer { /** * @var PolicyInterface */ private $policy; /** * @var array */ private $irremovablePackages = []; /** * @var array> */ private $requireConstraintsPerPackage = []; /** * @var array> */ private $conflictConstraintsPerPackage = []; /** * @var array */ private $packagesToRemove = []; /** * @var array */ private $aliasesPerPackage = []; /** * @var array> */ private $removedVersionsByPackage = []; public function __construct(\Composer\DependencyResolver\PolicyInterface $policy) { $this->policy = $policy; } public function optimize(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool) : \Composer\DependencyResolver\Pool { $this->prepare($request, $pool); $this->optimizeByIdenticalDependencies($request, $pool); $this->optimizeImpossiblePackagesAway($request, $pool); $optimizedPool = $this->applyRemovalsToPool($pool); // No need to run this recursively at the moment // because the current optimizations cannot provide // even more gains when ran again. Might change // in the future with additional optimizations. $this->irremovablePackages = []; $this->requireConstraintsPerPackage = []; $this->conflictConstraintsPerPackage = []; $this->packagesToRemove = []; $this->aliasesPerPackage = []; $this->removedVersionsByPackage = []; return $optimizedPool; } private function prepare(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool) : void { $irremovablePackageConstraintGroups = []; // Mark fixed or locked packages as irremovable foreach ($request->getFixedOrLockedPackages() as $package) { $irremovablePackageConstraintGroups[$package->getName()][] = new Constraint('==', $package->getVersion()); } // Extract requested package requirements foreach ($request->getRequires() as $require => $constraint) { $this->extractRequireConstraintsPerPackage($require, $constraint); } // First pass over all packages to extract information and mark package constraints irremovable foreach ($pool->getPackages() as $package) { // Extract package requirements foreach ($package->getRequires() as $link) { $this->extractRequireConstraintsPerPackage($link->getTarget(), $link->getConstraint()); } // Extract package conflicts foreach ($package->getConflicts() as $link) { $this->extractConflictConstraintsPerPackage($link->getTarget(), $link->getConstraint()); } // Keep track of alias packages for every package so if either the alias or aliased is kept // we keep the others as they are a unit of packages really if ($package instanceof AliasPackage) { $this->aliasesPerPackage[$package->getAliasOf()->id][] = $package; } } $irremovablePackageConstraints = []; foreach ($irremovablePackageConstraintGroups as $packageName => $constraints) { $irremovablePackageConstraints[$packageName] = 1 === \count($constraints) ? $constraints[0] : new MultiConstraint($constraints, \false); } unset($irremovablePackageConstraintGroups); // Mark the packages as irremovable based on the constraints foreach ($pool->getPackages() as $package) { if (!isset($irremovablePackageConstraints[$package->getName()])) { continue; } if (CompilingMatcher::match($irremovablePackageConstraints[$package->getName()], Constraint::OP_EQ, $package->getVersion())) { $this->markPackageIrremovable($package); } } } private function markPackageIrremovable(BasePackage $package) : void { $this->irremovablePackages[$package->id] = \true; if ($package instanceof AliasPackage) { // recursing here so aliasesPerPackage for the aliasOf can be checked // and all its aliases marked as irremovable as well $this->markPackageIrremovable($package->getAliasOf()); } if (isset($this->aliasesPerPackage[$package->id])) { foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) { $this->irremovablePackages[$aliasPackage->id] = \true; } } } /** * @return Pool Optimized pool */ private function applyRemovalsToPool(\Composer\DependencyResolver\Pool $pool) : \Composer\DependencyResolver\Pool { $packages = []; $removedVersions = []; foreach ($pool->getPackages() as $package) { if (!isset($this->packagesToRemove[$package->id])) { $packages[] = $package; } else { $removedVersions[$package->getName()][$package->getVersion()] = $package->getPrettyVersion(); } } $optimizedPool = new \Composer\DependencyResolver\Pool($packages, $pool->getUnacceptableFixedOrLockedPackages(), $removedVersions, $this->removedVersionsByPackage); return $optimizedPool; } private function optimizeByIdenticalDependencies(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool) : void { $identicalDefinitionsPerPackage = []; $packageIdenticalDefinitionLookup = []; foreach ($pool->getPackages() as $package) { // If that package was already marked irremovable, we can skip // the entire process for it if (isset($this->irremovablePackages[$package->id])) { continue; } $this->markPackageForRemoval($package->id); $dependencyHash = $this->calculateDependencyHash($package); foreach ($package->getNames(\false) as $packageName) { if (!isset($this->requireConstraintsPerPackage[$packageName])) { continue; } foreach ($this->requireConstraintsPerPackage[$packageName] as $requireConstraint) { $groupHashParts = []; if (CompilingMatcher::match($requireConstraint, Constraint::OP_EQ, $package->getVersion())) { $groupHashParts[] = 'require:' . (string) $requireConstraint; } if (\count($package->getReplaces()) > 0) { foreach ($package->getReplaces() as $link) { if (CompilingMatcher::match($link->getConstraint(), Constraint::OP_EQ, $package->getVersion())) { // Use the same hash part as the regular require hash because that's what the replacement does $groupHashParts[] = 'require:' . (string) $link->getConstraint(); } } } if (isset($this->conflictConstraintsPerPackage[$packageName])) { foreach ($this->conflictConstraintsPerPackage[$packageName] as $conflictConstraint) { if (CompilingMatcher::match($conflictConstraint, Constraint::OP_EQ, $package->getVersion())) { $groupHashParts[] = 'conflict:' . (string) $conflictConstraint; } } } if (0 === \count($groupHashParts)) { continue; } $groupHash = \implode('', $groupHashParts); $identicalDefinitionsPerPackage[$packageName][$groupHash][$dependencyHash][] = $package; $packageIdenticalDefinitionLookup[$package->id][$packageName] = ['groupHash' => $groupHash, 'dependencyHash' => $dependencyHash]; } } } foreach ($identicalDefinitionsPerPackage as $constraintGroups) { foreach ($constraintGroups as $constraintGroup) { foreach ($constraintGroup as $packages) { // Only one package in this constraint group has the same requirements, we're not allowed to remove that package if (1 === \count($packages)) { $this->keepPackage($packages[0], $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup); continue; } // Otherwise we find out which one is the preferred package in this constraint group which is // then not allowed to be removed either $literals = []; foreach ($packages as $package) { $literals[] = $package->id; } foreach ($this->policy->selectPreferredPackages($pool, $literals) as $preferredLiteral) { $this->keepPackage($pool->literalToPackage($preferredLiteral), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup); } } } } } private function calculateDependencyHash(BasePackage $package) : string { $hash = ''; $hashRelevantLinks = ['requires' => $package->getRequires(), 'conflicts' => $package->getConflicts(), 'replaces' => $package->getReplaces(), 'provides' => $package->getProvides()]; foreach ($hashRelevantLinks as $key => $links) { if (0 === \count($links)) { continue; } // start new hash section $hash .= $key . ':'; $subhash = []; foreach ($links as $link) { // To get the best dependency hash matches we should use Intervals::compactConstraint() here. // However, the majority of projects are going to specify their constraints already pretty // much in the best variant possible. In other words, we'd be wasting time here and it would actually hurt // performance more than the additional few packages that could be filtered out would benefit the process. $subhash[$link->getTarget()] = (string) $link->getConstraint(); } // Sort for best result \ksort($subhash); foreach ($subhash as $target => $constraint) { $hash .= $target . '@' . $constraint; } } return $hash; } private function markPackageForRemoval(int $id) : void { // We are not allowed to remove packages if they have been marked as irremovable if (isset($this->irremovablePackages[$id])) { throw new \LogicException('Attempted removing a package which was previously marked irremovable'); } $this->packagesToRemove[$id] = \true; } /** * @param array>>> $identicalDefinitionsPerPackage * @param array> $packageIdenticalDefinitionLookup */ private function keepPackage(BasePackage $package, array $identicalDefinitionsPerPackage, array $packageIdenticalDefinitionLookup) : void { // Already marked to keep if (!isset($this->packagesToRemove[$package->id])) { return; } unset($this->packagesToRemove[$package->id]); if ($package instanceof AliasPackage) { // recursing here so aliasesPerPackage for the aliasOf can be checked // and all its aliases marked to be kept as well $this->keepPackage($package->getAliasOf(), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup); } // record all the versions of the package group so we can list them later in Problem output foreach ($package->getNames(\false) as $name) { if (isset($packageIdenticalDefinitionLookup[$package->id][$name])) { $packageGroupPointers = $packageIdenticalDefinitionLookup[$package->id][$name]; $packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']]; foreach ($packageGroup as $pkg) { if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { $pkg = $pkg->getAliasOf(); } $this->removedVersionsByPackage[\spl_object_hash($package)][$pkg->getVersion()] = $pkg->getPrettyVersion(); } } } if (isset($this->aliasesPerPackage[$package->id])) { foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) { unset($this->packagesToRemove[$aliasPackage->id]); // record all the versions of the package group so we can list them later in Problem output foreach ($aliasPackage->getNames(\false) as $name) { if (isset($packageIdenticalDefinitionLookup[$aliasPackage->id][$name])) { $packageGroupPointers = $packageIdenticalDefinitionLookup[$aliasPackage->id][$name]; $packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']]; foreach ($packageGroup as $pkg) { if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { $pkg = $pkg->getAliasOf(); } $this->removedVersionsByPackage[\spl_object_hash($aliasPackage)][$pkg->getVersion()] = $pkg->getPrettyVersion(); } } } } } } /** * Use the list of locked packages to constrain the loaded packages * This will reduce packages with significant numbers of historical versions to a smaller number * and reduce the resulting rule set that is generated */ private function optimizeImpossiblePackagesAway(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool) : void { if (\count($request->getLockedPackages()) === 0) { return; } $packageIndex = []; foreach ($pool->getPackages() as $package) { $id = $package->id; // Do not remove irremovable packages if (isset($this->irremovablePackages[$id])) { continue; } // Do not remove a package aliased by another package, nor aliases if (isset($this->aliasesPerPackage[$id]) || $package instanceof AliasPackage) { continue; } // Do not remove locked packages if ($request->isFixedPackage($package) || $request->isLockedPackage($package)) { continue; } $packageIndex[$package->getName()][$package->id] = $package; } foreach ($request->getLockedPackages() as $package) { // If this locked package is no longer required by root or anything in the pool, it may get uninstalled so do not apply its requirements // In a case where a requirement WERE to appear in the pool by a package that would not be used, it would've been unlocked and so not filtered still $isUnusedPackage = \true; foreach ($package->getNames(\false) as $packageName) { if (isset($this->requireConstraintsPerPackage[$packageName])) { $isUnusedPackage = \false; break; } } if ($isUnusedPackage) { continue; } foreach ($package->getRequires() as $link) { $require = $link->getTarget(); if (!isset($packageIndex[$require])) { continue; } $linkConstraint = $link->getConstraint(); foreach ($packageIndex[$require] as $id => $requiredPkg) { if (\false === CompilingMatcher::match($linkConstraint, Constraint::OP_EQ, $requiredPkg->getVersion())) { $this->markPackageForRemoval($id); unset($packageIndex[$require][$id]); } } } } } /** * Disjunctive require constraints need to be considered in their own group. E.g. "^2.14 || ^3.3" needs to generate * two require constraint groups in order for us to keep the best matching package for "^2.14" AND "^3.3" as otherwise, we'd * only keep either one which can cause trouble (e.g. when using --prefer-lowest). * * @return void */ private function extractRequireConstraintsPerPackage(string $package, ConstraintInterface $constraint) { foreach ($this->expandDisjunctiveMultiConstraints($constraint) as $expanded) { $this->requireConstraintsPerPackage[$package][(string) $expanded] = $expanded; } } /** * Disjunctive conflict constraints need to be considered in their own group. E.g. "^2.14 || ^3.3" needs to generate * two conflict constraint groups in order for us to keep the best matching package for "^2.14" AND "^3.3" as otherwise, we'd * only keep either one which can cause trouble (e.g. when using --prefer-lowest). * * @return void */ private function extractConflictConstraintsPerPackage(string $package, ConstraintInterface $constraint) { foreach ($this->expandDisjunctiveMultiConstraints($constraint) as $expanded) { $this->conflictConstraintsPerPackage[$package][(string) $expanded] = $expanded; } } /** * @return ConstraintInterface[] */ private function expandDisjunctiveMultiConstraints(ConstraintInterface $constraint) { $constraint = Intervals::compactConstraint($constraint); if ($constraint instanceof MultiConstraint && $constraint->isDisjunctive()) { // No need to call ourselves recursively here because Intervals::compactConstraint() ensures that there // are no nested disjunctive MultiConstraint instances possible return $constraint->getConstraints(); } // Regular constraints and conjunctive MultiConstraints return [$constraint]; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\Package\BasePackage; use Composer\Package\AliasPackage; /** * @author Nils Adermann * @phpstan-import-type ReasonData from Rule */ class RuleSetGenerator { /** @var PolicyInterface */ protected $policy; /** @var Pool */ protected $pool; /** @var RuleSet */ protected $rules; /** @var array */ protected $addedMap = []; /** @var array */ protected $addedPackagesByNames = []; public function __construct(\Composer\DependencyResolver\PolicyInterface $policy, \Composer\DependencyResolver\Pool $pool) { $this->policy = $policy; $this->pool = $pool; $this->rules = new \Composer\DependencyResolver\RuleSet(); } /** * Creates a new rule for the requirements of a package * * This rule is of the form (-A|B|C), where B and C are the providers of * one requirement of the package A. * * @param BasePackage $package The package with a requirement * @param BasePackage[] $providers The providers of the requirement * @param Rule::RULE_* $reason A RULE_* constant describing the reason for generating this rule * @param mixed $reasonData Any data, e.g. the requirement name, that goes with the reason * @return Rule|null The generated rule or null if tautological * * @phpstan-param ReasonData $reasonData */ protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData) : ?\Composer\DependencyResolver\Rule { $literals = [-$package->id]; foreach ($providers as $provider) { // self fulfilling rule? if ($provider === $package) { return null; } $literals[] = $provider->id; } return new \Composer\DependencyResolver\GenericRule($literals, $reason, $reasonData); } /** * Creates a rule to install at least one of a set of packages * * The rule is (A|B|C) with A, B and C different packages. If the given * set of packages is empty an impossible rule is generated. * * @param non-empty-array $packages The set of packages to choose from * @param Rule::RULE_* $reason A RULE_* constant describing the reason for * generating this rule * @param mixed $reasonData Additional data like the root require or fix request info * @return Rule The generated rule * * @phpstan-param ReasonData $reasonData */ protected function createInstallOneOfRule(array $packages, $reason, $reasonData) : \Composer\DependencyResolver\Rule { $literals = []; foreach ($packages as $package) { $literals[] = $package->id; } return new \Composer\DependencyResolver\GenericRule($literals, $reason, $reasonData); } /** * Creates a rule for two conflicting packages * * The rule for conflicting packages A and B is (-A|-B). A is called the issuer * and B the provider. * * @param BasePackage $issuer The package declaring the conflict * @param BasePackage $provider The package causing the conflict * @param Rule::RULE_* $reason A RULE_* constant describing the reason for generating this rule * @param mixed $reasonData Any data, e.g. the package name, that goes with the reason * @return ?Rule The generated rule * * @phpstan-param ReasonData $reasonData */ protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData) : ?\Composer\DependencyResolver\Rule { // ignore self conflict if ($issuer === $provider) { return null; } return new \Composer\DependencyResolver\Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData); } /** * @param non-empty-array $packages * @param Rule::RULE_* $reason A RULE_* constant * @param mixed $reasonData * * @phpstan-param ReasonData $reasonData */ protected function createMultiConflictRule(array $packages, $reason, $reasonData) : \Composer\DependencyResolver\Rule { $literals = []; foreach ($packages as $package) { $literals[] = -$package->id; } if (\count($literals) === 2) { return new \Composer\DependencyResolver\Rule2Literals($literals[0], $literals[1], $reason, $reasonData); } return new \Composer\DependencyResolver\MultiConflictRule($literals, $reason, $reasonData); } /** * Adds a rule unless it duplicates an existing one of any type * * To be able to directly pass in the result of one of the rule creation * methods null is allowed which will not insert a rule. * * @param RuleSet::TYPE_* $type A TYPE_* constant defining the rule type * @param Rule $newRule The rule about to be added */ private function addRule($type, ?\Composer\DependencyResolver\Rule $newRule = null) : void { if (null === $newRule) { return; } $this->rules->add($newRule, $type); } protected function addRulesForPackage(BasePackage $package, PlatformRequirementFilterInterface $platformRequirementFilter) : void { /** @var \SplQueue */ $workQueue = new \SplQueue(); $workQueue->enqueue($package); while (!$workQueue->isEmpty()) { $package = $workQueue->dequeue(); if (isset($this->addedMap[$package->id])) { continue; } $this->addedMap[$package->id] = $package; if (!$package instanceof AliasPackage) { foreach ($package->getNames(\false) as $name) { $this->addedPackagesByNames[$name][] = $package; } } else { $workQueue->enqueue($package->getAliasOf()); $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, [$package->getAliasOf()], \Composer\DependencyResolver\Rule::RULE_PACKAGE_ALIAS, $package)); // aliases must be installed with their main package, so create a rule the other way around as well $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRequireRule($package->getAliasOf(), [$package], \Composer\DependencyResolver\Rule::RULE_PACKAGE_INVERSE_ALIAS, $package->getAliasOf())); // if alias package has no self.version requires, its requirements do not // need to be added as the aliased package processing will take care of it if (!$package->hasSelfVersionRequires()) { continue; } } foreach ($package->getRequires() as $link) { $constraint = $link->getConstraint(); if ($platformRequirementFilter->isIgnored($link->getTarget())) { continue; } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) { $constraint = $platformRequirementFilter->filterConstraint($link->getTarget(), $constraint); } $possibleRequires = $this->pool->whatProvides($link->getTarget(), $constraint); $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, \Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES, $link)); foreach ($possibleRequires as $require) { $workQueue->enqueue($require); } } } } protected function addConflictRules(PlatformRequirementFilterInterface $platformRequirementFilter) : void { /** @var BasePackage $package */ foreach ($this->addedMap as $package) { foreach ($package->getConflicts() as $link) { // even if conflict ends up being with an alias, there would be at least one actual package by this name if (!isset($this->addedPackagesByNames[$link->getTarget()])) { continue; } $constraint = $link->getConstraint(); if ($platformRequirementFilter->isIgnored($link->getTarget())) { continue; } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) { $constraint = $platformRequirementFilter->filterConstraint($link->getTarget(), $constraint, \false); } $conflicts = $this->pool->whatProvides($link->getTarget(), $constraint); foreach ($conflicts as $conflict) { // define the conflict rule for regular packages, for alias packages it's only needed if the name // matches the conflict exactly, otherwise the name match is by provide/replace which means the // package which this is an alias of will conflict anyway, so no need to create additional rules if (!$conflict instanceof AliasPackage || $conflict->getName() === $link->getTarget()) { $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT, $link)); } } } } foreach ($this->addedPackagesByNames as $name => $packages) { if (\count($packages) > 1) { $reason = \Composer\DependencyResolver\Rule::RULE_PACKAGE_SAME_NAME; $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_PACKAGE, $this->createMultiConflictRule($packages, $reason, $name)); } } } protected function addRulesForRequest(\Composer\DependencyResolver\Request $request, PlatformRequirementFilterInterface $platformRequirementFilter) : void { foreach ($request->getFixedPackages() as $package) { if ($package->id === -1) { // fixed package was not added to the pool as it did not pass the stability requirements, this is fine if ($this->pool->isUnacceptableFixedOrLockedPackage($package)) { continue; } // otherwise, looks like a bug throw new \LogicException("Fixed package " . $package->getPrettyString() . " was not added to solver pool."); } $this->addRulesForPackage($package, $platformRequirementFilter); $rule = $this->createInstallOneOfRule([$package], \Composer\DependencyResolver\Rule::RULE_FIXED, ['package' => $package]); $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST, $rule); } foreach ($request->getRequires() as $packageName => $constraint) { if ($platformRequirementFilter->isIgnored($packageName)) { continue; } elseif ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) { $constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint); } $packages = $this->pool->whatProvides($packageName, $constraint); if (\count($packages) > 0) { foreach ($packages as $package) { $this->addRulesForPackage($package, $platformRequirementFilter); } $rule = $this->createInstallOneOfRule($packages, \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint]); $this->addRule(\Composer\DependencyResolver\RuleSet::TYPE_REQUEST, $rule); } } } protected function addRulesForRootAliases(PlatformRequirementFilterInterface $platformRequirementFilter) : void { foreach ($this->pool->getPackages() as $package) { // ensure that rules for root alias packages and aliases of packages which were loaded are also loaded // even if the alias itself isn't required, otherwise a package could be installed without its alias which // leads to unexpected behavior if (!isset($this->addedMap[$package->id]) && $package instanceof AliasPackage && ($package->isRootPackageAlias() || isset($this->addedMap[$package->getAliasOf()->id]))) { $this->addRulesForPackage($package, $platformRequirementFilter); } } } public function getRulesFor(\Composer\DependencyResolver\Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null) : \Composer\DependencyResolver\RuleSet { $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing(); $this->addRulesForRequest($request, $platformRequirementFilter); $this->addRulesForRootAliases($platformRequirementFilter); $this->addConflictRules($platformRequirementFilter); // Remove references to packages $this->addedMap = $this->addedPackagesByNames = []; $rules = $this->rules; $this->rules = new \Composer\DependencyResolver\RuleSet(); return $rules; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * Stores decisions on installing, removing or keeping packages * * @author Nils Adermann * @implements \Iterator */ class Decisions implements \Iterator, \Countable { public const DECISION_LITERAL = 0; public const DECISION_REASON = 1; /** @var Pool */ protected $pool; /** @var array */ protected $decisionMap; /** * @var array */ protected $decisionQueue = []; public function __construct(\Composer\DependencyResolver\Pool $pool) { $this->pool = $pool; $this->decisionMap = []; } public function decide(int $literal, int $level, \Composer\DependencyResolver\Rule $why) : void { $this->addDecision($literal, $level); $this->decisionQueue[] = [self::DECISION_LITERAL => $literal, self::DECISION_REASON => $why]; } public function satisfy(int $literal) : bool { $packageId = \abs($literal); return $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 || $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0; } public function conflict(int $literal) : bool { $packageId = \abs($literal); return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0 || isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0; } public function decided(int $literalOrPackageId) : bool { return ($this->decisionMap[\abs($literalOrPackageId)] ?? 0) !== 0; } public function undecided(int $literalOrPackageId) : bool { return ($this->decisionMap[\abs($literalOrPackageId)] ?? 0) === 0; } public function decidedInstall(int $literalOrPackageId) : bool { $packageId = \abs($literalOrPackageId); return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0; } public function decisionLevel(int $literalOrPackageId) : int { $packageId = \abs($literalOrPackageId); if (isset($this->decisionMap[$packageId])) { return \abs($this->decisionMap[$packageId]); } return 0; } public function decisionRule(int $literalOrPackageId) : \Composer\DependencyResolver\Rule { $packageId = \abs($literalOrPackageId); foreach ($this->decisionQueue as $decision) { if ($packageId === \abs($decision[self::DECISION_LITERAL])) { return $decision[self::DECISION_REASON]; } } throw new \LogicException('Did not find a decision rule using ' . $literalOrPackageId); } /** * @return array{0: int, 1: Rule} a literal and decision reason */ public function atOffset(int $queueOffset) : array { return $this->decisionQueue[$queueOffset]; } public function validOffset(int $queueOffset) : bool { return $queueOffset >= 0 && $queueOffset < \count($this->decisionQueue); } public function lastReason() : \Composer\DependencyResolver\Rule { return $this->decisionQueue[\count($this->decisionQueue) - 1][self::DECISION_REASON]; } public function lastLiteral() : int { return $this->decisionQueue[\count($this->decisionQueue) - 1][self::DECISION_LITERAL]; } public function reset() : void { while ($decision = \array_pop($this->decisionQueue)) { $this->decisionMap[\abs($decision[self::DECISION_LITERAL])] = 0; } } /** * @param int<-1, max> $offset */ public function resetToOffset(int $offset) : void { while (\count($this->decisionQueue) > $offset + 1) { $decision = \array_pop($this->decisionQueue); $this->decisionMap[\abs($decision[self::DECISION_LITERAL])] = 0; } } public function revertLast() : void { $this->decisionMap[\abs($this->lastLiteral())] = 0; \array_pop($this->decisionQueue); } public function count() : int { return \count($this->decisionQueue); } public function rewind() : void { \end($this->decisionQueue); } /** * @return array{0: int, 1: Rule}|false */ #[\ReturnTypeWillChange] public function current() { return \current($this->decisionQueue); } public function key() : ?int { return \key($this->decisionQueue); } public function next() : void { \prev($this->decisionQueue); } public function valid() : bool { return \false !== \current($this->decisionQueue); } public function isEmpty() : bool { return \count($this->decisionQueue) === 0; } protected function addDecision(int $literal, int $level) : void { $packageId = \abs($literal); $previousDecision = $this->decisionMap[$packageId] ?? 0; if ($previousDecision !== 0) { $literalString = $this->pool->literalToPrettyString($literal, []); $package = $this->pool->literalToPackage($literal); throw new \Composer\DependencyResolver\SolverBugException("Trying to decide {$literalString} on level {$level}, even though {$package} was previously decided as " . $previousDecision . "."); } if ($literal > 0) { $this->decisionMap[$packageId] = $level; } else { $this->decisionMap[$packageId] = -$level; } } public function toString(?\Composer\DependencyResolver\Pool $pool = null) : string { $decisionMap = $this->decisionMap; \ksort($decisionMap); $str = '['; foreach ($decisionMap as $packageId => $level) { $str .= ($pool !== null ? $pool->literalToPackage($packageId) : $packageId) . ':' . $level . ','; } $str .= ']'; return $str; } public function __toString() : string { return $this->toString(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\EventDispatcher\EventDispatcher; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\CompletePackage; use Composer\Package\PackageInterface; use Composer\Package\Version\StabilityFilter; use Composer\Pcre\Preg; use Composer\Plugin\PluginEvents; use Composer\Plugin\PrePoolCreateEvent; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RootPackageRepository; use Composer\Semver\CompilingMatcher; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Semver\Constraint\MultiConstraint; use Composer\Semver\Intervals; /** * @author Nils Adermann */ class PoolBuilder { /** * @var int[] * @phpstan-var array, BasePackage::STABILITY_*> */ private $acceptableStabilities; /** * @var int[] * @phpstan-var array */ private $stabilityFlags; /** * @var array[] * @phpstan-var array> */ private $rootAliases; /** * @var string[] * @phpstan-var array */ private $rootReferences; /** * @var array */ private $temporaryConstraints; /** * @var ?EventDispatcher */ private $eventDispatcher; /** * @var PoolOptimizer|null */ private $poolOptimizer; /** * @var IOInterface */ private $io; /** * @var array[] * @phpstan-var array */ private $aliasMap = []; /** * @var ConstraintInterface[] * @phpstan-var array */ private $packagesToLoad = []; /** * @var ConstraintInterface[] * @phpstan-var array */ private $loadedPackages = []; /** * @var array[] * @phpstan-var array>> */ private $loadedPerRepo = []; /** * @var array */ private $packages = []; /** * @var BasePackage[] */ private $unacceptableFixedOrLockedPackages = []; /** @var array */ private $updateAllowList = []; /** @var array> */ private $skippedLoad = []; /** @var list */ private $ignoredTypes = []; /** @var list|null */ private $allowedTypes = null; /** * If provided, only these package names are loaded * * This is a special-use functionality of the Request class to optimize the pool creation process * when only a minimal subset of packages is needed and we do not need their dependencies. * * @var array|null */ private $restrictedPackagesList = null; /** * Keeps a list of dependencies which are locked but were auto-unlocked as they are path repositories * * This half-unlocked state means the package itself will update but the UPDATE_LISTED_WITH_TRANSITIVE_DEPS* * flags will not apply until the package really gets unlocked in some other way than being a path repo * * @var array */ private $pathRepoUnlocked = []; /** * Keeps a list of dependencies which are root requirements, and as such * have already their maximum required range loaded and can not be * extended by markPackageNameForLoading * * Packages get cleared from this list if they get unlocked as in that case * we need to actually load them * * @var array */ private $maxExtendedReqs = []; /** * @var array * @phpstan-var array */ private $updateAllowWarned = []; /** @var int */ private $indexCounter = 0; /** * @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value * @phpstan-param array, BasePackage::STABILITY_*> $acceptableStabilities * @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value * @phpstan-param array $stabilityFlags * @param array[] $rootAliases * @phpstan-param array> $rootAliases * @param string[] $rootReferences an array of package name => source reference * @phpstan-param array $rootReferences * @param array $temporaryConstraints Runtime temporary constraints that will be used to filter packages */ public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, IOInterface $io, ?EventDispatcher $eventDispatcher = null, ?\Composer\DependencyResolver\PoolOptimizer $poolOptimizer = null, array $temporaryConstraints = []) { $this->acceptableStabilities = $acceptableStabilities; $this->stabilityFlags = $stabilityFlags; $this->rootAliases = $rootAliases; $this->rootReferences = $rootReferences; $this->eventDispatcher = $eventDispatcher; $this->poolOptimizer = $poolOptimizer; $this->io = $io; $this->temporaryConstraints = $temporaryConstraints; } /** * Packages of those types are ignored * * @param list $types */ public function setIgnoredTypes(array $types) : void { $this->ignoredTypes = $types; } /** * Only packages of those types are allowed if set to non-null * * @param list|null $types */ public function setAllowedTypes(?array $types) : void { $this->allowedTypes = $types; } /** * @param RepositoryInterface[] $repositories */ public function buildPool(array $repositories, \Composer\DependencyResolver\Request $request) : \Composer\DependencyResolver\Pool { $this->restrictedPackagesList = $request->getRestrictedPackages() !== null ? \array_flip($request->getRestrictedPackages()) : null; if (\count($request->getUpdateAllowList()) > 0) { $this->updateAllowList = $request->getUpdateAllowList(); $this->warnAboutNonMatchingUpdateAllowList($request); if (null === $request->getLockedRepository()) { throw new \LogicException('No lock repo present and yet a partial update was requested.'); } foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) { if (!$this->isUpdateAllowed($lockedPackage)) { // remember which packages we skipped loading remote content for in this partial update $this->skippedLoad[$lockedPackage->getName()][] = $lockedPackage; foreach ($lockedPackage->getReplaces() as $link) { $this->skippedLoad[$link->getTarget()][] = $lockedPackage; } // Path repo packages are never loaded from lock, to force them to always remain in sync // unless symlinking is disabled in which case we probably should rather treat them like // regular packages. We mark them specially so they can be reloaded fully including update propagation // if they do get unlocked, but by default they are unlocked without update propagation. if ($lockedPackage->getDistType() === 'path') { $transportOptions = $lockedPackage->getTransportOptions(); if (!isset($transportOptions['symlink']) || $transportOptions['symlink'] !== \false) { $this->pathRepoUnlocked[$lockedPackage->getName()] = \true; continue; } } $request->lockPackage($lockedPackage); } } } foreach ($request->getFixedOrLockedPackages() as $package) { // using MatchAllConstraint here because fixed packages do not need to retrigger // loading any packages $this->loadedPackages[$package->getName()] = new MatchAllConstraint(); // replace means conflict, so if a fixed package replaces a name, no need to load that one, packages would conflict anyways foreach ($package->getReplaces() as $link) { $this->loadedPackages[$link->getTarget()] = new MatchAllConstraint(); } // TODO in how far can we do the above for conflicts? It's more tricky cause conflicts can be limited to // specific versions while replace is a conflict with all versions of the name if ($package->getRepository() instanceof RootPackageRepository || $package->getRepository() instanceof PlatformRepository || StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $package->getNames(), $package->getStability())) { $this->loadPackage($request, $repositories, $package, \false); } else { $this->unacceptableFixedOrLockedPackages[] = $package; } } foreach ($request->getRequires() as $packageName => $constraint) { // fixed and locked packages have already been added, so if a root require needs one of them, no need to do anything if (isset($this->loadedPackages[$packageName])) { continue; } $this->packagesToLoad[$packageName] = $constraint; $this->maxExtendedReqs[$packageName] = \true; } // clean up packagesToLoad for anything we manually marked loaded above foreach ($this->packagesToLoad as $name => $constraint) { if (isset($this->loadedPackages[$name])) { unset($this->packagesToLoad[$name]); } } while (\count($this->packagesToLoad) > 0) { $this->loadPackagesMarkedForLoading($request, $repositories); } if (\count($this->temporaryConstraints) > 0) { foreach ($this->packages as $i => $package) { // we check all alias related packages at once, so no need to check individual aliases if (!isset($this->temporaryConstraints[$package->getName()]) || $package instanceof AliasPackage) { continue; } $constraint = $this->temporaryConstraints[$package->getName()]; $packageAndAliases = [$i => $package]; if (isset($this->aliasMap[\spl_object_hash($package)])) { $packageAndAliases += $this->aliasMap[\spl_object_hash($package)]; } $found = \false; foreach ($packageAndAliases as $packageOrAlias) { if (CompilingMatcher::match($constraint, Constraint::OP_EQ, $packageOrAlias->getVersion())) { $found = \true; } } if (!$found) { foreach ($packageAndAliases as $index => $packageOrAlias) { unset($this->packages[$index]); } } } } if ($this->eventDispatcher !== null) { $prePoolCreateEvent = new PrePoolCreateEvent(PluginEvents::PRE_POOL_CREATE, $repositories, $request, $this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $this->packages, $this->unacceptableFixedOrLockedPackages); $this->eventDispatcher->dispatch($prePoolCreateEvent->getName(), $prePoolCreateEvent); $this->packages = $prePoolCreateEvent->getPackages(); $this->unacceptableFixedOrLockedPackages = $prePoolCreateEvent->getUnacceptableFixedPackages(); } $pool = new \Composer\DependencyResolver\Pool($this->packages, $this->unacceptableFixedOrLockedPackages); $this->aliasMap = []; $this->packagesToLoad = []; $this->loadedPackages = []; $this->loadedPerRepo = []; $this->packages = []; $this->unacceptableFixedOrLockedPackages = []; $this->maxExtendedReqs = []; $this->skippedLoad = []; $this->indexCounter = 0; $this->io->debug('Built pool.'); $pool = $this->runOptimizer($request, $pool); Intervals::clear(); return $pool; } private function markPackageNameForLoading(\Composer\DependencyResolver\Request $request, string $name, ConstraintInterface $constraint) : void { // Skip platform requires at this stage if (PlatformRepository::isPlatformPackage($name)) { return; } // Root require (which was not unlocked) already loaded the maximum range so no // need to check anything here if (isset($this->maxExtendedReqs[$name])) { return; } // Root requires can not be overruled by dependencies so there is no point in // extending the loaded constraint for those. // This is triggered when loading a root require which was locked but got unlocked, then // we make sure that we load at most the intervals covered by the root constraint. $rootRequires = $request->getRequires(); if (isset($rootRequires[$name]) && !Intervals::isSubsetOf($constraint, $rootRequires[$name])) { $constraint = $rootRequires[$name]; } // Not yet loaded or already marked for a reload, set the constraint to be loaded if (!isset($this->loadedPackages[$name])) { // Maybe it was already marked before but not loaded yet. In that case // we have to extend the constraint (we don't check if they are identical because // MultiConstraint::create() will optimize anyway) if (isset($this->packagesToLoad[$name])) { // Already marked for loading and this does not expand the constraint to be loaded, nothing to do if (Intervals::isSubsetOf($constraint, $this->packagesToLoad[$name])) { return; } // extend the constraint to be loaded $constraint = Intervals::compactConstraint(MultiConstraint::create([$this->packagesToLoad[$name], $constraint], \false)); } $this->packagesToLoad[$name] = $constraint; return; } // No need to load this package with this constraint because it is // a subset of the constraint with which we have already loaded packages if (Intervals::isSubsetOf($constraint, $this->loadedPackages[$name])) { return; } // We have already loaded that package but not in the constraint that's // required. We extend the constraint and mark that package as not being loaded // yet so we get the required package versions $this->packagesToLoad[$name] = Intervals::compactConstraint(MultiConstraint::create([$this->loadedPackages[$name], $constraint], \false)); unset($this->loadedPackages[$name]); } /** * @param RepositoryInterface[] $repositories */ private function loadPackagesMarkedForLoading(\Composer\DependencyResolver\Request $request, array $repositories) : void { foreach ($this->packagesToLoad as $name => $constraint) { if ($this->restrictedPackagesList !== null && !isset($this->restrictedPackagesList[$name])) { unset($this->packagesToLoad[$name]); continue; } $this->loadedPackages[$name] = $constraint; } $packageBatch = $this->packagesToLoad; $this->packagesToLoad = []; foreach ($repositories as $repoIndex => $repository) { if (0 === \count($packageBatch)) { break; } // these repos have their packages fixed or locked if they need to be loaded so we // never need to load anything else from them if ($repository instanceof PlatformRepository || $repository === $request->getLockedRepository()) { continue; } $result = $repository->loadPackages($packageBatch, $this->acceptableStabilities, $this->stabilityFlags, $this->loadedPerRepo[$repoIndex] ?? []); foreach ($result['namesFound'] as $name) { // avoid loading the same package again from other repositories once it has been found unset($packageBatch[$name]); } foreach ($result['packages'] as $package) { $this->loadedPerRepo[$repoIndex][$package->getName()][$package->getVersion()] = $package; if (\in_array($package->getType(), $this->ignoredTypes, \true) || $this->allowedTypes !== null && !\in_array($package->getType(), $this->allowedTypes, \true)) { continue; } $this->loadPackage($request, $repositories, $package, !isset($this->pathRepoUnlocked[$package->getName()])); } } } /** * @param RepositoryInterface[] $repositories */ private function loadPackage(\Composer\DependencyResolver\Request $request, array $repositories, BasePackage $package, bool $propagateUpdate) : void { $index = $this->indexCounter++; $this->packages[$index] = $package; if ($package instanceof AliasPackage) { $this->aliasMap[\spl_object_hash($package->getAliasOf())][$index] = $package; } $name = $package->getName(); // we're simply setting the root references on all versions for a name here and rely on the solver to pick the // right version. It'd be more work to figure out which versions and which aliases of those versions this may // apply to if (isset($this->rootReferences[$name])) { // do not modify the references on already locked or fixed packages if (!$request->isLockedPackage($package) && !$request->isFixedPackage($package)) { $package->setSourceDistReferences($this->rootReferences[$name]); } } // if propagateUpdate is false we are loading a fixed or locked package, root aliases do not apply as they are // manually loaded as separate packages in this case // // packages in pathRepoUnlocked however need to also load root aliases, they have propagateUpdate set to // false because their deps should not be unlocked, but that is irrelevant for root aliases if (($propagateUpdate || isset($this->pathRepoUnlocked[$package->getName()])) && isset($this->rootAliases[$name][$package->getVersion()])) { $alias = $this->rootAliases[$name][$package->getVersion()]; if ($package instanceof AliasPackage) { $basePackage = $package->getAliasOf(); } else { $basePackage = $package; } if ($basePackage instanceof CompletePackage) { $aliasPackage = new CompleteAliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']); } else { $aliasPackage = new AliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']); } $aliasPackage->setRootPackageAlias(\true); $newIndex = $this->indexCounter++; $this->packages[$newIndex] = $aliasPackage; $this->aliasMap[\spl_object_hash($aliasPackage->getAliasOf())][$newIndex] = $aliasPackage; } foreach ($package->getRequires() as $link) { $require = $link->getTarget(); $linkConstraint = $link->getConstraint(); // if the required package is loaded as a locked package only and hasn't had its deps analyzed if (isset($this->skippedLoad[$require])) { // if we're doing a full update or this is a partial update with transitive deps and we're currently // looking at a package which needs to be updated we need to unlock the package we now know is a // dependency of another package which we are trying to update, and then attempt to load it again if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) { $skippedRootRequires = $this->getSkippedRootRequires($request, $require); if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) { $this->unlockPackage($request, $repositories, $require); $this->markPackageNameForLoading($request, $require, $linkConstraint); } else { foreach ($skippedRootRequires as $rootRequire) { if (!isset($this->updateAllowWarned[$rootRequire])) { $this->updateAllowWarned[$rootRequire] = \true; $this->io->writeError('Dependency ' . $rootRequire . ' is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.'); } } } } elseif (isset($this->pathRepoUnlocked[$require]) && !isset($this->loadedPackages[$require])) { // if doing a partial update and a package depends on a path-repo-unlocked package which is not referenced by the root, we need to ensure it gets loaded as it was not loaded by the request's root requirements // and would not be loaded above if update propagation is not allowed (which happens if the requirer is itself a path-repo-unlocked package) or if transitive deps are not allowed to be unlocked $this->markPackageNameForLoading($request, $require, $linkConstraint); } } else { $this->markPackageNameForLoading($request, $require, $linkConstraint); } } // if we're doing a partial update with deps we also need to unlock packages which are being replaced in case // they are currently locked and thus prevent this updateable package from being installable/updateable if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) { foreach ($package->getReplaces() as $link) { $replace = $link->getTarget(); if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) { $skippedRootRequires = $this->getSkippedRootRequires($request, $replace); if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) { $this->unlockPackage($request, $repositories, $replace); // the replaced package only needs to be loaded if something else requires it $this->markPackageNameForLoadingIfRequired($request, $replace); } else { foreach ($skippedRootRequires as $rootRequire) { if (!isset($this->updateAllowWarned[$rootRequire])) { $this->updateAllowWarned[$rootRequire] = \true; $this->io->writeError('Dependency ' . $rootRequire . ' is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies (-W) to include root dependencies.'); } } } } } } } /** * Checks if a particular name is required directly in the request * * @param string $name packageName */ private function isRootRequire(\Composer\DependencyResolver\Request $request, string $name) : bool { $rootRequires = $request->getRequires(); return isset($rootRequires[$name]); } /** * @return string[] */ private function getSkippedRootRequires(\Composer\DependencyResolver\Request $request, string $name) : array { if (!isset($this->skippedLoad[$name])) { return []; } $rootRequires = $request->getRequires(); $matches = []; if (isset($rootRequires[$name])) { return \array_map(static function (PackageInterface $package) use($name) : string { if ($name !== $package->getName()) { return $package->getName() . ' (via replace of ' . $name . ')'; } return $package->getName(); }, $this->skippedLoad[$name]); } foreach ($this->skippedLoad[$name] as $packageOrReplacer) { if (isset($rootRequires[$packageOrReplacer->getName()])) { $matches[] = $packageOrReplacer->getName(); } foreach ($packageOrReplacer->getReplaces() as $link) { if (isset($rootRequires[$link->getTarget()])) { if ($name !== $packageOrReplacer->getName()) { $matches[] = $packageOrReplacer->getName() . ' (via replace of ' . $name . ')'; } else { $matches[] = $packageOrReplacer->getName(); } break; } } } return $matches; } /** * Checks whether the update allow list allows this package in the lock file to be updated */ private function isUpdateAllowed(BasePackage $package) : bool { foreach ($this->updateAllowList as $pattern) { $patternRegexp = BasePackage::packageNameToRegexp($pattern); if (Preg::isMatch($patternRegexp, $package->getName())) { return \true; } } return \false; } private function warnAboutNonMatchingUpdateAllowList(\Composer\DependencyResolver\Request $request) : void { if (null === $request->getLockedRepository()) { throw new \LogicException('No lock repo present and yet a partial update was requested.'); } foreach ($this->updateAllowList as $pattern) { $matchedPlatformPackage = \false; $patternRegexp = BasePackage::packageNameToRegexp($pattern); // update pattern matches a locked package? => all good foreach ($request->getLockedRepository()->getPackages() as $package) { if (Preg::isMatch($patternRegexp, $package->getName())) { continue 2; } } // update pattern matches a root require? => all good, probably a new package foreach ($request->getRequires() as $packageName => $constraint) { if (Preg::isMatch($patternRegexp, $packageName)) { if (PlatformRepository::isPlatformPackage($packageName)) { $matchedPlatformPackage = \true; continue; } continue 2; } } if ($matchedPlatformPackage) { $this->io->writeError('Pattern "' . $pattern . '" listed for update matches platform packages, but these cannot be updated by Composer.'); } elseif (\strpos($pattern, '*') !== \false) { $this->io->writeError('Pattern "' . $pattern . '" listed for update does not match any locked packages.'); } else { $this->io->writeError('Package "' . $pattern . '" listed for update is not locked.'); } } } /** * Reverts the decision to use a locked package if a partial update with transitive dependencies * found that this package actually needs to be updated * * @param RepositoryInterface[] $repositories */ private function unlockPackage(\Composer\DependencyResolver\Request $request, array $repositories, string $name) : void { foreach ($this->skippedLoad[$name] as $packageOrReplacer) { // if we unfixed a replaced package name, we also need to unfix the replacer itself // as long as it was not unfixed yet if ($packageOrReplacer->getName() !== $name && isset($this->skippedLoad[$packageOrReplacer->getName()])) { $replacerName = $packageOrReplacer->getName(); if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $name) && !$this->isRootRequire($request, $replacerName)) { $this->unlockPackage($request, $repositories, $replacerName); if ($this->isRootRequire($request, $replacerName)) { $this->markPackageNameForLoading($request, $replacerName, new MatchAllConstraint()); } else { foreach ($this->packages as $loadedPackage) { $requires = $loadedPackage->getRequires(); if (isset($requires[$replacerName])) { $this->markPackageNameForLoading($request, $replacerName, $requires[$replacerName]->getConstraint()); } } } } } } if (isset($this->pathRepoUnlocked[$name])) { foreach ($this->packages as $index => $package) { if ($package->getName() === $name) { $this->removeLoadedPackage($request, $repositories, $package, $index); } } } unset($this->skippedLoad[$name], $this->loadedPackages[$name], $this->maxExtendedReqs[$name], $this->pathRepoUnlocked[$name]); // remove locked package by this name which was already initialized foreach ($request->getLockedPackages() as $lockedPackage) { if (!$lockedPackage instanceof AliasPackage && $lockedPackage->getName() === $name) { if (\false !== ($index = \array_search($lockedPackage, $this->packages, \true))) { $request->unlockPackage($lockedPackage); $this->removeLoadedPackage($request, $repositories, $lockedPackage, $index); // make sure that any requirements for this package by other locked or fixed packages are now // also loaded, as they were previously ignored because the locked (now unlocked) package already // satisfied their requirements // and if this package is replacing another that is required by a locked or fixed package, ensure // that we load that replaced package in case an update to this package removes the replacement foreach ($request->getFixedOrLockedPackages() as $fixedOrLockedPackage) { if ($fixedOrLockedPackage === $lockedPackage) { continue; } if (isset($this->skippedLoad[$fixedOrLockedPackage->getName()])) { $requires = $fixedOrLockedPackage->getRequires(); if (isset($requires[$lockedPackage->getName()])) { $this->markPackageNameForLoading($request, $lockedPackage->getName(), $requires[$lockedPackage->getName()]->getConstraint()); } foreach ($lockedPackage->getReplaces() as $replace) { if (isset($requires[$replace->getTarget()], $this->skippedLoad[$replace->getTarget()])) { $this->unlockPackage($request, $repositories, $replace->getTarget()); // this package is in $requires so no need to call markPackageNameForLoadingIfRequired $this->markPackageNameForLoading($request, $replace->getTarget(), $replace->getConstraint()); } } } } } } } } private function markPackageNameForLoadingIfRequired(\Composer\DependencyResolver\Request $request, string $name) : void { if ($this->isRootRequire($request, $name)) { $this->markPackageNameForLoading($request, $name, $request->getRequires()[$name]); } foreach ($this->packages as $package) { foreach ($package->getRequires() as $link) { if ($name === $link->getTarget()) { $this->markPackageNameForLoading($request, $link->getTarget(), $link->getConstraint()); } } } } /** * @param RepositoryInterface[] $repositories */ private function removeLoadedPackage(\Composer\DependencyResolver\Request $request, array $repositories, BasePackage $package, int $index) : void { $repoIndex = \array_search($package->getRepository(), $repositories, \true); unset($this->loadedPerRepo[$repoIndex][$package->getName()][$package->getVersion()]); unset($this->packages[$index]); if (isset($this->aliasMap[\spl_object_hash($package)])) { foreach ($this->aliasMap[\spl_object_hash($package)] as $aliasIndex => $aliasPackage) { unset($this->loadedPerRepo[$repoIndex][$aliasPackage->getName()][$aliasPackage->getVersion()]); unset($this->packages[$aliasIndex]); } unset($this->aliasMap[\spl_object_hash($package)]); } } private function runOptimizer(\Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool) : \Composer\DependencyResolver\Pool { if (null === $this->poolOptimizer) { return $pool; } $this->io->debug('Running pool optimizer.'); $before = \microtime(\true); $total = \count($pool->getPackages()); $pool = $this->poolOptimizer->optimize($request, $pool); $filtered = $total - \count($pool->getPackages()); if (0 === $filtered) { return $pool; } $this->io->write(\sprintf('Pool optimizer completed in %.3f seconds', \microtime(\true) - $before), \true, IOInterface::VERY_VERBOSE); $this->io->write(\sprintf('Found %s package versions referenced in your dependency graph. %s (%d%%) were optimized away.', \number_format($total), \number_format($filtered), \round(100 / $total * $filtered)), \true, IOInterface::VERY_VERBOSE); return $pool; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; use Composer\Package\CompletePackageInterface; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; use Composer\Pcre\Preg; use Composer\Repository\RepositorySet; use Composer\Repository\LockArrayRepository; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Package\Version\VersionParser; use Composer\Repository\PlatformRepository; use Composer\Semver\Constraint\MultiConstraint; /** * Represents a problem detected while solving dependencies * * @author Nils Adermann */ class Problem { /** * A map containing the id of each rule part of this problem as a key * @var array */ protected $reasonSeen; /** * A set of reasons for the problem, each is a rule or a root require and a rule * @var array> */ protected $reasons = []; /** @var int */ protected $section = 0; /** * Add a rule as a reason * * @param Rule $rule A rule which is a reason for this problem */ public function addRule(\Composer\DependencyResolver\Rule $rule) : void { $this->addReason(\spl_object_hash($rule), $rule); } /** * Retrieve all reasons for this problem * * @return array> The problem's reasons */ public function getReasons() : array { return $this->reasons; } /** * A human readable textual representation of the problem's reasons * * @param array $installedMap A map of all present packages * @param array $learnedPool */ public function getPrettyString(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, array $installedMap = [], array $learnedPool = []) : string { // TODO doesn't this entirely defeat the purpose of the problem sections? what's the point of sections? $reasons = \array_merge(...\array_reverse($this->reasons)); if (\count($reasons) === 1) { \reset($reasons); $rule = \current($reasons); if ($rule->getReason() !== \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE) { throw new \LogicException("Single reason problems must contain a root require rule."); } $reasonData = $rule->getReasonData(); $packageName = $reasonData['packageName']; $constraint = $reasonData['constraint']; $packages = $pool->whatProvides($packageName, $constraint); if (\count($packages) === 0) { return "\n " . \implode(self::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $packageName, $constraint)); } } \usort($reasons, function (\Composer\DependencyResolver\Rule $rule1, \Composer\DependencyResolver\Rule $rule2) use($pool) { $rule1Prio = $this->getRulePriority($rule1); $rule2Prio = $this->getRulePriority($rule2); if ($rule1Prio !== $rule2Prio) { return $rule2Prio - $rule1Prio; } return $this->getSortableString($pool, $rule1) <=> $this->getSortableString($pool, $rule2); }); return self::formatDeduplicatedRules($reasons, ' ', $repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool); } private function getSortableString(\Composer\DependencyResolver\Pool $pool, \Composer\DependencyResolver\Rule $rule) : string { switch ($rule->getReason()) { case \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE: return $rule->getReasonData()['packageName']; case \Composer\DependencyResolver\Rule::RULE_FIXED: return (string) $rule->getReasonData()['package']; case \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT: case \Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES: return $rule->getSourcePackage($pool) . '//' . $rule->getReasonData()->getPrettyString($rule->getSourcePackage($pool)); case \Composer\DependencyResolver\Rule::RULE_PACKAGE_SAME_NAME: case \Composer\DependencyResolver\Rule::RULE_PACKAGE_ALIAS: case \Composer\DependencyResolver\Rule::RULE_PACKAGE_INVERSE_ALIAS: return (string) $rule->getReasonData(); case \Composer\DependencyResolver\Rule::RULE_LEARNED: return \implode('-', $rule->getLiterals()); } throw new \LogicException('Unknown rule type: ' . $rule->getReason()); } private function getRulePriority(\Composer\DependencyResolver\Rule $rule) : int { switch ($rule->getReason()) { case \Composer\DependencyResolver\Rule::RULE_FIXED: return 3; case \Composer\DependencyResolver\Rule::RULE_ROOT_REQUIRE: return 2; case \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT: case \Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES: return 1; case \Composer\DependencyResolver\Rule::RULE_PACKAGE_SAME_NAME: case \Composer\DependencyResolver\Rule::RULE_LEARNED: case \Composer\DependencyResolver\Rule::RULE_PACKAGE_ALIAS: case \Composer\DependencyResolver\Rule::RULE_PACKAGE_INVERSE_ALIAS: return 0; } throw new \LogicException('Unknown rule type: ' . $rule->getReason()); } /** * @param Rule[] $rules * @param array $installedMap A map of all present packages * @param array $learnedPool * @internal */ public static function formatDeduplicatedRules(array $rules, string $indent, RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, array $installedMap = [], array $learnedPool = []) : string { $messages = []; $templates = []; $parser = new VersionParser(); $deduplicatableRuleTypes = [\Composer\DependencyResolver\Rule::RULE_PACKAGE_REQUIRES, \Composer\DependencyResolver\Rule::RULE_PACKAGE_CONFLICT]; foreach ($rules as $rule) { $message = $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool); if (\in_array($rule->getReason(), $deduplicatableRuleTypes, \true) && Preg::isMatchStrictGroups('{^(?P\\S+) (?P\\S+) (?Prequires|conflicts)}', $message, $m)) { $message = \str_replace('%', '%%', $message); $template = Preg::replace('{^\\S+ \\S+ }', '%s%s ', $message); $messages[] = $template; $templates[$template][$m[1]][$parser->normalize($m[2])] = $m[2]; $sourcePackage = $rule->getSourcePackage($pool); foreach ($pool->getRemovedVersionsByPackage(\spl_object_hash($sourcePackage)) as $version => $prettyVersion) { $templates[$template][$m[1]][$version] = $prettyVersion; } } elseif ($message !== '') { $messages[] = $message; } } $result = []; foreach (\array_unique($messages) as $message) { if (isset($templates[$message])) { foreach ($templates[$message] as $package => $versions) { \uksort($versions, 'version_compare'); if (!$isVerbose) { $versions = self::condenseVersionList($versions, 1); } if (\count($versions) > 1) { // remove the s from requires/conflicts to correct grammar $message = Preg::replace('{^(%s%s (?:require|conflict))s}', '$1', $message); $result[] = \sprintf($message, $package, '[' . \implode(', ', $versions) . ']'); } else { $result[] = \sprintf($message, $package, ' ' . \reset($versions)); } } } else { $result[] = $message; } } return "\n{$indent}- " . \implode("\n{$indent}- ", $result); } public function isCausedByLock(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool) : bool { foreach ($this->reasons as $sectionRules) { foreach ($sectionRules as $rule) { if ($rule->isCausedByLock($repositorySet, $request, $pool)) { return \true; } } } return \false; } /** * Store a reason descriptor but ignore duplicates * * @param string $id A canonical identifier for the reason * @param Rule $reason The reason descriptor */ protected function addReason(string $id, \Composer\DependencyResolver\Rule $reason) : void { // TODO: if a rule is part of a problem description in two sections, isn't this going to remove a message // that is important to understand the issue? if (!isset($this->reasonSeen[$id])) { $this->reasonSeen[$id] = \true; $this->reasons[$this->section][] = $reason; } } public function nextSection() : void { $this->section++; } /** * @internal * @return array{0: string, 1: string} */ public static function getMissingPackageReason(RepositorySet $repositorySet, \Composer\DependencyResolver\Request $request, \Composer\DependencyResolver\Pool $pool, bool $isVerbose, string $packageName, ?ConstraintInterface $constraint = null) : array { if (PlatformRepository::isPlatformPackage($packageName)) { // handle php/php-*/hhvm if (0 === \stripos($packageName, 'php') || $packageName === 'hhvm') { $version = self::getPlatformPackageVersion($pool, $packageName, \phpversion()); $msg = "- Root composer.json requires " . $packageName . self::constraintToText($constraint) . ' but '; if (\defined('_ContaoManager\\HHVM_VERSION') || $packageName === 'hhvm' && \count($pool->whatProvides($packageName)) > 0) { return [$msg, 'your HHVM version does not satisfy that requirement.']; } if ($packageName === 'hhvm') { return [$msg, 'HHVM was not detected on this machine, make sure it is in your PATH.']; } if (null === $version) { return [$msg, 'the ' . $packageName . ' package is disabled by your platform config. Enable it again with "composer config platform.' . $packageName . ' --unset".']; } return [$msg, 'your ' . $packageName . ' version (' . $version . ') does not satisfy that requirement.']; } // handle php extensions if (0 === \stripos($packageName, 'ext-')) { if (\false !== \strpos($packageName, ' ')) { return ['- ', "PHP extension " . $packageName . ' should be required as ' . \str_replace(' ', '-', $packageName) . '.']; } $ext = \substr($packageName, 4); $msg = "- Root composer.json requires PHP extension " . $packageName . self::constraintToText($constraint) . ' but '; $version = self::getPlatformPackageVersion($pool, $packageName, \phpversion($ext) === \false ? '0' : \phpversion($ext)); if (null === $version) { $providersStr = self::getProvidersList($repositorySet, $packageName, 5); if ($providersStr !== null) { $providersStr = "\n\n Alternatively you can require one of these packages that provide the extension (or parts of it):\n{$providersStr}"; } if (\extension_loaded($ext)) { return [$msg, 'the ' . $packageName . ' package is disabled by your platform config. Enable it again with "composer config platform.' . $packageName . ' --unset".' . $providersStr]; } return [$msg, 'it is missing from your system. Install or enable PHP\'s ' . $ext . ' extension.' . $providersStr]; } return [$msg, 'it has the wrong version installed (' . $version . ').']; } // handle linked libs if (0 === \stripos($packageName, 'lib-')) { if (\strtolower($packageName) === 'lib-icu') { $error = \extension_loaded('intl') ? 'it has the wrong version installed, try upgrading the intl extension.' : 'it is missing from your system, make sure the intl extension is loaded.'; return ["- Root composer.json requires linked library " . $packageName . self::constraintToText($constraint) . ' but ', $error]; } $providersStr = self::getProvidersList($repositorySet, $packageName, 5); if ($providersStr !== null) { $providersStr = "\n\n Alternatively you can require one of these packages that provide the library (or parts of it):\n{$providersStr}"; } return ["- Root composer.json requires linked library " . $packageName . self::constraintToText($constraint) . ' but ', 'it has the wrong version installed or is missing from your system, make sure to load the extension providing it.' . $providersStr]; } } $lockedPackage = null; foreach ($request->getLockedPackages() as $package) { if ($package->getName() === $packageName) { $lockedPackage = $package; if ($pool->isUnacceptableFixedOrLockedPackage($package)) { return ["- ", $package->getPrettyName() . ' is fixed to ' . $package->getPrettyVersion() . ' (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you list it as an argument for the update command.']; } break; } } if ($constraint instanceof Constraint && $constraint->getOperator() === Constraint::STR_OP_EQ && Preg::isMatch('{^dev-.*#.*}', $constraint->getPrettyString())) { $newConstraint = Preg::replace('{ +as +([^,\\s|]+)$}', '', $constraint->getPrettyString()); $packages = $repositorySet->findPackages($packageName, new MultiConstraint([new Constraint(Constraint::STR_OP_EQ, $newConstraint), new Constraint(Constraint::STR_OP_EQ, \str_replace('#', '+', $newConstraint))], \false)); if (\count($packages) > 0) { return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . '. The # character in branch names is replaced by a + character. Make sure to require it as "' . \str_replace('#', '+', $constraint->getPrettyString()) . '".']; } } // first check if the actual requested package is found in normal conditions // if so it must mean it is rejected by another constraint than the one given here $packages = $repositorySet->findPackages($packageName, $constraint); if (\count($packages) > 0) { $rootReqs = $repositorySet->getRootRequires(); if (isset($rootReqs[$packageName])) { $filtered = \array_filter($packages, static function ($p) use($rootReqs, $packageName) : bool { return $rootReqs[$packageName]->matches(new Constraint('==', $p->getVersion())); }); if (0 === \count($filtered)) { return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts') . ' with your root composer.json require (' . $rootReqs[$packageName]->getPrettyString() . ').']; } } $tempReqs = $repositorySet->getTemporaryConstraints(); if (isset($tempReqs[$packageName])) { $filtered = \array_filter($packages, static function ($p) use($tempReqs, $packageName) : bool { return $tempReqs[$packageName]->matches(new Constraint('==', $p->getVersion())); }); if (0 === \count($filtered)) { return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts') . ' with your temporary update constraint (' . $packageName . ':' . $tempReqs[$packageName]->getPrettyString() . ').']; } } if ($lockedPackage !== null) { $fixedConstraint = new Constraint('==', $lockedPackage->getVersion()); $filtered = \array_filter($packages, static function ($p) use($fixedConstraint) : bool { return $fixedConstraint->matches(new Constraint('==', $p->getVersion())); }); if (0 === \count($filtered)) { return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but the package is fixed to ' . $lockedPackage->getPrettyVersion() . ' (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.']; } } $nonLockedPackages = \array_filter($packages, static function ($p) : bool { return !$p->getRepository() instanceof LockArrayRepository; }); if (0 === \count($nonLockedPackages)) { return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' in the lock file but not in remote repositories, make sure you avoid updating this package to keep the one from the lock file.']; } return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but these were not loaded, likely because ' . (self::hasMultipleNames($packages) ? 'they conflict' : 'it conflicts') . ' with another require.']; } // check if the package is found when bypassing stability checks $packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES); if (\count($packages) > 0) { // we must first verify if a valid package would be found in a lower priority repository $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES); if (\count($allReposPackages) > 0) { return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'minimum-stability', $constraint); } return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these do' : 'it does') . ' not match your minimum-stability.']; } // check if the package is found when bypassing the constraint and stability checks $packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES); if (\count($packages) > 0) { // we must first verify if a valid package would be found in a lower priority repository $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES); if (\count($allReposPackages) > 0) { return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'constraint', $constraint); } $suffix = ''; if ($constraint instanceof Constraint && $constraint->getVersion() === 'dev-master') { foreach ($packages as $candidate) { if (\in_array($candidate->getVersion(), ['dev-default', 'dev-main'], \true)) { $suffix = ' Perhaps dev-master was renamed to ' . $candidate->getPrettyVersion() . '?'; break; } } } // check if the root package is a name match and hint the dependencies on root troubleshooting article $allReposPackages = $packages; $topPackage = \reset($allReposPackages); if ($topPackage instanceof RootPackageInterface) { $suffix = ' See https://getcomposer.org/dep-on-root for details and assistance.'; } return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these do' : 'it does') . ' not match the constraint.' . $suffix]; } if (!Preg::isMatch('{^[A-Za-z0-9_./-]+$}', $packageName)) { $illegalChars = Preg::replace('{[A-Za-z0-9_./-]+}', '', $packageName); return ["- Root composer.json requires {$packageName}, it ", 'could not be found, it looks like its name is invalid, "' . $illegalChars . '" is not allowed in package names.']; } $providersStr = self::getProvidersList($repositorySet, $packageName, 15); if ($providersStr !== null) { return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ", it ", "could not be found in any version, but the following packages provide it:\n" . $providersStr . " Consider requiring one of these to satisfy the {$packageName} requirement."]; } return ["- Root composer.json requires {$packageName}, it ", "could not be found in any version, there may be a typo in the package name."]; } /** * @internal * @param PackageInterface[] $packages */ public static function getPackageList(array $packages, bool $isVerbose, ?\Composer\DependencyResolver\Pool $pool = null, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = \false) : string { $prepared = []; $hasDefaultBranch = []; foreach ($packages as $package) { $prepared[$package->getName()]['name'] = $package->getPrettyName(); $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion() . ($package instanceof AliasPackage ? ' (alias of ' . $package->getAliasOf()->getPrettyVersion() . ')' : ''); if ($pool !== null && $constraint !== null) { foreach ($pool->getRemovedVersions($package->getName(), $constraint) as $version => $prettyVersion) { $prepared[$package->getName()]['versions'][$version] = $prettyVersion; } } if ($pool !== null && $useRemovedVersionGroup) { foreach ($pool->getRemovedVersionsByPackage(\spl_object_hash($package)) as $version => $prettyVersion) { $prepared[$package->getName()]['versions'][$version] = $prettyVersion; } } if ($package->isDefaultBranch()) { $hasDefaultBranch[$package->getName()] = \true; } } $preparedStrings = []; foreach ($prepared as $name => $package) { // remove the implicit default branch alias to avoid cruft in the display if (isset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS], $hasDefaultBranch[$name])) { unset($package['versions'][VersionParser::DEFAULT_BRANCH_ALIAS]); } \uksort($package['versions'], 'version_compare'); if (!$isVerbose) { $package['versions'] = self::condenseVersionList($package['versions'], 4); } $preparedStrings[] = $package['name'] . '[' . \implode(', ', $package['versions']) . ']'; } return \implode(', ', $preparedStrings); } /** * @param string $version the effective runtime version of the platform package * @return ?string a version string or null if it appears the package was artificially disabled */ private static function getPlatformPackageVersion(\Composer\DependencyResolver\Pool $pool, string $packageName, string $version) : ?string { $available = $pool->whatProvides($packageName); if (\count($available) > 0) { $selected = null; foreach ($available as $pkg) { if ($pkg->getRepository() instanceof PlatformRepository) { $selected = $pkg; break; } } if ($selected === null) { $selected = \reset($available); } // must be a package providing/replacing and not a real platform package if ($selected->getName() !== $packageName) { /** @var Link $link */ foreach (\array_merge(\array_values($selected->getProvides()), \array_values($selected->getReplaces())) as $link) { if ($link->getTarget() === $packageName) { return $link->getPrettyConstraint() . ' ' . \substr($link->getDescription(), 0, -1) . 'd by ' . $selected->getPrettyString(); } } } $version = $selected->getPrettyVersion(); $extra = $selected->getExtra(); if ($selected instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === \true) { $version .= '; ' . \str_replace('Package ', '', (string) $selected->getDescription()); } } else { return null; } return $version; } /** * @param array $versions an array of pretty versions, with normalized versions as keys * @return list a list of pretty versions and '...' where versions were removed */ private static function condenseVersionList(array $versions, int $max, int $maxDev = 16) : array { if (\count($versions) <= $max) { return \array_values($versions); } $filtered = []; $byMajor = []; foreach ($versions as $version => $pretty) { if (0 === \stripos((string) $version, 'dev-')) { $byMajor['dev'][] = $pretty; } else { $byMajor[Preg::replace('{^(\\d+)\\..*}', '$1', (string) $version)][] = $pretty; } } foreach ($byMajor as $majorVersion => $versionsForMajor) { $maxVersions = $majorVersion === 'dev' ? $maxDev : $max; if (\count($versionsForMajor) > $maxVersions) { // output only 1st and last versions $filtered[] = $versionsForMajor[0]; $filtered[] = '...'; $filtered[] = $versionsForMajor[\count($versionsForMajor) - 1]; } else { $filtered = \array_merge($filtered, $versionsForMajor); } } return $filtered; } /** * @param PackageInterface[] $packages */ private static function hasMultipleNames(array $packages) : bool { $name = null; foreach ($packages as $package) { if ($name === null || $name === $package->getName()) { $name = $package->getName(); } else { return \true; } } return \false; } /** * @param non-empty-array $higherRepoPackages * @param non-empty-array $allReposPackages * @return array{0: string, 1: string} */ private static function computeCheckForLowerPrioRepo(\Composer\DependencyResolver\Pool $pool, bool $isVerbose, string $packageName, array $higherRepoPackages, array $allReposPackages, string $reason, ?ConstraintInterface $constraint = null) : array { $nextRepoPackages = []; $nextRepo = null; foreach ($allReposPackages as $package) { if ($nextRepo === null || $nextRepo === $package->getRepository()) { $nextRepoPackages[] = $package; $nextRepo = $package->getRepository(); } else { break; } } \assert(null !== $nextRepo); if (\count($higherRepoPackages) > 0) { $topPackage = \reset($higherRepoPackages); if ($topPackage instanceof RootPackageInterface) { return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', it is ', 'satisfiable by ' . self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint) . ' from ' . $nextRepo->getRepoName() . ' but ' . $topPackage->getPrettyName() . ' ' . $topPackage->getPrettyVersion() . ' is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.']; } } if ($nextRepo instanceof LockArrayRepository) { $singular = \count($higherRepoPackages) === 1; $suggestion = 'Make sure you either fix the ' . $reason . ' or avoid updating this package to keep the one present in the lock file (' . self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint) . ').'; // symlinked path repos cannot be locked so do not suggest keeping it locked if ($nextRepoPackages[0]->getDistType() === 'path') { $transportOptions = $nextRepoPackages[0]->getTransportOptions(); if (!isset($transportOptions['symlink']) || $transportOptions['symlink'] !== \false) { $suggestion = 'Make sure you fix the ' . $reason . ' as packages installed from symlinked path repos are updated even in partial updates and the one from the lock file can thus not be used.'; } } return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ', 'found ' . self::getPackageList($higherRepoPackages, $isVerbose, $pool, $constraint) . ' but ' . ($singular ? 'it does' : 'these do') . ' not match your ' . $reason . ' and ' . ($singular ? 'is' : 'are') . ' therefore not installable. ' . $suggestion]; } return ["- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', it is ', 'satisfiable by ' . self::getPackageList($nextRepoPackages, $isVerbose, $pool, $constraint) . ' from ' . $nextRepo->getRepoName() . ' but ' . self::getPackageList($higherRepoPackages, $isVerbose, $pool, $constraint) . ' from ' . \reset($higherRepoPackages)->getRepository()->getRepoName() . ' has higher repository priority. The packages from the higher priority repository do not match your ' . $reason . ' and are therefore not installable. That repository is canonical so the lower priority repo\'s packages are not installable. See https://getcomposer.org/repoprio for details and assistance.']; } /** * Turns a constraint into text usable in a sentence describing a request */ protected static function constraintToText(?ConstraintInterface $constraint = null) : string { if ($constraint instanceof Constraint && $constraint->getOperator() === Constraint::STR_OP_EQ && !\str_starts_with($constraint->getVersion(), 'dev-')) { if (!Preg::isMatch('{^\\d+(?:\\.\\d+)*$}', $constraint->getPrettyString())) { return ' ' . $constraint->getPrettyString() . ' (exact version match)'; } $versions = [$constraint->getPrettyString()]; for ($i = 3 - \substr_count($versions[0], '.'); $i > 0; $i--) { $versions[] = \end($versions) . '.0'; } return ' ' . $constraint->getPrettyString() . ' (exact version match: ' . (\count($versions) > 1 ? \implode(', ', \array_slice($versions, 0, -1)) . ' or ' . \end($versions) : $versions[0]) . ')'; } return $constraint !== null ? ' ' . $constraint->getPrettyString() : ''; } private static function getProvidersList(RepositorySet $repositorySet, string $packageName, int $maxProviders) : ?string { $providers = $repositorySet->getProviders($packageName); if (\count($providers) > 0) { $providersStr = \implode(\array_map(static function ($p) : string { $description = $p['description'] !== '' && $p['description'] !== null ? ' ' . \substr($p['description'], 0, 100) : ''; return ' - ' . $p['name'] . $description . "\n"; }, \count($providers) > $maxProviders + 1 ? \array_slice($providers, 0, $maxProviders) : $providers)); if (\count($providers) > $maxProviders + 1) { $providersStr .= ' ... and ' . (\count($providers) - $maxProviders) . ' more.' . "\n"; } return $providersStr; } return null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * @author Nils Adermann * @implements \Iterator */ class RuleSetIterator implements \Iterator { /** @var array */ protected $rules; /** @var array */ protected $types; /** @var int */ protected $currentOffset; /** @var RuleSet::TYPE_*|-1 */ protected $currentType; /** @var int */ protected $currentTypeOffset; /** * @param array $rules */ public function __construct(array $rules) { $this->rules = $rules; $this->types = \array_keys($rules); \sort($this->types); $this->rewind(); } public function current() : \Composer\DependencyResolver\Rule { return $this->rules[$this->currentType][$this->currentOffset]; } /** * @return RuleSet::TYPE_*|-1 */ public function key() : int { return $this->currentType; } public function next() : void { $this->currentOffset++; if (!isset($this->rules[$this->currentType])) { return; } if ($this->currentOffset >= \count($this->rules[$this->currentType])) { $this->currentOffset = 0; do { $this->currentTypeOffset++; if (!isset($this->types[$this->currentTypeOffset])) { $this->currentType = -1; break; } $this->currentType = $this->types[$this->currentTypeOffset]; } while (0 === \count($this->rules[$this->currentType])); } } public function rewind() : void { $this->currentOffset = 0; $this->currentTypeOffset = -1; $this->currentType = -1; do { $this->currentTypeOffset++; if (!isset($this->types[$this->currentTypeOffset])) { $this->currentType = -1; break; } $this->currentType = $this->types[$this->currentTypeOffset]; } while (0 === \count($this->rules[$this->currentType])); } public function valid() : bool { return isset($this->rules[$this->currentType], $this->rules[$this->currentType][$this->currentOffset]); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\DependencyResolver; /** * An extension of SplDoublyLinkedList with seek and removal of current element * * SplDoublyLinkedList only allows deleting a particular offset and has no * method to set the internal iterator to a particular offset. * * @author Nils Adermann * @extends \SplDoublyLinkedList */ class RuleWatchChain extends \SplDoublyLinkedList { /** * Moves the internal iterator to the specified offset * * @param int $offset The offset to seek to. */ public function seek(int $offset) : void { $this->rewind(); for ($i = 0; $i < $offset; $i++, $this->next()) { } } /** * Removes the current element from the list * * As SplDoublyLinkedList only allows deleting a particular offset and * incorrectly sets the internal iterator if you delete the current value * this method sets the internal iterator back to the following element * using the seek method. */ public function remove() : void { $offset = $this->key(); $this->offsetUnset($offset); $this->seek($offset); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Autoload; use Composer\ClassMapGenerator\ClassMap; use Composer\ClassMapGenerator\ClassMapGenerator; use Composer\Config; use Composer\EventDispatcher\EventDispatcher; use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\Installer\InstallationManager; use Composer\IO\IOInterface; use Composer\IO\NullIO; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; use Composer\Pcre\Preg; use Composer\Repository\InstalledRepositoryInterface; use Composer\Semver\Constraint\Bound; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Script\ScriptEvents; use Composer\Util\PackageSorter; use Composer\Json\JsonFile; use Composer\Package\Locker; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; /** * @author Igor Wiedler * @author Jordi Boggiano */ class AutoloadGenerator { /** * @var EventDispatcher */ private $eventDispatcher; /** * @var IOInterface */ private $io; /** * @var ?bool */ private $devMode = null; /** * @var bool */ private $classMapAuthoritative = \false; /** * @var bool */ private $apcu = \false; /** * @var string|null */ private $apcuPrefix; /** * @var bool */ private $dryRun = \false; /** * @var bool */ private $runScripts = \false; /** * @var PlatformRequirementFilterInterface */ private $platformRequirementFilter; public function __construct(EventDispatcher $eventDispatcher, ?IOInterface $io = null) { $this->eventDispatcher = $eventDispatcher; $this->io = $io ?? new NullIO(); $this->platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing(); } /** * @return void */ public function setDevMode(bool $devMode = \true) { $this->devMode = $devMode; } /** * Whether generated autoloader considers the class map authoritative. * * @return void */ public function setClassMapAuthoritative(bool $classMapAuthoritative) { $this->classMapAuthoritative = $classMapAuthoritative; } /** * Whether generated autoloader considers APCu caching. * * @return void */ public function setApcu(bool $apcu, ?string $apcuPrefix = null) { $this->apcu = $apcu; $this->apcuPrefix = $apcuPrefix; } /** * Whether to run scripts or not * * @return void */ public function setRunScripts(bool $runScripts = \true) { $this->runScripts = $runScripts; } /** * Whether to run in drymode or not */ public function setDryRun(bool $dryRun = \true) : void { $this->dryRun = $dryRun; } /** * Whether platform requirements should be ignored. * * If this is set to true, the platform check file will not be generated * If this is set to false, the platform check file will be generated with all requirements * If this is set to string[], those packages will be ignored from the platform check file * * @param bool|string[] $ignorePlatformReqs * @return void * * @deprecated use setPlatformRequirementFilter instead */ public function setIgnorePlatformRequirements($ignorePlatformReqs) { \trigger_error('AutoloadGenerator::setIgnorePlatformRequirements is deprecated since Composer 2.2, use setPlatformRequirementFilter instead.', \E_USER_DEPRECATED); $this->setPlatformRequirementFilter(PlatformRequirementFilterFactory::fromBoolOrList($ignorePlatformReqs)); } /** * @return void */ public function setPlatformRequirementFilter(PlatformRequirementFilterInterface $platformRequirementFilter) { $this->platformRequirementFilter = $platformRequirementFilter; } /** * @return ClassMap * @throws \Seld\JsonLint\ParsingException * @throws \RuntimeException */ public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, string $targetDir, bool $scanPsrPackages = \false, ?string $suffix = null, ?Locker $locker = null, bool $strictAmbiguous = \false) { if ($this->classMapAuthoritative) { // Force scanPsrPackages when classmap is authoritative $scanPsrPackages = \true; } // auto-set devMode based on whether dev dependencies are installed or not if (null === $this->devMode) { // we assume no-dev mode if no vendor dir is present or it is too old to contain dev information $this->devMode = \false; $installedJson = new JsonFile($config->get('vendor-dir') . '/composer/installed.json'); if ($installedJson->exists()) { $installedJson = $installedJson->read(); if (isset($installedJson['dev'])) { $this->devMode = $installedJson['dev']; } } } if ($this->runScripts) { // set COMPOSER_DEV_MODE in case not set yet so it is available in the dump-autoload event listeners if (!isset($_SERVER['COMPOSER_DEV_MODE'])) { Platform::putEnv('COMPOSER_DEV_MODE', $this->devMode ? '1' : '0'); } $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, [], ['optimize' => $scanPsrPackages]); } $classMapGenerator = new ClassMapGenerator(['php', 'inc', 'hh']); $classMapGenerator->avoidDuplicateScans(); $filesystem = new Filesystem(); $filesystem->ensureDirectoryExists($config->get('vendor-dir')); // Do not remove double realpath() calls. // Fixes failing Windows realpath() implementation. // See https://bugs.php.net/bug.php?id=72738 $basePath = $filesystem->normalizePath(\realpath(\realpath(Platform::getCwd()))); $vendorPath = $filesystem->normalizePath(\realpath(\realpath($config->get('vendor-dir')))); $useGlobalIncludePath = $config->get('use-include-path'); $prependAutoloader = $config->get('prepend-autoloader') === \false ? 'false' : 'true'; $targetDir = $vendorPath . '/' . $targetDir; $filesystem->ensureDirectoryExists($targetDir); $vendorPathCode = $filesystem->findShortestPathCode(\realpath($targetDir), $vendorPath, \true); $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, \realpath($targetDir), \true); $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, \true); $appBaseDirCode = \str_replace('__DIR__', '$vendorDir', $appBaseDirCode); $namespacesFile = <<getDevPackageNames(); $packageMap = $this->buildPackageMap($installationManager, $rootPackage, $localRepo->getCanonicalPackages()); if ($this->devMode) { // if dev mode is enabled, then we do not filter any dev packages out so disable this entirely $filteredDevPackages = \false; } else { // if the list of dev package names is available we use that straight, otherwise pass true which means use legacy algo to figure them out $filteredDevPackages = $devPackageNames ?: \true; } $autoloads = $this->parseAutoloads($packageMap, $rootPackage, $filteredDevPackages); // Process the 'psr-0' base directories. foreach ($autoloads['psr-0'] as $namespace => $paths) { $exportedPaths = []; foreach ($paths as $path) { $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); } $exportedPrefix = \var_export($namespace, \true); $namespacesFile .= " {$exportedPrefix} => "; $namespacesFile .= "array(" . \implode(', ', $exportedPaths) . "),\n"; } $namespacesFile .= ");\n"; // Process the 'psr-4' base directories. foreach ($autoloads['psr-4'] as $namespace => $paths) { $exportedPaths = []; foreach ($paths as $path) { $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path); } $exportedPrefix = \var_export($namespace, \true); $psr4File .= " {$exportedPrefix} => "; $psr4File .= "array(" . \implode(', ', $exportedPaths) . "),\n"; } $psr4File .= ");\n"; // add custom psr-0 autoloading if the root package has a target dir $targetDirLoader = null; $mainAutoload = $rootPackage->getAutoload(); if ($rootPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) { $levels = \substr_count($filesystem->normalizePath($rootPackage->getTargetDir()), '/') + 1; $prefixes = \implode(', ', \array_map(static function ($prefix) : string { return \var_export($prefix, \true); }, \array_keys($mainAutoload['psr-0']))); $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, \true); $targetDirLoader = <<scanPaths($dir, $this->buildExclusionRegex($dir, $excluded)); } if ($scanPsrPackages) { $namespacesToScan = []; // Scan the PSR-0/4 directories for class files, and add them to the class map foreach (['psr-4', 'psr-0'] as $psrType) { foreach ($autoloads[$psrType] as $namespace => $paths) { $namespacesToScan[$namespace][] = ['paths' => $paths, 'type' => $psrType]; } } \krsort($namespacesToScan); foreach ($namespacesToScan as $namespace => $groups) { foreach ($groups as $group) { foreach ($group['paths'] as $dir) { $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath . '/' . $dir); if (!\is_dir($dir)) { continue; } // if the vendor dir is contained within a psr-0/psr-4 dir being scanned we exclude it if (\str_contains($vendorPath, $dir . '/')) { $exclusionRegex = $this->buildExclusionRegex($dir, \array_merge($excluded, [$vendorPath . '/'])); } else { $exclusionRegex = $this->buildExclusionRegex($dir, $excluded); } $classMapGenerator->scanPaths($dir, $exclusionRegex, $group['type'], $namespace); } } } } $classMap = $classMapGenerator->getClassMap(); if ($strictAmbiguous) { $ambiguousClasses = $classMap->getAmbiguousClasses(\false); } else { $ambiguousClasses = $classMap->getAmbiguousClasses(); } foreach ($ambiguousClasses as $className => $ambiguousPaths) { if (\count($ambiguousPaths) > 1) { $this->io->writeError('Warning: Ambiguous class resolution, "' . $className . '"' . ' was found ' . (\count($ambiguousPaths) + 1) . 'x: in "' . $classMap->getClassPath($className) . '" and "' . \implode('", "', $ambiguousPaths) . '", the first will be used.'); } else { $this->io->writeError('Warning: Ambiguous class resolution, "' . $className . '"' . ' was found in both "' . $classMap->getClassPath($className) . '" and "' . \implode('", "', $ambiguousPaths) . '", the first will be used.'); } } if (\count($ambiguousClasses) > 0) { $this->io->writeError('To resolve ambiguity in classes not under your control you can ignore them by path using exclude-files-from-classmap'); } // output PSR violations which are not coming from the vendor dir $classMap->clearPsrViolationsByPath($vendorPath); foreach ($classMap->getPsrViolations() as $msg) { $this->io->writeError("{$msg}"); } $classMap->addClass('Composer\\InstalledVersions', $vendorPath . '/composer/InstalledVersions.php'); $classMap->sort(); $classmapFile = <<getMap() as $className => $path) { $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n"; $classmapFile .= ' ' . \var_export($className, \true) . ' => ' . $pathCode; } $classmapFile .= ");\n"; if ('' === $suffix) { $suffix = null; } if (null === $suffix) { $suffix = $config->get('autoloader-suffix'); // carry over existing autoload.php's suffix if possible and none is configured if (null === $suffix && Filesystem::isReadable($vendorPath . '/autoload.php')) { $content = (string) \file_get_contents($vendorPath . '/autoload.php'); if (Preg::isMatch('{ComposerAutoloaderInit([^:\\s]+)::}', $content, $match)) { $suffix = $match[1]; } } if (null === $suffix) { $suffix = $locker !== null && $locker->isLocked() ? $locker->getLockData()['content-hash'] : \bin2hex(\random_bytes(16)); } } if ($this->dryRun) { return $classMap; } $filesystem->filePutContentsIfModified($targetDir . '/autoload_namespaces.php', $namespacesFile); $filesystem->filePutContentsIfModified($targetDir . '/autoload_psr4.php', $psr4File); $filesystem->filePutContentsIfModified($targetDir . '/autoload_classmap.php', $classmapFile); $includePathFilePath = $targetDir . '/include_paths.php'; if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)) { $filesystem->filePutContentsIfModified($includePathFilePath, $includePathFileContents); } elseif (\file_exists($includePathFilePath)) { \unlink($includePathFilePath); } $includeFilesFilePath = $targetDir . '/autoload_files.php'; if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)) { $filesystem->filePutContentsIfModified($includeFilesFilePath, $includeFilesFileContents); } elseif (\file_exists($includeFilesFilePath)) { \unlink($includeFilesFilePath); } $filesystem->filePutContentsIfModified($targetDir . '/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath)); $checkPlatform = $config->get('platform-check') !== \false && !$this->platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter; $platformCheckContent = null; if ($checkPlatform) { $platformCheckContent = $this->getPlatformCheck($packageMap, $config->get('platform-check'), $devPackageNames); if (null === $platformCheckContent) { $checkPlatform = \false; } } if ($checkPlatform) { $filesystem->filePutContentsIfModified($targetDir . '/platform_check.php', $platformCheckContent); } elseif (\file_exists($targetDir . '/platform_check.php')) { \unlink($targetDir . '/platform_check.php'); } $filesystem->filePutContentsIfModified($vendorPath . '/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); $filesystem->filePutContentsIfModified($targetDir . '/autoload_real.php', $this->getAutoloadRealFile(\true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $checkPlatform)); $filesystem->safeCopy(__DIR__ . '/ClassLoader.php', $targetDir . '/ClassLoader.php'); $filesystem->safeCopy(__DIR__ . '/../../../LICENSE', $targetDir . '/LICENSE'); if ($this->runScripts) { $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, [], ['optimize' => $scanPsrPackages]); } return $classMap; } /** * @param array $excluded * @return non-empty-string|null */ private function buildExclusionRegex(string $dir, array $excluded) : ?string { if ([] === $excluded) { return null; } // filter excluded patterns here to only use those matching $dir // exclude-from-classmap patterns are all realpath'd so we can only filter them if $dir exists so that realpath($dir) will work // if $dir does not exist, it should anyway not find anything there so no trouble if (\file_exists($dir)) { // transform $dir in the same way that exclude-from-classmap patterns are transformed so we can match them against each other $dirMatch = \preg_quote(\strtr(\realpath($dir), '\\', '/')); foreach ($excluded as $index => $pattern) { // extract the constant string prefix of the pattern here, until we reach a non-escaped regex special character $pattern = Preg::replace('{^(([^.+*?\\[^\\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\\[^\\]$(){}=!<>|:#-])*).*}', '$1', $pattern); // if the pattern is not a subset or superset of $dir, it is unrelated and we skip it if (0 !== \strpos($pattern, $dirMatch) && 0 !== \strpos($dirMatch, $pattern)) { unset($excluded[$index]); } } } return \count($excluded) > 0 ? '{(' . \implode('|', $excluded) . ')}' : null; } /** * @param PackageInterface[] $packages * @return non-empty-array */ public function buildPackageMap(InstallationManager $installationManager, PackageInterface $rootPackage, array $packages) { // build package => install path map $packageMap = [[$rootPackage, '']]; foreach ($packages as $package) { if ($package instanceof AliasPackage) { continue; } $this->validatePackage($package); $packageMap[] = [$package, $installationManager->getInstallPath($package)]; } return $packageMap; } /** * @return void * @throws \InvalidArgumentException Throws an exception, if the package has illegal settings. */ protected function validatePackage(PackageInterface $package) { $autoload = $package->getAutoload(); if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) { $name = $package->getName(); $package->getTargetDir(); throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '{$name}'."); } if (!empty($autoload['psr-4'])) { foreach ($autoload['psr-4'] as $namespace => $dirs) { if ($namespace !== '' && '\\' !== \substr($namespace, -1)) { throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '{$namespace}' does not, use '{$namespace}\\'."); } } } } /** * Compiles an ordered list of namespace => path mappings * * @param non-empty-array $packageMap array of array(package, installDir-relative-to-composer.json or null for metapackages) * @param RootPackageInterface $rootPackage root package instance * @param bool|string[] $filteredDevPackages If an array, the list of packages that must be removed. If bool, whether to filter out require-dev packages * @return array * @phpstan-return array{ * 'psr-0': array>, * 'psr-4': array>, * 'classmap': array, * 'files': array, * 'exclude-from-classmap': array, * } */ public function parseAutoloads(array $packageMap, PackageInterface $rootPackage, $filteredDevPackages = \false) { $rootPackageMap = \array_shift($packageMap); if (\is_array($filteredDevPackages)) { $packageMap = \array_filter($packageMap, static function ($item) use($filteredDevPackages) : bool { return !\in_array($item[0]->getName(), $filteredDevPackages, \true); }); } elseif ($filteredDevPackages) { $packageMap = $this->filterPackageMap($packageMap, $rootPackage); } $sortedPackageMap = $this->sortPackageMap($packageMap); $sortedPackageMap[] = $rootPackageMap; $reverseSortedMap = \array_reverse($sortedPackageMap); // reverse-sorted means root first, then dependents, then their dependents, etc. // which makes sense to allow root to override classmap or psr-0/4 entries with higher precedence rules $psr0 = $this->parseAutoloadsType($reverseSortedMap, 'psr-0', $rootPackage); $psr4 = $this->parseAutoloadsType($reverseSortedMap, 'psr-4', $rootPackage); $classmap = $this->parseAutoloadsType($reverseSortedMap, 'classmap', $rootPackage); // sorted (i.e. dependents first) for files to ensure that dependencies are loaded/available once a file is included $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $rootPackage); // using sorted here but it does not really matter as all are excluded equally $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $rootPackage); \krsort($psr0); \krsort($psr4); return ['psr-0' => $psr0, 'psr-4' => $psr4, 'classmap' => $classmap, 'files' => $files, 'exclude-from-classmap' => $exclude]; } /** * Registers an autoloader based on an autoload-map returned by parseAutoloads * * @param array $autoloads see parseAutoloads return value * @return ClassLoader */ public function createLoader(array $autoloads, ?string $vendorDir = null) { $loader = new \Composer\Autoload\ClassLoader($vendorDir); if (isset($autoloads['psr-0'])) { foreach ($autoloads['psr-0'] as $namespace => $path) { $loader->add($namespace, $path); } } if (isset($autoloads['psr-4'])) { foreach ($autoloads['psr-4'] as $namespace => $path) { $loader->addPsr4($namespace, $path); } } if (isset($autoloads['classmap'])) { $excluded = []; if (!empty($autoloads['exclude-from-classmap'])) { $excluded = $autoloads['exclude-from-classmap']; } $classMapGenerator = new ClassMapGenerator(['php', 'inc', 'hh']); $classMapGenerator->avoidDuplicateScans(); foreach ($autoloads['classmap'] as $dir) { try { $classMapGenerator->scanPaths($dir, $this->buildExclusionRegex($dir, $excluded)); } catch (\RuntimeException $e) { $this->io->writeError('' . $e->getMessage() . ''); } } $loader->addClassMap($classMapGenerator->getClassMap()->getMap()); } return $loader; } /** * @param array $packageMap * @return ?string */ protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, string $basePath, string $vendorPath, string $vendorPathCode, string $appBaseDirCode) { $includePaths = []; foreach ($packageMap as $item) { [$package, $installPath] = $item; // packages that are not installed cannot autoload anything if (null === $installPath) { continue; } if (null !== $package->getTargetDir() && \strlen($package->getTargetDir()) > 0) { $installPath = \substr($installPath, 0, -\strlen('/' . $package->getTargetDir())); } foreach ($package->getIncludePaths() as $includePath) { $includePath = \trim($includePath, '/'); $includePaths[] = $installPath === '' ? $includePath : $installPath . '/' . $includePath; } } if (\count($includePaths) === 0) { return null; } $includePathsCode = ''; foreach ($includePaths as $path) { $includePathsCode .= " " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n"; } return << $files * @return ?string */ protected function getIncludeFilesFile(array $files, Filesystem $filesystem, string $basePath, string $vendorPath, string $vendorPathCode, string $appBaseDirCode) { // Get the path to each file, and make sure these paths are unique. $files = \array_map(function (string $functionFile) use($filesystem, $basePath, $vendorPath) : string { return $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile); }, $files); $uniqueFiles = \array_unique($files); if (\count($uniqueFiles) < \count($files)) { $this->io->writeError('The following "files" autoload rules are included multiple times, this may cause issues and should be resolved:'); foreach (\array_unique(\array_diff_assoc($files, $uniqueFiles)) as $duplicateFile) { $this->io->writeError(' - ' . $duplicateFile . ''); } } unset($uniqueFiles); $filesCode = ''; foreach ($files as $fileIdentifier => $functionFile) { $filesCode .= ' ' . \var_export($fileIdentifier, \true) . ' => ' . $functionFile . ",\n"; } if (!$filesCode) { return null; } return <<isAbsolutePath($path)) { $path = $basePath . '/' . $path; } $path = $filesystem->normalizePath($path); $baseDir = ''; if (\strpos($path . '/', $vendorPath . '/') === 0) { $path = (string) \substr($path, \strlen($vendorPath)); $baseDir = '$vendorDir . '; } else { $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, \true)); if (!$filesystem->isAbsolutePath($path)) { $baseDir = '$baseDir . '; $path = '/' . $path; } } if (\strpos($path, '.phar') !== \false) { $baseDir = "'phar://' . " . $baseDir; } return $baseDir . \var_export($path, \true); } /** * @param array $packageMap * @param bool|'php-only' $checkPlatform * @param string[] $devPackageNames * @return ?string */ protected function getPlatformCheck(array $packageMap, $checkPlatform, array $devPackageNames) { $lowestPhpVersion = Bound::zero(); $requiredPhp64bit = \false; $requiredExtensions = []; $extensionProviders = []; foreach ($packageMap as $item) { $package = $item[0]; foreach (\array_merge($package->getReplaces(), $package->getProvides()) as $link) { if (Preg::isMatch('{^ext-(.+)$}iD', $link->getTarget(), $match)) { $extensionProviders[$match[1]][] = $link->getConstraint(); } } } foreach ($packageMap as $item) { $package = $item[0]; // skip dev dependencies platform requirements as platform-check really should only be a production safeguard if (\in_array($package->getName(), $devPackageNames, \true)) { continue; } foreach ($package->getRequires() as $link) { if ($this->platformRequirementFilter->isIgnored($link->getTarget())) { continue; } if (\in_array($link->getTarget(), ['php', 'php-64bit'], \true)) { $constraint = $link->getConstraint(); if ($constraint->getLowerBound()->compareTo($lowestPhpVersion, '>')) { $lowestPhpVersion = $constraint->getLowerBound(); } } if ('php-64bit' === $link->getTarget()) { $requiredPhp64bit = \true; } if ($checkPlatform === \true && Preg::isMatch('{^ext-(.+)$}iD', $link->getTarget(), $match)) { // skip extension checks if they have a valid provider/replacer if (isset($extensionProviders[$match[1]])) { foreach ($extensionProviders[$match[1]] as $provided) { if ($provided->matches($link->getConstraint())) { continue 2; } } } if ($match[1] === 'zend-opcache') { $match[1] = 'zend opcache'; } $extension = \var_export($match[1], \true); if ($match[1] === 'pcntl' || $match[1] === 'readline') { $requiredExtensions[$extension] = "PHP_SAPI !== 'cli' || extension_loaded({$extension}) || \$missingExtensions[] = {$extension};\n"; } else { $requiredExtensions[$extension] = "extension_loaded({$extension}) || \$missingExtensions[] = {$extension};\n"; } } } } \ksort($requiredExtensions); $formatToPhpVersionId = static function (Bound $bound) : int { if ($bound->isZero()) { return 0; } if ($bound->isPositiveInfinity()) { return 99999; } $version = \str_replace('-', '.', $bound->getVersion()); $chunks = \array_map('intval', \explode('.', $version)); return $chunks[0] * 10000 + $chunks[1] * 100 + $chunks[2]; }; $formatToHumanReadable = static function (Bound $bound) { if ($bound->isZero()) { return 0; } if ($bound->isPositiveInfinity()) { return 99999; } $version = \str_replace('-', '.', $bound->getVersion()); $chunks = \explode('.', $version); $chunks = \array_slice($chunks, 0, 3); return \implode('.', $chunks); }; $requiredPhp = ''; $requiredPhpError = ''; if (!$lowestPhpVersion->isZero()) { $operator = $lowestPhpVersion->isInclusive() ? '>=' : '>'; $requiredPhp = 'PHP_VERSION_ID ' . $operator . ' ' . $formatToPhpVersionId($lowestPhpVersion); $requiredPhpError = '"' . $operator . ' ' . $formatToHumanReadable($lowestPhpVersion) . '"'; } if ($requiredPhp) { $requiredPhp = <<classMapAuthoritative) { $file .= <<<'CLASSMAPAUTHORITATIVE' $loader->setClassMapAuthoritative(true); CLASSMAPAUTHORITATIVE; } if ($this->apcu) { $apcuPrefix = \var_export($this->apcuPrefix !== null ? $this->apcuPrefix : \bin2hex(\random_bytes(10)), \true); $file .= <<setApcuPrefix({$apcuPrefix}); APCU; } if ($useGlobalIncludePath) { $file .= <<<'INCLUDEPATH' $loader->setUseIncludePath(true); INCLUDEPATH; } if ($targetDirLoader) { $file .= <<register({$prependAutoloader}); REGISTER_LOADER; if ($useIncludeFiles) { $file .= << \$file) { \$requireFile(\$fileIdentifier, \$file); } INCLUDE_FILES; } $file .= << $path) { $loader->set($namespace, $path); } $map = (require $targetDir . '/autoload_psr4.php'); foreach ($map as $namespace => $path) { $loader->setPsr4($namespace, $path); } /** * @var string $vendorDir * @var string $baseDir */ $classMap = (require $targetDir . '/autoload_classmap.php'); if ($classMap) { $loader->addClassMap($classMap); } $filesystem = new Filesystem(); $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(\realpath($targetDir), $vendorPath, \true, \true) . " . '/"; $vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(\realpath($targetDir), $vendorPath, \true, \true) . " . '/"; $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(\realpath($targetDir), $basePath, \true, \true) . " . '/"; $appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(\realpath($targetDir), $basePath, \true, \true) . " . '/"; $absoluteVendorPathCode = ' => ' . \substr(\var_export(\rtrim($vendorDir, '\\/') . '/', \true), 0, -1); $absoluteVendorPharPathCode = ' => ' . \substr(\var_export(\rtrim('phar://' . $vendorDir, '\\/') . '/', \true), 0, -1); $absoluteAppBaseDirCode = ' => ' . \substr(\var_export(\rtrim($baseDir, '\\/') . '/', \true), 0, -1); $absoluteAppBaseDirPharCode = ' => ' . \substr(\var_export(\rtrim('phar://' . $baseDir, '\\/') . '/', \true), 0, -1); $initializer = ''; $prefix = "\x00Composer\\Autoload\\ClassLoader\x00"; $prefixLen = \strlen($prefix); if (\file_exists($targetDir . '/autoload_files.php')) { $maps = ['files' => require $targetDir . '/autoload_files.php']; } else { $maps = []; } foreach ((array) $loader as $prop => $value) { if (!\is_array($value) || \count($value) === 0 || !\str_starts_with($prop, $prefix)) { continue; } $maps[\substr($prop, $prefixLen)] = $value; } foreach ($maps as $prop => $value) { $value = \strtr(\var_export($value, \true), [$absoluteVendorPathCode => $vendorPathCode, $absoluteVendorPharPathCode => $vendorPharPathCode, $absoluteAppBaseDirCode => $appBaseDirCode, $absoluteAppBaseDirPharCode => $appBaseDirPharCode]); $value = \ltrim(Preg::replace('/^ */m', ' $0$0', $value)); $file .= \sprintf(" public static \$%s = %s;\n\n", $prop, $value); if ('files' !== $prop) { $initializer .= " \$loader->{$prop} = ComposerStaticInit{$suffix}::\${$prop};\n"; } } return $file . << $packageMap * @param string $type one of: 'psr-0'|'psr-4'|'classmap'|'files' * @return array|array>|array */ protected function parseAutoloadsType(array $packageMap, string $type, RootPackageInterface $rootPackage) { $autoloads = []; foreach ($packageMap as $item) { [$package, $installPath] = $item; // packages that are not installed cannot autoload anything if (null === $installPath) { continue; } $autoload = $package->getAutoload(); if ($this->devMode && $package === $rootPackage) { $autoload = \array_merge_recursive($autoload, $package->getDevAutoload()); } // skip misconfigured packages if (!isset($autoload[$type]) || !\is_array($autoload[$type])) { continue; } if (null !== $package->getTargetDir() && $package !== $rootPackage) { $installPath = \substr($installPath, 0, -\strlen('/' . $package->getTargetDir())); } foreach ($autoload[$type] as $namespace => $paths) { if (\in_array($type, ['psr-4', 'psr-0'], \true)) { // normalize namespaces to ensure "\" becomes "" and others do not have leading separators as they are not needed $namespace = \ltrim($namespace, '\\'); } foreach ((array) $paths as $path) { if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !Filesystem::isReadable($installPath . '/' . $path)) { // remove target-dir from file paths of the root package if ($package === $rootPackage) { $targetDir = \str_replace('\\', '[\\\\/]', \preg_quote(\str_replace(['/', '\\'], '', $package->getTargetDir()))); $path = \ltrim(Preg::replace('{^' . $targetDir . '}', '', \ltrim($path, '\\/')), '\\/'); } else { // add target-dir from file paths that don't have it $path = $package->getTargetDir() . '/' . $path; } } if ($type === 'exclude-from-classmap') { // first escape user input $path = Preg::replace('{/+}', '/', \preg_quote(\trim(\strtr($path, '\\', '/'), '/'))); // add support for wildcards * and ** $path = \strtr($path, ['\\*\\*' => '.+?', '\\*' => '[^/]+?']); // add support for up-level relative paths $updir = null; $path = Preg::replaceCallback('{^((?:(?:\\\\\\.){1,2}+/)+)}', static function ($matches) use(&$updir) : string { // undo preg_quote for the matched string $updir = \str_replace('\\.', '.', $matches[1]); return ''; }, $path); if (empty($installPath)) { $installPath = \strtr(Platform::getCwd(), '\\', '/'); } $resolvedPath = \realpath($installPath . '/' . $updir); if (\false === $resolvedPath) { continue; } $autoloads[] = \preg_quote(\strtr($resolvedPath, '\\', '/')) . '/' . $path . '($|/)'; continue; } $relativePath = empty($installPath) ? empty($path) ? '.' : $path : $installPath . '/' . $path; if ($type === 'files') { $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath; continue; } if ($type === 'classmap') { $autoloads[] = $relativePath; continue; } $autoloads[$namespace][] = $relativePath; } } } return $autoloads; } /** * @return string */ protected function getFileIdentifier(PackageInterface $package, string $path) { // TODO composer v3 change this to sha1 or xxh3? Possibly not worth the potential breakage though return \hash('md5', $package->getName() . ':' . $path); } /** * Filters out dev-dependencies * * @param array $packageMap * @return array */ protected function filterPackageMap(array $packageMap, RootPackageInterface $rootPackage) { $packages = []; $include = []; $replacedBy = []; foreach ($packageMap as $item) { $package = $item[0]; $name = $package->getName(); $packages[$name] = $package; foreach ($package->getReplaces() as $replace) { $replacedBy[$replace->getTarget()] = $name; } } $add = static function (PackageInterface $package) use(&$add, $packages, &$include, $replacedBy) : void { foreach ($package->getRequires() as $link) { $target = $link->getTarget(); if (isset($replacedBy[$target])) { $target = $replacedBy[$target]; } if (!isset($include[$target])) { $include[$target] = \true; if (isset($packages[$target])) { $add($packages[$target]); } } } }; $add($rootPackage); return \array_filter($packageMap, static function ($item) use($include) : bool { $package = $item[0]; foreach ($package->getNames() as $name) { if (isset($include[$name])) { return \true; } } return \false; }); } /** * Sorts packages by dependency weight * * Packages of equal weight are sorted alphabetically * * @param array $packageMap * @return array */ protected function sortPackageMap(array $packageMap) { $packages = []; $paths = []; foreach ($packageMap as $item) { [$package, $path] = $item; $name = $package->getName(); $packages[$name] = $package; $paths[$name] = $path; } $sortedPackages = PackageSorter::sortPackages($packages); $sortedPackageMap = []; foreach ($sortedPackages as $package) { $name = $package->getName(); $sortedPackageMap[] = [$packages[$name], $paths[$name]]; } return $sortedPackageMap; } } function composerRequire(string $fileIdentifier, string $file) : void { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = \true; require $file; } } * 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 \Closure(string):void */ private static $includeFile; /** @var string|null */ private $vendorDir; // PSR-4 /** * @var array> */ private $prefixLengthsPsr4 = array(); /** * @var array> */ private $prefixDirsPsr4 = array(); /** * @var list */ private $fallbackDirsPsr4 = array(); // PSR-0 /** * List of PSR-0 prefixes * * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) * * @var array>> */ private $prefixesPsr0 = array(); /** * @var list */ private $fallbackDirsPsr0 = array(); /** @var bool */ private $useIncludePath = \false; /** * @var array */ private $classMap = array(); /** @var bool */ private $classMapAuthoritative = \false; /** * @var array */ private $missingClasses = array(); /** @var string|null */ private $apcuPrefix; /** * @var array */ private static $registeredLoaders = array(); /** * @param string|null $vendorDir */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; self::initializeIncludeClosure(); } /** * @return array> */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { return \call_user_func_array('array_merge', \array_values($this->prefixesPsr0)); } return array(); } /** * @return array> */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } /** * @return list */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } /** * @return list */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } /** * @return array Array of classname => path */ public function getClassMap() { return $this->classMap; } /** * @param array $classMap Class to filename map * * @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 list|string $paths The PSR-0 root directories * @param bool $prepend Whether to prepend the directories * * @return void */ public function add($prefix, $paths, $prepend = \false) { $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = \array_merge($paths, $this->fallbackDirsPsr0); } else { $this->fallbackDirsPsr0 = \array_merge($this->fallbackDirsPsr0, $paths); } return; } $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = \array_merge($paths, $this->prefixesPsr0[$first][$prefix]); } else { $this->prefixesPsr0[$first][$prefix] = \array_merge($this->prefixesPsr0[$first][$prefix], $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 list|string $paths The PSR-4 base directories * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException * * @return void */ public function addPsr4($prefix, $paths, $prepend = \false) { $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = \array_merge($paths, $this->fallbackDirsPsr4); } else { $this->fallbackDirsPsr4 = \array_merge($this->fallbackDirsPsr4, $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] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = \array_merge($paths, $this->prefixDirsPsr4[$prefix]); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = \array_merge($this->prefixDirsPsr4[$prefix], $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 list|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 list|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 = self::$includeFile; $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('_ContaoManager\\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 keyed by their corresponding vendor directories. * * @return array */ public static function getRegisteredLoaders() { return self::$registeredLoaders; } /** * @param string $class * @param string $ext * @return string|false */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup $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; } /** * @return void */ private static function initializeIncludeClosure() { if (self::$includeFile !== null) { return; } /** * Scope isolated include. * * Prevents access to $this/self from included files. * * @param string $file * @return void */ self::$includeFile = \Closure::bind(static function ($file) { include $file; }, null, null); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * This file is copied from the Symfony package. * * (c) Fabien Potencier */ namespace Composer\Autoload; use Composer\ClassMapGenerator\FileList; use Composer\IO\IOInterface; /** * ClassMapGenerator * * @author Gyula Sallai * @author Jordi Boggiano * * @deprecated Since Composer 2.4.0 use the composer/class-map-generator package instead */ class ClassMapGenerator { /** * Generate a class map file * * @param \Traversable|array $dirs Directories or a single path to search in * @param string $file The name of the class map file */ public static function dump(iterable $dirs, string $file) : void { $maps = []; foreach ($dirs as $dir) { $maps = \array_merge($maps, static::createMap($dir)); } \file_put_contents($file, \sprintf('|string|array<\SplFileInfo> $path The path to search in or an iterator * @param non-empty-string|null $excluded Regex that matches file paths to be excluded from the classmap * @param ?IOInterface $io IO object * @param null|string $namespace Optional namespace prefix to filter by * @param null|'psr-0'|'psr-4'|'classmap' $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules * @param array $scannedFiles * @return array A class map array * @throws \RuntimeException When the path is neither an existing file nor directory */ public static function createMap($path, ?string $excluded = null, ?IOInterface $io = null, ?string $namespace = null, ?string $autoloadType = null, array &$scannedFiles = []) : array { $generator = new \Composer\ClassMapGenerator\ClassMapGenerator(['php', 'inc', 'hh']); $fileList = new FileList(); $fileList->files = $scannedFiles; $generator->avoidDuplicateScans($fileList); $generator->scanPaths($path, $excluded, $autoloadType ?? 'classmap', $namespace); $classMap = $generator->getClassMap(); $scannedFiles = $fileList->files; if ($io !== null) { foreach ($classMap->getPsrViolations() as $msg) { $io->writeError("{$msg}"); } foreach ($classMap->getAmbiguousClasses() as $class => $paths) { if (\count($paths) > 1) { $io->writeError('Warning: Ambiguous class resolution, "' . $class . '"' . ' was found ' . (\count($paths) + 1) . 'x: in "' . $classMap->getClassPath($class) . '" and "' . \implode('", "', $paths) . '", the first will be used.'); } else { $io->writeError('Warning: Ambiguous class resolution, "' . $class . '"' . ' was found in both "' . $classMap->getClassPath($class) . '" and "' . \implode('", "', $paths) . '", the first will be used.'); } } } return $classMap->getMap(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Repository\PlatformRepository; use Composer\Repository\RootPackageRepository; use Composer\Repository\InstalledRepository; use Composer\Installer\SuggestedPackagesReporter; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; class SuggestsCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; protected function configure() : void { $this->setName('suggests')->setDescription('Shows package suggestions')->setDefinition([new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package (default)'), new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'), new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show suggestions from all dependencies, including transitive ones'), new InputOption('list', null, InputOption::VALUE_NONE, 'Show only list of suggested package names'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'), new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.', null, $this->suggestInstalledPackage())])->setHelp(<<%command.name% command shows a sorted list of suggested packages. Read more at https://getcomposer.org/doc/03-cli.md#suggests EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->requireComposer(); $installedRepos = [new RootPackageRepository(clone $composer->getPackage())]; $locker = $composer->getLocker(); if ($locker->isLocked()) { $installedRepos[] = new PlatformRepository([], $locker->getPlatformOverrides()); $installedRepos[] = $locker->getLockedRepository(!$input->getOption('no-dev')); } else { $installedRepos[] = new PlatformRepository([], $composer->getConfig()->get('platform')); $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository(); } $installedRepo = new InstalledRepository($installedRepos); $reporter = new SuggestedPackagesReporter($this->getIO()); $filter = $input->getArgument('packages'); $packages = $installedRepo->getPackages(); $packages[] = $composer->getPackage(); foreach ($packages as $package) { if (!empty($filter) && !\in_array($package->getName(), $filter)) { continue; } $reporter->addSuggestionsFromPackage($package); } // Determine output mode, default is by-package $mode = SuggestedPackagesReporter::MODE_BY_PACKAGE; // if by-suggestion is given we override the default if ($input->getOption('by-suggestion')) { $mode = SuggestedPackagesReporter::MODE_BY_SUGGESTION; } // unless by-package is also present then we enable both if ($input->getOption('by-package')) { $mode |= SuggestedPackagesReporter::MODE_BY_PACKAGE; } // list is exclusive and overrides everything else if ($input->getOption('list')) { $mode = SuggestedPackagesReporter::MODE_LIST; } $reporter->output($mode, $installedRepo, empty($filter) && !$input->getOption('all') ? $composer->getPackage() : null); return 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Factory; use Composer\Json\JsonFile; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputArgument; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; /** * @author Robert Schönthal */ class SearchCommand extends \Composer\Command\BaseCommand { protected function configure() : void { $this->setName('search')->setDescription('Searches for packages')->setDefinition([new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in package names'), new InputOption('only-vendor', 'O', InputOption::VALUE_NONE, 'Search only for vendor / organization names, returns only "vendor" as result'), new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text']), new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for')])->setHelp(<<php composer.phar search symfony composer Read more at https://getcomposer.org/doc/03-cli.md#search EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { // init repos $platformRepo = new PlatformRepository(); $io = $this->getIO(); $format = $input->getOption('format'); if (!\in_array($format, ['text', 'json'])) { $io->writeError(\sprintf('Unsupported format "%s". See help for supported formats.', $format)); return 1; } if (!($composer = $this->tryComposer())) { $composer = $this->createComposerInstance($input, $this->getIO(), []); } $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $installedRepo = new CompositeRepository([$localRepo, $platformRepo]); $repos = new CompositeRepository(\array_merge([$installedRepo], $composer->getRepositoryManager()->getRepositories())); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $mode = RepositoryInterface::SEARCH_FULLTEXT; if ($input->getOption('only-name') === \true) { if ($input->getOption('only-vendor') === \true) { throw new \InvalidArgumentException('--only-name and --only-vendor cannot be used together'); } $mode = RepositoryInterface::SEARCH_NAME; } elseif ($input->getOption('only-vendor') === \true) { $mode = RepositoryInterface::SEARCH_VENDOR; } $type = $input->getOption('type'); $query = \implode(' ', $input->getArgument('tokens')); if ($mode !== RepositoryInterface::SEARCH_FULLTEXT) { $query = \preg_quote($query); } $results = $repos->search($query, $mode, $type); if (\count($results) > 0 && $format === 'text') { $width = $this->getTerminalWidth(); $nameLength = 0; foreach ($results as $result) { $nameLength = \max(\strlen($result['name']), $nameLength); } $nameLength += 1; foreach ($results as $result) { $description = $result['description'] ?? ''; $warning = !empty($result['abandoned']) ? '! Abandoned ! ' : ''; $remaining = $width - $nameLength - \strlen($warning) - 2; if (\strlen($description) > $remaining) { $description = \substr($description, 0, $remaining - 3) . '...'; } $link = $result['url'] ?? null; if ($link !== null) { $io->write('' . $result['name'] . '' . \str_repeat(' ', $nameLength - \strlen($result['name'])) . $warning . $description); } else { $io->write(\str_pad($result['name'], $nameLength, ' ') . $warning . $description); } } } elseif ($format === 'json') { $io->write(JsonFile::encode($results)); } return 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Locker; use Composer\Package\Version\VersionBumper; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputArgument; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Factory; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; use Composer\Repository\PlatformRepository; use Composer\Util\Silencer; /** * @author Jordi Boggiano */ final class BumpCommand extends \Composer\Command\BaseCommand { private const ERROR_GENERIC = 1; private const ERROR_LOCK_OUTDATED = 2; use \Composer\Command\CompletionTrait; protected function configure() : void { $this->setName('bump')->setDescription('Increases the lower limit of your composer.json requirements to the currently installed versions')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name(s) to restrict which packages are bumped.', null, $this->suggestRootRequirement()), new InputOption('dev-only', 'D', InputOption::VALUE_NONE, 'Only bump requirements in "require-dev".'), new InputOption('no-dev-only', 'R', InputOption::VALUE_NONE, 'Only bump requirements in "require".'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the packages to bump, but will not execute anything.')])->setHelp(<<bump command increases the lower limit of your composer.json requirements to the currently installed versions. This helps to ensure your dependencies do not accidentally get downgraded due to some other conflict, and can slightly improve dependency resolution performance as it limits the amount of package versions Composer has to look at. Running this blindly on libraries is **NOT** recommended as it will narrow down your allowed dependencies, which may cause dependency hell for your users. Running it with --dev-only on libraries may be fine however as dev requirements are local to the library and do not affect consumers of the package. EOT ); } /** * @throws \Seld\JsonLint\ParsingException */ protected function execute(InputInterface $input, OutputInterface $output) : int { return $this->doBump($this->getIO(), $input->getOption('dev-only'), $input->getOption('no-dev-only'), $input->getOption('dry-run'), $input->getArgument('packages')); } /** * @param string[] $packagesFilter * @throws \Seld\JsonLint\ParsingException */ public function doBump(IOInterface $io, bool $devOnly, bool $noDevOnly, bool $dryRun, array $packagesFilter) : int { /** @readonly */ $composerJsonPath = Factory::getComposerFile(); if (!Filesystem::isReadable($composerJsonPath)) { $io->writeError('' . $composerJsonPath . ' is not readable.'); return self::ERROR_GENERIC; } $composerJson = new JsonFile($composerJsonPath); $contents = \file_get_contents($composerJson->getPath()); if (\false === $contents) { $io->writeError('' . $composerJsonPath . ' is not readable.'); return self::ERROR_GENERIC; } // check for writability by writing to the file as is_writable can not be trusted on network-mounts // see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926 if (!\is_writable($composerJsonPath) && \false === Silencer::call('file_put_contents', $composerJsonPath, $contents)) { $io->writeError('' . $composerJsonPath . ' is not writable.'); return self::ERROR_GENERIC; } unset($contents); $composer = $this->requireComposer(); if ($composer->getLocker()->isLocked()) { if (!$composer->getLocker()->isFresh()) { $io->writeError('The lock file is not up to date with the latest changes in composer.json. Run the appropriate `update` to fix that before you use the `bump` command.'); return self::ERROR_LOCK_OUTDATED; } $repo = $composer->getLocker()->getLockedRepository(\true); } else { $repo = $composer->getRepositoryManager()->getLocalRepository(); } if ($composer->getPackage()->getType() !== 'project' && !$devOnly) { $io->writeError('Warning: Bumping dependency constraints is not recommended for libraries as it will narrow down your dependencies and may cause problems for your users.'); $contents = $composerJson->read(); if (!isset($contents['type'])) { $io->writeError('If your package is not a library, you can explicitly specify the "type" by using "composer config type project".'); $io->writeError('Alternatively you can use --dev-only to only bump dependencies within "require-dev".'); } unset($contents); } $bumper = new VersionBumper(); $tasks = []; if (!$devOnly) { $tasks['require'] = $composer->getPackage()->getRequires(); } if (!$noDevOnly) { $tasks['require-dev'] = $composer->getPackage()->getDevRequires(); } if (\count($packagesFilter) > 0) { // support proxied args from the update command that contain constraints together with the package names $packagesFilter = \array_map(function ($constraint) { return Preg::replace('{[:= ].+}', '', $constraint); }, $packagesFilter); $pattern = BasePackage::packageNamesToRegexp(\array_unique(\array_map('strtolower', $packagesFilter))); foreach ($tasks as $key => $reqs) { foreach ($reqs as $pkgName => $link) { if (!Preg::isMatch($pattern, $pkgName)) { unset($tasks[$key][$pkgName]); } } } } $updates = []; foreach ($tasks as $key => $reqs) { foreach ($reqs as $pkgName => $link) { if (PlatformRepository::isPlatformPackage($pkgName)) { continue; } $currentConstraint = $link->getPrettyConstraint(); $package = $repo->findPackage($pkgName, '*'); // name must be provided or replaced if (null === $package) { continue; } while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } $bumped = $bumper->bumpRequirement($link->getConstraint(), $package); if ($bumped === $currentConstraint) { continue; } $updates[$key][$pkgName] = $bumped; } } if (!$dryRun && !$this->updateFileCleanly($composerJson, $updates)) { $composerDefinition = $composerJson->read(); foreach ($updates as $key => $packages) { foreach ($packages as $package => $version) { $composerDefinition[$key][$package] = $version; } } $composerJson->write($composerDefinition); } $changeCount = \array_sum(\array_map('count', $updates)); if ($changeCount > 0) { if ($dryRun) { $io->write('' . $composerJsonPath . ' would be updated with:'); foreach ($updates as $requireType => $packages) { foreach ($packages as $package => $version) { $io->write(\sprintf(' - %s.%s: %s', $requireType, $package, $version)); } } } else { $io->write('' . $composerJsonPath . ' has been updated (' . $changeCount . ' changes).'); } } else { $io->write('No requirements to update in ' . $composerJsonPath . '.'); } if (!$dryRun && $composer->getLocker()->isLocked() && $composer->getConfig()->get('lock') && $changeCount > 0) { $composer->getLocker()->updateHash($composerJson); } if ($dryRun && $changeCount > 0) { return self::ERROR_GENERIC; } return 0; } /** * @param array<'require'|'require-dev', array> $updates */ private function updateFileCleanly(JsonFile $json, array $updates) : bool { $contents = \file_get_contents($json->getPath()); if (\false === $contents) { throw new \RuntimeException('Unable to read ' . $json->getPath() . ' contents.'); } $manipulator = new JsonManipulator($contents); foreach ($updates as $key => $packages) { foreach ($packages as $package => $version) { if (!$manipulator->addLink($key, $package, $version)) { return \false; } } } if (\false === \file_put_contents($json->getPath(), $manipulator->getContents())) { throw new \RuntimeException('Unable to write new ' . $json->getPath() . ' contents.'); } return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Factory; use Composer\IO\IOInterface; use Composer\Config; use Composer\Composer; use Composer\Package\BasePackage; use Composer\Package\CompletePackageInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionSelector; use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Repository\RepositoryFactory; use Composer\Repository\RepositorySet; use Composer\Script\ScriptEvents; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Util\Filesystem; use Composer\Util\Loop; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * Creates an archive of a package for distribution. * * @author Nils Adermann */ class ArchiveCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; private const FORMATS = ['tar', 'tar.gz', 'tar.bz2', 'zip']; protected function configure() : void { $this->setName('archive')->setDescription('Creates an archive of this composer package')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project', null, $this->suggestAvailablePackage()), new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar, tar.gz, tar.bz2 or zip (default tar)', null, self::FORMATS), new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'), new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.' . ' Note that the format will be appended.'), new InputOption('ignore-filters', null, InputOption::VALUE_NONE, 'Ignore filters when saving package')])->setHelp(<<archive command creates an archive of the specified format containing the files and directories of the Composer project or the specified package in the specified version and writes it to the specified directory. php composer.phar archive [--format=zip] [--dir=/foo] [--file=filename] [package [version]] Read more at https://getcomposer.org/doc/03-cli.md#archive EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->tryComposer(); $config = null; if ($composer) { $config = $composer->getConfig(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output); $eventDispatcher = $composer->getEventDispatcher(); $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent); $eventDispatcher->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD); } if (!$config) { $config = Factory::createConfig(); } $format = $input->getOption('format') ?? $config->get('archive-format'); $dir = $input->getOption('dir') ?? $config->get('archive-dir'); $returnCode = $this->archive($this->getIO(), $config, $input->getArgument('package'), $input->getArgument('version'), $format, $dir, $input->getOption('file'), $input->getOption('ignore-filters'), $composer); if (0 === $returnCode && $composer) { $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD); } return $returnCode; } /** * @throws \Exception */ protected function archive(IOInterface $io, Config $config, ?string $packageName, ?string $version, string $format, string $dest, ?string $fileName, bool $ignoreFilters, ?Composer $composer) : int { if ($composer) { $archiveManager = $composer->getArchiveManager(); } else { $factory = new Factory(); $process = new ProcessExecutor(); $httpDownloader = Factory::createHttpDownloader($io, $config); $downloadManager = $factory->createDownloadManager($io, $config, $httpDownloader, $process); $archiveManager = $factory->createArchiveManager($config, $downloadManager, new Loop($httpDownloader, $process)); } if ($packageName) { $package = $this->selectPackage($io, $packageName, $version); if (!$package) { return 1; } } else { $package = $this->requireComposer()->getPackage(); } $io->writeError('Creating the archive into "' . $dest . '".'); $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters); $fs = new Filesystem(); $shortPath = $fs->findShortestPath(Platform::getCwd(), $packagePath, \true); $io->writeError('Created: ', \false); $io->write(\strlen($shortPath) < \strlen($packagePath) ? $shortPath : $packagePath); return 0; } /** * @return (BasePackage&CompletePackageInterface)|false */ protected function selectPackage(IOInterface $io, string $packageName, ?string $version = null) { $io->writeError('Searching for the specified package.'); if ($composer = $this->tryComposer()) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $repo = new CompositeRepository(\array_merge([$localRepo], $composer->getRepositoryManager()->getRepositories())); $minStability = $composer->getPackage()->getMinimumStability(); } else { $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io); $io->writeError('No composer.json found in the current directory, searching packages from ' . \implode(', ', \array_keys($defaultRepos))); $repo = new CompositeRepository($defaultRepos); $minStability = 'stable'; } if ($version !== null && Preg::isMatchStrictGroups('{@(stable|RC|beta|alpha|dev)$}i', $version, $match)) { $minStability = VersionParser::normalizeStability($match[1]); $version = (string) \substr($version, 0, -\strlen($match[0])); } $repoSet = new RepositorySet($minStability); $repoSet->addRepository($repo); $parser = new VersionParser(); $constraint = $version !== null ? $parser->parseConstraints($version) : null; $packages = $repoSet->findPackages(\strtolower($packageName), $constraint); if (\count($packages) > 1) { $versionSelector = new VersionSelector($repoSet); $package = $versionSelector->findBestCandidate(\strtolower($packageName), $version, $minStability); if ($package === \false) { $package = \reset($packages); } $io->writeError('Found multiple matches, selected ' . $package->getPrettyString() . '.'); $io->writeError('Alternatives were ' . \implode(', ', \array_map(static function ($p) : string { return $p->getPrettyString(); }, $packages)) . '.'); $io->writeError('Please use a more specific constraint to pick a different package.'); } elseif (\count($packages) === 1) { $package = \reset($packages); $io->writeError('Found an exact match ' . $package->getPrettyString() . '.'); } else { $io->writeError('Could not find a package matching ' . $packageName . '.'); return \false; } if (!$package instanceof CompletePackageInterface) { throw new \LogicException('Expected a CompletePackageInterface instance but found ' . \get_class($package)); } if (!$package instanceof BasePackage) { throw new \LogicException('Expected a BasePackage instance but found ' . \get_class($package)); } return $package; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use Composer\Repository\RepositorySet; use Composer\Repository\RepositoryUtils; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepository; use Composer\Advisory\Auditor; use Composer\Console\Input\InputOption; class AuditCommand extends \Composer\Command\BaseCommand { protected function configure() : void { $this->setName('audit')->setDescription('Checks for security vulnerability advisories for installed packages')->setDefinition([new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables auditing of require-dev packages.'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_TABLE, Auditor::FORMATS), new InputOption('locked', null, InputOption::VALUE_NONE, 'Audit based on the lock file instead of the installed packages.'), new InputOption('abandoned', null, InputOption::VALUE_REQUIRED, 'Behavior on abandoned packages. Must be "ignore", "report", or "fail".', null, Auditor::ABANDONEDS), new InputOption('ignore-severity', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Ignore advisories of a certain severity level.', [], ['low', 'medium', 'high', 'critical'])])->setHelp(<<audit command checks for security vulnerability advisories for installed packages. If you do not want to include dev dependencies in the audit you can omit them with --no-dev Read more at https://getcomposer.org/doc/03-cli.md#audit EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->requireComposer(); $packages = $this->getPackages($composer, $input); if (\count($packages) === 0) { $this->getIO()->writeError('No packages - skipping audit.'); return 0; } $auditor = new Auditor(); $repoSet = new RepositorySet(); foreach ($composer->getRepositoryManager()->getRepositories() as $repo) { $repoSet->addRepository($repo); } $auditConfig = $composer->getConfig()->get('audit'); $abandoned = $input->getOption('abandoned'); if ($abandoned !== null && !\in_array($abandoned, Auditor::ABANDONEDS, \true)) { throw new \InvalidArgumentException('--audit must be one of ' . \implode(', ', Auditor::ABANDONEDS) . '.'); } $abandoned = $abandoned ?? $auditConfig['abandoned'] ?? Auditor::ABANDONED_FAIL; $ignoreSeverities = $input->getOption('ignore-severity') ?? []; return \min(255, $auditor->audit($this->getIO(), $repoSet, $packages, $this->getAuditFormat($input, 'format'), \false, $auditConfig['ignore'] ?? [], $abandoned, $ignoreSeverities)); } /** * @return PackageInterface[] */ private function getPackages(Composer $composer, InputInterface $input) : array { if ($input->getOption('locked')) { if (!$composer->getLocker()->isLocked()) { throw new \UnexpectedValueException('Valid composer.json and composer.lock files are required to run this command with --locked'); } $locker = $composer->getLocker(); return $locker->getLockedRepository(!$input->getOption('no-dev'))->getPackages(); } $rootPkg = $composer->getPackage(); $installedRepo = new InstalledRepository([$composer->getRepositoryManager()->getLocalRepository()]); if ($input->getOption('no-dev')) { return RepositoryUtils::filterRequiredPackages($installedRepo->getPackages(), $rootPkg); } return $installedRepo->getPackages(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Factory; use Composer\IO\IOInterface; use Composer\Package\Loader\ValidatingArrayLoader; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\InstalledRepository; use Composer\Repository\PlatformRepository; use Composer\Util\ConfigValidator; use Composer\Util\Filesystem; use _ContaoManager\Symfony\Component\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * ValidateCommand * * @author Robert Schönthal * @author Jordi Boggiano */ class ValidateCommand extends \Composer\Command\BaseCommand { /** * configure */ protected function configure() : void { $this->setName('validate')->setDescription('Validates a composer.json and composer.lock')->setDefinition([new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not validate requires for overly strict/loose constraints'), new InputOption('check-lock', null, InputOption::VALUE_NONE, 'Check if lock file is up to date (even when config.lock is false)'), new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'), new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'), new InputOption('no-check-version', null, InputOption::VALUE_NONE, 'Do not report a warning if the version field is present'), new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'), new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'), new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file')])->setHelp(<<getArgument('file') ?? Factory::getComposerFile(); $io = $this->getIO(); if (!\file_exists($file)) { $io->writeError('' . $file . ' not found.'); return 3; } if (!Filesystem::isReadable($file)) { $io->writeError('' . $file . ' is not readable.'); return 3; } $validator = new ConfigValidator($io); $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL; $checkPublish = !$input->getOption('no-check-publish'); $checkLock = !$input->getOption('no-check-lock'); $checkVersion = $input->getOption('no-check-version') ? 0 : ConfigValidator::CHECK_VERSION; $isStrict = $input->getOption('strict'); [$errors, $publishErrors, $warnings] = $validator->validate($file, $checkAll, $checkVersion); $lockErrors = []; $composer = $this->createComposerInstance($input, $io, $file); // config.lock = false ~= implicit --no-check-lock; --check-lock overrides $checkLock = $checkLock && $composer->getConfig()->get('lock') || $input->getOption('check-lock'); $locker = $composer->getLocker(); if ($locker->isLocked() && !$locker->isFresh()) { $lockErrors[] = '- The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update` or `composer update `.'; } if ($locker->isLocked()) { $lockErrors = \array_merge($lockErrors, $locker->getMissingRequirementInfo($composer->getPackage(), \true)); } $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, \true); // $errors include publish and lock errors when exists $exitCode = \count($errors) > 0 ? 2 : ($isStrict && \count($warnings) > 0 ? 1 : 0); if ($input->getOption('with-dependencies')) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); foreach ($localRepo->getPackages() as $package) { $path = $composer->getInstallationManager()->getInstallPath($package); if (null === $path) { continue; } $file = $path . '/composer.json'; if (\is_dir($path) && \file_exists($file)) { [$errors, $publishErrors, $warnings] = $validator->validate($file, $checkAll, $checkVersion); $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors); // $errors include publish errors when exists $depCode = \count($errors) > 0 ? 2 : ($isStrict && \count($warnings) > 0 ? 1 : 0); $exitCode = \max($depCode, $exitCode); } } } $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output); $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); return \max($eventCode, $exitCode); } /** * @param string[] $errors * @param string[] $warnings * @param string[] $publishErrors * @param string[] $lockErrors */ private function outputResult(IOInterface $io, string $name, array &$errors, array &$warnings, bool $checkPublish = \false, array $publishErrors = [], bool $checkLock = \false, array $lockErrors = [], bool $printSchemaUrl = \false) : void { $doPrintSchemaUrl = \false; if (\count($errors) > 0) { $io->writeError('' . $name . ' is invalid, the following errors/warnings were found:'); } elseif (\count($publishErrors) > 0 && $checkPublish) { $io->writeError('' . $name . ' is valid for simple usage with Composer but has'); $io->writeError('strict errors that make it unable to be published as a package'); $doPrintSchemaUrl = $printSchemaUrl; } elseif (\count($warnings) > 0) { $io->writeError('' . $name . ' is valid, but with a few warnings'); $doPrintSchemaUrl = $printSchemaUrl; } elseif (\count($lockErrors) > 0) { $io->write('' . $name . ' is valid but your composer.lock has some ' . ($checkLock ? 'errors' : 'warnings') . ''); } else { $io->write('' . $name . ' is valid'); } if ($doPrintSchemaUrl) { $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); } if (\count($errors) > 0) { $errors = \array_map(static function ($err) : string { return '- ' . $err; }, $errors); \array_unshift($errors, '# General errors'); } if (\count($warnings) > 0) { $warnings = \array_map(static function ($err) : string { return '- ' . $err; }, $warnings); \array_unshift($warnings, '# General warnings'); } // Avoid setting the exit code to 1 in case --strict and --no-check-publish/--no-check-lock are combined $extraWarnings = []; // If checking publish errors, display them as errors, otherwise just show them as warnings if (\count($publishErrors) > 0 && $checkPublish) { $publishErrors = \array_map(static function ($err) : string { return '- ' . $err; }, $publishErrors); \array_unshift($publishErrors, '# Publish errors'); $errors = \array_merge($errors, $publishErrors); } // If checking lock errors, display them as errors, otherwise just show them as warnings if (\count($lockErrors) > 0) { if ($checkLock) { \array_unshift($lockErrors, '# Lock file errors'); $errors = \array_merge($errors, $lockErrors); } else { \array_unshift($lockErrors, '# Lock file warnings'); $extraWarnings = \array_merge($extraWarnings, $lockErrors); } } $messages = ['error' => $errors, 'warning' => \array_merge($warnings, $extraWarnings)]; foreach ($messages as $style => $msgs) { foreach ($msgs as $msg) { if (\strpos($msg, '#') === 0) { $io->writeError('<' . $style . '>' . $msg . ''); } else { $io->writeError($msg); } } } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Json\JsonFile; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\CompletePackageInterface; use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Semver\Constraint\MatchAllConstraint; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Nicolas Grekas * @author Jordi Boggiano */ class FundCommand extends \Composer\Command\BaseCommand { protected function configure() : void { $this->setName('fund')->setDescription('Discover how to help fund the maintenance of your dependencies')->setDefinition([new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['text', 'json'])]); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->requireComposer(); $repo = $composer->getRepositoryManager()->getLocalRepository(); $remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); $fundings = []; $packagesToLoad = []; foreach ($repo->getPackages() as $package) { if ($package instanceof AliasPackage) { continue; } $packagesToLoad[$package->getName()] = new MatchAllConstraint(); } // load all packages dev versions in parallel $result = $remoteRepos->loadPackages($packagesToLoad, ['dev' => BasePackage::STABILITY_DEV], []); // collect funding data from default branches foreach ($result['packages'] as $package) { if (!$package instanceof AliasPackage && $package instanceof CompletePackageInterface && $package->isDefaultBranch() && $package->getFunding() && isset($packagesToLoad[$package->getName()])) { $fundings = $this->insertFundingData($fundings, $package); unset($packagesToLoad[$package->getName()]); } } // collect funding from installed packages if none was found in the default branch above foreach ($repo->getPackages() as $package) { if ($package instanceof AliasPackage || !isset($packagesToLoad[$package->getName()])) { continue; } if ($package instanceof CompletePackageInterface && $package->getFunding()) { $fundings = $this->insertFundingData($fundings, $package); } } \ksort($fundings); $io = $this->getIO(); $format = $input->getOption('format'); if (!\in_array($format, ['text', 'json'])) { $io->writeError(\sprintf('Unsupported format "%s". See help for supported formats.', $format)); return 1; } if ($fundings && $format === 'text') { $prev = null; $io->write('The following packages were found in your dependencies which publish funding information:'); foreach ($fundings as $vendor => $links) { $io->write(''); $io->write(\sprintf("%s", $vendor)); foreach ($links as $url => $packages) { $line = \sprintf(' %s', \implode(', ', $packages)); if ($prev !== $line) { $io->write($line); $prev = $line; } $io->write(\sprintf(' %s', OutputFormatter::escape($url), $url)); } } $io->write(""); $io->write("Please consider following these links and sponsoring the work of package authors!"); $io->write("Thank you!"); } elseif ($format === 'json') { $io->write(JsonFile::encode($fundings)); } else { $io->write("No funding links were found in your package dependencies. This doesn't mean they don't need your support!"); } return 0; } /** * @param mixed[] $fundings * @return mixed[] */ private function insertFundingData(array $fundings, CompletePackageInterface $package) : array { foreach ($package->getFunding() as $fundingOption) { [$vendor, $packageName] = \explode('/', $package->getPrettyName()); // ignore malformed funding entries if (empty($fundingOption['url'])) { continue; } $url = $fundingOption['url']; if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && Preg::isMatch('{^https://github.com/([^/]+)$}', $url, $match)) { $url = 'https://github.com/sponsors/' . $match[1]; } $fundings[$vendor][$url][] = $packageName; } return $fundings; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Factory; use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\IO\IOInterface; use Composer\Package\BasePackage; use Composer\Package\CompletePackageInterface; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionSelector; use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryFactory; use Composer\Repository\RepositorySet; use Composer\Semver\Constraint\Constraint; use Composer\Util\Filesystem; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @internal */ trait PackageDiscoveryTrait { /** @var ?CompositeRepository */ private $repos; /** @var RepositorySet[] */ private $repositorySets; protected function getRepos() : CompositeRepository { if (null === $this->repos) { $this->repos = new CompositeRepository(\array_merge([new PlatformRepository()], RepositoryFactory::defaultReposWithDefaultManager($this->getIO()))); } return $this->repos; } /** * @param key-of|null $minimumStability */ private function getRepositorySet(InputInterface $input, ?string $minimumStability = null) : RepositorySet { $key = $minimumStability ?? 'default'; if (!isset($this->repositorySets[$key])) { $this->repositorySets[$key] = $repositorySet = new RepositorySet($minimumStability ?? $this->getMinimumStability($input)); $repositorySet->addRepository($this->getRepos()); } return $this->repositorySets[$key]; } /** * @return key-of */ private function getMinimumStability(InputInterface $input) : string { if ($input->hasOption('stability')) { // @phpstan-ignore-line as InitCommand does have this option but not all classes using this trait do return VersionParser::normalizeStability($input->getOption('stability') ?? 'stable'); } // @phpstan-ignore-next-line as RequireCommand does not have the option above so this code is reachable there $file = Factory::getComposerFile(); if (\is_file($file) && Filesystem::isReadable($file) && \is_array($composer = \json_decode((string) \file_get_contents($file), \true))) { if (isset($composer['minimum-stability'])) { return VersionParser::normalizeStability($composer['minimum-stability']); } } return 'stable'; } /** * @param array $requires * * @return array * @throws \Exception */ protected final function determineRequirements(InputInterface $input, OutputInterface $output, array $requires = [], ?PlatformRepository $platformRepo = null, string $preferredStability = 'stable', bool $useBestVersionConstraint = \true, bool $fixed = \false) : array { if (\count($requires) > 0) { $requires = $this->normalizeRequirements($requires); $result = []; $io = $this->getIO(); foreach ($requires as $requirement) { if (isset($requirement['version']) && Preg::isMatch('{^\\d+(\\.\\d+)?$}', $requirement['version'])) { $io->writeError('The "' . $requirement['version'] . '" constraint for "' . $requirement['name'] . '" appears too strict and will likely not match what you want. See https://getcomposer.org/constraints'); } if (!isset($requirement['version'])) { // determine the best version automatically [$name, $version] = $this->findBestVersionAndNameForPackage($this->getIO(), $input, $requirement['name'], $platformRepo, $preferredStability, $fixed); // replace package name from packagist.org $requirement['name'] = $name; if ($useBestVersionConstraint) { $requirement['version'] = $version; $io->writeError(\sprintf('Using version %s for %s', $requirement['version'], $requirement['name'])); } else { $requirement['version'] = 'guess'; } } $result[] = $requirement['name'] . ' ' . $requirement['version']; } return $result; } $versionParser = new VersionParser(); // Collect existing packages $composer = $this->tryComposer(); $installedRepo = null; if (null !== $composer) { $installedRepo = $composer->getRepositoryManager()->getLocalRepository(); } $existingPackages = []; if (null !== $installedRepo) { foreach ($installedRepo->getPackages() as $package) { $existingPackages[] = $package->getName(); } } unset($composer, $installedRepo); $io = $this->getIO(); while (null !== ($package = $io->ask('Search for a package: '))) { $matches = $this->getRepos()->search($package); if (\count($matches) > 0) { // Remove existing packages from search results. foreach ($matches as $position => $foundPackage) { if (\in_array($foundPackage['name'], $existingPackages, \true)) { unset($matches[$position]); } } $matches = \array_values($matches); $exactMatch = \false; foreach ($matches as $match) { if ($match['name'] === $package) { $exactMatch = \true; break; } } // no match, prompt which to pick if (!$exactMatch) { $providers = $this->getRepos()->getProviders($package); if (\count($providers) > 0) { \array_unshift($matches, ['name' => $package, 'description' => '']); } $choices = []; foreach ($matches as $position => $foundPackage) { $abandoned = ''; if (isset($foundPackage['abandoned'])) { if (\is_string($foundPackage['abandoned'])) { $replacement = \sprintf('Use %s instead', $foundPackage['abandoned']); } else { $replacement = 'No replacement was suggested'; } $abandoned = \sprintf('Abandoned. %s.', $replacement); } $choices[] = \sprintf(' %5s %s %s', "[{$position}]", $foundPackage['name'], $abandoned); } $io->writeError(['', \sprintf('Found %s packages matching %s', \count($matches), $package), '']); $io->writeError($choices); $io->writeError(''); $validator = static function (string $selection) use($matches, $versionParser) { if ('' === $selection) { return \false; } if (\is_numeric($selection) && isset($matches[(int) $selection])) { $package = $matches[(int) $selection]; return $package['name']; } if (Preg::isMatch('{^\\s*(?P[\\S/]+)(?:\\s+(?P\\S+))?\\s*$}', $selection, $packageMatches)) { if (isset($packageMatches['version'])) { // parsing `acme/example ~2.3` // validate version constraint $versionParser->parseConstraints($packageMatches['version']); return $packageMatches['name'] . ' ' . $packageMatches['version']; } // parsing `acme/example` return $packageMatches['name']; } throw new \Exception('Not a valid selection'); }; $package = $io->askAndValidate('Enter package # to add, or the complete package name if it is not listed: ', $validator, 3, ''); } // no constraint yet, determine the best version automatically if (\false !== $package && \false === \strpos($package, ' ')) { $validator = static function (string $input) { $input = \trim($input); return \strlen($input) > 0 ? $input : \false; }; $constraint = $io->askAndValidate('Enter the version constraint to require (or leave blank to use the latest version): ', $validator, 3, ''); if (\false === $constraint) { [, $constraint] = $this->findBestVersionAndNameForPackage($this->getIO(), $input, $package, $platformRepo, $preferredStability); $io->writeError(\sprintf('Using version %s for %s', $constraint, $package)); } $package .= ' ' . $constraint; } if (\false !== $package) { $requires[] = $package; $existingPackages[] = \explode(' ', $package)[0]; } } } return $requires; } /** * Given a package name, this determines the best version to use in the require key. * * This returns a version with the ~ operator prefixed when possible. * * @throws \InvalidArgumentException * @return array{string, string} name version */ private function findBestVersionAndNameForPackage(IOInterface $io, InputInterface $input, string $name, ?PlatformRepository $platformRepo = null, string $preferredStability = 'stable', bool $fixed = \false) : array { // handle ignore-platform-reqs flag if present if ($input->hasOption('ignore-platform-reqs') && $input->hasOption('ignore-platform-req')) { $platformRequirementFilter = $this->getPlatformRequirementFilter($input); } else { $platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing(); } // find the latest version allowed in this repo set $repoSet = $this->getRepositorySet($input); $versionSelector = new VersionSelector($repoSet, $platformRepo); $effectiveMinimumStability = $this->getMinimumStability($input); $package = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, 0, $this->getIO()); if (\false === $package) { // platform packages can not be found in the pool in versions other than the local platform's has // so if platform reqs are ignored we just take the user's word for it if ($platformRequirementFilter->isIgnored($name)) { return [$name, '*']; } // Check if it is a virtual package provided by others $providers = $repoSet->getProviders($name); if (\count($providers) > 0) { $constraint = '*'; if ($input->isInteractive()) { $constraint = $this->getIO()->askAndValidate('Package "' . $name . '" does not exist but is provided by ' . \count($providers) . ' packages. Which version constraint would you like to use? [*] ', static function ($value) { $parser = new VersionParser(); $parser->parseConstraints($value); return $value; }, 3, '*'); } return [$name, $constraint]; } // Check whether the package requirements were the problem if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && \false !== ($candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll()))) { throw new \InvalidArgumentException(\sprintf('Package %s has requirements incompatible with your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo), $name)); } // Check whether the minimum stability was the problem but the package exists if (\false !== ($package = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES))) { // we must first verify if a valid package would be found in a lower priority repository if (\false !== ($allReposPackage = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_SHADOWED_REPOSITORIES))) { throw new \InvalidArgumentException('Package ' . $name . ' exists in ' . $allReposPackage->getRepository()->getRepoName() . ' and ' . $package->getRepository()->getRepoName() . ' which has a higher repository priority. The packages from the higher priority repository do not match your minimum-stability and are therefore not installable. That repository is canonical so the lower priority repo\'s packages are not installable. See https://getcomposer.org/repoprio for details and assistance.'); } throw new \InvalidArgumentException(\sprintf('Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.', $name, $effectiveMinimumStability)); } // Check whether the PHP version was the problem for all versions if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && \false !== ($candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll(), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES))) { $additional = ''; if (\false === $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll())) { $additional = \PHP_EOL . \PHP_EOL . 'Additionally, the package was only found with a stability of "' . $candidate->getStability() . '" while your minimum stability is "' . $effectiveMinimumStability . '".'; } throw new \InvalidArgumentException(\sprintf('Could not find package %s in any version matching your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo) . '%s', $name, $additional)); } // Check for similar names/typos $similar = $this->findSimilar($name); if (\count($similar) > 0) { if (\in_array($name, $similar, \true)) { throw new \InvalidArgumentException(\sprintf("Could not find package %s. It was however found via repository search, which indicates a consistency issue with the repository.", $name)); } if ($input->isInteractive()) { $result = $io->select("Could not find package {$name}.\nPick one of these or leave empty to abort:", $similar, \false, 1); if ($result !== \false) { return $this->findBestVersionAndNameForPackage($io, $input, $similar[$result], $platformRepo, $preferredStability, $fixed); } } throw new \InvalidArgumentException(\sprintf("Could not find package %s.\n\nDid you mean " . (\count($similar) > 1 ? 'one of these' : 'this') . "?\n %s", $name, \implode("\n ", $similar))); } throw new \InvalidArgumentException(\sprintf('Could not find a matching version of package %s. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (%s).', $name, $effectiveMinimumStability)); } return [$package->getPrettyName(), $fixed ? $package->getPrettyVersion() : $versionSelector->findRecommendedRequireVersion($package)]; } /** * @return array */ private function findSimilar(string $package) : array { try { if (null === $this->repos) { throw new \LogicException('findSimilar was called before $this->repos was initialized'); } $results = $this->repos->search($package); } catch (\Throwable $e) { if ($e instanceof \LogicException) { throw $e; } // ignore search errors return []; } $similarPackages = []; $installedRepo = $this->requireComposer()->getRepositoryManager()->getLocalRepository(); foreach ($results as $result) { if (null !== $installedRepo->findPackage($result['name'], '*')) { // Ignore installed package continue; } $similarPackages[$result['name']] = \levenshtein($package, $result['name']); } \asort($similarPackages); return \array_keys(\array_slice($similarPackages, 0, 5)); } private function getPlatformExceptionDetails(PackageInterface $candidate, ?PlatformRepository $platformRepo = null) : string { $details = []; if (null === $platformRepo) { return ''; } foreach ($candidate->getRequires() as $link) { if (!PlatformRepository::isPlatformPackage($link->getTarget())) { continue; } $platformPkg = $platformRepo->findPackage($link->getTarget(), '*'); if (null === $platformPkg) { if ($platformRepo->isPlatformPackageDisabled($link->getTarget())) { $details[] = $candidate->getPrettyName() . ' ' . $candidate->getPrettyVersion() . ' requires ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' but it is disabled by your platform config. Enable it again with "composer config platform.' . $link->getTarget() . ' --unset".'; } else { $details[] = $candidate->getPrettyName() . ' ' . $candidate->getPrettyVersion() . ' requires ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' but it is not present.'; } continue; } if (!$link->getConstraint()->matches(new Constraint('==', $platformPkg->getVersion()))) { $platformPkgVersion = $platformPkg->getPrettyVersion(); $platformExtra = $platformPkg->getExtra(); if (isset($platformExtra['config.platform']) && $platformPkg instanceof CompletePackageInterface) { $platformPkgVersion .= ' (' . $platformPkg->getDescription() . ')'; } $details[] = $candidate->getPrettyName() . ' ' . $candidate->getPrettyVersion() . ' requires ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' which does not match your installed version ' . $platformPkgVersion . '.'; } } if (\count($details) === 0) { return ''; } return ':' . \PHP_EOL . ' - ' . \implode(\PHP_EOL . ' - ', $details); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Pcre\Preg; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano */ class ScriptAliasCommand extends \Composer\Command\BaseCommand { /** @var string */ private $script; /** @var string */ private $description; /** @var string[] */ private $aliases; /** * @param string[] $aliases */ public function __construct(string $script, ?string $description, array $aliases = []) { $this->script = $script; $this->description = $description ?? 'Runs the ' . $script . ' script as defined in composer.json'; $this->aliases = $aliases; foreach ($this->aliases as $alias) { if (!\is_string($alias)) { throw new \InvalidArgumentException('"scripts-aliases" element array values should contain only strings'); } } $this->ignoreValidationErrors(); parent::__construct(); } protected function configure() : void { $this->setName($this->script)->setDescription($this->description)->setAliases($this->aliases)->setDefinition([new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, '')])->setHelp(<<run-script command runs scripts defined in composer.json: php composer.phar run-script post-update-cmd Read more at https://getcomposer.org/doc/03-cli.md#run-script-run EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->requireComposer(); $args = $input->getArguments(); // TODO remove for Symfony 6+ as it is then in the interface if (!\method_exists($input, '__toString')) { // @phpstan-ignore-line throw new \LogicException('Expected an Input instance that is stringable, got ' . \get_class($input)); } return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args'], ['script-alias-input' => Preg::replace('{^\\S+ ?}', '', $input->__toString(), 1)]); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Config; use Composer\Factory; use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\Installer; use Composer\Installer\ProjectInstaller; use Composer\Installer\SuggestedPackagesReporter; use Composer\IO\IOInterface; use Composer\Package\BasePackage; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\Package\Version\VersionSelector; use Composer\Package\AliasPackage; use Composer\Pcre\Preg; use Composer\Plugin\PluginBlockedException; use Composer\Repository\RepositoryFactory; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\InstalledArrayRepository; use Composer\Repository\RepositorySet; use Composer\Script\ScriptEvents; use Composer\Util\Silencer; use Composer\Console\Input\InputArgument; use _ContaoManager\Seld\Signal\SignalHandler; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Finder\Finder; use Composer\Json\JsonFile; use Composer\Config\JsonConfigSource; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Package\Version\VersionParser; use Composer\Advisory\Auditor; /** * Install a package as new project into new directory. * * @author Benjamin Eberlei * @author Jordi Boggiano * @author Tobias Munk * @author Nils Adermann */ class CreateProjectCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; /** * @var SuggestedPackagesReporter */ protected $suggestedPackagesReporter; protected function configure() : void { $this->setName('create-project')->setDescription('Creates new project from a package into given directory')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed', null, $this->suggestAvailablePackage()), new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'), new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'), new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories to look the package up, either by URL or using JSON arrays'), new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'), new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the custom repository in the composer.json. If a lock file is present it will be deleted and an update will be run instead of install.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'), new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-secure-http', null, InputOption::VALUE_NONE, 'Disable the secure-http config option temporarily while installing the root package. Use at your own risk. Using this flag is a bad idea.'), new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'), new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Whether to skip auditing of the installed package dependencies (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json" or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('ask', null, InputOption::VALUE_NONE, 'Whether to ask for project directory.')])->setHelp(<<create-project command creates a new project from a given package into a new directory. If executed without params and in a directory with a composer.json file it installs the packages for the current project. You can use this command to bootstrap new projects or setup a clean version-controlled installation for developers of your project. php composer.phar create-project vendor/project target-directory [version] You can also specify the version with the package name using = or : as separator. php composer.phar create-project vendor/project:version target-directory To install unstable packages, either specify the version you want, or use the --stability=dev (where dev can be one of RC, beta, alpha or dev). To setup a developer workable version you should create the project using the source controlled code by appending the '--prefer-source' flag. To install a package from another repository than the default one you can pass the '--repository=https://myrepository.org' flag. Read more at https://getcomposer.org/doc/03-cli.md#create-project EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $config = Factory::createConfig(); $io = $this->getIO(); [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input, \true); if ($input->getOption('dev')) { $io->writeError('You are using the deprecated option "dev". Dev packages are installed by default now.'); } if ($input->getOption('no-custom-installers')) { $io->writeError('You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.'); $input->setOption('no-plugins', \true); } if ($input->isInteractive() && $input->getOption('ask')) { $package = $input->getArgument('package'); if (null === $package) { throw new \RuntimeException('Not enough arguments (missing: "package").'); } $parts = \explode("/", \strtolower($package), 2); $input->setArgument('directory', $io->ask('New project directory [' . \array_pop($parts) . ']: ')); } return $this->installProject($io, $config, $input, $input->getArgument('package'), $input->getArgument('directory'), $input->getArgument('version'), $input->getOption('stability'), $preferSource, $preferDist, !$input->getOption('no-dev'), \count($input->getOption('repository')) > 0 ? $input->getOption('repository') : $input->getOption('repository-url'), $input->getOption('no-plugins'), $input->getOption('no-scripts'), $input->getOption('no-progress'), $input->getOption('no-install'), $this->getPlatformRequirementFilter($input), !$input->getOption('no-secure-http'), $input->getOption('add-repository')); } /** * @param string|array|null $repositories * * @throws \Exception */ public function installProject(IOInterface $io, Config $config, InputInterface $input, ?string $packageName = null, ?string $directory = null, ?string $packageVersion = null, ?string $stability = 'stable', bool $preferSource = \false, bool $preferDist = \false, bool $installDevPackages = \false, $repositories = null, bool $disablePlugins = \false, bool $disableScripts = \false, bool $noProgress = \false, bool $noInstall = \false, ?PlatformRequirementFilterInterface $platformRequirementFilter = null, bool $secureHttp = \true, bool $addRepository = \false) : int { $oldCwd = Platform::getCwd(); if ($repositories !== null && !\is_array($repositories)) { $repositories = (array) $repositories; } $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing(); // we need to manually load the configuration to pass the auth credentials to the io interface! $io->loadConfiguration($config); $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io); if ($packageName !== null) { $installedFromVcs = $this->installRootPackage($input, $io, $config, $packageName, $platformRequirementFilter, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repositories, $disablePlugins, $disableScripts, $noProgress, $secureHttp); } else { $installedFromVcs = \false; } if ($repositories !== null && $addRepository && \is_file('composer.lock')) { \unlink('composer.lock'); } $composer = $this->createComposerInstance($input, $io, null, $disablePlugins, $disableScripts); // add the repository to the composer.json and use it for the install run later if ($repositories !== null && $addRepository) { foreach ($repositories as $index => $repo) { $repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repo, \true); $composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories(); $name = RepositoryFactory::generateRepositoryName($index, $repoConfig, $composerJsonRepositoriesConfig); $configSource = new JsonConfigSource(new JsonFile('composer.json')); if (isset($repoConfig['packagist']) && $repoConfig === ['packagist' => \false] || isset($repoConfig['packagist.org']) && $repoConfig === ['packagist.org' => \false]) { $configSource->addRepository('packagist.org', \false); } else { $configSource->addRepository($name, $repoConfig, \false); } $composer = $this->createComposerInstance($input, $io, null, $disablePlugins); } } $process = $composer->getLoop()->getProcessExecutor(); $fs = new Filesystem($process); // dispatch event $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages); // use the new config including the newly installed project $config = $composer->getConfig(); [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input); // install dependencies of the created project if ($noInstall === \false) { $composer->getInstallationManager()->setOutputProgress(!$noProgress); $installer = Installer::create($io, $composer); $installer->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode($installDevPackages)->setPlatformRequirementFilter($platformRequirementFilter)->setSuggestedPackagesReporter($this->suggestedPackagesReporter)->setOptimizeAutoloader($config->get('optimize-autoloader'))->setClassMapAuthoritative($config->get('classmap-authoritative'))->setApcuAutoloader($config->get('apcu-autoloader'))->setAudit(!$input->getOption('no-audit'))->setAuditFormat($this->getAuditFormat($input)); if (!$composer->getLocker()->isLocked()) { $installer->setUpdate(\true); } if ($disablePlugins) { $installer->disablePlugins(); } try { $status = $installer->run(); if (0 !== $status) { return $status; } } catch (PluginBlockedException $e) { $io->writeError('Hint: To allow running the config command recommended below before dependencies are installed, run create-project with --no-install.'); $io->writeError('You can then cd into ' . \getcwd() . ', configure allow-plugins, and finally run a composer install to complete the process.'); throw $e; } } $hasVcs = $installedFromVcs; if (!$input->getOption('keep-vcs') && $installedFromVcs && ($input->getOption('remove-vcs') || !$io->isInteractive() || $io->askConfirmation('Do you want to remove the existing VCS (.git, .svn..) history? [Y,n]? '))) { $finder = new Finder(); $finder->depth(0)->directories()->in(Platform::getCwd())->ignoreVCS(\false)->ignoreDotFiles(\false); foreach (['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_'] as $vcsName) { $finder->name($vcsName); } try { $dirs = \iterator_to_array($finder); unset($finder); foreach ($dirs as $dir) { if (!$fs->removeDirectory((string) $dir)) { throw new \RuntimeException('Could not remove ' . $dir); } } } catch (\Exception $e) { $io->writeError('An error occurred while removing the VCS metadata: ' . $e->getMessage() . ''); } $hasVcs = \false; } // rewriting self.version dependencies with explicit version numbers if the package's vcs metadata is gone if (!$hasVcs) { $package = $composer->getPackage(); $configSource = new JsonConfigSource(new JsonFile('composer.json')); foreach (BasePackage::$supportedLinkTypes as $type => $meta) { foreach ($package->{'get' . $meta['method']}() as $link) { if ($link->getPrettyConstraint() === 'self.version') { $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion()); } } } } // dispatch event $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages); \chdir($oldCwd); return 0; } /** * @param array|null $repositories * * @throws \Exception */ protected function installRootPackage(InputInterface $input, IOInterface $io, Config $config, string $packageName, PlatformRequirementFilterInterface $platformRequirementFilter, ?string $directory = null, ?string $packageVersion = null, ?string $stability = 'stable', bool $preferSource = \false, bool $preferDist = \false, bool $installDevPackages = \false, ?array $repositories = null, bool $disablePlugins = \false, bool $disableScripts = \false, bool $noProgress = \false, bool $secureHttp = \true) : bool { $parser = new VersionParser(); $requirements = $parser->parseNameVersionPairs([$packageName]); $name = \strtolower($requirements[0]['name']); if (!$packageVersion && isset($requirements[0]['version'])) { $packageVersion = $requirements[0]['version']; } // if no directory was specified, use the 2nd part of the package name if (null === $directory) { $parts = \explode("/", $name, 2); $directory = Platform::getCwd() . \DIRECTORY_SEPARATOR . \array_pop($parts); } $directory = \rtrim($directory, '/\\'); $process = new ProcessExecutor($io); $fs = new Filesystem($process); if (!$fs->isAbsolutePath($directory)) { $directory = Platform::getCwd() . \DIRECTORY_SEPARATOR . $directory; } if ('' === $directory) { throw new \UnexpectedValueException('Got an empty target directory, something went wrong'); } // set the base dir to ensure $config->all() below resolves the correct absolute paths to vendor-dir etc $config->setBaseDir($directory); if (!$secureHttp) { $config->merge(['config' => ['secure-http' => \false]], Config::SOURCE_COMMAND); } $io->writeError('Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(Platform::getCwd(), $directory, \true) . '"'); if (\file_exists($directory)) { if (!\is_dir($directory)) { throw new \InvalidArgumentException('Cannot create project directory at "' . $directory . '", it exists as a file.'); } if (!$fs->isDirEmpty($directory)) { throw new \InvalidArgumentException('Project directory "' . $directory . '" is not empty.'); } } if (null === $stability) { if (null === $packageVersion) { $stability = 'stable'; } elseif (Preg::isMatchStrictGroups('{^[^,\\s]*?@(' . \implode('|', \array_keys(BasePackage::STABILITIES)) . ')$}i', $packageVersion, $match)) { $stability = $match[1]; } else { $stability = VersionParser::parseStability($packageVersion); } } $stability = VersionParser::normalizeStability($stability); if (!isset(BasePackage::STABILITIES[$stability])) { throw new \InvalidArgumentException('Invalid stability provided (' . $stability . '), must be one of: ' . \implode(', ', \array_keys(BasePackage::STABILITIES))); } $composer = $this->createComposerInstance($input, $io, $config->all(), $disablePlugins, $disableScripts); $config = $composer->getConfig(); // set the base dir here again on the new config instance, as otherwise in case the vendor dir is defined in an env var for example it would still override the value set above by $config->all() $config->setBaseDir($directory); $rm = $composer->getRepositoryManager(); $repositorySet = new RepositorySet($stability); if (null === $repositories) { $repositorySet->addRepository(new CompositeRepository(RepositoryFactory::defaultRepos($io, $config, $rm))); } else { foreach ($repositories as $repo) { $repoConfig = RepositoryFactory::configFromString($io, $config, $repo, \true); if (isset($repoConfig['packagist']) && $repoConfig === ['packagist' => \false] || isset($repoConfig['packagist.org']) && $repoConfig === ['packagist.org' => \false]) { continue; } // disable symlinking for the root package by default as that most likely makes no sense if (($repoConfig['type'] ?? null) === 'path' && !isset($repoConfig['options']['symlink'])) { $repoConfig['options']['symlink'] = \false; } $repositorySet->addRepository(RepositoryFactory::createRepo($io, $config, $repoConfig, $rm)); } } $platformOverrides = $config->get('platform'); $platformRepo = new PlatformRepository([], $platformOverrides); // find the latest version if there are multiple $versionSelector = new VersionSelector($repositorySet, $platformRepo); $package = $versionSelector->findBestCandidate($name, $packageVersion, $stability, $platformRequirementFilter, 0, $io); if (!$package) { $errorMessage = "Could not find package {$name} with " . ($packageVersion ? "version {$packageVersion}" : "stability {$stability}"); if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && $versionSelector->findBestCandidate($name, $packageVersion, $stability, PlatformRequirementFilterFactory::ignoreAll())) { throw new \InvalidArgumentException($errorMessage . ' in a version installable using your PHP version, PHP extensions and Composer version.'); } throw new \InvalidArgumentException($errorMessage . '.'); } // handler Ctrl+C aborts gracefully @\mkdir($directory, 0777, \true); if (\false !== ($realDir = \realpath($directory))) { $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) use($realDir) { $this->getIO()->writeError('Received ' . $signal . ', aborting', \true, IOInterface::DEBUG); $fs = new Filesystem(); $fs->removeDirectory($realDir); $handler->exitWithLastSignal(); }); } // avoid displaying 9999999-dev as version if default-branch was selected if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { $package = $package->getAliasOf(); } $io->writeError('Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(\false) . ')'); if ($disablePlugins) { $io->writeError('Plugins have been disabled.'); } if ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } $dm = $composer->getDownloadManager(); $dm->setPreferSource($preferSource)->setPreferDist($preferDist); $projectInstaller = new ProjectInstaller($directory, $dm, $fs); $im = $composer->getInstallationManager(); $im->setOutputProgress(!$noProgress); $im->addInstaller($projectInstaller); $im->execute(new InstalledArrayRepository(), [new InstallOperation($package)]); $im->notifyInstalls($io); // collect suggestions $this->suggestedPackagesReporter->addSuggestionsFromPackage($package); $installedFromVcs = 'source' === $package->getInstallationSource(); $io->writeError('Created project in ' . $directory . ''); \chdir($directory); // ensure that the env var being set does not interfere with create-project // as it is probably not meant to be used here, so we do not use it if a composer.json can be found // in the project if (\file_exists($directory . '/composer.json') && Platform::getEnv('COMPOSER') !== \false) { Platform::clearEnv('COMPOSER'); } Platform::putEnv('COMPOSER_ROOT_VERSION', $package->getPrettyVersion()); // once the root project is fully initialized, we do not need to wipe everything on user abort anymore even if it happens during deps install if (isset($signalHandler)) { $signalHandler->unregister(); } return $installedFromVcs; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use Composer\Config; use Composer\Console\Application; use Composer\Console\Input\InputArgument; use Composer\Console\Input\InputOption; use Composer\Factory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\IO\IOInterface; use Composer\IO\NullIO; use Composer\Plugin\PreCommandRunEvent; use Composer\Package\Version\VersionParser; use Composer\Plugin\PluginEvents; use Composer\Advisory\Auditor; use Composer\Util\Platform; use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput; use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions; use _ContaoManager\Symfony\Component\Console\Helper\Table; use _ContaoManager\Symfony\Component\Console\Helper\TableSeparator; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Console\Command\Command; use _ContaoManager\Symfony\Component\Console\Terminal; /** * Base class for Composer commands * * @author Ryan Weaver * @author Konstantin Kudryashov */ abstract class BaseCommand extends Command { /** * @var Composer|null */ private $composer; /** * @var IOInterface */ private $io; /** * Gets the application instance for this command. */ public function getApplication() : Application { $application = parent::getApplication(); if (!$application instanceof Application) { throw new \RuntimeException('Composer commands can only work with an ' . Application::class . ' instance set'); } return $application; } /** * @param bool $required Should be set to false, or use `requireComposer` instead * @param bool|null $disablePlugins If null, reads --no-plugins as default * @param bool|null $disableScripts If null, reads --no-scripts as default * @throws \RuntimeException * @return Composer|null * @deprecated since Composer 2.3.0 use requireComposer or tryComposer depending on whether you have $required set to true or false */ public function getComposer(bool $required = \true, ?bool $disablePlugins = null, ?bool $disableScripts = null) { if ($required) { return $this->requireComposer($disablePlugins, $disableScripts); } return $this->tryComposer($disablePlugins, $disableScripts); } /** * Retrieves the default Composer\Composer instance or throws * * Use this instead of getComposer if you absolutely need an instance * * @param bool|null $disablePlugins If null, reads --no-plugins as default * @param bool|null $disableScripts If null, reads --no-scripts as default * @throws \RuntimeException */ public function requireComposer(?bool $disablePlugins = null, ?bool $disableScripts = null) : Composer { if (null === $this->composer) { $application = parent::getApplication(); if ($application instanceof Application) { $this->composer = $application->getComposer(\true, $disablePlugins, $disableScripts); \assert($this->composer instanceof Composer); } else { throw new \RuntimeException('Could not create a Composer\\Composer instance, you must inject ' . 'one if this command is not used with a Composer\\Console\\Application instance'); } } return $this->composer; } /** * Retrieves the default Composer\Composer instance or null * * Use this instead of getComposer(false) * * @param bool|null $disablePlugins If null, reads --no-plugins as default * @param bool|null $disableScripts If null, reads --no-scripts as default */ public function tryComposer(?bool $disablePlugins = null, ?bool $disableScripts = null) : ?Composer { if (null === $this->composer) { $application = parent::getApplication(); if ($application instanceof Application) { $this->composer = $application->getComposer(\false, $disablePlugins, $disableScripts); } } return $this->composer; } /** * @return void */ public function setComposer(Composer $composer) { $this->composer = $composer; } /** * Removes the cached composer instance * * @return void */ public function resetComposer() { $this->composer = null; $this->getApplication()->resetComposer(); } /** * Whether or not this command is meant to call another command. * * This is mainly needed to avoid duplicated warnings messages. * * @return bool */ public function isProxyCommand() { return \false; } /** * @return IOInterface */ public function getIO() { if (null === $this->io) { $application = parent::getApplication(); if ($application instanceof Application) { $this->io = $application->getIO(); } else { $this->io = new NullIO(); } } return $this->io; } /** * @return void */ public function setIO(IOInterface $io) { $this->io = $io; } /** * @inheritdoc * * Backport suggested values definition from symfony/console 6.1+ * * TODO drop when PHP 8.1 / symfony 6.1+ can be required */ public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void { $definition = $this->getDefinition(); $name = (string) $input->getCompletionName(); if (CompletionInput::TYPE_OPTION_VALUE === $input->getCompletionType() && $definition->hasOption($name) && ($option = $definition->getOption($name)) instanceof InputOption) { $option->complete($input, $suggestions); } elseif (CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() && $definition->hasArgument($name) && ($argument = $definition->getArgument($name)) instanceof InputArgument) { $argument->complete($input, $suggestions); } else { parent::complete($input, $suggestions); } } /** * @inheritDoc * * @return void */ protected function initialize(InputInterface $input, OutputInterface $output) { // initialize a plugin-enabled Composer instance, either local or global $disablePlugins = $input->hasParameterOption('--no-plugins'); $disableScripts = $input->hasParameterOption('--no-scripts'); $application = parent::getApplication(); if ($application instanceof Application && $application->getDisablePluginsByDefault()) { $disablePlugins = \true; } if ($application instanceof Application && $application->getDisableScriptsByDefault()) { $disableScripts = \true; } if ($this instanceof \Composer\Command\SelfUpdateCommand) { $disablePlugins = \true; $disableScripts = \true; } $composer = $this->tryComposer($disablePlugins, $disableScripts); $io = $this->getIO(); if (null === $composer) { $composer = Factory::createGlobal($this->getIO(), $disablePlugins, $disableScripts); } if ($composer) { $preCommandRunEvent = new PreCommandRunEvent(PluginEvents::PRE_COMMAND_RUN, $input, $this->getName()); $composer->getEventDispatcher()->dispatch($preCommandRunEvent->getName(), $preCommandRunEvent); } if (\true === $input->hasParameterOption(['--no-ansi']) && $input->hasOption('no-progress')) { $input->setOption('no-progress', \true); } $envOptions = ['COMPOSER_NO_AUDIT' => ['no-audit'], 'COMPOSER_NO_DEV' => ['no-dev', 'update-no-dev'], 'COMPOSER_PREFER_STABLE' => ['prefer-stable'], 'COMPOSER_PREFER_LOWEST' => ['prefer-lowest'], 'COMPOSER_MINIMAL_CHANGES' => ['minimal-changes']]; foreach ($envOptions as $envName => $optionNames) { foreach ($optionNames as $optionName) { if (\true === $input->hasOption($optionName)) { if (\false === $input->getOption($optionName) && (bool) Platform::getEnv($envName)) { $input->setOption($optionName, \true); } } } } if (\true === $input->hasOption('ignore-platform-reqs')) { if (!$input->getOption('ignore-platform-reqs') && (bool) Platform::getEnv('COMPOSER_IGNORE_PLATFORM_REQS')) { $input->setOption('ignore-platform-reqs', \true); $io->writeError('COMPOSER_IGNORE_PLATFORM_REQS is set. You may experience unexpected errors.'); } } if (\true === $input->hasOption('ignore-platform-req') && (!$input->hasOption('ignore-platform-reqs') || !$input->getOption('ignore-platform-reqs'))) { $ignorePlatformReqEnv = Platform::getEnv('COMPOSER_IGNORE_PLATFORM_REQ'); if (0 === \count($input->getOption('ignore-platform-req')) && \is_string($ignorePlatformReqEnv) && '' !== $ignorePlatformReqEnv) { $input->setOption('ignore-platform-req', \explode(',', $ignorePlatformReqEnv)); $io->writeError('COMPOSER_IGNORE_PLATFORM_REQ is set to ignore ' . $ignorePlatformReqEnv . '. You may experience unexpected errors.'); } } parent::initialize($input, $output); } /** * Calls {@see Factory::create()} with the given arguments, taking into account flags and default states for disabling scripts and plugins * * @param mixed $config either a configuration array or a filename to read from, if null it will read from * the default filename * @return Composer */ protected function createComposerInstance(InputInterface $input, IOInterface $io, $config = null, ?bool $disablePlugins = null, ?bool $disableScripts = null) : Composer { $disablePlugins = $disablePlugins === \true || $input->hasParameterOption('--no-plugins'); $disableScripts = $disableScripts === \true || $input->hasParameterOption('--no-scripts'); $application = parent::getApplication(); if ($application instanceof Application && $application->getDisablePluginsByDefault()) { $disablePlugins = \true; } if ($application instanceof Application && $application->getDisableScriptsByDefault()) { $disableScripts = \true; } return Factory::create($io, $config, $disablePlugins, $disableScripts); } /** * Returns preferSource and preferDist values based on the configuration. * * @return bool[] An array composed of the preferSource and preferDist values */ protected function getPreferredInstallOptions(Config $config, InputInterface $input, bool $keepVcsRequiresPreferSource = \false) { $preferSource = \false; $preferDist = \false; switch ($config->get('preferred-install')) { case 'source': $preferSource = \true; break; case 'dist': $preferDist = \true; break; case 'auto': default: // noop break; } if (!$input->hasOption('prefer-dist') || !$input->hasOption('prefer-source')) { return [$preferSource, $preferDist]; } if ($input->hasOption('prefer-install') && \is_string($input->getOption('prefer-install'))) { if ($input->getOption('prefer-source')) { throw new \InvalidArgumentException('--prefer-source can not be used together with --prefer-install'); } if ($input->getOption('prefer-dist')) { throw new \InvalidArgumentException('--prefer-dist can not be used together with --prefer-install'); } switch ($input->getOption('prefer-install')) { case 'dist': $input->setOption('prefer-dist', \true); break; case 'source': $input->setOption('prefer-source', \true); break; case 'auto': $preferDist = \false; $preferSource = \false; break; default: throw new \UnexpectedValueException('--prefer-install accepts one of "dist", "source" or "auto", got ' . $input->getOption('prefer-install')); } } if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || $keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs')) { $preferSource = $input->getOption('prefer-source') || $keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'); $preferDist = $input->getOption('prefer-dist'); } return [$preferSource, $preferDist]; } protected function getPlatformRequirementFilter(InputInterface $input) : PlatformRequirementFilterInterface { if (!$input->hasOption('ignore-platform-reqs') || !$input->hasOption('ignore-platform-req')) { throw new \LogicException('Calling getPlatformRequirementFilter from a command which does not define the --ignore-platform-req[s] flags is not permitted.'); } if (\true === $input->getOption('ignore-platform-reqs')) { return PlatformRequirementFilterFactory::ignoreAll(); } $ignores = $input->getOption('ignore-platform-req'); if (\count($ignores) > 0) { return PlatformRequirementFilterFactory::fromBoolOrList($ignores); } return PlatformRequirementFilterFactory::ignoreNothing(); } /** * @param array $requirements * * @return array */ protected function formatRequirements(array $requirements) { $requires = []; $requirements = $this->normalizeRequirements($requirements); foreach ($requirements as $requirement) { if (!isset($requirement['version'])) { throw new \UnexpectedValueException('Option ' . $requirement['name'] . ' is missing a version constraint, use e.g. ' . $requirement['name'] . ':^1.0'); } $requires[$requirement['name']] = $requirement['version']; } return $requires; } /** * @param array $requirements * * @return list */ protected function normalizeRequirements(array $requirements) { $parser = new VersionParser(); return $parser->parseNameVersionPairs($requirements); } /** * @param array $table * * @return void */ protected function renderTable(array $table, OutputInterface $output) { $renderer = new Table($output); $renderer->setStyle('compact'); $renderer->setRows($table)->render(); } /** * @return int */ protected function getTerminalWidth() { $terminal = new Terminal(); $width = $terminal->getWidth(); if (Platform::isWindows()) { $width--; } else { $width = \max(80, $width); } return $width; } /** * @internal * @param 'format'|'audit-format' $optName * @return Auditor::FORMAT_* */ protected function getAuditFormat(InputInterface $input, string $optName = 'audit-format') : string { if (!$input->hasOption($optName)) { throw new \LogicException('This should not be called on a Command which has no ' . $optName . ' option defined.'); } $val = $input->getOption($optName); if (!\in_array($val, Auditor::FORMATS, \true)) { throw new \InvalidArgumentException('--' . $optName . ' must be one of ' . \implode(', ', Auditor::FORMATS) . '.'); } return $val; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Input\ArrayInput; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano */ class OutdatedCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; protected function configure() : void { $this->setName('outdated')->setDescription('Shows a list of installed packages that have updates available, including their latest version')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.', null, $this->suggestInstalledPackage(\false)), new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'), new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'), new InputOption('locked', null, InputOption::VALUE_NONE, 'Shows updates for packages from the lock file, regardless of what is currently in vendor dir'), new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'), new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'), new InputOption('major-only', 'M', InputOption::VALUE_NONE, 'Show only packages that have major SemVer-compatible updates.'), new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates.'), new InputOption('patch-only', 'p', InputOption::VALUE_NONE, 'Show only packages that have patch SemVer-compatible updates.'), new InputOption('sort-by-age', 'A', InputOption::VALUE_NONE, 'Displays the installed version\'s age, and sorts packages oldest first.'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text']), new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Can contain wildcards (*). Use it if you don\'t want to be informed about new versions of some packages.', null, $this->suggestInstalledPackage(\false)), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages). Use with the --outdated option'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages). Use with the --outdated option')])->setHelp(<<green (=): Dependency is in the latest version and is up to date. - yellow (~): Dependency has a new version available that includes backwards compatibility breaks according to semver, so upgrade when you can but it may involve work. - red (!): Dependency has a new version that is semver-compatible and you should upgrade it. Read more at https://getcomposer.org/doc/03-cli.md#outdated EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $args = ['command' => 'show', '--latest' => \true]; if ($input->getOption('no-interaction')) { $args['--no-interaction'] = \true; } if ($input->getOption('no-plugins')) { $args['--no-plugins'] = \true; } if ($input->getOption('no-scripts')) { $args['--no-scripts'] = \true; } if ($input->getOption('no-cache')) { $args['--no-cache'] = \true; } if (!$input->getOption('all')) { $args['--outdated'] = \true; } if ($input->getOption('direct')) { $args['--direct'] = \true; } if (null !== $input->getArgument('package')) { $args['package'] = $input->getArgument('package'); } if ($input->getOption('strict')) { $args['--strict'] = \true; } if ($input->getOption('major-only')) { $args['--major-only'] = \true; } if ($input->getOption('minor-only')) { $args['--minor-only'] = \true; } if ($input->getOption('patch-only')) { $args['--patch-only'] = \true; } if ($input->getOption('locked')) { $args['--locked'] = \true; } if ($input->getOption('no-dev')) { $args['--no-dev'] = \true; } if ($input->getOption('sort-by-age')) { $args['--sort-by-age'] = \true; } $args['--ignore-platform-req'] = $input->getOption('ignore-platform-req'); if ($input->getOption('ignore-platform-reqs')) { $args['--ignore-platform-reqs'] = \true; } $args['--format'] = $input->getOption('format'); $args['--ignore'] = $input->getOption('ignore'); $input = new ArrayInput($args); return $this->getApplication()->run($input, $output); } /** * @inheritDoc */ public function isProxyCommand() : bool { return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Package\AliasPackage; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano */ class DumpAutoloadCommand extends \Composer\Command\BaseCommand { /** * @return void */ protected function configure() { $this->setName('dump-autoload')->setAliases(['dumpautoload'])->setDescription('Dumps the autoloader')->setDefinition([new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'), new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables autoload-dev rules. Composer will by default infer this automatically according to the last install or update --no-dev state.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules. Composer will by default infer this automatically according to the last install or update --no-dev state.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('strict-psr', null, InputOption::VALUE_NONE, 'Return a failed status code (1) if PSR-4 or PSR-0 mapping errors are present. Requires --optimize to work.'), new InputOption('strict-ambiguous', null, InputOption::VALUE_NONE, 'Return a failed status code (2) if the same class is found in multiple files. Requires --optimize to work.')])->setHelp(<<php composer.phar dump-autoload Read more at https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->requireComposer(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $installationManager = $composer->getInstallationManager(); $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $package = $composer->getPackage(); $config = $composer->getConfig(); $missingDependencies = \false; foreach ($localRepo->getCanonicalPackages() as $localPkg) { $installPath = $installationManager->getInstallPath($localPkg); if ($installPath !== null && \file_exists($installPath) === \false) { $missingDependencies = \true; $this->getIO()->write('Not all dependencies are installed. Make sure to run a "composer install" to install missing dependencies'); break; } } $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader'); $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); $apcuPrefix = $input->getOption('apcu-prefix'); $apcu = $apcuPrefix !== null || $input->getOption('apcu') || $config->get('apcu-autoloader'); if ($input->getOption('strict-psr') && !$optimize && !$authoritative) { throw new \InvalidArgumentException('--strict-psr mode only works with optimized autoloader, use --optimize or --classmap-authoritative if you want a strict return value.'); } if ($input->getOption('strict-ambiguous') && !$optimize && !$authoritative) { throw new \InvalidArgumentException('--strict-ambiguous mode only works with optimized autoloader, use --optimize or --classmap-authoritative if you want a strict return value.'); } if ($authoritative) { $this->getIO()->write('Generating optimized autoload files (authoritative)'); } elseif ($optimize) { $this->getIO()->write('Generating optimized autoload files'); } else { $this->getIO()->write('Generating autoload files'); } $generator = $composer->getAutoloadGenerator(); if ($input->getOption('dry-run')) { $generator->setDryRun(\true); } if ($input->getOption('no-dev')) { $generator->setDevMode(\false); } if ($input->getOption('dev')) { if ($input->getOption('no-dev')) { throw new \InvalidArgumentException('You can not use both --no-dev and --dev as they conflict with each other.'); } $generator->setDevMode(\true); } $generator->setClassMapAuthoritative($authoritative); $generator->setRunScripts(\true); $generator->setApcu($apcu, $apcuPrefix); $generator->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input)); $classMap = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize, null, $composer->getLocker(), $input->getOption('strict-ambiguous')); $numberOfClasses = \count($classMap); if ($authoritative) { $this->getIO()->write('Generated optimized autoload files (authoritative) containing ' . $numberOfClasses . ' classes'); } elseif ($optimize) { $this->getIO()->write('Generated optimized autoload files containing ' . $numberOfClasses . ' classes'); } else { $this->getIO()->write('Generated autoload files'); } if ($missingDependencies || $input->getOption('strict-psr') && \count($classMap->getPsrViolations()) > 0) { return 1; } if ($input->getOption('strict-ambiguous') && \count($classMap->getAmbiguousClasses(\false)) > 0) { return 2; } return 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Package\CompletePackageInterface; use Composer\Repository\RepositoryInterface; use Composer\Repository\RootPackageRepository; use Composer\Repository\RepositoryFactory; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Console\Input\InputArgument; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Robert Schönthal */ class HomeCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; /** * @inheritDoc */ protected function configure() : void { $this->setName('browse')->setAliases(['home'])->setDescription('Opens the package\'s repository URL or homepage in your browser')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.', null, $this->suggestInstalledPackage()), new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'), new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.')])->setHelp(<<initializeRepos(); $io = $this->getIO(); $return = 0; $packages = $input->getArgument('packages'); if (\count($packages) === 0) { $io->writeError('No package specified, opening homepage for the root package'); $packages = [$this->requireComposer()->getPackage()->getName()]; } foreach ($packages as $packageName) { $handled = \false; $packageExists = \false; foreach ($repos as $repo) { foreach ($repo->findPackages($packageName) as $package) { $packageExists = \true; if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) { $handled = \true; break 2; } } } if (!$packageExists) { $return = 1; $io->writeError('Package ' . $packageName . ' not found'); } if (!$handled) { $return = 1; $io->writeError('' . ($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL') . ' for ' . $packageName . ''); } } return $return; } private function handlePackage(CompletePackageInterface $package, bool $showHomepage, bool $showOnly) : bool { $support = $package->getSupport(); $url = $support['source'] ?? $package->getSourceUrl(); if (!$url || $showHomepage) { $url = $package->getHomepage(); } if (!$url || !\filter_var($url, \FILTER_VALIDATE_URL)) { return \false; } if ($showOnly) { $this->getIO()->write(\sprintf('%s', $url)); } else { $this->openBrowser($url); } return \true; } /** * opens a url in your system default browser */ private function openBrowser(string $url) : void { $process = new ProcessExecutor($this->getIO()); if (Platform::isWindows()) { $process->execute(['start', '"web"', 'explorer', $url], $output); return; } $linux = $process->execute(['which', 'xdg-open'], $output); $osx = $process->execute(['which', 'open'], $output); if (0 === $linux) { $process->execute(['xdg-open', $url], $output); } elseif (0 === $osx) { $process->execute(['open', $url], $output); } else { $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url); } } /** * Initializes repositories * * Returns an array of repos in order they should be checked in * * @return RepositoryInterface[] */ private function initializeRepos() : array { $composer = $this->tryComposer(); if ($composer) { return \array_merge( [new RootPackageRepository(clone $composer->getPackage())], // root package [$composer->getRepositoryManager()->getLocalRepository()], // installed packages $composer->getRepositoryManager()->getRepositories() ); } return RepositoryFactory::defaultReposWithDefaultManager($this->getIO()); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UninstallOperation; use Composer\DependencyResolver\Transaction; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Script\ScriptEvents; use Composer\Util\Platform; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano */ class ReinstallCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; protected function configure() : void { $this->setName('reinstall')->setDescription('Uninstalls and reinstalls the given package names')->setDefinition([new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Filter packages to reinstall by type(s)', null, $this->suggestInstalledPackageTypes(\false)), new InputArgument('packages', InputArgument::IS_ARRAY, 'List of package names to reinstall, can include a wildcard (*) to match any substring.', null, $this->suggestInstalledPackage(\false))])->setHelp(<<reinstall command looks up installed packages by name, uninstalls them and reinstalls them. This lets you do a clean install of a package if you messed with its files, or if you wish to change the installation type using --prefer-install. php composer.phar reinstall acme/foo "acme/bar-*" Read more at https://getcomposer.org/doc/03-cli.md#reinstall EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $io = $this->getIO(); $composer = $this->requireComposer(); $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $packagesToReinstall = []; $packageNamesToReinstall = []; if (\count($input->getOption('type')) > 0) { if (\count($input->getArgument('packages')) > 0) { throw new \InvalidArgumentException('You cannot specify package names and filter by type at the same time.'); } foreach ($localRepo->getCanonicalPackages() as $package) { if (\in_array($package->getType(), $input->getOption('type'), \true)) { $packagesToReinstall[] = $package; $packageNamesToReinstall[] = $package->getName(); } } } else { if (\count($input->getArgument('packages')) === 0) { throw new \InvalidArgumentException('You must pass one or more package names to be reinstalled.'); } foreach ($input->getArgument('packages') as $pattern) { $patternRegexp = BasePackage::packageNameToRegexp($pattern); $matched = \false; foreach ($localRepo->getCanonicalPackages() as $package) { if (Preg::isMatch($patternRegexp, $package->getName())) { $matched = \true; $packagesToReinstall[] = $package; $packageNamesToReinstall[] = $package->getName(); } } if (!$matched) { $io->writeError('Pattern "' . $pattern . '" does not match any currently installed packages.'); } } } if (0 === \count($packagesToReinstall)) { $io->writeError('Found no packages to reinstall, aborting.'); return 1; } $uninstallOperations = []; foreach ($packagesToReinstall as $package) { $uninstallOperations[] = new UninstallOperation($package); } // make sure we have a list of install operations ordered by dependency/plugins $presentPackages = $localRepo->getPackages(); $resultPackages = $presentPackages; foreach ($presentPackages as $index => $package) { if (\in_array($package->getName(), $packageNamesToReinstall, \true)) { unset($presentPackages[$index]); } } $transaction = new Transaction($presentPackages, $resultPackages); $installOperations = $transaction->getOperations(); // reverse-sort the uninstalls based on the install order $installOrder = []; foreach ($installOperations as $index => $op) { if ($op instanceof InstallOperation && !$op->getPackage() instanceof AliasPackage) { $installOrder[$op->getPackage()->getName()] = $index; } } \usort($uninstallOperations, static function ($a, $b) use($installOrder) : int { return $installOrder[$b->getPackage()->getName()] - $installOrder[$a->getPackage()->getName()]; }); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'reinstall', $input, $output); $eventDispatcher = $composer->getEventDispatcher(); $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent); $config = $composer->getConfig(); [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input); $installationManager = $composer->getInstallationManager(); $downloadManager = $composer->getDownloadManager(); $package = $composer->getPackage(); $installationManager->setOutputProgress(!$input->getOption('no-progress')); if ($input->getOption('no-plugins')) { $installationManager->disablePlugins(); } $downloadManager->setPreferSource($preferSource); $downloadManager->setPreferDist($preferDist); $devMode = $localRepo->getDevMode() !== null ? $localRepo->getDevMode() : \true; Platform::putEnv('COMPOSER_DEV_MODE', $devMode ? '1' : '0'); $eventDispatcher->dispatchScript(ScriptEvents::PRE_INSTALL_CMD, $devMode); $installationManager->execute($localRepo, $uninstallOperations, $devMode); $installationManager->execute($localRepo, $installOperations, $devMode); if (!$input->getOption('no-autoloader')) { $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); $apcuPrefix = $input->getOption('apcu-autoloader-prefix'); $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader'); $generator = $composer->getAutoloadGenerator(); $generator->setClassMapAuthoritative($authoritative); $generator->setApcu($apcu, $apcuPrefix); $generator->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input)); $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize, null, $composer->getLocker()); } $eventDispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, $devMode); return 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Config\JsonConfigSource; use Composer\DependencyResolver\Request; use Composer\Installer; use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Json\JsonFile; use Composer\Factory; use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Package\BasePackage; use Composer\Advisory\Auditor; /** * @author Pierre du Plessis * @author Jordi Boggiano */ class RemoveCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; /** * @return void */ protected function configure() { $this->setName('remove')->setAliases(['rm', 'uninstall'])->setDescription('Removes a package from the require or require-dev')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY, 'Packages that should be removed.', null, $this->suggestRootRequirement()), new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies (implies --no-install).'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'), new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecated, is now default behavior)'), new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'), new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'), new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'), new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During an update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'), new InputOption('unused', null, InputOption::VALUE_NONE, 'Remove all packages which are locked but not required by any other package.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader')])->setHelp(<<remove command removes a package from the current list of installed packages php composer.phar remove Read more at https://getcomposer.org/doc/03-cli.md#remove-rm EOT ); } /** * @throws \Seld\JsonLint\ParsingException */ protected function execute(InputInterface $input, OutputInterface $output) : int { if ($input->getArgument('packages') === [] && !$input->getOption('unused')) { throw new InvalidArgumentException('Not enough arguments (missing: "packages").'); } $packages = $input->getArgument('packages'); $packages = \array_map('strtolower', $packages); if ($input->getOption('unused')) { $composer = $this->requireComposer(); $locker = $composer->getLocker(); if (!$locker->isLocked()) { throw new \UnexpectedValueException('A valid composer.lock file is required to run this command with --unused'); } $lockedPackages = $locker->getLockedRepository()->getPackages(); $required = []; foreach (\array_merge($composer->getPackage()->getRequires(), $composer->getPackage()->getDevRequires()) as $link) { $required[$link->getTarget()] = \true; } do { $found = \false; foreach ($lockedPackages as $index => $package) { foreach ($package->getNames() as $name) { if (isset($required[$name])) { foreach ($package->getRequires() as $link) { $required[$link->getTarget()] = \true; } $found = \true; unset($lockedPackages[$index]); break; } } } } while ($found); $unused = []; foreach ($lockedPackages as $package) { $unused[] = $package->getName(); } $packages = \array_merge($packages, $unused); if (\count($packages) === 0) { $this->getIO()->writeError('No unused packages to remove'); return 0; } } $file = Factory::getComposerFile(); $jsonFile = new JsonFile($file); /** @var array{require?: array, require-dev?: array} $composer */ $composer = $jsonFile->read(); $composerBackup = \file_get_contents($jsonFile->getPath()); $json = new JsonConfigSource($jsonFile); $type = $input->getOption('dev') ? 'require-dev' : 'require'; $altType = !$input->getOption('dev') ? 'require-dev' : 'require'; $io = $this->getIO(); if ($input->getOption('update-with-dependencies')) { $io->writeError('You are using the deprecated option "update-with-dependencies". This is now default behaviour. The --no-update-with-dependencies option can be used to remove a package without its dependencies.'); } // make sure name checks are done case insensitively foreach (['require', 'require-dev'] as $linkType) { if (isset($composer[$linkType])) { foreach ($composer[$linkType] as $name => $version) { $composer[$linkType][\strtolower($name)] = $name; } } } $dryRun = $input->getOption('dry-run'); $toRemove = []; foreach ($packages as $package) { if (isset($composer[$type][$package])) { if ($dryRun) { $toRemove[$type][] = $composer[$type][$package]; } else { $json->removeLink($type, $composer[$type][$package]); } } elseif (isset($composer[$altType][$package])) { $io->writeError('' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . ''); if ($io->isInteractive()) { if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [yes]? ')) { if ($dryRun) { $toRemove[$altType][] = $composer[$altType][$package]; } else { $json->removeLink($altType, $composer[$altType][$package]); } } } } elseif (isset($composer[$type]) && \count($matches = Preg::grep(BasePackage::packageNameToRegexp($package), \array_keys($composer[$type]))) > 0) { foreach ($matches as $matchedPackage) { if ($dryRun) { $toRemove[$type][] = $matchedPackage; } else { $json->removeLink($type, $matchedPackage); } } } elseif (isset($composer[$altType]) && \count($matches = Preg::grep(BasePackage::packageNameToRegexp($package), \array_keys($composer[$altType]))) > 0) { foreach ($matches as $matchedPackage) { $io->writeError('' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . ''); if ($io->isInteractive()) { if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [yes]? ')) { if ($dryRun) { $toRemove[$altType][] = $matchedPackage; } else { $json->removeLink($altType, $matchedPackage); } } } } } else { $io->writeError('' . $package . ' is not required in your composer.json and has not been removed'); } } $io->writeError('' . $file . ' has been updated'); if ($input->getOption('no-update')) { return 0; } if ($composer = $this->tryComposer()) { $composer->getPluginManager()->deactivateInstalledPlugins(); } // Update packages $this->resetComposer(); $composer = $this->requireComposer(); if ($dryRun) { $rootPackage = $composer->getPackage(); $links = ['require' => $rootPackage->getRequires(), 'require-dev' => $rootPackage->getDevRequires()]; foreach ($toRemove as $type => $names) { foreach ($names as $name) { unset($links[$type][$name]); } } $rootPackage->setRequires($links['require']); $rootPackage->setDevRequires($links['require-dev']); } $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $allowPlugins = $composer->getConfig()->get('allow-plugins'); $removedPlugins = \is_array($allowPlugins) ? \array_intersect(\array_keys($allowPlugins), $packages) : []; if (!$dryRun && \is_array($allowPlugins) && \count($removedPlugins) > 0) { if (\count($allowPlugins) === \count($removedPlugins)) { $json->removeConfigSetting('allow-plugins'); } else { foreach ($removedPlugins as $plugin) { $json->removeConfigSetting('allow-plugins.' . $plugin); } } } $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress')); $install = Installer::create($io, $composer); $updateDevMode = !$input->getOption('update-no-dev'); $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader'); $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative'); $apcuPrefix = $input->getOption('apcu-autoloader-prefix'); $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader'); $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE; $flags = ''; if ($input->getOption('update-with-all-dependencies') || $input->getOption('with-all-dependencies')) { $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS; $flags .= ' --with-all-dependencies'; } elseif ($input->getOption('no-update-with-dependencies')) { $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED; $flags .= ' --with-dependencies'; } $io->writeError('Running composer update ' . \implode(' ', $packages) . $flags . ''); $install->setVerbose($input->getOption('verbose'))->setDevMode($updateDevMode)->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setUpdate(\true)->setInstall(!$input->getOption('no-install'))->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setDryRun($dryRun)->setAudit(!$input->getOption('no-audit'))->setAuditFormat($this->getAuditFormat($input))->setMinimalUpdate($input->getOption('minimal-changes')); // if no lock is present, we do not do a partial update as // this is not supported by the Installer if ($composer->getLocker()->isLocked()) { $install->setUpdateAllowList($packages); } $status = $install->run(); if ($status !== 0) { $io->writeError("\n" . 'Removal failed, reverting ' . $file . ' to its original content.'); \file_put_contents($jsonFile->getPath(), $composerBackup); } if (!$dryRun) { foreach ($packages as $package) { if ($composer->getRepositoryManager()->getLocalRepository()->findPackages($package)) { $io->writeError('Removal failed, ' . $package . ' is still present, it may be required by another package. See `composer why ' . $package . '`.'); return 2; } } } return $status; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use Composer\DependencyResolver\DefaultPolicy; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\BasePackage; use Composer\Package\CompletePackageInterface; use Composer\Package\Link; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionSelector; use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\ArrayRepository; use Composer\Repository\InstalledArrayRepository; use Composer\Repository\ComposerRepository; use Composer\Repository\CompositeRepository; use Composer\Repository\FilterRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryFactory; use Composer\Repository\InstalledRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositorySet; use Composer\Repository\RepositoryUtils; use Composer\Repository\RootPackageRepository; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Semver; use Composer\Spdx\SpdxLicenses; use Composer\Util\PackageInfo; use DateTimeInterface; use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Robert Schönthal * @author Jordi Boggiano * @author Jérémy Romey * @author Mihai Plasoianu * * @phpstan-import-type AutoloadRules from PackageInterface * @phpstan-type JsonStructure array|AutoloadRules> */ class ShowCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; /** @var VersionParser */ protected $versionParser; /** @var string[] */ protected $colors; /** @var ?RepositorySet */ private $repositorySet; /** * @return void */ protected function configure() { $this->setName('show')->setAliases(['info'])->setDescription('Shows information about packages')->setDefinition([new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.', null, $this->suggestPackageBasedOnMode()), new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'), new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'), new InputOption('locked', null, InputOption::VALUE_NONE, 'List all locked packages'), new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'), new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'), new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'), new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'), new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'), new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'), new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'), new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'), new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'), new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Can contain wildcards (*). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.', null, $this->suggestInstalledPackage(\false)), new InputOption('major-only', 'M', InputOption::VALUE_NONE, 'Show only packages that have major SemVer-compatible updates. Use with the --latest or --outdated option.'), new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --latest or --outdated option.'), new InputOption('patch-only', null, InputOption::VALUE_NONE, 'Show only packages that have patch SemVer-compatible updates. Use with the --latest or --outdated option.'), new InputOption('sort-by-age', 'A', InputOption::VALUE_NONE, 'Displays the installed version\'s age, and sorts packages oldest first. Use with the --latest or --outdated option.'), new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'), new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text']), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages). Use with the --outdated option'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages). Use with the --outdated option')])->setHelp(<<getOption('available') || $input->getOption('all')) { return $this->suggestAvailablePackageInclPlatform()($input); } if ($input->getOption('platform')) { return $this->suggestPlatformPackage()($input); } return $this->suggestInstalledPackage(\false)($input); }; } protected function execute(InputInterface $input, OutputInterface $output) : int { $this->versionParser = new VersionParser(); if ($input->getOption('tree')) { $this->initStyles($output); } $composer = $this->tryComposer(); $io = $this->getIO(); if ($input->getOption('installed') && !$input->getOption('self')) { $io->writeError('You are using the deprecated option "installed". Only installed packages are shown by default now. The --all option can be used to show all packages.'); } if ($input->getOption('outdated')) { $input->setOption('latest', \true); } elseif (\count($input->getOption('ignore')) > 0) { $io->writeError('You are using the option "ignore" for action other than "outdated", it will be ignored.'); } if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) { $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)'); return 1; } if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) { $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)'); return 1; } if (\count(\array_filter([$input->getOption('patch-only'), $input->getOption('minor-only'), $input->getOption('major-only')])) > 1) { $io->writeError('Only one of --major-only, --minor-only or --patch-only can be used at once'); return 1; } if ($input->getOption('tree') && $input->getOption('latest')) { $io->writeError('The --tree (-t) option is not usable in combination with --latest (-l)'); return 1; } if ($input->getOption('tree') && $input->getOption('path')) { $io->writeError('The --tree (-t) option is not usable in combination with --path (-P)'); return 1; } $format = $input->getOption('format'); if (!\in_array($format, ['text', 'json'])) { $io->writeError(\sprintf('Unsupported format "%s". See help for supported formats.', $format)); return 1; } $platformReqFilter = $this->getPlatformRequirementFilter($input); // init repos $platformOverrides = []; if ($composer) { $platformOverrides = $composer->getConfig()->get('platform'); } $platformRepo = new PlatformRepository([], $platformOverrides); $lockedRepo = null; if ($input->getOption('self') && !$input->getOption('installed') && !$input->getOption('locked')) { $package = clone $this->requireComposer()->getPackage(); if ($input->getOption('name-only')) { $io->write($package->getName()); return 0; } if ($input->getArgument('package')) { throw new \InvalidArgumentException('You cannot use --self together with a package name'); } $repos = $installedRepo = new InstalledRepository([new RootPackageRepository($package)]); } elseif ($input->getOption('platform')) { $repos = $installedRepo = new InstalledRepository([$platformRepo]); } elseif ($input->getOption('available')) { $installedRepo = new InstalledRepository([$platformRepo]); if ($composer) { $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); $installedRepo->addRepository($composer->getRepositoryManager()->getLocalRepository()); } else { $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io); $repos = new CompositeRepository($defaultRepos); $io->writeError('No composer.json found in the current directory, showing available packages from ' . \implode(', ', \array_keys($defaultRepos))); } } elseif ($input->getOption('all') && $composer) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $locker = $composer->getLocker(); if ($locker->isLocked()) { $lockedRepo = $locker->getLockedRepository(\true); $installedRepo = new InstalledRepository([$lockedRepo, $localRepo, $platformRepo]); } else { $installedRepo = new InstalledRepository([$localRepo, $platformRepo]); } $repos = new CompositeRepository(\array_merge([new FilterRepository($installedRepo, ['canonical' => \false])], $composer->getRepositoryManager()->getRepositories())); } elseif ($input->getOption('all')) { $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io); $io->writeError('No composer.json found in the current directory, showing available packages from ' . \implode(', ', \array_keys($defaultRepos))); $installedRepo = new InstalledRepository([$platformRepo]); $repos = new CompositeRepository(\array_merge([$installedRepo], $defaultRepos)); } elseif ($input->getOption('locked')) { if (!$composer || !$composer->getLocker()->isLocked()) { throw new \UnexpectedValueException('A valid composer.json and composer.lock files is required to run this command with --locked'); } $locker = $composer->getLocker(); $lockedRepo = $locker->getLockedRepository(!$input->getOption('no-dev')); if ($input->getOption('self')) { $lockedRepo->addPackage(clone $composer->getPackage()); } $repos = $installedRepo = new InstalledRepository([$lockedRepo]); } else { // --installed / default case if (!$composer) { $composer = $this->requireComposer(); } $rootPkg = $composer->getPackage(); $rootRepo = new InstalledArrayRepository(); if ($input->getOption('self')) { $rootRepo = new RootPackageRepository(clone $rootPkg); } if ($input->getOption('no-dev')) { $packages = RepositoryUtils::filterRequiredPackages($composer->getRepositoryManager()->getLocalRepository()->getPackages(), $rootPkg); $repos = $installedRepo = new InstalledRepository([$rootRepo, new InstalledArrayRepository(\array_map(static function ($pkg) : PackageInterface { return clone $pkg; }, $packages))]); } else { $repos = $installedRepo = new InstalledRepository([$rootRepo, $composer->getRepositoryManager()->getLocalRepository()]); } if (!$installedRepo->getPackages()) { $hasNonPlatformReqs = static function (array $reqs) : bool { return (bool) \array_filter(\array_keys($reqs), function (string $name) { return !PlatformRepository::isPlatformPackage($name); }); }; if ($hasNonPlatformReqs($rootPkg->getRequires()) || $hasNonPlatformReqs($rootPkg->getDevRequires())) { $io->writeError('No dependencies installed. Try running composer install or update.'); } } } if ($composer) { $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); } if ($input->getOption('latest') && null === $composer) { $io->writeError('No composer.json found in the current directory, disabling "latest" option'); $input->setOption('latest', \false); } $packageFilter = $input->getArgument('package'); // show single package or single version if (isset($package)) { $versions = [$package->getPrettyVersion() => $package->getVersion()]; } elseif (null !== $packageFilter && !\str_contains($packageFilter, '*')) { [$package, $versions] = $this->getPackage($installedRepo, $repos, $packageFilter, $input->getArgument('version')); if (isset($package) && $input->getOption('direct')) { if (!\in_array($package->getName(), $this->getRootRequires(), \true)) { throw new \InvalidArgumentException('Package "' . $package->getName() . '" is installed but not a direct dependent of the root package.'); } } if (!isset($package)) { $options = $input->getOptions(); $hint = ''; if ($input->getOption('locked')) { $hint .= ' in lock file'; } if (isset($options['working-dir'])) { $hint .= ' in ' . $options['working-dir'] . '/composer.json'; } if (PlatformRepository::isPlatformPackage($packageFilter) && !$input->getOption('platform')) { $hint .= ', try using --platform (-p) to show platform packages'; } if (!$input->getOption('all') && !$input->getOption('available')) { $hint .= ', try using --available (-a) to show all available packages'; } throw new \InvalidArgumentException('Package "' . $packageFilter . '" not found' . $hint . '.'); } } if (isset($package)) { \assert(isset($versions)); $exitCode = 0; if ($input->getOption('tree')) { $arrayTree = $this->generatePackageTree($package, $installedRepo, $repos); if ('json' === $format) { $io->write(JsonFile::encode(['installed' => [$arrayTree]])); } else { $this->displayPackageTree([$arrayTree]); } return $exitCode; } $latestPackage = null; if ($input->getOption('latest')) { $latestPackage = $this->findLatestPackage($package, $composer, $platformRepo, $input->getOption('major-only'), $input->getOption('minor-only'), $input->getOption('patch-only'), $platformReqFilter); } if ($input->getOption('outdated') && $input->getOption('strict') && null !== $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && (!$latestPackage instanceof CompletePackageInterface || !$latestPackage->isAbandoned())) { $exitCode = 1; } if ($input->getOption('path')) { $io->write($package->getName(), \false); $path = $composer->getInstallationManager()->getInstallPath($package); if (\is_string($path)) { $io->write(' ' . \strtok(\realpath($path), "\r\n")); } else { $io->write(' null'); } return $exitCode; } if ('json' === $format) { $this->printPackageInfoAsJson($package, $versions, $installedRepo, $latestPackage ?: null); } else { $this->printPackageInfo($package, $versions, $installedRepo, $latestPackage ?: null); } return $exitCode; } // show tree view if requested if ($input->getOption('tree')) { $rootRequires = $this->getRootRequires(); $packages = $installedRepo->getPackages(); \usort($packages, static function (BasePackage $a, BasePackage $b) : int { return \strcmp((string) $a, (string) $b); }); $arrayTree = []; foreach ($packages as $package) { if (\in_array($package->getName(), $rootRequires, \true)) { $arrayTree[] = $this->generatePackageTree($package, $installedRepo, $repos); } } if ('json' === $format) { $io->write(JsonFile::encode(['installed' => $arrayTree])); } else { $this->displayPackageTree($arrayTree); } return 0; } // list packages /** @var array> $packages */ $packages = []; $packageFilterRegex = null; if (null !== $packageFilter) { $packageFilterRegex = '{^' . \str_replace('\\*', '.*?', \preg_quote($packageFilter)) . '$}i'; } $packageListFilter = null; if ($input->getOption('direct')) { $packageListFilter = $this->getRootRequires(); } if ($input->getOption('path') && null === $composer) { $io->writeError('No composer.json found in the current directory, disabling "path" option'); $input->setOption('path', \false); } foreach (RepositoryUtils::flattenRepositories($repos) as $repo) { if ($repo === $platformRepo) { $type = 'platform'; } elseif ($lockedRepo !== null && $repo === $lockedRepo) { $type = 'locked'; } elseif ($repo === $installedRepo || \in_array($repo, $installedRepo->getRepositories(), \true)) { $type = 'installed'; } else { $type = 'available'; } if ($repo instanceof ComposerRepository) { foreach ($repo->getPackageNames($packageFilter) as $name) { $packages[$type][$name] = $name; } } else { foreach ($repo->getPackages() as $package) { if (!isset($packages[$type][$package->getName()]) || !\is_object($packages[$type][$package->getName()]) || \version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')) { while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } if (!$packageFilterRegex || Preg::isMatch($packageFilterRegex, $package->getName())) { if (null === $packageListFilter || \in_array($package->getName(), $packageListFilter, \true)) { $packages[$type][$package->getName()] = $package; } } } } if ($repo === $platformRepo) { foreach ($platformRepo->getDisabledPackages() as $name => $package) { $packages[$type][$name] = $package; } } } } $showAllTypes = $input->getOption('all'); $showLatest = $input->getOption('latest'); $showMajorOnly = $input->getOption('major-only'); $showMinorOnly = $input->getOption('minor-only'); $showPatchOnly = $input->getOption('patch-only'); $ignoredPackagesRegex = BasePackage::packageNamesToRegexp(\array_map('strtolower', $input->getOption('ignore'))); $indent = $showAllTypes ? ' ' : ''; /** @var PackageInterface[] $latestPackages */ $latestPackages = []; $exitCode = 0; $viewData = []; $viewMetaData = []; $writeVersion = \false; $writeDescription = \false; foreach (['platform' => \true, 'locked' => \true, 'available' => \false, 'installed' => \true] as $type => $showVersion) { if (isset($packages[$type])) { \ksort($packages[$type]); $nameLength = $versionLength = $latestLength = $releaseDateLength = 0; if ($showLatest && $showVersion) { foreach ($packages[$type] as $package) { if (\is_object($package) && !Preg::isMatch($ignoredPackagesRegex, $package->getPrettyName())) { $latestPackage = $this->findLatestPackage($package, $composer, $platformRepo, $showMajorOnly, $showMinorOnly, $showPatchOnly, $platformReqFilter); if ($latestPackage === null) { continue; } $latestPackages[$package->getPrettyName()] = $latestPackage; } } } $writePath = !$input->getOption('name-only') && $input->getOption('path'); $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion; $writeLatest = $writeVersion && $showLatest; $writeDescription = !$input->getOption('name-only') && !$input->getOption('path'); $writeReleaseDate = $writeLatest && ($input->getOption('sort-by-age') || $format === 'json'); $hasOutdatedPackages = \false; if ($input->getOption('sort-by-age')) { \usort($packages[$type], function ($a, $b) { if (\is_object($a) && \is_object($b)) { return $a->getReleaseDate() <=> $b->getReleaseDate(); } return 0; }); } $viewData[$type] = []; foreach ($packages[$type] as $package) { $packageViewData = []; if (\is_object($package)) { $latestPackage = null; if ($showLatest && isset($latestPackages[$package->getPrettyName()])) { $latestPackage = $latestPackages[$package->getPrettyName()]; } // Determine if Composer is checking outdated dependencies and if current package should trigger non-default exit code $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && (!$latestPackage instanceof CompletePackageInterface || !$latestPackage->isAbandoned()); // When using --major-only, and no bigger version than current major is found then it is considered up to date $packageIsUpToDate = $packageIsUpToDate || $latestPackage === null && $showMajorOnly; $packageIsIgnored = Preg::isMatch($ignoredPackagesRegex, $package->getPrettyName()); if ($input->getOption('outdated') && ($packageIsUpToDate || $packageIsIgnored)) { continue; } if ($input->getOption('outdated') || $input->getOption('strict')) { $hasOutdatedPackages = \true; } $packageViewData['name'] = $package->getPrettyName(); $packageViewData['direct-dependency'] = \in_array($package->getName(), $this->getRootRequires(), \true); if ($format !== 'json' || \true !== $input->getOption('name-only')) { $packageViewData['homepage'] = $package instanceof CompletePackageInterface ? $package->getHomepage() : null; $packageViewData['source'] = PackageInfo::getViewSourceUrl($package); } $nameLength = \max($nameLength, \strlen($packageViewData['name'])); if ($writeVersion) { $packageViewData['version'] = $package->getFullPrettyVersion(); if ($format === 'text') { $packageViewData['version'] = \ltrim($packageViewData['version'], 'v'); } $versionLength = \max($versionLength, \strlen($packageViewData['version'])); } if ($writeReleaseDate) { if ($package->getReleaseDate() !== null) { $packageViewData['release-age'] = \str_replace(' ago', ' old', $this->getRelativeTime($package->getReleaseDate())); if (!\str_contains($packageViewData['release-age'], ' old')) { $packageViewData['release-age'] = 'from ' . $packageViewData['release-age']; } $releaseDateLength = \max($releaseDateLength, \strlen($packageViewData['release-age'])); $packageViewData['release-date'] = $package->getReleaseDate()->format(DateTimeInterface::ATOM); } else { $packageViewData['release-age'] = ''; $packageViewData['release-date'] = ''; } } if ($writeLatest && $latestPackage) { $packageViewData['latest'] = $latestPackage->getFullPrettyVersion(); if ($format === 'text') { $packageViewData['latest'] = \ltrim($packageViewData['latest'], 'v'); } $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package); $latestLength = \max($latestLength, \strlen($packageViewData['latest'])); if ($latestPackage->getReleaseDate() !== null) { $packageViewData['latest-release-date'] = $latestPackage->getReleaseDate()->format(DateTimeInterface::ATOM); } else { $packageViewData['latest-release-date'] = ''; } } elseif ($writeLatest) { $packageViewData['latest'] = '[none matched]'; $packageViewData['latest-status'] = 'up-to-date'; $latestLength = \max($latestLength, \strlen($packageViewData['latest'])); } if ($writeDescription && $package instanceof CompletePackageInterface) { $packageViewData['description'] = $package->getDescription(); } if ($writePath) { $path = $composer->getInstallationManager()->getInstallPath($package); if (\is_string($path)) { $packageViewData['path'] = \strtok(\realpath($path), "\r\n"); } else { $packageViewData['path'] = null; } } $packageIsAbandoned = \false; if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) { $replacementPackageName = $latestPackage->getReplacementPackage(); $replacement = $replacementPackageName !== null ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead' : 'No replacement was suggested'; $packageWarning = \sprintf('Package %s is abandoned, you should avoid using it. %s.', $package->getPrettyName(), $replacement); $packageViewData['warning'] = $packageWarning; $packageIsAbandoned = $replacementPackageName ?? \true; } $packageViewData['abandoned'] = $packageIsAbandoned; } else { $packageViewData['name'] = $package; $nameLength = \max($nameLength, \strlen($package)); } $viewData[$type][] = $packageViewData; } $viewMetaData[$type] = ['nameLength' => $nameLength, 'versionLength' => $versionLength, 'latestLength' => $latestLength, 'releaseDateLength' => $releaseDateLength, 'writeLatest' => $writeLatest, 'writeReleaseDate' => $writeReleaseDate]; if ($input->getOption('strict') && $hasOutdatedPackages) { $exitCode = 1; break; } } } if ('json' === $format) { $io->write(JsonFile::encode($viewData)); } else { if ($input->getOption('latest') && \array_filter($viewData)) { if (!$io->isDecorated()) { $io->writeError('Legend:'); $io->writeError('! patch or minor release available - update recommended'); $io->writeError('~ major release available - update possible'); if (!$input->getOption('outdated')) { $io->writeError('= up to date version'); } } else { $io->writeError('Color legend:'); $io->writeError('- patch or minor release available - update recommended'); $io->writeError('- major release available - update possible'); if (!$input->getOption('outdated')) { $io->writeError('- up to date version'); } } } $width = $this->getTerminalWidth(); foreach ($viewData as $type => $packages) { $nameLength = $viewMetaData[$type]['nameLength']; $versionLength = $viewMetaData[$type]['versionLength']; $latestLength = $viewMetaData[$type]['latestLength']; $releaseDateLength = $viewMetaData[$type]['releaseDateLength']; $writeLatest = $viewMetaData[$type]['writeLatest']; $writeReleaseDate = $viewMetaData[$type]['writeReleaseDate']; $versionFits = $nameLength + $versionLength + 3 <= $width; $latestFits = $nameLength + $versionLength + $latestLength + 3 <= $width; $releaseDateFits = $nameLength + $versionLength + $latestLength + $releaseDateLength + 3 <= $width; $descriptionFits = $nameLength + $versionLength + $latestLength + $releaseDateLength + 24 <= $width; if ($latestFits && !$io->isDecorated()) { $latestLength += 2; } if ($showAllTypes) { if ('available' === $type) { $io->write('' . $type . ':'); } else { $io->write('' . $type . ':'); } } if ($writeLatest && !$input->getOption('direct')) { $directDeps = []; $transitiveDeps = []; foreach ($packages as $pkg) { if ($pkg['direct-dependency'] ?? \false) { $directDeps[] = $pkg; } else { $transitiveDeps[] = $pkg; } } $io->writeError(''); $io->writeError('Direct dependencies required in composer.json:'); if (\count($directDeps) > 0) { $this->printPackages($io, $directDeps, $indent, $writeVersion && $versionFits, $latestFits, $writeDescription && $descriptionFits, $width, $versionLength, $nameLength, $latestLength, $writeReleaseDate && $releaseDateFits, $releaseDateLength); } else { $io->writeError('Everything up to date'); } $io->writeError(''); $io->writeError('Transitive dependencies not required in composer.json:'); if (\count($transitiveDeps) > 0) { $this->printPackages($io, $transitiveDeps, $indent, $writeVersion && $versionFits, $latestFits, $writeDescription && $descriptionFits, $width, $versionLength, $nameLength, $latestLength, $writeReleaseDate && $releaseDateFits, $releaseDateLength); } else { $io->writeError('Everything up to date'); } } else { if ($writeLatest && \count($packages) === 0) { $io->writeError('All your direct dependencies are up to date'); } else { $this->printPackages($io, $packages, $indent, $writeVersion && $versionFits, $writeLatest && $latestFits, $writeDescription && $descriptionFits, $width, $versionLength, $nameLength, $latestLength, $writeReleaseDate && $releaseDateFits, $releaseDateLength); } } if ($showAllTypes) { $io->write(''); } } } return $exitCode; } /** * @param array $packages */ private function printPackages(IOInterface $io, array $packages, string $indent, bool $writeVersion, bool $writeLatest, bool $writeDescription, int $width, int $versionLength, int $nameLength, int $latestLength, bool $writeReleaseDate, int $releaseDateLength) : void { $padName = $writeVersion || $writeLatest || $writeReleaseDate || $writeDescription; $padVersion = $writeLatest || $writeReleaseDate || $writeDescription; $padLatest = $writeDescription || $writeReleaseDate; $padReleaseDate = $writeDescription; foreach ($packages as $package) { $link = $package['source'] ?? $package['homepage'] ?? ''; if ($link !== '') { $io->write($indent . '' . $package['name'] . '' . \str_repeat(' ', $padName ? $nameLength - \strlen($package['name']) : 0), \false); } else { $io->write($indent . \str_pad($package['name'], $padName ? $nameLength : 0, ' '), \false); } if (isset($package['version']) && $writeVersion) { $io->write(' ' . \str_pad($package['version'], $padVersion ? $versionLength : 0, ' '), \false); } if (isset($package['latest']) && isset($package['latest-status']) && $writeLatest) { $latestVersion = $package['latest']; $updateStatus = $package['latest-status']; $style = $this->updateStatusToVersionStyle($updateStatus); if (!$io->isDecorated()) { $latestVersion = \str_replace(['up-to-date', 'semver-safe-update', 'update-possible'], ['=', '!', '~'], $updateStatus) . ' ' . $latestVersion; } $io->write(' <' . $style . '>' . \str_pad($latestVersion, $padLatest ? $latestLength : 0, ' ') . '', \false); if ($writeReleaseDate && isset($package['release-age'])) { $io->write(' ' . \str_pad($package['release-age'], $padReleaseDate ? $releaseDateLength : 0, ' '), \false); } } if (isset($package['description']) && $writeDescription) { $description = \strtok($package['description'], "\r\n"); $remaining = $width - $nameLength - $versionLength - $releaseDateLength - 4; if ($writeLatest) { $remaining -= $latestLength; } if (\strlen($description) > $remaining) { $description = \substr($description, 0, $remaining - 3) . '...'; } $io->write(' ' . $description, \false); } if (\array_key_exists('path', $package)) { $io->write(' ' . (\is_string($package['path']) ? $package['path'] : 'null'), \false); } $io->write(''); if (isset($package['warning'])) { $io->write('' . $package['warning'] . ''); } } } /** * @return string[] */ protected function getRootRequires() : array { $composer = $this->tryComposer(); if ($composer === null) { return []; } $rootPackage = $composer->getPackage(); return \array_map('strtolower', \array_keys(\array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))); } /** * @return array|string|string[] */ protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package) { return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package)); } /** * finds a package by name and version if provided * * @param ConstraintInterface|string $version * @throws \InvalidArgumentException * @return array{CompletePackageInterface|null, array} */ protected function getPackage(InstalledRepository $installedRepo, RepositoryInterface $repos, string $name, $version = null) : array { $name = \strtolower($name); $constraint = \is_string($version) ? $this->versionParser->parseConstraints($version) : $version; $policy = new DefaultPolicy(); $repositorySet = new RepositorySet('dev'); $repositorySet->allowInstalledRepositories(); $repositorySet->addRepository($repos); $matchedPackage = null; $versions = []; if (PlatformRepository::isPlatformPackage($name)) { $pool = $repositorySet->createPoolWithAllPackages(); } else { $pool = $repositorySet->createPoolForPackage($name); } $matches = $pool->whatProvides($name, $constraint); $literals = []; foreach ($matches as $package) { // avoid showing the 9999999-dev alias if the default branch has no branch-alias set if ($package instanceof AliasPackage && $package->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { $package = $package->getAliasOf(); } // select an exact match if it is in the installed repo and no specific version was required if (null === $version && $installedRepo->hasPackage($package)) { $matchedPackage = $package; } $versions[$package->getPrettyVersion()] = $package->getVersion(); $literals[] = $package->getId(); } // select preferred package according to policy rules if (null === $matchedPackage && \count($literals) > 0) { $preferred = $policy->selectPreferredPackages($pool, $literals); $matchedPackage = $pool->literalToPackage($preferred[0]); } if ($matchedPackage !== null && !$matchedPackage instanceof CompletePackageInterface) { throw new \LogicException('ShowCommand::getPackage can only work with CompletePackageInterface, but got ' . \get_class($matchedPackage)); } return [$matchedPackage, $versions]; } /** * Prints package info. * * @param array $versions */ protected function printPackageInfo(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, ?PackageInterface $latestPackage = null) : void { $io = $this->getIO(); $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null); $this->printLinks($package, Link::TYPE_REQUIRE); $this->printLinks($package, Link::TYPE_DEV_REQUIRE, 'requires (dev)'); if ($package->getSuggests()) { $io->write("\nsuggests"); foreach ($package->getSuggests() as $suggested => $reason) { $io->write($suggested . ' ' . $reason . ''); } } $this->printLinks($package, Link::TYPE_PROVIDE); $this->printLinks($package, Link::TYPE_CONFLICT); $this->printLinks($package, Link::TYPE_REPLACE); } /** * Prints package metadata. * * @param array $versions */ protected function printMeta(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, ?PackageInterface $latestPackage = null) : void { $isInstalledPackage = !PlatformRepository::isPlatformPackage($package->getName()) && $installedRepo->hasPackage($package); $io = $this->getIO(); $io->write('name : ' . $package->getPrettyName()); $io->write('descrip. : ' . $package->getDescription()); $io->write('keywords : ' . \implode(', ', $package->getKeywords() ?: [])); $this->printVersions($package, $versions, $installedRepo); if ($isInstalledPackage && $package->getReleaseDate() !== null) { $io->write('released : ' . $package->getReleaseDate()->format('Y-m-d') . ', ' . $this->getRelativeTime($package->getReleaseDate())); } if ($latestPackage) { $style = $this->getVersionStyle($latestPackage, $package); $releasedTime = $latestPackage->getReleaseDate() === null ? '' : ' released ' . $latestPackage->getReleaseDate()->format('Y-m-d') . ', ' . $this->getRelativeTime($latestPackage->getReleaseDate()); $io->write('latest : <' . $style . '>' . $latestPackage->getPrettyVersion() . '' . $releasedTime); } else { $latestPackage = $package; } $io->write('type : ' . $package->getType()); $this->printLicenses($package); $io->write('homepage : ' . $package->getHomepage()); $io->write('source : ' . \sprintf('[%s] %s %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference())); $io->write('dist : ' . \sprintf('[%s] %s %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference())); if ($isInstalledPackage) { $path = $this->requireComposer()->getInstallationManager()->getInstallPath($package); if (\is_string($path)) { $io->write('path : ' . \realpath($path)); } else { $io->write('path : null'); } } $io->write('names : ' . \implode(', ', $package->getNames())); if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) { $replacement = $latestPackage->getReplacementPackage() !== null ? ' The author suggests using the ' . $latestPackage->getReplacementPackage() . ' package instead.' : null; $io->writeError(\sprintf('Attention: This package is abandoned and no longer maintained.%s', $replacement)); } if ($package->getSupport()) { $io->write("\nsupport"); foreach ($package->getSupport() as $type => $value) { $io->write('' . $type . ' : ' . $value); } } if (\count($package->getAutoload()) > 0) { $io->write("\nautoload"); $autoloadConfig = $package->getAutoload(); foreach ($autoloadConfig as $type => $autoloads) { $io->write('' . $type . ''); if ($type === 'psr-0' || $type === 'psr-4') { foreach ($autoloads as $name => $path) { $io->write(($name ?: '*') . ' => ' . (\is_array($path) ? \implode(', ', $path) : ($path ?: '.'))); } } elseif ($type === 'classmap') { $io->write(\implode(', ', $autoloadConfig[$type])); } } if ($package->getIncludePaths()) { $io->write('include-path'); $io->write(\implode(', ', $package->getIncludePaths())); } } } /** * Prints all available versions of this package and highlights the installed one if any. * * @param array $versions */ protected function printVersions(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo) : void { $versions = \array_keys($versions); $versions = Semver::rsort($versions); // highlight installed version if ($installedPackages = $installedRepo->findPackages($package->getName())) { foreach ($installedPackages as $installedPackage) { $installedVersion = $installedPackage->getPrettyVersion(); $key = \array_search($installedVersion, $versions); if (\false !== $key) { $versions[$key] = '* ' . $installedVersion . ''; } } } $versions = \implode(', ', $versions); $this->getIO()->write('versions : ' . $versions); } /** * print link objects * * @param string $title */ protected function printLinks(CompletePackageInterface $package, string $linkType, ?string $title = null) : void { $title = $title ?: $linkType; $io = $this->getIO(); if ($links = $package->{'get' . \ucfirst($linkType)}()) { $io->write("\n" . $title . ""); foreach ($links as $link) { $io->write($link->getTarget() . ' ' . $link->getPrettyConstraint() . ''); } } } /** * Prints the licenses of a package with metadata */ protected function printLicenses(CompletePackageInterface $package) : void { $spdxLicenses = new SpdxLicenses(); $licenses = $package->getLicense(); $io = $this->getIO(); foreach ($licenses as $licenseId) { $license = $spdxLicenses->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url if (!$license) { $out = $licenseId; } else { // is license OSI approved? if ($license[1] === \true) { $out = \sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]); } else { $out = \sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]); } } $io->write('license : ' . $out); } } /** * Prints package info in JSON format. * * @param array $versions */ protected function printPackageInfoAsJson(CompletePackageInterface $package, array $versions, InstalledRepository $installedRepo, ?PackageInterface $latestPackage = null) : void { $json = ['name' => $package->getPrettyName(), 'description' => $package->getDescription(), 'keywords' => $package->getKeywords() ?: [], 'type' => $package->getType(), 'homepage' => $package->getHomepage(), 'names' => $package->getNames()]; $json = $this->appendVersions($json, $versions); $json = $this->appendLicenses($json, $package); if ($latestPackage) { $json['latest'] = $latestPackage->getPrettyVersion(); } else { $latestPackage = $package; } if (null !== $package->getSourceType()) { $json['source'] = ['type' => $package->getSourceType(), 'url' => $package->getSourceUrl(), 'reference' => $package->getSourceReference()]; } if (null !== $package->getDistType()) { $json['dist'] = ['type' => $package->getDistType(), 'url' => $package->getDistUrl(), 'reference' => $package->getDistReference()]; } if (!PlatformRepository::isPlatformPackage($package->getName()) && $installedRepo->hasPackage($package)) { $path = $this->requireComposer()->getInstallationManager()->getInstallPath($package); if (\is_string($path)) { $path = \realpath($path); if ($path !== \false) { $json['path'] = $path; } } else { $json['path'] = null; } if ($package->getReleaseDate() !== null) { $json['released'] = $package->getReleaseDate()->format(\DATE_ATOM); } } if ($latestPackage instanceof CompletePackageInterface && $latestPackage->isAbandoned()) { $json['replacement'] = $latestPackage->getReplacementPackage(); } if ($package->getSuggests()) { $json['suggests'] = $package->getSuggests(); } if ($package->getSupport()) { $json['support'] = $package->getSupport(); } $json = $this->appendAutoload($json, $package); if ($package->getIncludePaths()) { $json['include_path'] = $package->getIncludePaths(); } $json = $this->appendLinks($json, $package); $this->getIO()->write(JsonFile::encode($json)); } /** * @param JsonStructure $json * @param array $versions * @return JsonStructure */ private function appendVersions(array $json, array $versions) : array { \uasort($versions, 'version_compare'); $versions = \array_keys(\array_reverse($versions)); $json['versions'] = $versions; return $json; } /** * @param JsonStructure $json * @return JsonStructure */ private function appendLicenses(array $json, CompletePackageInterface $package) : array { if ($licenses = $package->getLicense()) { $spdxLicenses = new SpdxLicenses(); $json['licenses'] = \array_map(static function ($licenseId) use($spdxLicenses) { $license = $spdxLicenses->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url if (!$license) { return $licenseId; } return ['name' => $license[0], 'osi' => $licenseId, 'url' => $license[2]]; }, $licenses); } return $json; } /** * @param JsonStructure $json * @return JsonStructure */ private function appendAutoload(array $json, CompletePackageInterface $package) : array { if (\count($package->getAutoload()) > 0) { $autoload = []; foreach ($package->getAutoload() as $type => $autoloads) { if ($type === 'psr-0' || $type === 'psr-4') { $psr = []; foreach ($autoloads as $name => $path) { if (!$path) { $path = '.'; } $psr[$name ?: '*'] = $path; } $autoload[$type] = $psr; } elseif ($type === 'classmap') { $autoload['classmap'] = $autoloads; } } $json['autoload'] = $autoload; } return $json; } /** * @param JsonStructure $json * @return JsonStructure */ private function appendLinks(array $json, CompletePackageInterface $package) : array { foreach (Link::$TYPES as $linkType) { $json = $this->appendLink($json, $package, $linkType); } return $json; } /** * @param JsonStructure $json * @return JsonStructure */ private function appendLink(array $json, CompletePackageInterface $package, string $linkType) : array { $links = $package->{'get' . \ucfirst($linkType)}(); if ($links) { $json[$linkType] = []; foreach ($links as $link) { $json[$linkType][$link->getTarget()] = $link->getPrettyConstraint(); } } return $json; } /** * Init styles for tree */ protected function initStyles(OutputInterface $output) : void { $this->colors = ['green', 'yellow', 'cyan', 'magenta', 'blue']; foreach ($this->colors as $color) { $style = new OutputFormatterStyle($color); $output->getFormatter()->setStyle($color, $style); } } /** * Display the tree * * @param array> $arrayTree */ protected function displayPackageTree(array $arrayTree) : void { $io = $this->getIO(); foreach ($arrayTree as $package) { $io->write(\sprintf('%s', $package['name']), \false); $io->write(' ' . $package['version'], \false); if (isset($package['description'])) { $io->write(' ' . \strtok($package['description'], "\r\n")); } else { // output newline $io->write(''); } if (isset($package['requires'])) { $requires = $package['requires']; $treeBar = '├'; $j = 0; $total = \count($requires); foreach ($requires as $require) { $requireName = $require['name']; $j++; if ($j === $total) { $treeBar = '└'; } $level = 1; $color = $this->colors[$level]; $info = \sprintf('%s──<%s>%s %s', $treeBar, $color, $requireName, $color, $require['version']); $this->writeTreeLine($info); $treeBar = \str_replace('└', ' ', $treeBar); $packagesInTree = [$package['name'], $requireName]; $this->displayTree($require, $packagesInTree, $treeBar, $level + 1); } } } } /** * Generate the package tree * * @return array>|string|null> */ protected function generatePackageTree(PackageInterface $package, InstalledRepository $installedRepo, RepositoryInterface $remoteRepos) : array { $requires = $package->getRequires(); \ksort($requires); $children = []; foreach ($requires as $requireName => $require) { $packagesInTree = [$package->getName(), $requireName]; $treeChildDesc = ['name' => $requireName, 'version' => $require->getPrettyConstraint()]; $deepChildren = $this->addTree($requireName, $require, $installedRepo, $remoteRepos, $packagesInTree); if ($deepChildren) { $treeChildDesc['requires'] = $deepChildren; } $children[] = $treeChildDesc; } $tree = ['name' => $package->getPrettyName(), 'version' => $package->getPrettyVersion(), 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : '']; if ($children) { $tree['requires'] = $children; } return $tree; } /** * Display a package tree * * @param array>|string|null>|string $package * @param array $packagesInTree */ protected function displayTree($package, array $packagesInTree, string $previousTreeBar = '├', int $level = 1) : void { $previousTreeBar = \str_replace('├', '│', $previousTreeBar); if (\is_array($package) && isset($package['requires'])) { $requires = $package['requires']; $treeBar = $previousTreeBar . ' ├'; $i = 0; $total = \count($requires); foreach ($requires as $require) { $currentTree = $packagesInTree; $i++; if ($i === $total) { $treeBar = $previousTreeBar . ' └'; } $colorIdent = $level % \count($this->colors); $color = $this->colors[$colorIdent]; \assert(\is_string($require['name'])); \assert(\is_string($require['version'])); $circularWarn = \in_array($require['name'], $currentTree, \true) ? '(circular dependency aborted here)' : ''; $info = \rtrim(\sprintf('%s──<%s>%s %s %s', $treeBar, $color, $require['name'], $color, $require['version'], $circularWarn)); $this->writeTreeLine($info); $treeBar = \str_replace('└', ' ', $treeBar); $currentTree[] = $require['name']; $this->displayTree($require, $currentTree, $treeBar, $level + 1); } } } /** * Display a package tree * * @param string[] $packagesInTree * @return array>|string>> */ protected function addTree(string $name, Link $link, InstalledRepository $installedRepo, RepositoryInterface $remoteRepos, array $packagesInTree) : array { $children = []; [$package] = $this->getPackage($installedRepo, $remoteRepos, $name, $link->getPrettyConstraint() === 'self.version' ? $link->getConstraint() : $link->getPrettyConstraint()); if (\is_object($package)) { $requires = $package->getRequires(); \ksort($requires); foreach ($requires as $requireName => $require) { $currentTree = $packagesInTree; $treeChildDesc = ['name' => $requireName, 'version' => $require->getPrettyConstraint()]; if (!\in_array($requireName, $currentTree, \true)) { $currentTree[] = $requireName; $deepChildren = $this->addTree($requireName, $require, $installedRepo, $remoteRepos, $currentTree); if ($deepChildren) { $treeChildDesc['requires'] = $deepChildren; } } $children[] = $treeChildDesc; } } return $children; } private function updateStatusToVersionStyle(string $updateStatus) : string { // 'up-to-date' is printed green // 'semver-safe-update' is printed red // 'update-possible' is printed yellow return \str_replace(['up-to-date', 'semver-safe-update', 'update-possible'], ['info', 'highlight', 'comment'], $updateStatus); } private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package) : string { if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) { return 'up-to-date'; } $constraint = $package->getVersion(); if (0 !== \strpos($constraint, 'dev-')) { $constraint = '^' . $constraint; } if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) { // it needs an immediate semver-compliant upgrade return 'semver-safe-update'; } // it needs an upgrade but has potential BC breaks so is not urgent return 'update-possible'; } private function writeTreeLine(string $line) : void { $io = $this->getIO(); if (!$io->isDecorated()) { $line = \str_replace(['└', '├', '──', '│'], ['`-', '|-', '-', '|'], $line); } $io->write($line); } /** * Given a package, this finds the latest package matching it */ private function findLatestPackage(PackageInterface $package, Composer $composer, PlatformRepository $platformRepo, bool $majorOnly, bool $minorOnly, bool $patchOnly, PlatformRequirementFilterInterface $platformReqFilter) : ?PackageInterface { // find the latest version allowed in this repo set $name = $package->getName(); $versionSelector = new VersionSelector($this->getRepositorySet($composer), $platformRepo); $stability = $composer->getPackage()->getMinimumStability(); $flags = $composer->getPackage()->getStabilityFlags(); if (isset($flags[$name])) { $stability = \array_search($flags[$name], BasePackage::STABILITIES, \true); } $bestStability = $stability; if ($composer->getPackage()->getPreferStable()) { $bestStability = $package->getStability(); } $targetVersion = null; if (0 === \strpos($package->getVersion(), 'dev-')) { $targetVersion = $package->getVersion(); // dev-x branches are considered to be on the latest major version always, do not look up for a new commit as that is deemed a minor upgrade (albeit risky) if ($majorOnly) { return null; } } if ($targetVersion === null) { if ($majorOnly && Preg::isMatch('{^(?P(?:0\\.)+)?(?P\\d+)\\.}', $package->getVersion(), $match)) { $targetVersion = '>=' . $match['zero_major'] . ((int) $match['first_meaningful'] + 1) . ',<9999999-dev'; } if ($minorOnly) { $targetVersion = '^' . $package->getVersion(); } if ($patchOnly) { $trimmedVersion = Preg::replace('{(\\.0)+$}D', '', $package->getVersion()); $partsNeeded = \substr($trimmedVersion, 0, 1) === '0' ? 4 : 3; while (\substr_count($trimmedVersion, '.') + 1 < $partsNeeded) { $trimmedVersion .= '.0'; } $targetVersion = '~' . $trimmedVersion; } } if ($this->getIO()->isVerbose()) { $showWarnings = \true; } else { $showWarnings = static function (PackageInterface $candidate) use($package) : bool { if (\str_starts_with($candidate->getVersion(), 'dev-') || \str_starts_with($package->getVersion(), 'dev-')) { return \false; } return \version_compare($candidate->getVersion(), $package->getVersion(), '<='); }; } $candidate = $versionSelector->findBestCandidate($name, $targetVersion, $bestStability, $platformReqFilter, 0, $this->getIO(), $showWarnings); while ($candidate instanceof AliasPackage) { $candidate = $candidate->getAliasOf(); } return $candidate !== \false ? $candidate : null; } private function getRepositorySet(Composer $composer) : RepositorySet { if (!$this->repositorySet) { $this->repositorySet = new RepositorySet($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags()); $this->repositorySet->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories())); } return $this->repositorySet; } private function getRelativeTime(\DateTimeInterface $releaseDate) : string { if ($releaseDate->format('Ymd') === \date('Ymd')) { return 'today'; } $diff = $releaseDate->diff(new \DateTimeImmutable()); if ($diff->days < 7) { return 'this week'; } if ($diff->days < 14) { return 'last week'; } if ($diff->m < 1 && $diff->days < 31) { return \floor($diff->days / 7) . ' weeks ago'; } if ($diff->y < 1) { return $diff->m . ' month' . ($diff->m > 1 ? 's' : '') . ' ago'; } return $diff->y . ' year' . ($diff->y > 1 ? 's' : '') . ' ago'; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Installer; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Advisory\Auditor; use Composer\Util\HttpDownloader; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano * @author Ryan Weaver * @author Konstantin Kudryashov * @author Nils Adermann */ class InstallCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; /** * @return void */ protected function configure() { $this->setName('install')->setAliases(['i'])->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json')->setDefinition([new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('download-only', null, InputOption::VALUE_NONE, 'Download only, do not install packages.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'DEPRECATED: Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Do not use, only defined here to catch misuse of the install command.'), new InputOption('audit', null, InputOption::VALUE_NONE, 'Run an audit after installation is complete.'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.')])->setHelp(<<install command reads the composer.lock file from the current directory, processes it, and downloads and installs all the libraries and dependencies outlined in that file. If the file does not exist it will look for composer.json and do the same. php composer.phar install Read more at https://getcomposer.org/doc/03-cli.md#install-i EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $io = $this->getIO(); if ($input->getOption('dev')) { $io->writeError('You are using the deprecated option "--dev". It has no effect and will break in Composer 3.'); } if ($input->getOption('no-suggest')) { $io->writeError('You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.'); } $args = $input->getArgument('packages'); if (\count($args) > 0) { $io->writeError('Invalid argument ' . \implode(' ', $args) . '. Use "composer require ' . \implode(' ', $args) . '" instead to add packages to your composer.json.'); return 1; } if ($input->getOption('no-install')) { $io->writeError('Invalid option "--no-install". Use "composer update --no-install" instead if you are trying to update the composer.lock file.'); return 1; } $composer = $this->requireComposer(); if (!$composer->getLocker()->isLocked() && !HttpDownloader::isCurlEnabled()) { $io->writeError('Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled.'); } $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $install = Installer::create($io, $composer); $config = $composer->getConfig(); [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input); $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); $apcuPrefix = $input->getOption('apcu-autoloader-prefix'); $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader'); $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress')); $install->setDryRun($input->getOption('dry-run'))->setDownloadOnly($input->getOption('download-only'))->setVerbose($input->getOption('verbose'))->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode(!$input->getOption('no-dev'))->setDumpAutoloader(!$input->getOption('no-autoloader'))->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setAudit($input->getOption('audit'))->setErrorOnAudit($input->getOption('audit'))->setAuditFormat($this->getAuditFormat($input)); if ($input->getOption('no-plugins')) { $install->disablePlugins(); } return $install->run(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Factory; use Composer\Json\JsonFile; use Composer\Json\JsonValidationException; use Composer\Package\BasePackage; use Composer\Package\Package; use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryFactory; use Composer\Spdx\SpdxLicenses; use Composer\Util\Filesystem; use Composer\Util\Silencer; use _ContaoManager\Symfony\Component\Console\Input\ArrayInput; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Util\ProcessExecutor; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Process\ExecutableFinder; use _ContaoManager\Symfony\Component\Process\Process; use _ContaoManager\Symfony\Component\Console\Helper\FormatterHelper; /** * @author Justin Rainbow * @author Jordi Boggiano */ class InitCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; use \Composer\Command\PackageDiscoveryTrait; /** @var array */ private $gitConfig; /** * @inheritDoc * * @return void */ protected function configure() { $this->setName('init')->setDescription('Creates a basic composer.json file in current directory')->setDefinition([new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'), new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'), new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'), new InputOption('type', null, InputOption::VALUE_REQUIRED, 'Type of package (e.g. library, project, metapackage, composer-plugin)'), new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'), new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()), new InputOption('require-dev', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require for development with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()), new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: ' . \implode(', ', \array_keys(BasePackage::STABILITIES)) . ')'), new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'), new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'), new InputOption('autoload', 'a', InputOption::VALUE_REQUIRED, 'Add PSR-4 autoload mapping. Maps your package\'s namespace to the provided directory. (Expects a relative path, e.g. src/)')])->setHelp(<<init command creates a basic composer.json file in the current directory. php composer.phar init Read more at https://getcomposer.org/doc/03-cli.md#init EOT ); } /** * @throws \Seld\JsonLint\ParsingException */ protected function execute(InputInterface $input, OutputInterface $output) : int { $io = $this->getIO(); $allowlist = ['name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license', 'autoload']; $options = \array_filter(\array_intersect_key($input->getOptions(), \array_flip($allowlist)), function ($val) { return $val !== null && $val !== []; }); if (isset($options['name']) && !Preg::isMatch('{^[a-z0-9]([_.-]?[a-z0-9]+)*\\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$}D', $options['name'])) { throw new \InvalidArgumentException('The package name ' . $options['name'] . ' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'); } if (isset($options['author'])) { $options['authors'] = $this->formatAuthors($options['author']); unset($options['author']); } $repositories = $input->getOption('repository'); if (\count($repositories) > 0) { $config = Factory::createConfig($io); foreach ($repositories as $repo) { $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo, \true); } } if (isset($options['stability'])) { $options['minimum-stability'] = $options['stability']; unset($options['stability']); } $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass(); if ([] === $options['require']) { $options['require'] = new \stdClass(); } if (isset($options['require-dev'])) { $options['require-dev'] = $this->formatRequirements($options['require-dev']); if ([] === $options['require-dev']) { $options['require-dev'] = new \stdClass(); } } // --autoload - create autoload object $autoloadPath = null; if (isset($options['autoload'])) { $autoloadPath = $options['autoload']; $namespace = $this->namespaceFromPackageName((string) $input->getOption('name')); $options['autoload'] = (object) ['psr-4' => [$namespace . '\\' => $autoloadPath]]; } $file = new JsonFile(Factory::getComposerFile()); $json = JsonFile::encode($options); if ($input->isInteractive()) { $io->writeError(['', $json, '']); if (!$io->askConfirmation('Do you confirm generation [yes]? ')) { $io->writeError('Command aborted'); return 1; } } else { if (\json_encode($options) === '{"require":{}}') { throw new \RuntimeException('You have to run this command in interactive mode, or specify at least some data using --name, --require, etc.'); } $io->writeError('Writing ' . $file->getPath()); } $file->write($options); try { $file->validateSchema(JsonFile::LAX_SCHEMA); } catch (JsonValidationException $e) { $io->writeError('Schema validation error, aborting'); $errors = ' - ' . \implode(\PHP_EOL . ' - ', $e->getErrors()); $io->writeError($e->getMessage() . ':' . \PHP_EOL . $errors); Silencer::call('unlink', $file->getPath()); return 1; } // --autoload - Create src folder if ($autoloadPath) { $filesystem = new Filesystem(); $filesystem->ensureDirectoryExists($autoloadPath); // dump-autoload only for projects without added dependencies. if (!$this->hasDependencies($options)) { $this->runDumpAutoloadCommand($output); } } if ($input->isInteractive() && \is_dir('.git')) { $ignoreFile = \realpath('.gitignore'); if (\false === $ignoreFile) { $ignoreFile = \realpath('.') . '/.gitignore'; } if (!$this->hasVendorIgnore($ignoreFile)) { $question = 'Would you like the vendor directory added to your .gitignore [yes]? '; if ($io->askConfirmation($question)) { $this->addVendorIgnore($ignoreFile); } } } $question = 'Would you like to install dependencies now [yes]? '; if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question)) { $this->updateDependencies($output); } // --autoload - Show post-install configuration info if ($autoloadPath) { $namespace = $this->namespaceFromPackageName((string) $input->getOption('name')); $io->writeError('PSR-4 autoloading configured. Use "namespace ' . $namespace . ';" in ' . $autoloadPath); $io->writeError('Include the Composer autoloader with: require \'vendor/autoload.php\';'); } return 0; } /** * @inheritDoc * * @return void */ protected function interact(InputInterface $input, OutputInterface $output) { $git = $this->getGitConfig(); $io = $this->getIO(); /** @var FormatterHelper $formatter */ $formatter = $this->getHelperSet()->get('formatter'); // initialize repos if configured $repositories = $input->getOption('repository'); if (\count($repositories) > 0) { $config = Factory::createConfig($io); $io->loadConfiguration($config); $repoManager = RepositoryFactory::manager($io, $config); $repos = [new PlatformRepository()]; $createDefaultPackagistRepo = \true; foreach ($repositories as $repo) { $repoConfig = RepositoryFactory::configFromString($io, $config, $repo, \true); if (isset($repoConfig['packagist']) && $repoConfig === ['packagist' => \false] || isset($repoConfig['packagist.org']) && $repoConfig === ['packagist.org' => \false]) { $createDefaultPackagistRepo = \false; continue; } $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig, $repoManager); } if ($createDefaultPackagistRepo) { $repos[] = RepositoryFactory::createRepo($io, $config, ['type' => 'composer', 'url' => 'https://repo.packagist.org'], $repoManager); } $this->repos = new CompositeRepository($repos); unset($repos, $config, $repositories); } $io->writeError(['', $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', \true), '']); // namespace $io->writeError(['', 'This command will guide you through creating your composer.json config.', '']); $cwd = \realpath("."); $name = $input->getOption('name'); if (null === $name) { $name = \basename($cwd); $name = $this->sanitizePackageNameComponent($name); $vendor = $name; if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) { $vendor = $_SERVER['COMPOSER_DEFAULT_VENDOR']; } elseif (isset($git['github.user'])) { $vendor = $git['github.user']; } elseif (!empty($_SERVER['USERNAME'])) { $vendor = $_SERVER['USERNAME']; } elseif (!empty($_SERVER['USER'])) { $vendor = $_SERVER['USER']; } elseif (\get_current_user()) { $vendor = \get_current_user(); } $vendor = $this->sanitizePackageNameComponent($vendor); $name = $vendor . '/' . $name; } $name = $io->askAndValidate('Package name (/) [' . $name . ']: ', static function ($value) use($name) { if (null === $value) { return $name; } if (!Preg::isMatch('{^[a-z0-9]([_.-]?[a-z0-9]+)*\\/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$}D', $value)) { throw new \InvalidArgumentException('The package name ' . $value . ' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'); } return $value; }, null, $name); $input->setOption('name', $name); $description = $input->getOption('description') ?: null; $description = $io->ask('Description [' . $description . ']: ', $description); $input->setOption('description', $description); if (null === ($author = $input->getOption('author'))) { if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) { $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR']; } elseif (isset($git['user.name'])) { $author_name = $git['user.name']; } if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) { $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL']; } elseif (isset($git['user.email'])) { $author_email = $git['user.email']; } if (isset($author_name, $author_email)) { $author = \sprintf('%s <%s>', $author_name, $author_email); } } $author = $io->askAndValidate('Author [' . (\is_string($author) ? '' . $author . ', ' : '') . 'n to skip]: ', function ($value) use($author) { if ($value === 'n' || $value === 'no') { return; } $value = $value ?: $author; $author = $this->parseAuthorString($value ?? ''); if ($author['email'] === null) { return $author['name']; } return \sprintf('%s <%s>', $author['name'], $author['email']); }, null, $author); $input->setOption('author', $author); $minimumStability = $input->getOption('stability') ?: null; $minimumStability = $io->askAndValidate('Minimum Stability [' . $minimumStability . ']: ', static function ($value) use($minimumStability) { if (null === $value) { return $minimumStability; } if (!isset(BasePackage::STABILITIES[$value])) { throw new \InvalidArgumentException('Invalid minimum stability "' . $value . '". Must be empty or one of: ' . \implode(', ', \array_keys(BasePackage::STABILITIES))); } return $value; }, null, $minimumStability); $input->setOption('stability', $minimumStability); $type = $input->getOption('type'); $type = $io->ask('Package Type (e.g. library, project, metapackage, composer-plugin) [' . $type . ']: ', $type); if ($type === '' || $type === \false) { $type = null; } $input->setOption('type', $type); if (null === ($license = $input->getOption('license'))) { if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) { $license = $_SERVER['COMPOSER_DEFAULT_LICENSE']; } } $license = $io->ask('License [' . $license . ']: ', $license); $spdx = new SpdxLicenses(); if (null !== $license && !$spdx->validate($license) && $license !== 'proprietary') { throw new \InvalidArgumentException('Invalid license provided: ' . $license . '. Only SPDX license identifiers (https://spdx.org/licenses/) or "proprietary" are accepted.'); } $input->setOption('license', $license); $io->writeError(['', 'Define your dependencies.', '']); // prepare to resolve dependencies $repos = $this->getRepos(); $preferredStability = $minimumStability ?: 'stable'; $platformRepo = null; if ($repos instanceof CompositeRepository) { foreach ($repos->getRepositories() as $candidateRepo) { if ($candidateRepo instanceof PlatformRepository) { $platformRepo = $candidateRepo; break; } } } $question = 'Would you like to define your dependencies (require) interactively [yes]? '; $require = $input->getOption('require'); $requirements = []; if (\count($require) > 0 || $io->askConfirmation($question)) { $requirements = $this->determineRequirements($input, $output, $require, $platformRepo, $preferredStability); } $input->setOption('require', $requirements); $question = 'Would you like to define your dev dependencies (require-dev) interactively [yes]? '; $requireDev = $input->getOption('require-dev'); $devRequirements = []; if (\count($requireDev) > 0 || $io->askConfirmation($question)) { $devRequirements = $this->determineRequirements($input, $output, $requireDev, $platformRepo, $preferredStability); } $input->setOption('require-dev', $devRequirements); // --autoload - input and validation $autoload = $input->getOption('autoload') ?: 'src/'; $namespace = $this->namespaceFromPackageName((string) $input->getOption('name')); $autoload = $io->askAndValidate('Add PSR-4 autoload mapping? Maps namespace "' . $namespace . '" to the entered relative path. [' . $autoload . ', n to skip]: ', static function ($value) use($autoload) { if (null === $value) { return $autoload; } if ($value === 'n' || $value === 'no') { return; } $value = $value ?: $autoload; if (!Preg::isMatch('{^[^/][A-Za-z0-9\\-_/]+/$}', $value)) { throw new \InvalidArgumentException(\sprintf('The src folder name "%s" is invalid. Please add a relative path with tailing forward slash. [A-Za-z0-9_-/]+/', $value)); } return $value; }, null, $autoload); $input->setOption('autoload', $autoload); } /** * @return array{name: string, email: string|null} */ private function parseAuthorString(string $author) : array { if (Preg::isMatch('/^(?P[- .,\\p{L}\\p{N}\\p{Mn}\'’"()]+)(?:\\s+<(?P.+?)>)?$/u', $author, $match)) { if (null !== $match['email'] && !$this->isValidEmail($match['email'])) { throw new \InvalidArgumentException('Invalid email "' . $match['email'] . '"'); } return ['name' => \trim($match['name']), 'email' => $match['email']]; } throw new \InvalidArgumentException('Invalid author string. Must be in the formats: ' . 'Jane Doe or John Smith '); } /** * @return array */ protected function formatAuthors(string $author) : array { $author = $this->parseAuthorString($author); if (null === $author['email']) { unset($author['email']); } return [$author]; } /** * Extract namespace from package's vendor name. * * new_projects.acme-extra/package-name becomes "NewProjectsAcmeExtra\PackageName" */ public function namespaceFromPackageName(string $packageName) : ?string { if (!$packageName || \strpos($packageName, '/') === \false) { return null; } $namespace = \array_map(static function ($part) : string { $part = Preg::replace('/[^a-z0-9]/i', ' ', $part); $part = \ucwords($part); return \str_replace(' ', '', $part); }, \explode('/', $packageName)); return \implode('\\', $namespace); } /** * @return array */ protected function getGitConfig() : array { if (null !== $this->gitConfig) { return $this->gitConfig; } $process = new ProcessExecutor($this->getIO()); if (0 === $process->execute(['git', 'config', '-l'], $output)) { $this->gitConfig = []; Preg::matchAllStrictGroups('{^([^=]+)=(.*)$}m', $output, $matches); foreach ($matches[1] as $key => $match) { $this->gitConfig[$match] = $matches[2][$key]; } return $this->gitConfig; } return $this->gitConfig = []; } /** * Checks the local .gitignore file for the Composer vendor directory. * * Tested patterns include: * "/$vendor" * "$vendor" * "$vendor/" * "/$vendor/" * "/$vendor/*" * "$vendor/*" */ protected function hasVendorIgnore(string $ignoreFile, string $vendor = 'vendor') : bool { if (!\file_exists($ignoreFile)) { return \false; } $pattern = \sprintf('{^/?%s(/\\*?)?$}', \preg_quote($vendor)); $lines = \file($ignoreFile, \FILE_IGNORE_NEW_LINES); foreach ($lines as $line) { if (Preg::isMatch($pattern, $line)) { return \true; } } return \false; } protected function addVendorIgnore(string $ignoreFile, string $vendor = '/vendor/') : void { $contents = ""; if (\file_exists($ignoreFile)) { $contents = \file_get_contents($ignoreFile); if (\strpos($contents, "\n") !== 0) { $contents .= "\n"; } } \file_put_contents($ignoreFile, $contents . $vendor . "\n"); } protected function isValidEmail(string $email) : bool { // assume it's valid if we can't validate it if (!\function_exists('filter_var')) { return \true; } return \false !== \filter_var($email, \FILTER_VALIDATE_EMAIL); } private function updateDependencies(OutputInterface $output) : void { try { $updateCommand = $this->getApplication()->find('update'); $this->getApplication()->resetComposer(); $updateCommand->run(new ArrayInput([]), $output); } catch (\Exception $e) { $this->getIO()->writeError('Could not update dependencies. Run `composer update` to see more information.'); } } private function runDumpAutoloadCommand(OutputInterface $output) : void { try { $command = $this->getApplication()->find('dump-autoload'); $this->getApplication()->resetComposer(); $command->run(new ArrayInput([]), $output); } catch (\Exception $e) { $this->getIO()->writeError('Could not run dump-autoload.'); } } /** * @param array> $options */ private function hasDependencies(array $options) : bool { $requires = (array) $options['require']; $devRequires = isset($options['require-dev']) ? (array) $options['require-dev'] : []; return !empty($requires) || !empty($devRequires); } private function sanitizePackageNameComponent(string $name) : string { $name = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '_ContaoManager\\1\\3-\\2\\4', $name); $name = \strtolower($name); $name = Preg::replace('{^[_.-]+|[_.-]+$|[^a-z0-9_.-]}u', '', $name); $name = Preg::replace('{([_.-]){2,}}u', '$1', $name); return $name; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Script\Event as ScriptEvent; use Composer\Script\ScriptEvents; use Composer\Util\ProcessExecutor; use Composer\Util\Platform; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Fabien Potencier */ class RunScriptCommand extends \Composer\Command\BaseCommand { /** * @var string[] Array with command events */ protected $scriptEvents = [ScriptEvents::PRE_INSTALL_CMD, ScriptEvents::POST_INSTALL_CMD, ScriptEvents::PRE_UPDATE_CMD, ScriptEvents::POST_UPDATE_CMD, ScriptEvents::PRE_STATUS_CMD, ScriptEvents::POST_STATUS_CMD, ScriptEvents::POST_ROOT_PACKAGE_INSTALL, ScriptEvents::POST_CREATE_PROJECT_CMD, ScriptEvents::PRE_ARCHIVE_CMD, ScriptEvents::POST_ARCHIVE_CMD, ScriptEvents::PRE_AUTOLOAD_DUMP, ScriptEvents::POST_AUTOLOAD_DUMP]; protected function configure() : void { $this->setName('run-script')->setAliases(['run'])->setDescription('Runs the scripts defined in composer.json')->setDefinition([new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.', null, function () { return \array_map(static function ($script) { return $script['name']; }, $this->getScripts()); }), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''), new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'), new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.')])->setHelp(<<run-script command runs scripts defined in composer.json: php composer.phar run-script post-update-cmd Read more at https://getcomposer.org/doc/03-cli.md#run-script-run EOT ); } protected function interact(InputInterface $input, OutputInterface $output) : void { $scripts = $this->getScripts(); if (\count($scripts) === 0) { return; } if ($input->getArgument('script') !== null || $input->getOption('list')) { return; } $options = []; foreach ($scripts as $script) { $options[$script['name']] = $script['description']; } $io = $this->getIO(); $script = $io->select('Script to run: ', $options, '', 1, 'Invalid script name "%s"'); $input->setArgument('script', $script); } protected function execute(InputInterface $input, OutputInterface $output) : int { if ($input->getOption('list')) { return $this->listScripts($output); } $script = $input->getArgument('script'); if ($script === null) { throw new \RuntimeException('Missing required argument "script"'); } if (!\in_array($script, $this->scriptEvents)) { if (\defined('Composer\\Script\\ScriptEvents::' . \str_replace('-', '_', \strtoupper($script)))) { throw new \InvalidArgumentException(\sprintf('Script "%s" cannot be run with this command', $script)); } } $composer = $this->requireComposer(); $devMode = $input->getOption('dev') || !$input->getOption('no-dev'); $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode); $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event); if (!$hasListeners) { throw new \InvalidArgumentException(\sprintf('Script "%s" is not defined in this package', $script)); } $args = $input->getArgument('args'); if (null !== ($timeout = $input->getOption('timeout'))) { if (!\ctype_digit($timeout)) { throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever'); } // Override global timeout set before in Composer by environment or config ProcessExecutor::setTimeout((int) $timeout); } Platform::putEnv('COMPOSER_DEV_MODE', $devMode ? '1' : '0'); return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args); } protected function listScripts(OutputInterface $output) : int { $scripts = $this->getScripts(); if (\count($scripts) === 0) { return 0; } $io = $this->getIO(); $io->writeError('scripts:'); $table = []; foreach ($scripts as $script) { $table[] = [' ' . $script['name'], $script['description']]; } $this->renderTable($table, $output); return 0; } /** * @return list */ private function getScripts() : array { $scripts = $this->requireComposer()->getPackage()->getScripts(); if (\count($scripts) === 0) { return []; } $result = []; foreach ($scripts as $name => $script) { $description = ''; try { $cmd = $this->getApplication()->find($name); if ($cmd instanceof \Composer\Command\ScriptAliasCommand) { $description = $cmd->getDescription(); } } catch (\_ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException $e) { // ignore scripts that have no command associated, like native Composer script listeners } $result[] = ['name' => $name, 'description' => $description]; } return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Advisory\Auditor; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\Silencer; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput; use _ContaoManager\Symfony\Component\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Config; use Composer\Config\JsonConfigSource; use Composer\Factory; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Semver\VersionParser; use Composer\Package\BasePackage; /** * @author Joshua Estes * @author Jordi Boggiano */ class ConfigCommand extends \Composer\Command\BaseCommand { /** * List of additional configurable package-properties * * @var string[] */ protected const CONFIGURABLE_PACKAGE_PROPERTIES = ['name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'repositories', 'suggest', 'extra']; /** * @var Config */ protected $config; /** * @var JsonFile */ protected $configFile; /** * @var JsonConfigSource */ protected $configSource; /** * @var JsonFile */ protected $authConfigFile; /** * @var JsonConfigSource */ protected $authConfigSource; protected function configure() : void { $this->setName('config')->setDescription('Sets config options')->setDefinition([new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'), new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'), new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'), new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'), new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'), new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'), new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'), new InputOption('json', 'j', InputOption::VALUE_NONE, 'JSON decode the setting value, to be used with extra.* keys'), new InputOption('merge', 'm', InputOption::VALUE_NONE, 'Merge the setting value with the current value, to be used with extra.* keys in combination with --json'), new InputOption('append', null, InputOption::VALUE_NONE, 'When adding a repository, append it (lowest priority) to the existing ones instead of prepending it (highest priority)'), new InputOption('source', null, InputOption::VALUE_NONE, 'Display where the config value is loaded from'), new InputArgument('setting-key', null, 'Setting key', null, $this->suggestSettingKeys()), new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value')])->setHelp(<<%command.full_name% bin-dir bin/ To read a config setting: %command.full_name% bin-dir Outputs: bin To edit the global config.json file: %command.full_name% --global To add a repository: %command.full_name% repositories.foo vcs https://bar.com To remove a repository (repo is a short alias for repositories): %command.full_name% --unset repo.foo To disable packagist: %command.full_name% repo.packagist false You can alter repositories in the global config.json file by passing in the --global option. To add or edit suggested packages you can use: %command.full_name% suggest.package reason for the suggestion To add or edit extra properties you can use: %command.full_name% extra.property value Or to add a complex value you can use json with: %command.full_name% extra.property --json '{"foo":true, "bar": []}' To edit the file in an external editor: %command.full_name% --editor To choose your editor you can set the "EDITOR" env variable. To get a list of configuration values in the file: %command.full_name% --list You can always pass more than one option. As an example, if you want to edit the global config.json file. %command.full_name% --editor --global Read more at https://getcomposer.org/doc/03-cli.md#config EOT ); } /** * @throws \Exception */ protected function initialize(InputInterface $input, OutputInterface $output) : void { parent::initialize($input, $output); if ($input->getOption('global') && null !== $input->getOption('file')) { throw new \RuntimeException('--file and --global can not be combined'); } $io = $this->getIO(); $this->config = Factory::createConfig($io); $configFile = $this->getComposerConfigFile($input, $this->config); // Create global composer.json if this was invoked using `composer global config` if (($configFile === 'composer.json' || $configFile === './composer.json') && !\file_exists($configFile) && \realpath(Platform::getCwd()) === \realpath($this->config->get('home'))) { \file_put_contents($configFile, "{\n}\n"); } $this->configFile = new JsonFile($configFile, null, $io); $this->configSource = new JsonConfigSource($this->configFile); $authConfigFile = $this->getAuthConfigFile($input, $this->config); $this->authConfigFile = new JsonFile($authConfigFile, null, $io); $this->authConfigSource = new JsonConfigSource($this->authConfigFile, \true); // Initialize the global file if it's not there, ignoring any warnings or notices if ($input->getOption('global') && !$this->configFile->exists()) { \touch($this->configFile->getPath()); $this->configFile->write(['config' => new \ArrayObject()]); Silencer::call('chmod', $this->configFile->getPath(), 0600); } if ($input->getOption('global') && !$this->authConfigFile->exists()) { \touch($this->authConfigFile->getPath()); $this->authConfigFile->write(['bitbucket-oauth' => new \ArrayObject(), 'github-oauth' => new \ArrayObject(), 'gitlab-oauth' => new \ArrayObject(), 'gitlab-token' => new \ArrayObject(), 'http-basic' => new \ArrayObject(), 'bearer' => new \ArrayObject()]); Silencer::call('chmod', $this->authConfigFile->getPath(), 0600); } if (!$this->configFile->exists()) { throw new \RuntimeException(\sprintf('File "%s" cannot be found in the current directory', $configFile)); } } /** * @throws \Seld\JsonLint\ParsingException */ protected function execute(InputInterface $input, OutputInterface $output) : int { // Open file in editor if (\true === $input->getOption('editor')) { $editor = Platform::getEnv('EDITOR'); if (\false === $editor || '' === $editor) { if (Platform::isWindows()) { $editor = 'notepad'; } else { foreach (['editor', 'vim', 'vi', 'nano', 'pico', 'ed'] as $candidate) { if (\exec('which ' . $candidate)) { $editor = $candidate; break; } } } } else { $editor = \escapeshellcmd($editor); } $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath(); \system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`')); return 0; } if (\false === $input->getOption('global')) { $this->config->merge($this->configFile->read(), $this->configFile->getPath()); $this->config->merge(['config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : []], $this->authConfigFile->getPath()); } $this->getIO()->loadConfiguration($this->config); // List the configuration of the file settings if (\true === $input->getOption('list')) { $this->listConfiguration($this->config->all(), $this->config->raw(), $output, null, $input->getOption('source')); return 0; } $settingKey = $input->getArgument('setting-key'); if (!\is_string($settingKey)) { return 0; } // If the user enters in a config variable, parse it and save to file if ([] !== $input->getArgument('setting-value') && $input->getOption('unset')) { throw new \RuntimeException('You can not combine a setting value with --unset'); } // show the value if no value is provided if ([] === $input->getArgument('setting-value') && !$input->getOption('unset')) { $properties = self::CONFIGURABLE_PACKAGE_PROPERTIES; $propertiesDefaults = ['type' => 'library', 'description' => '', 'homepage' => '', 'minimum-stability' => 'stable', 'prefer-stable' => \false, 'keywords' => [], 'license' => [], 'suggest' => [], 'extra' => []]; $rawData = $this->configFile->read(); $data = $this->config->all(); $source = $this->config->getSourceOfValue($settingKey); if (Preg::isMatch('/^repos?(?:itories)?(?:\\.(.+))?/', $settingKey, $matches)) { if (!isset($matches[1])) { $value = $data['repositories'] ?? []; } else { if (!isset($data['repositories'][$matches[1]])) { throw new \InvalidArgumentException('There is no ' . $matches[1] . ' repository defined'); } $value = $data['repositories'][$matches[1]]; } } elseif (\strpos($settingKey, '.')) { $bits = \explode('.', $settingKey); if ($bits[0] === 'extra' || $bits[0] === 'suggest') { $data = $rawData; } else { $data = $data['config']; } $match = \false; foreach ($bits as $bit) { $key = isset($key) ? $key . '.' . $bit : $bit; $match = \false; if (isset($data[$key])) { $match = \true; $data = $data[$key]; unset($key); } } if (!$match) { throw new \RuntimeException($settingKey . ' is not defined.'); } $value = $data; } elseif (isset($data['config'][$settingKey])) { $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS); // ensure we get {} output for properties which are objects if ($value === []) { $schema = JsonFile::parseJson((string) \file_get_contents(JsonFile::COMPOSER_SCHEMA_PATH)); if (isset($schema['properties']['config']['properties'][$settingKey]['type']) && \in_array('object', (array) $schema['properties']['config']['properties'][$settingKey]['type'], \true)) { $value = new \stdClass(); } } } elseif (isset($rawData[$settingKey]) && \in_array($settingKey, $properties, \true)) { $value = $rawData[$settingKey]; $source = $this->configFile->getPath(); } elseif (isset($propertiesDefaults[$settingKey])) { $value = $propertiesDefaults[$settingKey]; $source = 'defaults'; } else { throw new \RuntimeException($settingKey . ' is not defined'); } if (\is_array($value) || \is_object($value) || \is_bool($value)) { $value = JsonFile::encode($value, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); } $sourceOfConfigValue = ''; if ($input->getOption('source')) { $sourceOfConfigValue = ' (' . $source . ')'; } $this->getIO()->write($value . $sourceOfConfigValue, \true, IOInterface::QUIET); return 0; } $values = $input->getArgument('setting-value'); // what the user is trying to add/change $booleanValidator = static function ($val) : bool { return \in_array($val, ['true', 'false', '1', '0'], \true); }; $booleanNormalizer = static function ($val) : bool { return $val !== 'false' && (bool) $val; }; // handle config values $uniqueConfigValues = ['process-timeout' => ['is_numeric', 'intval'], 'use-include-path' => [$booleanValidator, $booleanNormalizer], 'use-github-api' => [$booleanValidator, $booleanNormalizer], 'preferred-install' => [static function ($val) : bool { return \in_array($val, ['auto', 'source', 'dist'], \true); }, static function ($val) { return $val; }], 'gitlab-protocol' => [static function ($val) : bool { return \in_array($val, ['git', 'http', 'https'], \true); }, static function ($val) { return $val; }], 'store-auths' => [static function ($val) : bool { return \in_array($val, ['true', 'false', 'prompt'], \true); }, static function ($val) { if ('prompt' === $val) { return 'prompt'; } return $val !== 'false' && (bool) $val; }], 'notify-on-install' => [$booleanValidator, $booleanNormalizer], 'vendor-dir' => ['is_string', static function ($val) { return $val; }], 'bin-dir' => ['is_string', static function ($val) { return $val; }], 'archive-dir' => ['is_string', static function ($val) { return $val; }], 'archive-format' => ['is_string', static function ($val) { return $val; }], 'data-dir' => ['is_string', static function ($val) { return $val; }], 'cache-dir' => ['is_string', static function ($val) { return $val; }], 'cache-files-dir' => ['is_string', static function ($val) { return $val; }], 'cache-repo-dir' => ['is_string', static function ($val) { return $val; }], 'cache-vcs-dir' => ['is_string', static function ($val) { return $val; }], 'cache-ttl' => ['is_numeric', 'intval'], 'cache-files-ttl' => ['is_numeric', 'intval'], 'cache-files-maxsize' => [static function ($val) : bool { return Preg::isMatch('/^\\s*([0-9.]+)\\s*(?:([kmg])(?:i?b)?)?\\s*$/i', $val); }, static function ($val) { return $val; }], 'bin-compat' => [static function ($val) : bool { return \in_array($val, ['auto', 'full', 'proxy', 'symlink']); }, static function ($val) { return $val; }], 'discard-changes' => [static function ($val) : bool { return \in_array($val, ['stash', 'true', 'false', '1', '0'], \true); }, static function ($val) { if ('stash' === $val) { return 'stash'; } return $val !== 'false' && (bool) $val; }], 'autoloader-suffix' => ['is_string', static function ($val) { return $val === 'null' ? null : $val; }], 'sort-packages' => [$booleanValidator, $booleanNormalizer], 'optimize-autoloader' => [$booleanValidator, $booleanNormalizer], 'classmap-authoritative' => [$booleanValidator, $booleanNormalizer], 'apcu-autoloader' => [$booleanValidator, $booleanNormalizer], 'prepend-autoloader' => [$booleanValidator, $booleanNormalizer], 'disable-tls' => [$booleanValidator, $booleanNormalizer], 'secure-http' => [$booleanValidator, $booleanNormalizer], 'bump-after-update' => [static function ($val) : bool { return \in_array($val, ['dev', 'no-dev', 'true', 'false', '1', '0'], \true); }, static function ($val) { if ('dev' === $val || 'no-dev' === $val) { return $val; } return $val !== 'false' && (bool) $val; }], 'cafile' => [static function ($val) : bool { return \file_exists($val) && Filesystem::isReadable($val); }, static function ($val) { return $val === 'null' ? null : $val; }], 'capath' => [static function ($val) : bool { return \is_dir($val) && Filesystem::isReadable($val); }, static function ($val) { return $val === 'null' ? null : $val; }], 'github-expose-hostname' => [$booleanValidator, $booleanNormalizer], 'htaccess-protect' => [$booleanValidator, $booleanNormalizer], 'lock' => [$booleanValidator, $booleanNormalizer], 'allow-plugins' => [$booleanValidator, $booleanNormalizer], 'platform-check' => [static function ($val) : bool { return \in_array($val, ['php-only', 'true', 'false', '1', '0'], \true); }, static function ($val) { if ('php-only' === $val) { return 'php-only'; } return $val !== 'false' && (bool) $val; }], 'use-parent-dir' => [static function ($val) : bool { return \in_array($val, ['true', 'false', 'prompt'], \true); }, static function ($val) { if ('prompt' === $val) { return 'prompt'; } return $val !== 'false' && (bool) $val; }], 'audit.abandoned' => [static function ($val) : bool { return \in_array($val, [Auditor::ABANDONED_IGNORE, Auditor::ABANDONED_REPORT, Auditor::ABANDONED_FAIL], \true); }, static function ($val) { return $val; }]]; $multiConfigValues = ['github-protocols' => [static function ($vals) { if (!\is_array($vals)) { return 'array expected'; } foreach ($vals as $val) { if (!\in_array($val, ['git', 'https', 'ssh'])) { return 'valid protocols include: git, https, ssh'; } } return \true; }, static function ($vals) { return $vals; }], 'github-domains' => [static function ($vals) { if (!\is_array($vals)) { return 'array expected'; } return \true; }, static function ($vals) { return $vals; }], 'gitlab-domains' => [static function ($vals) { if (!\is_array($vals)) { return 'array expected'; } return \true; }, static function ($vals) { return $vals; }], 'audit.ignore' => [static function ($vals) { if (!\is_array($vals)) { return 'array expected'; } return \true; }, static function ($vals) { return $vals; }]]; // allow unsetting audit config entirely if ($input->getOption('unset') && $settingKey === 'audit') { $this->configSource->removeConfigSetting($settingKey); return 0; } if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) { if ($settingKey === 'disable-tls' && $this->config->get('disable-tls')) { $this->getIO()->writeError('You are now running Composer with SSL/TLS protection enabled.'); } $this->configSource->removeConfigSetting($settingKey); return 0; } if (isset($uniqueConfigValues[$settingKey])) { $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting'); return 0; } if (isset($multiConfigValues[$settingKey])) { $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting'); return 0; } // handle preferred-install per-package config if (Preg::isMatch('/^preferred-install\\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeConfigSetting($settingKey); return 0; } [$validator] = $uniqueConfigValues['preferred-install']; if (!$validator($values[0])) { throw new \RuntimeException('Invalid value for ' . $settingKey . '. Should be one of: auto, source, or dist'); } $this->configSource->addConfigSetting($settingKey, $values[0]); return 0; } // handle allow-plugins config setting elements true or false to add/remove if (Preg::isMatch('{^allow-plugins\\.([a-zA-Z0-9/*-]+)}', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeConfigSetting($settingKey); return 0; } if (\true !== $booleanValidator($values[0])) { throw new \RuntimeException(\sprintf('"%s" is an invalid value', $values[0])); } $normalizedValue = $booleanNormalizer($values[0]); $this->configSource->addConfigSetting($settingKey, $normalizedValue); return 0; } // handle properties $uniqueProps = ['name' => ['is_string', static function ($val) { return $val; }], 'type' => ['is_string', static function ($val) { return $val; }], 'description' => ['is_string', static function ($val) { return $val; }], 'homepage' => ['is_string', static function ($val) { return $val; }], 'version' => ['is_string', static function ($val) { return $val; }], 'minimum-stability' => [static function ($val) : bool { return isset(BasePackage::STABILITIES[VersionParser::normalizeStability($val)]); }, static function ($val) : string { return VersionParser::normalizeStability($val); }], 'prefer-stable' => [$booleanValidator, $booleanNormalizer]]; $multiProps = ['keywords' => [static function ($vals) { if (!\is_array($vals)) { return 'array expected'; } return \true; }, static function ($vals) { return $vals; }], 'license' => [static function ($vals) { if (!\is_array($vals)) { return 'array expected'; } return \true; }, static function ($vals) { return $vals; }]]; if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || \strpos($settingKey, 'extra.') === 0)) { throw new \InvalidArgumentException('The ' . $settingKey . ' property can not be set in the global config.json file. Use `composer global config` to apply changes to the global composer.json'); } if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) { $this->configSource->removeProperty($settingKey); return 0; } if (isset($uniqueProps[$settingKey])) { $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty'); return 0; } if (isset($multiProps[$settingKey])) { $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty'); return 0; } // handle repositories if (Preg::isMatchStrictGroups('/^repos?(?:itories)?\\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeRepository($matches[1]); return 0; } if (2 === \count($values)) { $this->configSource->addRepository($matches[1], ['type' => $values[0], 'url' => $values[1]], $input->getOption('append')); return 0; } if (1 === \count($values)) { $value = \strtolower($values[0]); if (\true === $booleanValidator($value)) { if (\false === $booleanNormalizer($value)) { $this->configSource->addRepository($matches[1], \false, $input->getOption('append')); return 0; } } else { $value = JsonFile::parseJson($values[0]); $this->configSource->addRepository($matches[1], $value, $input->getOption('append')); return 0; } } throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com'); } // handle extra if (Preg::isMatch('/^extra\\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeProperty($settingKey); return 0; } $value = $values[0]; if ($input->getOption('json')) { $value = JsonFile::parseJson($value); if ($input->getOption('merge')) { $currentValue = $this->configFile->read(); $bits = \explode('.', $settingKey); foreach ($bits as $bit) { $currentValue = $currentValue[$bit] ?? null; } if (\is_array($currentValue) && \is_array($value)) { if (\array_is_list($currentValue) && \array_is_list($value)) { $value = \array_merge($currentValue, $value); } else { $value = $value + $currentValue; } } } } $this->configSource->addProperty($settingKey, $value); return 0; } // handle suggest if (Preg::isMatch('/^suggest\\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeProperty($settingKey); return 0; } $this->configSource->addProperty($settingKey, \implode(' ', $values)); return 0; } // handle unsetting extra/suggest if (\in_array($settingKey, ['suggest', 'extra'], \true) && $input->getOption('unset')) { $this->configSource->removeProperty($settingKey); return 0; } // handle platform if (Preg::isMatch('/^platform\\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeConfigSetting($settingKey); return 0; } $this->configSource->addConfigSetting($settingKey, $values[0] === 'false' ? \false : $values[0]); return 0; } // handle unsetting platform if ($settingKey === 'platform' && $input->getOption('unset')) { $this->configSource->removeConfigSetting($settingKey); return 0; } // handle auth if (Preg::isMatch('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|bearer)\\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->authConfigSource->removeConfigSetting($matches[1] . '.' . $matches[2]); $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]); return 0; } if ($matches[1] === 'bitbucket-oauth') { if (2 !== \count($values)) { throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got ' . \count($values)); } $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]); $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], ['consumer-key' => $values[0], 'consumer-secret' => $values[1]]); } elseif ($matches[1] === 'gitlab-token' && 2 === \count($values)) { $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]); $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], ['username' => $values[0], 'token' => $values[1]]); } elseif (\in_array($matches[1], ['github-oauth', 'gitlab-oauth', 'gitlab-token', 'bearer'], \true)) { if (1 !== \count($values)) { throw new \RuntimeException('Too many arguments, expected only one token'); } $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]); $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], $values[0]); } elseif ($matches[1] === 'http-basic') { if (2 !== \count($values)) { throw new \RuntimeException('Expected two arguments (username, password), got ' . \count($values)); } $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]); $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], ['username' => $values[0], 'password' => $values[1]]); } return 0; } // handle script if (Preg::isMatch('/^scripts\\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeProperty($settingKey); return 0; } $this->configSource->addProperty($settingKey, \count($values) > 1 ? $values : $values[0]); return 0; } // handle unsetting other top level properties if ($input->getOption('unset')) { $this->configSource->removeProperty($settingKey); return 0; } throw new \InvalidArgumentException('Setting ' . $settingKey . ' does not exist or is not supported by this command'); } /** * @param array{callable, callable} $callbacks Validator and normalizer callbacks * @param array $values */ protected function handleSingleValue(string $key, array $callbacks, array $values, string $method) : void { [$validator, $normalizer] = $callbacks; if (1 !== \count($values)) { throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300'); } if (\true !== ($validation = $validator($values[0]))) { throw new \RuntimeException(\sprintf('"%s" is an invalid value' . ($validation ? ' (' . $validation . ')' : ''), $values[0])); } $normalizedValue = $normalizer($values[0]); if ($key === 'disable-tls') { if (!$normalizedValue && $this->config->get('disable-tls')) { $this->getIO()->writeError('You are now running Composer with SSL/TLS protection enabled.'); } elseif ($normalizedValue && !$this->config->get('disable-tls')) { $this->getIO()->writeError('You are now running Composer with SSL/TLS protection disabled.'); } } \call_user_func([$this->configSource, $method], $key, $normalizedValue); } /** * @param array{callable, callable} $callbacks Validator and normalizer callbacks * @param array $values */ protected function handleMultiValue(string $key, array $callbacks, array $values, string $method) : void { [$validator, $normalizer] = $callbacks; if (\true !== ($validation = $validator($values))) { throw new \RuntimeException(\sprintf('%s is an invalid value' . ($validation ? ' (' . $validation . ')' : ''), \json_encode($values))); } \call_user_func([$this->configSource, $method], $key, $normalizer($values)); } /** * Display the contents of the file in a pretty formatted way * * @param array $contents * @param array $rawContents */ protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, ?string $k = null, bool $showSource = \false) : void { $origK = $k; $io = $this->getIO(); foreach ($contents as $key => $value) { if ($k === null && !\in_array($key, ['config', 'repositories'])) { continue; } $rawVal = $rawContents[$key] ?? null; if (\is_array($value) && (!\is_numeric(\key($value)) || $key === 'repositories' && null === $k)) { $k .= Preg::replace('{^config\\.}', '', $key . '.'); $this->listConfiguration($value, $rawVal, $output, $k, $showSource); $k = $origK; continue; } if (\is_array($value)) { $value = \array_map(static function ($val) { return \is_array($val) ? \json_encode($val) : $val; }, $value); $value = '[' . \implode(', ', $value) . ']'; } if (\is_bool($value)) { $value = \var_export($value, \true); } $source = ''; if ($showSource) { $source = ' (' . $this->config->getSourceOfValue($k . $key) . ')'; } if (null !== $k && 0 === \strpos($k, 'repositories')) { $link = 'https://getcomposer.org/doc/05-repositories.md'; } else { $id = Preg::replace('{\\..*$}', '', $k === '' || $k === null ? (string) $key : $k); $id = Preg::replace('{[^a-z0-9]}i', '-', \strtolower(\trim($id))); $id = Preg::replace('{-+}', '-', $id); $link = 'https://getcomposer.org/doc/06-config.md#' . $id; } if (\is_string($rawVal) && $rawVal !== $value) { $io->write('[' . $k . $key . '] ' . $rawVal . ' (' . $value . ')' . $source, \true, IOInterface::QUIET); } else { $io->write('[' . $k . $key . '] ' . $value . '' . $source, \true, IOInterface::QUIET); } } } /** * Get the local composer.json, global config.json, or the file passed by the user */ private function getComposerConfigFile(InputInterface $input, Config $config) : string { return $input->getOption('global') ? $config->get('home') . '/config.json' : ($input->getOption('file') ?: Factory::getComposerFile()); } /** * Get the local auth.json or global auth.json, or if the user passed in a file to use, * the corresponding auth.json */ private function getAuthConfigFile(InputInterface $input, Config $config) : string { return $input->getOption('global') ? $config->get('home') . '/auth.json' : \dirname($this->getComposerConfigFile($input, $config)) . '/auth.json'; } /** * Suggest setting-keys, while taking given options in account. */ private function suggestSettingKeys() : \Closure { return function (CompletionInput $input) : array { if ($input->getOption('list') || $input->getOption('editor') || $input->getOption('auth')) { return []; } // initialize configuration $config = Factory::createConfig(); // load configuration $configFile = new JsonFile($this->getComposerConfigFile($input, $config)); if ($configFile->exists()) { $config->merge($configFile->read(), $configFile->getPath()); } // load auth-configuration $authConfigFile = new JsonFile($this->getAuthConfigFile($input, $config)); if ($authConfigFile->exists()) { $config->merge(['config' => $authConfigFile->read()], $authConfigFile->getPath()); } // collect all configuration setting-keys $rawConfig = $config->raw(); $keys = \array_merge($this->flattenSettingKeys($rawConfig['config']), $this->flattenSettingKeys($rawConfig['repositories'], 'repositories.')); // if unsetting … if ($input->getOption('unset')) { // … keep only the currently customized setting-keys … $sources = [$configFile->getPath(), $authConfigFile->getPath()]; $keys = \array_filter($keys, static function (string $key) use($config, $sources) : bool { return \in_array($config->getSourceOfValue($key), $sources, \true); }); // … else if showing or setting a value … } else { // … add all configurable package-properties, no matter if it exist $keys = \array_merge($keys, self::CONFIGURABLE_PACKAGE_PROPERTIES); // it would be nice to distinguish between showing and setting // a value, but that makes the implementation much more complex // and partially impossible because symfony's implementation // does not complete arguments followed by other arguments } // add all existing configurable package-properties if ($configFile->exists()) { $properties = \array_filter($configFile->read(), static function (string $key) : bool { return \in_array($key, self::CONFIGURABLE_PACKAGE_PROPERTIES, \true); }, \ARRAY_FILTER_USE_KEY); $keys = \array_merge($keys, $this->flattenSettingKeys($properties)); } // filter settings-keys by completion value $completionValue = $input->getCompletionValue(); if ($completionValue !== '') { $keys = \array_filter($keys, static function (string $key) use($completionValue) : bool { return \str_starts_with($key, $completionValue); }); } \sort($keys); return \array_unique($keys); }; } /** * build a flat list of dot-separated setting-keys from given config * * @param array $config * @return string[] */ private function flattenSettingKeys(array $config, string $prefix = '') : array { $keys = []; foreach ($config as $key => $value) { $keys[] = [$prefix . $key]; // array-lists must not be added to completion // sub-keys of repository-keys must not be added to completion if (\is_array($value) && !\array_is_list($value) && $prefix !== 'repositories.') { $keys[] = $this->flattenSettingKeys($value, $prefix . $key . '.'); } } return \array_merge(...$keys); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Console\Input\InputOption; use Composer\Json\JsonFile; use Composer\Package\CompletePackageInterface; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\RepositoryUtils; use Composer\Util\PackageInfo; use Composer\Util\PackageSorter; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; use _ContaoManager\Symfony\Component\Console\Helper\Table; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Console\Style\SymfonyStyle; /** * @author Benoît Merlet */ class LicensesCommand extends \Composer\Command\BaseCommand { protected function configure() : void { $this->setName('licenses')->setDescription('Shows information about licenses of dependencies')->setDefinition([new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text, json or summary', 'text', ['text', 'json', 'summary']), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.')])->setHelp(<<requireComposer(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $root = $composer->getPackage(); $repo = $composer->getRepositoryManager()->getLocalRepository(); if ($input->getOption('no-dev')) { $packages = RepositoryUtils::filterRequiredPackages($repo->getPackages(), $root); } else { $packages = $repo->getPackages(); } $packages = PackageSorter::sortPackagesAlphabetically($packages); $io = $this->getIO(); switch ($format = $input->getOption('format')) { case 'text': $io->write('Name: ' . $root->getPrettyName() . ''); $io->write('Version: ' . $root->getFullPrettyVersion() . ''); $io->write('Licenses: ' . (\implode(', ', $root->getLicense()) ?: 'none') . ''); $io->write('Dependencies:'); $io->write(''); $table = new Table($output); $table->setStyle('compact'); $table->setHeaders(['Name', 'Version', 'Licenses']); foreach ($packages as $package) { $link = PackageInfo::getViewSourceOrHomepageUrl($package); if ($link !== null) { $name = '' . $package->getPrettyName() . ''; } else { $name = $package->getPrettyName(); } $table->addRow([$name, $package->getFullPrettyVersion(), \implode(', ', $package instanceof CompletePackageInterface ? $package->getLicense() : []) ?: 'none']); } $table->render(); break; case 'json': $dependencies = []; foreach ($packages as $package) { $dependencies[$package->getPrettyName()] = ['version' => $package->getFullPrettyVersion(), 'license' => $package instanceof CompletePackageInterface ? $package->getLicense() : []]; } $io->write(JsonFile::encode(['name' => $root->getPrettyName(), 'version' => $root->getFullPrettyVersion(), 'license' => $root->getLicense(), 'dependencies' => $dependencies])); break; case 'summary': $usedLicenses = []; foreach ($packages as $package) { $licenses = $package instanceof CompletePackageInterface ? $package->getLicense() : []; if (\count($licenses) === 0) { $licenses[] = 'none'; } foreach ($licenses as $licenseName) { if (!isset($usedLicenses[$licenseName])) { $usedLicenses[$licenseName] = 0; } $usedLicenses[$licenseName]++; } } // Sort licenses so that the most used license will appear first \arsort($usedLicenses, \SORT_NUMERIC); $rows = []; foreach ($usedLicenses as $usedLicense => $numberOfDependencies) { $rows[] = [$usedLicense, $numberOfDependencies]; } $symfonyIo = new SymfonyStyle($input, $output); $symfonyIo->table(['License', 'Number of dependencies'], $rows); break; default: throw new \RuntimeException(\sprintf('Unsupported format "%s". See help for supported formats.', $format)); } return 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use Composer\DependencyResolver\Request; use Composer\Installer; use Composer\IO\IOInterface; use Composer\Package\BasePackage; use Composer\Package\Loader\RootPackageLoader; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionSelector; use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Package\Version\VersionParser; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositorySet; use Composer\Semver\Constraint\MultiConstraint; use Composer\Semver\Intervals; use Composer\Util\HttpDownloader; use Composer\Advisory\Auditor; use Composer\Util\Platform; use _ContaoManager\Symfony\Component\Console\Helper\Table; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano * @author Nils Adermann */ class UpdateCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; /** * @return void */ protected function configure() { $this->setName('update')->setAliases(['u', 'upgrade'])->setDescription('Updates your dependencies to the latest version according to composer.json, and updates the composer.lock file')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.', null, $this->suggestInstalledPackage(\false)), new InputOption('with', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Temporary version constraint to add, e.g. foo/bar:1.0.0 or foo/bar=1.0.0'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('dev', null, InputOption::VALUE_NONE, 'DEPRECATED: Enables installation of require-dev packages (enabled by default, only present for BC).'), new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'), new InputOption('lock', null, InputOption::VALUE_NONE, 'Overwrites the lock file hash to suppress warning about the lock file being out of date without updating package versions. Package metadata like mirrors and URLs are updated if they changed.'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('with-dependencies', 'w', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, except those which are root requirements.'), new InputOption('with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Update also dependencies of packages in the argument list, including those which are root requirements.'), new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies (can also be set via the COMPOSER_PREFER_STABLE=1 env var).'), new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies (can also be set via the COMPOSER_PREFER_LOWEST=1 env var).'), new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During a partial update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'), new InputOption('patch-only', null, InputOption::VALUE_NONE, 'Only allow patch version updates for currently installed dependencies.'), new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'), new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'), new InputOption('bump-after-update', null, InputOption::VALUE_OPTIONAL, 'Runs bump after performing the update.', \false, ['dev', 'no-dev', 'all'])])->setHelp(<<update command reads the composer.json file from the current directory, processes it, and updates, removes or installs all the dependencies. php composer.phar update To limit the update operation to a few packages, you can list the package(s) you want to update as such: php composer.phar update vendor/package1 foo/mypackage [...] You may also use an asterisk (*) pattern to limit the update operation to package(s) from a specific vendor: php composer.phar update vendor/package1 foo/* [...] To run an update with more restrictive constraints you can use: php composer.phar update --with vendor/package:1.0.* To run a partial update with more restrictive constraints you can use the shorthand: php composer.phar update vendor/package:1.0.* To select packages names interactively with auto-completion use -i. Read more at https://getcomposer.org/doc/03-cli.md#update-u-upgrade EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $io = $this->getIO(); if ($input->getOption('dev')) { $io->writeError('You are using the deprecated option "--dev". It has no effect and will break in Composer 3.'); } if ($input->getOption('no-suggest')) { $io->writeError('You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.'); } $composer = $this->requireComposer(); if (!HttpDownloader::isCurlEnabled()) { $io->writeError('Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled.'); } $packages = $input->getArgument('packages'); $reqs = $this->formatRequirements($input->getOption('with')); // extract --with shorthands from the allowlist if (\count($packages) > 0) { $allowlistPackagesWithRequirements = \array_filter($packages, static function ($pkg) : bool { return Preg::isMatch('{\\S+[ =:]\\S+}', $pkg); }); foreach ($this->formatRequirements($allowlistPackagesWithRequirements) as $package => $constraint) { $reqs[$package] = $constraint; } // replace the foo/bar:req by foo/bar in the allowlist foreach ($allowlistPackagesWithRequirements as $package) { $packageName = Preg::replace('{^([^ =:]+)[ =:].*$}', '$1', $package); $index = \array_search($package, $packages); $packages[$index] = $packageName; } } $rootPackage = $composer->getPackage(); $rootPackage->setReferences(RootPackageLoader::extractReferences($reqs, $rootPackage->getReferences())); $rootPackage->setStabilityFlags(RootPackageLoader::extractStabilityFlags($reqs, $rootPackage->getMinimumStability(), $rootPackage->getStabilityFlags())); $parser = new VersionParser(); $temporaryConstraints = []; $rootRequirements = \array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()); foreach ($reqs as $package => $constraint) { $package = \strtolower($package); $parsedConstraint = $parser->parseConstraints($constraint); $temporaryConstraints[$package] = $parsedConstraint; if (isset($rootRequirements[$package]) && !Intervals::haveIntersections($parsedConstraint, $rootRequirements[$package]->getConstraint())) { $io->writeError('The temporary constraint "' . $constraint . '" for "' . $package . '" must be a subset of the constraint in your composer.json (' . $rootRequirements[$package]->getPrettyConstraint() . ')'); $io->write('Run `composer require ' . $package . '` or `composer require ' . $package . ':' . $constraint . '` instead to replace the constraint'); return self::FAILURE; } } if ($input->getOption('patch-only')) { if (!$composer->getLocker()->isLocked()) { throw new \InvalidArgumentException('patch-only can only be used with a lock file present'); } foreach ($composer->getLocker()->getLockedRepository(\true)->getCanonicalPackages() as $package) { if ($package->isDev()) { continue; } if (!Preg::isMatch('{^(\\d+\\.\\d+\\.\\d+)}', $package->getVersion(), $match)) { continue; } $constraint = $parser->parseConstraints('~' . $match[1]); if (isset($temporaryConstraints[$package->getName()])) { $temporaryConstraints[$package->getName()] = MultiConstraint::create([$temporaryConstraints[$package->getName()], $constraint], \true); } else { $temporaryConstraints[$package->getName()] = $constraint; } } } if ($input->getOption('interactive')) { $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages); } if ($input->getOption('root-reqs')) { $requires = \array_keys($rootPackage->getRequires()); if (!$input->getOption('no-dev')) { $requires = \array_merge($requires, \array_keys($rootPackage->getDevRequires())); } if (!empty($packages)) { $packages = \array_intersect($packages, $requires); } else { $packages = $requires; } } // the arguments lock/nothing/mirrors are not package names but trigger a mirror update instead // they are further mutually exclusive with listing actual package names $filteredPackages = \array_filter($packages, static function ($package) : bool { return !\in_array($package, ['lock', 'nothing', 'mirrors'], \true); }); $updateMirrors = $input->getOption('lock') || \count($filteredPackages) !== \count($packages); $packages = $filteredPackages; if ($updateMirrors && !empty($packages)) { $io->writeError('You cannot simultaneously update only a selection of packages and regenerate the lock file metadata.'); return -1; } $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress')); $install = Installer::create($io, $composer); $config = $composer->getConfig(); [$preferSource, $preferDist] = $this->getPreferredInstallOptions($config, $input); $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader'); $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative'); $apcuPrefix = $input->getOption('apcu-autoloader-prefix'); $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader'); $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED; if ($input->getOption('with-all-dependencies')) { $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS; } elseif ($input->getOption('with-dependencies')) { $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE; } $install->setDryRun($input->getOption('dry-run'))->setVerbose($input->getOption('verbose'))->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode(!$input->getOption('no-dev'))->setDumpAutoloader(!$input->getOption('no-autoloader'))->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setUpdate(\true)->setInstall(!$input->getOption('no-install'))->setUpdateMirrors($updateMirrors)->setUpdateAllowList($packages)->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setPreferStable($input->getOption('prefer-stable'))->setPreferLowest($input->getOption('prefer-lowest'))->setTemporaryConstraints($temporaryConstraints)->setAudit(!$input->getOption('no-audit'))->setAuditFormat($this->getAuditFormat($input))->setMinimalUpdate($input->getOption('minimal-changes')); if ($input->getOption('no-plugins')) { $install->disablePlugins(); } $result = $install->run(); if ($result === 0) { $bumpAfterUpdate = $input->getOption('bump-after-update'); if (\false === $bumpAfterUpdate) { $bumpAfterUpdate = $composer->getConfig()->get('bump-after-update'); } if (\false !== $bumpAfterUpdate) { $io->writeError('Bumping dependencies'); $bumpCommand = new \Composer\Command\BumpCommand(); $bumpCommand->setComposer($composer); $result = $bumpCommand->doBump($io, $bumpAfterUpdate === 'dev', $bumpAfterUpdate === 'no-dev', $input->getOption('dry-run'), $input->getArgument('packages')); } } return $result; } /** * @param array $packages * @return array */ private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages) : array { if (!$input->isInteractive()) { throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.'); } $platformReqFilter = $this->getPlatformRequirementFilter($input); $stabilityFlags = $composer->getPackage()->getStabilityFlags(); $requires = \array_merge($composer->getPackage()->getRequires(), $composer->getPackage()->getDevRequires()); $filter = \count($packages) > 0 ? BasePackage::packageNamesToRegexp($packages) : null; $io->writeError('Loading packages that can be updated...'); $autocompleterValues = []; $installedPackages = $composer->getLocker()->isLocked() ? $composer->getLocker()->getLockedRepository(\true)->getPackages() : $composer->getRepositoryManager()->getLocalRepository()->getPackages(); $versionSelector = $this->createVersionSelector($composer); foreach ($installedPackages as $package) { if ($filter !== null && !Preg::isMatch($filter, $package->getName())) { continue; } $currentVersion = $package->getPrettyVersion(); $constraint = isset($requires[$package->getName()]) ? $requires[$package->getName()]->getPrettyConstraint() : null; $stability = isset($stabilityFlags[$package->getName()]) ? (string) \array_search($stabilityFlags[$package->getName()], BasePackage::STABILITIES, \true) : $composer->getPackage()->getMinimumStability(); $latestVersion = $versionSelector->findBestCandidate($package->getName(), $constraint, $stability, $platformReqFilter); if ($latestVersion !== \false && ($package->getVersion() !== $latestVersion->getVersion() || $latestVersion->isDev())) { $autocompleterValues[$package->getName()] = '' . $currentVersion . ' => ' . $latestVersion->getPrettyVersion() . ''; } } if (0 === \count($installedPackages)) { foreach ($requires as $req => $constraint) { if (PlatformRepository::isPlatformPackage($req)) { continue; } $autocompleterValues[$req] = ''; } } if (0 === \count($autocompleterValues)) { throw new \RuntimeException('Could not find any package with new versions available'); } $packages = $io->select('Select packages: (Select more than one value separated by comma) ', $autocompleterValues, \false, 1, 'No package named "%s" is installed.', \true); $table = new Table($output); $table->setHeaders(['Selected packages']); foreach ($packages as $package) { $table->addRow([$package]); } $table->render(); if ($io->askConfirmation(\sprintf('Would you like to continue and update the above package%s [yes]? ', 1 === \count($packages) ? '' : 's'))) { return $packages; } throw new \RuntimeException('Installation aborted.'); } private function createVersionSelector(Composer $composer) : VersionSelector { $repositorySet = new RepositorySet(); $repositorySet->addRepository(new CompositeRepository(\array_filter($composer->getRepositoryManager()->getRepositories(), function (RepositoryInterface $repository) { return !$repository instanceof PlatformRepository; }))); return new VersionSelector($repositorySet); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Downloader\ChangeReportInterface; use Composer\Downloader\DvcsDownloaderInterface; use Composer\Downloader\VcsCapableDownloaderInterface; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Script\ScriptEvents; use Composer\Util\ProcessExecutor; /** * @author Tiago Ribeiro * @author Rui Marinho */ class StatusCommand extends \Composer\Command\BaseCommand { private const EXIT_CODE_ERRORS = 1; private const EXIT_CODE_UNPUSHED_CHANGES = 2; private const EXIT_CODE_VERSION_CHANGES = 4; /** * @throws \Symfony\Component\Console\Exception\InvalidArgumentException */ protected function configure() : void { $this->setName('status')->setDescription('Shows a list of locally modified packages')->setDefinition([new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.')])->setHelp(<<requireComposer(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); // Dispatch pre-status-command $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, \true); $exitCode = $this->doExecute($input); // Dispatch post-status-command $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, \true); return $exitCode; } private function doExecute(InputInterface $input) : int { // init repos $composer = $this->requireComposer(); $installedRepo = $composer->getRepositoryManager()->getLocalRepository(); $dm = $composer->getDownloadManager(); $im = $composer->getInstallationManager(); $errors = []; $io = $this->getIO(); $unpushedChanges = []; $vcsVersionChanges = []; $parser = new VersionParser(); $guesser = new VersionGuesser($composer->getConfig(), $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io), $parser, $io); $dumper = new ArrayDumper(); // list packages foreach ($installedRepo->getCanonicalPackages() as $package) { $downloader = $dm->getDownloaderForPackage($package); $targetDir = $im->getInstallPath($package); if ($targetDir === null) { continue; } if ($downloader instanceof ChangeReportInterface) { if (\is_link($targetDir)) { $errors[$targetDir] = $targetDir . ' is a symbolic link.'; } if (null !== ($changes = $downloader->getLocalChanges($package, $targetDir))) { $errors[$targetDir] = $changes; } } if ($downloader instanceof VcsCapableDownloaderInterface) { if ($downloader->getVcsReference($package, $targetDir)) { switch ($package->getInstallationSource()) { case 'source': $previousRef = $package->getSourceReference(); break; case 'dist': $previousRef = $package->getDistReference(); break; default: $previousRef = null; } $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir); if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef && $currentVersion['pretty_version'] !== $previousRef) { $vcsVersionChanges[$targetDir] = ['previous' => ['version' => $package->getPrettyVersion(), 'ref' => $previousRef], 'current' => ['version' => $currentVersion['pretty_version'], 'ref' => $currentVersion['commit']]]; } } } if ($downloader instanceof DvcsDownloaderInterface) { if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) { $unpushedChanges[$targetDir] = $unpushed; } } } // output errors/warnings if (!$errors && !$unpushedChanges && !$vcsVersionChanges) { $io->writeError('No local changes'); return 0; } if ($errors) { $io->writeError('You have changes in the following dependencies:'); foreach ($errors as $path => $changes) { if ($input->getOption('verbose')) { $indentedChanges = \implode("\n", \array_map(static function ($line) : string { return ' ' . \ltrim($line); }, \explode("\n", $changes))); $io->write('' . $path . ':'); $io->write($indentedChanges); } else { $io->write($path); } } } if ($unpushedChanges) { $io->writeError('You have unpushed changes on the current branch in the following dependencies:'); foreach ($unpushedChanges as $path => $changes) { if ($input->getOption('verbose')) { $indentedChanges = \implode("\n", \array_map(static function ($line) : string { return ' ' . \ltrim($line); }, \explode("\n", $changes))); $io->write('' . $path . ':'); $io->write($indentedChanges); } else { $io->write($path); } } } if ($vcsVersionChanges) { $io->writeError('You have version variations in the following dependencies:'); foreach ($vcsVersionChanges as $path => $changes) { if ($input->getOption('verbose')) { // If we don't can't find a version, use the ref instead. $currentVersion = $changes['current']['version'] ?: $changes['current']['ref']; $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref']; if ($io->isVeryVerbose()) { // Output the ref regardless of whether or not it's being used as the version $currentVersion .= \sprintf(' (%s)', $changes['current']['ref']); $previousVersion .= \sprintf(' (%s)', $changes['previous']['ref']); } $io->write('' . $path . ':'); $io->write(\sprintf(' From %s to %s', $previousVersion, $currentVersion)); } else { $io->write($path); } } } if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) { $io->writeError('Use --verbose (-v) to see a list of files'); } return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Package\Link; use Composer\Package\Package; use Composer\Package\PackageInterface; use Composer\Package\CompletePackageInterface; use Composer\Package\RootPackage; use Composer\Repository\InstalledArrayRepository; use Composer\Repository\CompositeRepository; use Composer\Repository\RootPackageRepository; use Composer\Repository\InstalledRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryFactory; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Semver\Constraint\Bound; use Composer\Util\Platform; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle; use Composer\Package\Version\VersionParser; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Util\PackageInfo; /** * Base implementation for commands mapping dependency relationships. * * @author Niels Keurentjes */ abstract class BaseDependencyCommand extends \Composer\Command\BaseCommand { protected const ARGUMENT_PACKAGE = 'package'; protected const ARGUMENT_CONSTRAINT = 'version'; protected const OPTION_RECURSIVE = 'recursive'; protected const OPTION_TREE = 'tree'; /** @var string[] */ protected $colors; /** * Execute the command. * * @param bool $inverted Whether to invert matching process (why-not vs why behaviour) * @return int Exit code of the operation. */ protected function doExecute(InputInterface $input, OutputInterface $output, bool $inverted = \false) : int { // Emit command event on startup $composer = $this->requireComposer(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $repos = []; $repos[] = new RootPackageRepository(clone $composer->getPackage()); if ($input->getOption('locked')) { $locker = $composer->getLocker(); if (!$locker->isLocked()) { throw new \UnexpectedValueException('A valid composer.lock file is required to run this command with --locked'); } $repos[] = $locker->getLockedRepository(\true); $repos[] = new PlatformRepository([], $locker->getPlatformOverrides()); } else { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $rootPkg = $composer->getPackage(); if (\count($localRepo->getPackages()) === 0 && (\count($rootPkg->getRequires()) > 0 || \count($rootPkg->getDevRequires()) > 0)) { $output->writeln('No dependencies installed. Try running composer install or update, or use --locked.'); return 1; } $repos[] = $localRepo; $platformOverrides = $composer->getConfig()->get('platform') ?: []; $repos[] = new PlatformRepository([], $platformOverrides); } $installedRepo = new InstalledRepository($repos); // Parse package name and constraint $needle = $input->getArgument(self::ARGUMENT_PACKAGE); $textConstraint = $input->hasArgument(self::ARGUMENT_CONSTRAINT) ? $input->getArgument(self::ARGUMENT_CONSTRAINT) : '*'; // Find packages that are or provide the requested package first $packages = $installedRepo->findPackagesWithReplacersAndProviders($needle); if (empty($packages)) { throw new \InvalidArgumentException(\sprintf('Could not find package "%s" in your project', $needle)); } // If the version we ask for is not installed then we need to locate it in remote repos and add it. // This is needed for why-not to resolve conflicts from an uninstalled version against installed packages. $matchedPackage = $installedRepo->findPackage($needle, $textConstraint); if (!$matchedPackage) { $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO(), $composer->getConfig(), $composer->getRepositoryManager())); if ($match = $defaultRepos->findPackage($needle, $textConstraint)) { $installedRepo->addRepository(new InstalledArrayRepository([clone $match])); } elseif (PlatformRepository::isPlatformPackage($needle)) { $parser = new VersionParser(); $constraint = $parser->parseConstraints($textConstraint); if ($constraint->getLowerBound() !== Bound::zero()) { $tempPlatformPkg = new Package($needle, $constraint->getLowerBound()->getVersion(), $constraint->getLowerBound()->getVersion()); $installedRepo->addRepository(new InstalledArrayRepository([$tempPlatformPkg])); } } else { $this->getIO()->writeError('Package "' . $needle . '" could not be found with constraint "' . $textConstraint . '", results below will most likely be incomplete.'); } } elseif (PlatformRepository::isPlatformPackage($needle)) { $extraNotice = ''; if (($matchedPackage->getExtra()['config.platform'] ?? \false) === \true) { $extraNotice = ' (version provided by config.platform)'; } $this->getIO()->writeError('Package "' . $needle . ' ' . $textConstraint . '" found in version "' . $matchedPackage->getPrettyVersion() . '"' . $extraNotice . '.'); } elseif ($inverted) { $this->getIO()->write('Package "' . $needle . '" ' . $matchedPackage->getPrettyVersion() . ' is already installed! To find out why, run `composer why ' . $needle . '`'); return 0; } // Include replaced packages for inverted lookups as they are then the actual starting point to consider $needles = [$needle]; if ($inverted) { foreach ($packages as $package) { $needles = \array_merge($needles, \array_map(static function (Link $link) : string { return $link->getTarget(); }, $package->getReplaces())); } } // Parse constraint if one was supplied if ('*' !== $textConstraint) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($textConstraint); } else { $constraint = null; } // Parse rendering options $renderTree = $input->getOption(self::OPTION_TREE); $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE); $return = $inverted ? 1 : 0; // Resolve dependencies $results = $installedRepo->getDependents($needles, $constraint, $inverted, $recursive); if (empty($results)) { $extra = null !== $constraint ? \sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : ''; $this->getIO()->writeError(\sprintf('There is no installed package depending on "%s"%s', $needle, $extra)); $return = $inverted ? 0 : 1; } elseif ($renderTree) { $this->initStyles($output); $root = $packages[0]; $this->getIO()->write(\sprintf('%s %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root instanceof CompletePackageInterface ? $root->getDescription() : '')); $this->printTree($results); } else { $this->printTable($output, $results); } if ($inverted && $input->hasArgument(self::ARGUMENT_CONSTRAINT) && !PlatformRepository::isPlatformPackage($needle)) { $composerCommand = 'update'; foreach ($composer->getPackage()->getRequires() as $rootRequirement) { if ($rootRequirement->getTarget() === $needle) { $composerCommand = 'require'; break; } } foreach ($composer->getPackage()->getDevRequires() as $rootRequirement) { if ($rootRequirement->getTarget() === $needle) { $composerCommand = 'require --dev'; break; } } $this->getIO()->writeError('Not finding what you were looking for? Try calling `composer ' . $composerCommand . ' "' . $needle . ':' . $textConstraint . '" --dry-run` to get another view on the problem.'); } return $return; } /** * Assembles and prints a bottom-up table of the dependencies. * * @param array{PackageInterface, Link, array|false}[] $results */ protected function printTable(OutputInterface $output, array $results) : void { $table = []; $doubles = []; do { $queue = []; $rows = []; foreach ($results as $result) { /** * @var PackageInterface $package * @var Link $link */ [$package, $link, $children] = $result; $unique = (string) $link; if (isset($doubles[$unique])) { continue; } $doubles[$unique] = \true; $version = $package->getPrettyVersion() === RootPackage::DEFAULT_PRETTY_VERSION ? '-' : $package->getPrettyVersion(); $packageUrl = PackageInfo::getViewSourceOrHomepageUrl($package); $nameWithLink = $packageUrl !== null ? '' . $package->getPrettyName() . '' : $package->getPrettyName(); $rows[] = [$nameWithLink, $version, $link->getDescription(), \sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint())]; if (\is_array($children)) { $queue = \array_merge($queue, $children); } } $results = $queue; $table = \array_merge($rows, $table); } while (\count($results) > 0); $this->renderTable($table, $output); } /** * Init styles for tree */ protected function initStyles(OutputInterface $output) : void { $this->colors = ['green', 'yellow', 'cyan', 'magenta', 'blue']; foreach ($this->colors as $color) { $style = new OutputFormatterStyle($color); $output->getFormatter()->setStyle($color, $style); } } /** * Recursively prints a tree of the selected results. * * @param array{PackageInterface, Link, array|false}[] $results Results to be printed at this level. * @param string $prefix Prefix of the current tree level. * @param int $level Current level of recursion. */ protected function printTree(array $results, string $prefix = '', int $level = 1) : void { $count = \count($results); $idx = 0; foreach ($results as $result) { [$package, $link, $children] = $result; $color = $this->colors[$level % \count($this->colors)]; $prevColor = $this->colors[($level - 1) % \count($this->colors)]; $isLast = ++$idx === $count; $versionText = $package->getPrettyVersion() === RootPackage::DEFAULT_PRETTY_VERSION ? '' : $package->getPrettyVersion(); $packageUrl = PackageInfo::getViewSourceOrHomepageUrl($package); $nameWithLink = $packageUrl !== null ? '' . $package->getPrettyName() . '' : $package->getPrettyName(); $packageText = \rtrim(\sprintf('<%s>%s %s', $color, $nameWithLink, $versionText)); $linkText = \sprintf('%s <%s>%s %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint()); $circularWarn = $children === \false ? '(circular dependency aborted here)' : ''; $this->writeTreeLine(\rtrim(\sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn))); if (\is_array($children)) { $this->printTree($children, $prefix . ($isLast ? ' ' : '│ '), $level + 1); } } } private function writeTreeLine(string $line) : void { $io = $this->getIO(); if (!$io->isDecorated()) { $line = \str_replace(['└', '├', '──', '│'], ['`-', '|-', '-', '|'], $line); } $io->write($line); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Console\Input\InputArgument; use Composer\Console\Input\InputOption; /** * @author Niels Keurentjes */ class DependsCommand extends \Composer\Command\BaseDependencyCommand { use \Composer\Command\CompletionTrait; /** * Configure command metadata. */ protected function configure() : void { $this->setName('depends')->setAliases(['why'])->setDescription('Shows which packages cause the given package to be installed')->setDefinition([new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect', null, $this->suggestInstalledPackage(\true, \true)), new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'), new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'), new InputOption('locked', null, InputOption::VALUE_NONE, 'Read dependency information from composer.lock')])->setHelp(<<php composer.phar depends composer/composer Read more at https://getcomposer.org/doc/03-cli.md#depends-why EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { return parent::doExecute($input, $output); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Console\Input\InputArgument; use Composer\Console\Input\InputOption; /** * @author Niels Keurentjes */ class ProhibitsCommand extends \Composer\Command\BaseDependencyCommand { use \Composer\Command\CompletionTrait; /** * Configure command metadata. */ protected function configure() : void { $this->setName('prohibits')->setAliases(['why-not'])->setDescription('Shows which packages prevent the given package from being installed')->setDefinition([new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect', null, $this->suggestAvailablePackage()), new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::REQUIRED, 'Version constraint, which version you expected to be installed'), new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'), new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'), new InputOption('locked', null, InputOption::VALUE_NONE, 'Read dependency information from composer.lock')])->setHelp(<<php composer.phar prohibits composer/composer Read more at https://getcomposer.org/doc/03-cli.md#prohibits-why-not EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { return parent::doExecute($input, $output, \true); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Package\Link; use Composer\Semver\Constraint\Constraint; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Repository\PlatformRepository; use Composer\Repository\RootPackageRepository; use Composer\Repository\InstalledRepository; use Composer\Json\JsonFile; class CheckPlatformReqsCommand extends \Composer\Command\BaseCommand { protected function configure() : void { $this->setName('check-platform-reqs')->setDescription('Check that platform requirements are satisfied')->setDefinition([new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables checking of require-dev packages requirements.'), new InputOption('lock', null, InputOption::VALUE_NONE, 'Checks requirements only from the lock file, not from installed packages.'), new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text', ['json', 'text'])])->setHelp(<<php composer.phar check-platform-reqs EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->requireComposer(); $requires = []; $removePackages = []; if ($input->getOption('lock')) { $this->getIO()->writeError('Checking ' . ($input->getOption('no-dev') ? 'non-dev ' : '') . 'platform requirements using the lock file'); $installedRepo = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev')); } else { $installedRepo = $composer->getRepositoryManager()->getLocalRepository(); // fallback to lockfile if installed repo is empty if (!$installedRepo->getPackages()) { $this->getIO()->writeError('No vendor dir present, checking ' . ($input->getOption('no-dev') ? 'non-dev ' : '') . 'platform requirements from the lock file'); $installedRepo = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev')); } else { if ($input->getOption('no-dev')) { $removePackages = $installedRepo->getDevPackageNames(); } $this->getIO()->writeError('Checking ' . ($input->getOption('no-dev') ? 'non-dev ' : '') . 'platform requirements for packages in the vendor dir'); } } if (!$input->getOption('no-dev')) { foreach ($composer->getPackage()->getDevRequires() as $require => $link) { $requires[$require] = [$link]; } } $installedRepo = new InstalledRepository([$installedRepo, new RootPackageRepository(clone $composer->getPackage())]); foreach ($installedRepo->getPackages() as $package) { if (\in_array($package->getName(), $removePackages, \true)) { continue; } foreach ($package->getRequires() as $require => $link) { $requires[$require][] = $link; } } \ksort($requires); $installedRepo->addRepository(new PlatformRepository([], [])); $results = []; $exitCode = 0; /** * @var Link[] $links */ foreach ($requires as $require => $links) { if (PlatformRepository::isPlatformPackage($require)) { $candidates = $installedRepo->findPackagesWithReplacersAndProviders($require); if ($candidates) { $reqResults = []; foreach ($candidates as $candidate) { $candidateConstraint = null; if ($candidate->getName() === $require) { $candidateConstraint = new Constraint('=', $candidate->getVersion()); $candidateConstraint->setPrettyString($candidate->getPrettyVersion()); } else { foreach (\array_merge($candidate->getProvides(), $candidate->getReplaces()) as $link) { if ($link->getTarget() === $require) { $candidateConstraint = $link->getConstraint(); break; } } } // safety check for phpstan, but it should not be possible to get a candidate out of findPackagesWithReplacersAndProviders without a constraint matching $require if (!$candidateConstraint) { continue; } foreach ($links as $link) { if (!$link->getConstraint()->matches($candidateConstraint)) { $reqResults[] = [$candidate->getName() === $require ? $candidate->getPrettyName() : $require, $candidateConstraint->getPrettyString(), $link, 'failed', $candidate->getName() === $require ? '' : 'provided by ' . $candidate->getPrettyName() . '']; // skip to next candidate continue 2; } } $results[] = [$candidate->getName() === $require ? $candidate->getPrettyName() : $require, $candidateConstraint->getPrettyString(), null, 'success', $candidate->getName() === $require ? '' : 'provided by ' . $candidate->getPrettyName() . '']; // candidate matched, skip to next requirement continue 2; } // show the first error from every failed candidate $results = \array_merge($results, $reqResults); $exitCode = \max($exitCode, 1); continue; } $results[] = [$require, 'n/a', $links[0], 'missing', '']; $exitCode = \max($exitCode, 2); } } $this->printTable($output, $results, $input->getOption('format')); return $exitCode; } /** * @param mixed[] $results */ protected function printTable(OutputInterface $output, array $results, string $format) : void { $rows = []; foreach ($results as $result) { /** * @var Link|null $link */ [$platformPackage, $version, $link, $status, $provider] = $result; if ('json' === $format) { $rows[] = ["name" => $platformPackage, "version" => $version, "status" => \strip_tags($status), "failed_requirement" => $link instanceof Link ? ['source' => $link->getSource(), 'type' => $link->getDescription(), 'target' => $link->getTarget(), 'constraint' => $link->getPrettyConstraint()] : null, "provider" => $provider === '' ? null : \strip_tags($provider)]; } else { $rows[] = [$platformPackage, $version, $link, $link ? \sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '', \rtrim($status . ' ' . $provider)]; } } if ('json' === $format) { $this->getIO()->write(JsonFile::encode($rows)); } else { $this->renderTable($rows, $output); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use Composer\Factory; use Composer\Config; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\SelfUpdate\Keys; use Composer\SelfUpdate\Versions; use Composer\IO\IOInterface; use Composer\Downloader\FilesystemException; use Composer\Downloader\TransportException; use Phar; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Finder\Finder; /** * @author Igor Wiedler * @author Kevin Ran * @author Jordi Boggiano */ class SelfUpdateCommand extends \Composer\Command\BaseCommand { private const HOMEPAGE = 'getcomposer.org'; private const OLD_INSTALL_EXT = '-old.phar'; protected function configure() : void { $this->setName('self-update')->setAliases(['selfupdate'])->setDescription('Updates composer.phar to the latest version')->setDefinition([new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'), new InputOption('clean-backups', null, InputOption::VALUE_NONE, 'Delete old backups during an update. This makes the current version of composer the only backup available after the update'), new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'), new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'), new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'), new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'), new InputOption('1', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 1.x versions'), new InputOption('2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.x versions'), new InputOption('2.2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.2.x LTS versions'), new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit')])->setHelp(<<self-update command checks getcomposer.org for newer versions of composer and if found, installs the latest. php composer.phar self-update Read more at https://getcomposer.org/doc/03-cli.md#self-update-selfupdate EOT ); } /** * @throws FilesystemException */ protected function execute(InputInterface $input, OutputInterface $output) : int { if ($_SERVER['argv'][0] === 'Standard input code') { return 1; } // trigger autoloading of a few classes which may be needed when verifying/swapping the phar file // to ensure we do not try to load them from the new phar, see https://github.com/composer/composer/issues/10252 \class_exists('Composer\\Util\\Platform'); \class_exists('Composer\\Downloader\\FilesystemException'); $config = Factory::createConfig(); if ($config->get('disable-tls') === \true) { $baseUrl = 'http://' . self::HOMEPAGE; } else { $baseUrl = 'https://' . self::HOMEPAGE; } $io = $this->getIO(); $httpDownloader = Factory::createHttpDownloader($io, $config); $versionsUtil = new Versions($config, $httpDownloader); // switch channel if requested $requestedChannel = null; foreach (Versions::CHANNELS as $channel) { if ($input->getOption($channel)) { $requestedChannel = $channel; $versionsUtil->setChannel($channel, $io); break; } } if ($input->getOption('set-channel-only')) { return 0; } $cacheDir = $config->get('cache-dir'); $rollbackDir = $config->get('data-dir'); $home = $config->get('home'); $localFilename = Phar::running(\false); if ('' === $localFilename) { throw new \RuntimeException('Could not determine the location of the composer.phar file as it appears you are not running this code from a phar archive.'); } if ($input->getOption('update-keys')) { $this->fetchKeys($io, $config); return 0; } // ensure composer.phar location is accessible if (!\file_exists($localFilename)) { throw new FilesystemException('Composer update failed: the "' . $localFilename . '" is not accessible'); } // check if current dir is writable and if not try the cache dir from settings $tmpDir = \is_writable(\dirname($localFilename)) ? \dirname($localFilename) : $cacheDir; // check for permissions in local filesystem before start connection process if (!\is_writable($tmpDir)) { throw new FilesystemException('Composer update failed: the "' . $tmpDir . '" directory used to download the temp file could not be written'); } // check if composer is running as the same user that owns the directory root, only if POSIX is defined and callable if (\function_exists('posix_getpwuid') && \function_exists('posix_geteuid')) { $composerUser = \posix_getpwuid(\posix_geteuid()); $homeDirOwnerId = \fileowner($home); if (\is_array($composerUser) && $homeDirOwnerId !== \false) { $homeOwner = \posix_getpwuid($homeDirOwnerId); if (\is_array($homeOwner) && $composerUser['name'] !== $homeOwner['name']) { $io->writeError('You are running Composer as "' . $composerUser['name'] . '", while "' . $home . '" is owned by "' . $homeOwner['name'] . '"'); } } } if ($input->getOption('rollback')) { return $this->rollback($output, $rollbackDir, $localFilename); } if ($input->getArgument('command') === 'self' && $input->getArgument('version') === 'update') { $input->setArgument('version', null); } $latest = $versionsUtil->getLatest(); $latestStable = $versionsUtil->getLatest('stable'); try { $latestPreview = $versionsUtil->getLatest('preview'); } catch (\UnexpectedValueException $e) { $latestPreview = $latestStable; } $latestVersion = $latest['version']; $updateVersion = $input->getArgument('version') ?? $latestVersion; $currentMajorVersion = Preg::replace('{^(\\d+).*}', '$1', Composer::getVersion()); $updateMajorVersion = Preg::replace('{^(\\d+).*}', '$1', $updateVersion); $previewMajorVersion = Preg::replace('{^(\\d+).*}', '$1', $latestPreview['version']); if ($versionsUtil->getChannel() === 'stable' && null === $input->getArgument('version')) { // if requesting stable channel and no specific version, avoid automatically upgrading to the next major // simply output a warning that the next major stable is available and let users upgrade to it manually if ($currentMajorVersion < $updateMajorVersion) { $skippedVersion = $updateVersion; $versionsUtil->setChannel($currentMajorVersion); $latest = $versionsUtil->getLatest(); $latestStable = $versionsUtil->getLatest('stable'); $latestVersion = $latest['version']; $updateVersion = $latestVersion; $io->writeError('A new stable major version of Composer is available (' . $skippedVersion . '), run "composer self-update --' . $updateMajorVersion . '" to update to it. See also https://getcomposer.org/' . $updateMajorVersion . ''); } elseif ($currentMajorVersion < $previewMajorVersion) { // promote next major version if available in preview $io->writeError('A preview release of the next major version of Composer is available (' . $latestPreview['version'] . '), run "composer self-update --preview" to give it a try. See also https://github.com/composer/composer/releases for changelogs.'); } } $effectiveChannel = $requestedChannel === null ? $versionsUtil->getChannel() : $requestedChannel; if (\is_numeric($effectiveChannel) && \strpos($latestStable['version'], $effectiveChannel) !== 0) { $io->writeError('Warning: You forced the install of ' . $latestVersion . ' via --' . $effectiveChannel . ', but ' . $latestStable['version'] . ' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); } if (isset($latest['eol'])) { $io->writeError('Warning: Version ' . $latestVersion . ' is EOL / End of Life. ' . $latestStable['version'] . ' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); } if (Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) { $io->writeError('You can not update to a specific SHA-1 as those phars are not available for download'); return 1; } $channelString = $versionsUtil->getChannel(); if (\is_numeric($channelString)) { $channelString .= '.x'; } if (Composer::VERSION === $updateVersion) { $io->writeError(\sprintf('You are already using the latest available Composer version %s (%s channel).', $updateVersion, $channelString)); // remove all backups except for the most recent, if any if ($input->getOption('clean-backups')) { $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir)); } return 0; } $tempFilename = $tmpDir . '/' . \basename($localFilename, '.phar') . '-temp' . \random_int(0, 10000000) . '.phar'; $backupFile = \sprintf('%s/%s-%s%s', $rollbackDir, \strtr(Composer::RELEASE_DATE, ' :', '_-'), Preg::replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION), self::OLD_INSTALL_EXT); $updatingToTag = !Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion); $io->write(\sprintf("Upgrading to version %s (%s channel).", $updateVersion, $channelString)); $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar'); try { $signature = $httpDownloader->get($remoteFilename . '.sig')->getBody(); } catch (TransportException $e) { if ($e->getStatusCode() === 404) { throw new \InvalidArgumentException('Version "' . $updateVersion . '" could not be found.', 0, $e); } throw $e; } $io->writeError(' ', \false); $httpDownloader->copy($remoteFilename, $tempFilename); $io->writeError(''); if (!\file_exists($tempFilename) || null === $signature || '' === $signature) { $io->writeError('The download of the new composer version failed for an unexpected reason'); return 1; } // verify phar signature if (!\extension_loaded('openssl') && $config->get('disable-tls')) { $io->writeError('Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls'); } else { if (!\extension_loaded('openssl')) { throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. ' . 'If you can not enable the openssl extension, you can disable this error, at your own risk, by setting the \'disable-tls\' option to true.'); } $sigFile = 'file://' . $home . '/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub'); if (!\file_exists($sigFile)) { \file_put_contents($home . '/keys.dev.pub', <<getOption('clean-backups')) { $this->cleanBackups($rollbackDir); } if (!$this->setLocalPhar($localFilename, $tempFilename, $backupFile)) { @\unlink($tempFilename); return 1; } if (\file_exists($backupFile)) { $io->writeError(\sprintf('Use composer self-update --rollback to return to version %s', Composer::VERSION)); } else { $io->writeError('A backup of the current version could not be written to ' . $backupFile . ', no rollback possible'); } return 0; } /** * @throws \Exception */ protected function fetchKeys(IOInterface $io, Config $config) : void { if (!$io->isInteractive()) { throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively'); } $io->write('Open https://composer.github.io/pubkeys.html to find the latest keys'); $validator = static function ($value) : string { $value = (string) $value; if (!Preg::isMatch('{^-----BEGIN PUBLIC KEY-----$}', \trim($value))) { throw new \UnexpectedValueException('Invalid input'); } return \trim($value) . "\n"; }; $devKey = ''; while (!Preg::isMatch('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) { $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator); while ($line = $io->ask('', '')) { $devKey .= \trim($line) . "\n"; if (\trim($line) === '-----END PUBLIC KEY-----') { break; } } } \file_put_contents($keyPath = $config->get('home') . '/keys.dev.pub', $match[0]); $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath)); $tagsKey = ''; while (!Preg::isMatch('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) { $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator); while ($line = $io->ask('', '')) { $tagsKey .= \trim($line) . "\n"; if (\trim($line) === '-----END PUBLIC KEY-----') { break; } } } \file_put_contents($keyPath = $config->get('home') . '/keys.tags.pub', $match[0]); $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath)); $io->write('Public keys stored in ' . $config->get('home')); } /** * @throws FilesystemException */ protected function rollback(OutputInterface $output, string $rollbackDir, string $localFilename) : int { $rollbackVersion = $this->getLastBackupVersion($rollbackDir); if (null === $rollbackVersion) { throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "' . $rollbackDir . '"'); } $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT; if (!\is_file($oldFile)) { throw new FilesystemException('Composer rollback failed: "' . $oldFile . '" could not be found'); } if (!Filesystem::isReadable($oldFile)) { throw new FilesystemException('Composer rollback failed: "' . $oldFile . '" could not be read'); } $io = $this->getIO(); $io->writeError(\sprintf("Rolling back to version %s.", $rollbackVersion)); if (!$this->setLocalPhar($localFilename, $oldFile)) { return 1; } return 0; } /** * Checks if the downloaded/rollback phar is valid then moves it * * @param string $localFilename The composer.phar location * @param string $newFilename The downloaded or backup phar * @param string $backupTarget The filename to use for the backup * @throws FilesystemException If the file cannot be moved * @return bool Whether the phar is valid and has been moved */ protected function setLocalPhar(string $localFilename, string $newFilename, ?string $backupTarget = null) : bool { $io = $this->getIO(); $perms = @\fileperms($localFilename); if ($perms !== \false) { @\chmod($newFilename, $perms); } // check phar validity if (!$this->validatePhar($newFilename, $error)) { $io->writeError('The ' . ($backupTarget !== null ? 'update' : 'backup') . ' file is corrupted (' . $error . ')'); if ($backupTarget !== null) { $io->writeError('Please re-run the self-update command to try again.'); } return \false; } // copy current file into backups dir if ($backupTarget !== null) { @\copy($localFilename, $backupTarget); } try { if (Platform::isWindows()) { // use copy to apply permissions from the destination directory // as rename uses source permissions and may block other users \copy($newFilename, $localFilename); @\unlink($newFilename); } else { \rename($newFilename, $localFilename); } return \true; } catch (\Exception $e) { // see if we can run this operation as an Admin on Windows if (!\is_writable(\dirname($localFilename)) && $io->isInteractive() && $this->isWindowsNonAdminUser()) { return $this->tryAsWindowsAdmin($localFilename, $newFilename); } @\unlink($newFilename); $action = 'Composer ' . ($backupTarget !== null ? 'update' : 'rollback'); throw new FilesystemException($action . ' failed: "' . $localFilename . '" could not be written.' . \PHP_EOL . $e->getMessage()); } } protected function cleanBackups(string $rollbackDir, ?string $except = null) : void { $finder = $this->getOldInstallationFinder($rollbackDir); $io = $this->getIO(); $fs = new Filesystem(); foreach ($finder as $file) { if ($file->getBasename(self::OLD_INSTALL_EXT) === $except) { continue; } $file = (string) $file; $io->writeError('Removing: ' . $file . ''); $fs->remove($file); } } protected function getLastBackupVersion(string $rollbackDir) : ?string { $finder = $this->getOldInstallationFinder($rollbackDir); $finder->sortByName(); $files = \iterator_to_array($finder); if (\count($files) > 0) { return \end($files)->getBasename(self::OLD_INSTALL_EXT); } return null; } protected function getOldInstallationFinder(string $rollbackDir) : Finder { return Finder::create()->depth(0)->files()->name('*' . self::OLD_INSTALL_EXT)->in($rollbackDir); } /** * Validates the downloaded/backup phar file * * @param string $pharFile The downloaded or backup phar * @param null|string $error Set by method on failure * * Code taken from getcomposer.org/installer. Any changes should be made * there and replicated here * * @throws \Exception * @return bool If the operation succeeded */ protected function validatePhar(string $pharFile, ?string &$error) : bool { if ((bool) \ini_get('phar.readonly')) { return \true; } try { // Test the phar validity $phar = new \Phar($pharFile); // Free the variable to unlock the file unset($phar); $result = \true; } catch (\Exception $e) { if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { throw $e; } $error = $e->getMessage(); $result = \false; } return $result; } /** * Returns true if this is a non-admin Windows user account */ protected function isWindowsNonAdminUser() : bool { if (!Platform::isWindows()) { return \false; } // fltmc.exe manages filter drivers and errors without admin privileges \exec('fltmc.exe filters', $output, $exitCode); return $exitCode !== 0; } /** * Invokes a UAC prompt to update composer.phar as an admin * * Uses a .vbs script to elevate and run the cmd.exe copy command. * * @param string $localFilename The composer.phar location * @param string $newFilename The downloaded or backup phar * @return bool Whether composer.phar has been updated */ protected function tryAsWindowsAdmin(string $localFilename, string $newFilename) : bool { $io = $this->getIO(); $io->writeError('Unable to write "' . $localFilename . '". Access is denied.'); $helpMessage = 'Please run the self-update command as an Administrator.'; $question = 'Complete this operation with Administrator privileges [Y,n]? '; if (!$io->askConfirmation($question, \true)) { $io->writeError('Operation cancelled. ' . $helpMessage . ''); return \false; } $tmpFile = \tempnam(\sys_get_temp_dir(), ''); if (\false === $tmpFile) { $io->writeError('Operation failed.' . $helpMessage . ''); return \false; } $script = $tmpFile . '.vbs'; \rename($tmpFile, $script); $checksum = \hash_file('sha256', $newFilename); // cmd's internal copy is fussy about backslashes $source = \str_replace('/', '\\', $newFilename); $destination = \str_replace('/', '\\', $localFilename); $vbs = <<writeError('Operation succeeded.'); @\unlink($newFilename); } else { $io->writeError('Operation failed.' . $helpMessage . ''); } return $result; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\DependencyResolver\Request; use Composer\Package\AliasPackage; use Composer\Package\CompletePackageInterface; use Composer\Package\Loader\RootPackageLoader; use Composer\Package\Locker; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionBumper; use Composer\Package\Version\VersionSelector; use Composer\Pcre\Preg; use Composer\Repository\RepositorySet; use Composer\Util\Filesystem; use Composer\Util\PackageSorter; use _ContaoManager\Seld\Signal\SignalHandler; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputArgument; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Factory; use Composer\Installer; use Composer\Installer\InstallerEvents; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; use Composer\Package\Version\VersionParser; use Composer\Package\Loader\ArrayLoader; use Composer\Package\BasePackage; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\IO\IOInterface; use Composer\Advisory\Auditor; use Composer\Util\Silencer; /** * @author Jérémy Romey * @author Jordi Boggiano */ class RequireCommand extends \Composer\Command\BaseCommand { use \Composer\Command\CompletionTrait; use \Composer\Command\PackageDiscoveryTrait; /** @var bool */ private $newlyCreated; /** @var bool */ private $firstRequire; /** @var JsonFile */ private $json; /** @var string */ private $file; /** @var string */ private $composerBackup; /** @var string file name */ private $lock; /** @var ?string contents before modification if the lock file exists */ private $lockBackup; /** @var bool */ private $dependencyResolutionCompleted = \false; /** * @return void */ protected function configure() { $this->setName('require')->setAliases(['r'])->setDescription('Adds required packages to your composer.json and installs them')->setDefinition([new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"', null, $this->suggestAvailablePackageInclPlatform()), new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist (default behavior).'), new InputOption('prefer-install', null, InputOption::VALUE_REQUIRED, 'Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).', null, $this->suggestPreferInstall()), new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'DEPRECATED: This flag does not exist anymore.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies (implies --no-install).'), new InputOption('no-install', null, InputOption::VALUE_NONE, 'Skip the install step after updating the composer.lock file.'), new InputOption('no-audit', null, InputOption::VALUE_NONE, 'Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).'), new InputOption('audit-format', null, InputOption::VALUE_REQUIRED, 'Audit output format. Must be "table", "plain", "json", or "summary".', Auditor::FORMAT_SUMMARY, Auditor::FORMATS), new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'), new InputOption('update-with-dependencies', 'w', InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'), new InputOption('update-with-all-dependencies', 'W', InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'), new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-dependencies'), new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Alias for --update-with-all-dependencies'), new InputOption('ignore-platform-req', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore a specific platform requirement (php & ext- packages).'), new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore all platform requirements (php & ext- packages).'), new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies (can also be set via the COMPOSER_PREFER_STABLE=1 env var).'), new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies (can also be set via the COMPOSER_PREFER_LOWEST=1 env var).'), new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During an update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'), new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'), new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'), new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'), new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'), new InputOption('apcu-autoloader-prefix', null, InputOption::VALUE_REQUIRED, 'Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader')])->setHelp(<<file = Factory::getComposerFile(); $io = $this->getIO(); if ($input->getOption('no-suggest')) { $io->writeError('You are using the deprecated option "--no-suggest". It has no effect and will break in Composer 3.'); } $this->newlyCreated = !\file_exists($this->file); if ($this->newlyCreated && !\file_put_contents($this->file, "{\n}\n")) { $io->writeError('' . $this->file . ' could not be created.'); return 1; } if (!Filesystem::isReadable($this->file)) { $io->writeError('' . $this->file . ' is not readable.'); return 1; } if (\filesize($this->file) === 0) { \file_put_contents($this->file, "{\n}\n"); } $this->json = new JsonFile($this->file); $this->lock = Factory::getLockFile($this->file); $this->composerBackup = \file_get_contents($this->json->getPath()); $this->lockBackup = \file_exists($this->lock) ? \file_get_contents($this->lock) : null; $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) { $this->getIO()->writeError('Received ' . $signal . ', aborting', \true, IOInterface::DEBUG); $this->revertComposerFile(); $handler->exitWithLastSignal(); }); // check for writability by writing to the file as is_writable can not be trusted on network-mounts // see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926 if (!\is_writable($this->file) && \false === Silencer::call('file_put_contents', $this->file, $this->composerBackup)) { $io->writeError('' . $this->file . ' is not writable.'); return 1; } if ($input->getOption('fixed') === \true) { $config = $this->json->read(); $packageType = empty($config['type']) ? 'library' : $config['type']; /** * @see https://github.com/composer/composer/pull/8313#issuecomment-532637955 */ if ($packageType !== 'project' && !$input->getOption('dev')) { $io->writeError('The "--fixed" option is only allowed for packages with a "project" type or for dev dependencies to prevent possible misuses.'); if (!isset($config['type'])) { $io->writeError('If your package is not a library, you can explicitly specify the "type" by using "composer config type project".'); } return 1; } } $composer = $this->requireComposer(); $repos = $composer->getRepositoryManager()->getRepositories(); $platformOverrides = $composer->getConfig()->get('platform'); // initialize $this->repos as it is used by the PackageDiscoveryTrait $this->repos = new CompositeRepository(\array_merge([$platformRepo = new PlatformRepository([], $platformOverrides)], $repos)); if ($composer->getPackage()->getPreferStable()) { $preferredStability = 'stable'; } else { $preferredStability = $composer->getPackage()->getMinimumStability(); } try { $requirements = $this->determineRequirements( $input, $output, $input->getArgument('packages'), $platformRepo, $preferredStability, $input->getOption('no-update'), // if there is no update, we need to use the best possible version constraint directly as we cannot rely on the solver to guess the best constraint $input->getOption('fixed') ); } catch (\Exception $e) { if ($this->newlyCreated) { $this->revertComposerFile(); throw new \RuntimeException('No composer.json present in the current directory (' . $this->file . '), this may be the cause of the following exception.', 0, $e); } throw $e; } $requirements = $this->formatRequirements($requirements); if (!$input->getOption('dev') && $io->isInteractive() && !$composer->isGlobal()) { $devPackages = []; $devTags = ['dev', 'testing', 'static analysis']; $currentRequiresByKey = $this->getPackagesByRequireKey(); foreach ($requirements as $name => $version) { // skip packages which are already in the composer.json as those have already been decided if (isset($currentRequiresByKey[$name])) { continue; } $pkg = PackageSorter::getMostCurrentVersion($this->getRepos()->findPackages($name)); if ($pkg instanceof CompletePackageInterface) { $pkgDevTags = \array_intersect($devTags, \array_map('strtolower', $pkg->getKeywords())); if (\count($pkgDevTags) > 0) { $devPackages[] = $pkgDevTags; } } } if (\count($devPackages) === \count($requirements)) { $plural = \count($requirements) > 1 ? 's' : ''; $plural2 = \count($requirements) > 1 ? 'are' : 'is'; $plural3 = \count($requirements) > 1 ? 'they are' : 'it is'; $pkgDevTags = \array_unique(\array_merge(...$devPackages)); $io->warning('The package' . $plural . ' you required ' . $plural2 . ' recommended to be placed in require-dev (because ' . $plural3 . ' tagged as "' . \implode('", "', $pkgDevTags) . '") but you did not use --dev.'); if ($io->askConfirmation('Do you want to re-run the command with --dev? [yes]? ')) { $input->setOption('dev', \true); } } unset($devPackages, $pkgDevTags); } $requireKey = $input->getOption('dev') ? 'require-dev' : 'require'; $removeKey = $input->getOption('dev') ? 'require' : 'require-dev'; // check which requirements need the version guessed $requirementsToGuess = []; foreach ($requirements as $package => $constraint) { if ($constraint === 'guess') { $requirements[$package] = '*'; $requirementsToGuess[] = $package; } } // validate requirements format $versionParser = new VersionParser(); foreach ($requirements as $package => $constraint) { if (\strtolower($package) === $composer->getPackage()->getName()) { $io->writeError(\sprintf('Root package \'%s\' cannot require itself in its composer.json', $package)); return 1; } if ($constraint === 'self.version') { continue; } $versionParser->parseConstraints($constraint); } $inconsistentRequireKeys = $this->getInconsistentRequireKeys($requirements, $requireKey); if (\count($inconsistentRequireKeys) > 0) { foreach ($inconsistentRequireKeys as $package) { $io->warning(\sprintf('%s is currently present in the %s key and you ran the command %s the --dev flag, which will move it to the %s key.', $package, $removeKey, $input->getOption('dev') ? 'with' : 'without', $requireKey)); } if ($io->isInteractive()) { if (!$io->askConfirmation(\sprintf('Do you want to move %s? [no]? ', \count($inconsistentRequireKeys) > 1 ? 'these requirements' : 'this requirement'), \false)) { if (!$io->askConfirmation(\sprintf('Do you want to re-run the command %s --dev? [yes]? ', $input->getOption('dev') ? 'without' : 'with'), \true)) { return 0; } $input->setOption('dev', \true); [$requireKey, $removeKey] = [$removeKey, $requireKey]; } } } $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages'); $this->firstRequire = $this->newlyCreated; if (!$this->firstRequire) { $composerDefinition = $this->json->read(); if (\count($composerDefinition['require'] ?? []) === 0 && \count($composerDefinition['require-dev'] ?? []) === 0) { $this->firstRequire = \true; } } if (!$input->getOption('dry-run')) { $this->updateFile($this->json, $requirements, $requireKey, $removeKey, $sortPackages); } $io->writeError('' . $this->file . ' has been ' . ($this->newlyCreated ? 'created' : 'updated') . ''); if ($input->getOption('no-update')) { return 0; } $composer->getPluginManager()->deactivateInstalledPlugins(); try { $result = $this->doUpdate($input, $output, $io, $requirements, $requireKey, $removeKey); if ($result === 0 && \count($requirementsToGuess) > 0) { $result = $this->updateRequirementsAfterResolution($requirementsToGuess, $requireKey, $removeKey, $sortPackages, $input->getOption('dry-run'), $input->getOption('fixed')); } return $result; } catch (\Exception $e) { if (!$this->dependencyResolutionCompleted) { $this->revertComposerFile(); } throw $e; } finally { if ($input->getOption('dry-run') && $this->newlyCreated) { @\unlink($this->json->getPath()); } $signalHandler->unregister(); } } /** * @param array $newRequirements * @return string[] */ private function getInconsistentRequireKeys(array $newRequirements, string $requireKey) : array { $requireKeys = $this->getPackagesByRequireKey(); $inconsistentRequirements = []; foreach ($requireKeys as $package => $packageRequireKey) { if (!isset($newRequirements[$package])) { continue; } if ($requireKey !== $packageRequireKey) { $inconsistentRequirements[] = $package; } } return $inconsistentRequirements; } /** * @return array */ private function getPackagesByRequireKey() : array { $composerDefinition = $this->json->read(); $require = []; $requireDev = []; if (isset($composerDefinition['require'])) { $require = $composerDefinition['require']; } if (isset($composerDefinition['require-dev'])) { $requireDev = $composerDefinition['require-dev']; } return \array_merge(\array_fill_keys(\array_keys($require), 'require'), \array_fill_keys(\array_keys($requireDev), 'require-dev')); } /** * @param array $requirements * @param 'require'|'require-dev' $requireKey * @param 'require'|'require-dev' $removeKey * @throws \Exception */ private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements, string $requireKey, string $removeKey) : int { // Update packages $this->resetComposer(); $composer = $this->requireComposer(); $this->dependencyResolutionCompleted = \false; $composer->getEventDispatcher()->addListener(InstallerEvents::PRE_OPERATIONS_EXEC, function () : void { $this->dependencyResolutionCompleted = \true; }, 10000); if ($input->getOption('dry-run')) { $rootPackage = $composer->getPackage(); $links = ['require' => $rootPackage->getRequires(), 'require-dev' => $rootPackage->getDevRequires()]; $loader = new ArrayLoader(); $newLinks = $loader->parseLinks($rootPackage->getName(), $rootPackage->getPrettyVersion(), BasePackage::$supportedLinkTypes[$requireKey]['method'], $requirements); $links[$requireKey] = \array_merge($links[$requireKey], $newLinks); foreach ($requirements as $package => $constraint) { unset($links[$removeKey][$package]); } $rootPackage->setRequires($links['require']); $rootPackage->setDevRequires($links['require-dev']); // extract stability flags & references as they weren't present when loading the unmodified composer.json $references = $rootPackage->getReferences(); $references = RootPackageLoader::extractReferences($requirements, $references); $rootPackage->setReferences($references); $stabilityFlags = $rootPackage->getStabilityFlags(); $stabilityFlags = RootPackageLoader::extractStabilityFlags($requirements, $rootPackage->getMinimumStability(), $stabilityFlags); $rootPackage->setStabilityFlags($stabilityFlags); unset($stabilityFlags, $references); } $updateDevMode = !$input->getOption('update-no-dev'); $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader'); $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative'); $apcuPrefix = $input->getOption('apcu-autoloader-prefix'); $apcu = $apcuPrefix !== null || $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader'); $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED; $flags = ''; if ($input->getOption('update-with-all-dependencies') || $input->getOption('with-all-dependencies')) { $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS; $flags .= ' --with-all-dependencies'; } elseif ($input->getOption('update-with-dependencies') || $input->getOption('with-dependencies')) { $updateAllowTransitiveDependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE; $flags .= ' --with-dependencies'; } $io->writeError('Running composer update ' . \implode(' ', \array_keys($requirements)) . $flags . ''); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $composer->getInstallationManager()->setOutputProgress(!$input->getOption('no-progress')); $install = Installer::create($io, $composer); [$preferSource, $preferDist] = $this->getPreferredInstallOptions($composer->getConfig(), $input); $install->setDryRun($input->getOption('dry-run'))->setVerbose($input->getOption('verbose'))->setPreferSource($preferSource)->setPreferDist($preferDist)->setDevMode($updateDevMode)->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setApcuAutoloader($apcu, $apcuPrefix)->setUpdate(\true)->setInstall(!$input->getOption('no-install'))->setUpdateAllowTransitiveDependencies($updateAllowTransitiveDependencies)->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input))->setPreferStable($input->getOption('prefer-stable'))->setPreferLowest($input->getOption('prefer-lowest'))->setAudit(!$input->getOption('no-audit'))->setAuditFormat($this->getAuditFormat($input))->setMinimalUpdate($input->getOption('minimal-changes')); // if no lock is present, or the file is brand new, we do not do a // partial update as this is not supported by the Installer if (!$this->firstRequire && $composer->getLocker()->isLocked()) { $install->setUpdateAllowList(\array_keys($requirements)); } $status = $install->run(); if ($status !== 0 && $status !== Installer::ERROR_AUDIT_FAILED) { if ($status === Installer::ERROR_DEPENDENCY_RESOLUTION_FAILED) { foreach ($this->normalizeRequirements($input->getArgument('packages')) as $req) { if (!isset($req['version'])) { $io->writeError('You can also try re-running composer require with an explicit version constraint, e.g. "composer require ' . $req['name'] . ':*" to figure out if any version is installable, or "composer require ' . $req['name'] . ':^2.1" if you know which you need.'); break; } } } $this->revertComposerFile(); } return $status; } /** * @param list $requirementsToUpdate */ private function updateRequirementsAfterResolution(array $requirementsToUpdate, string $requireKey, string $removeKey, bool $sortPackages, bool $dryRun, bool $fixed) : int { $composer = $this->requireComposer(); $locker = $composer->getLocker(); $requirements = []; $versionSelector = new VersionSelector(new RepositorySet()); $repo = $locker->isLocked() ? $composer->getLocker()->getLockedRepository(\true) : $composer->getRepositoryManager()->getLocalRepository(); foreach ($requirementsToUpdate as $packageName) { $package = $repo->findPackage($packageName, '*'); while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } if (!$package instanceof PackageInterface) { continue; } if ($fixed) { $requirements[$packageName] = $package->getPrettyVersion(); } else { $requirements[$packageName] = $versionSelector->findRecommendedRequireVersion($package); } $this->getIO()->writeError(\sprintf('Using version %s for %s', $requirements[$packageName], $packageName)); if (Preg::isMatch('{^dev-(?!main$|master$|trunk$|latest$)}', $requirements[$packageName])) { $this->getIO()->warning('Version ' . $requirements[$packageName] . ' looks like it may be a feature branch which is unlikely to keep working in the long run and may be in an unstable state'); if ($this->getIO()->isInteractive() && !$this->getIO()->askConfirmation('Are you sure you want to use this constraint (Y) or would you rather abort (n) the whole operation [Y,n]? ')) { $this->revertComposerFile(); return 1; } } } if (!$dryRun) { $this->updateFile($this->json, $requirements, $requireKey, $removeKey, $sortPackages); if ($locker->isLocked() && $composer->getConfig()->get('lock')) { $stabilityFlags = RootPackageLoader::extractStabilityFlags($requirements, $composer->getPackage()->getMinimumStability(), []); $locker->updateHash($this->json, function (array $lockData) use($stabilityFlags) { foreach ($stabilityFlags as $packageName => $flag) { $lockData['stability-flags'][$packageName] = $flag; } return $lockData; }); } } return 0; } /** * @param array $new */ private function updateFile(JsonFile $json, array $new, string $requireKey, string $removeKey, bool $sortPackages) : void { if ($this->updateFileCleanly($json, $new, $requireKey, $removeKey, $sortPackages)) { return; } $composerDefinition = $this->json->read(); foreach ($new as $package => $version) { $composerDefinition[$requireKey][$package] = $version; unset($composerDefinition[$removeKey][$package]); if (isset($composerDefinition[$removeKey]) && \count($composerDefinition[$removeKey]) === 0) { unset($composerDefinition[$removeKey]); } } $this->json->write($composerDefinition); } /** * @param array $new */ private function updateFileCleanly(JsonFile $json, array $new, string $requireKey, string $removeKey, bool $sortPackages) : bool { $contents = \file_get_contents($json->getPath()); $manipulator = new JsonManipulator($contents); foreach ($new as $package => $constraint) { if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) { return \false; } if (!$manipulator->removeSubNode($removeKey, $package)) { return \false; } } $manipulator->removeMainKeyIfEmpty($removeKey); \file_put_contents($json->getPath(), $manipulator->getContents()); return \true; } protected function interact(InputInterface $input, OutputInterface $output) : void { } private function revertComposerFile() : void { $io = $this->getIO(); if ($this->newlyCreated) { $io->writeError("\n" . 'Installation failed, deleting ' . $this->file . '.'); \unlink($this->json->getPath()); if (\file_exists($this->lock)) { \unlink($this->lock); } } else { $msg = ' to its '; if ($this->lockBackup) { $msg = ' and ' . $this->lock . ' to their '; } $io->writeError("\n" . 'Installation failed, reverting ' . $this->file . $msg . 'original content.'); \file_put_contents($this->json->getPath(), $this->composerBackup); if ($this->lockBackup) { \file_put_contents($this->lock, $this->lockBackup); } } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Repository\InstalledRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RootPackageRepository; use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput; /** * Adds completion to arguments and options. * * @internal */ trait CompletionTrait { /** * @see BaseCommand::requireComposer() */ public abstract function requireComposer(?bool $disablePlugins = null, ?bool $disableScripts = null) : Composer; /** * Suggestion values for "prefer-install" option * * @return list */ private function suggestPreferInstall() : array { return ['dist', 'source', 'auto']; } /** * Suggest package names from root requirements. */ private function suggestRootRequirement() : \Closure { return function (CompletionInput $input) : array { $composer = $this->requireComposer(); return \array_merge(\array_keys($composer->getPackage()->getRequires()), \array_keys($composer->getPackage()->getDevRequires())); }; } /** * Suggest package names from installed. */ private function suggestInstalledPackage(bool $includeRootPackage = \true, bool $includePlatformPackages = \false) : \Closure { return function (CompletionInput $input) use($includeRootPackage, $includePlatformPackages) : array { $composer = $this->requireComposer(); $installedRepos = []; if ($includeRootPackage) { $installedRepos[] = new RootPackageRepository(clone $composer->getPackage()); } $locker = $composer->getLocker(); if ($locker->isLocked()) { $installedRepos[] = $locker->getLockedRepository(\true); } else { $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository(); } $platformHint = []; if ($includePlatformPackages) { if ($locker->isLocked()) { $platformRepo = new PlatformRepository([], $locker->getPlatformOverrides()); } else { $platformRepo = new PlatformRepository([], $composer->getConfig()->get('platform')); } if ($input->getCompletionValue() === '') { // to reduce noise, when no text is yet entered we list only two entries for ext- and lib- prefixes $hintsToFind = ['ext-' => 0, 'lib-' => 0, 'php' => 99, 'composer' => 99]; foreach ($platformRepo->getPackages() as $pkg) { foreach ($hintsToFind as $hintPrefix => $hintCount) { if (\str_starts_with($pkg->getName(), $hintPrefix)) { if ($hintCount === 0 || $hintCount >= 99) { $platformHint[] = $pkg->getName(); $hintsToFind[$hintPrefix]++; } elseif ($hintCount === 1) { unset($hintsToFind[$hintPrefix]); $platformHint[] = \substr($pkg->getName(), 0, \max(\strlen($pkg->getName()) - 3, \strlen($hintPrefix) + 1)) . '...'; } continue 2; } } } } else { $installedRepos[] = $platformRepo; } } $installedRepo = new InstalledRepository($installedRepos); return \array_merge(\array_map(static function (PackageInterface $package) { return $package->getName(); }, $installedRepo->getPackages()), $platformHint); }; } /** * Suggest package names from installed. */ private function suggestInstalledPackageTypes(bool $includeRootPackage = \true) : \Closure { return function (CompletionInput $input) use($includeRootPackage) : array { $composer = $this->requireComposer(); $installedRepos = []; if ($includeRootPackage) { $installedRepos[] = new RootPackageRepository(clone $composer->getPackage()); } $locker = $composer->getLocker(); if ($locker->isLocked()) { $installedRepos[] = $locker->getLockedRepository(\true); } else { $installedRepos[] = $composer->getRepositoryManager()->getLocalRepository(); } $installedRepo = new InstalledRepository($installedRepos); return \array_values(\array_unique(\array_map(static function (PackageInterface $package) { return $package->getType(); }, $installedRepo->getPackages()))); }; } /** * Suggest package names available on all configured repositories. */ private function suggestAvailablePackage(int $max = 99) : \Closure { return function (CompletionInput $input) use($max) : array { if ($max < 1) { return []; } $composer = $this->requireComposer(); $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); $results = []; $showVendors = \false; if (!\str_contains($input->getCompletionValue(), '/')) { $results = $repos->search('^' . \preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_VENDOR); $showVendors = \true; } // if we get a single vendor, we expand it into its contents already if (\count($results) <= 1) { $results = $repos->search('^' . \preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_NAME); $showVendors = \false; } $results = \array_column($results, 'name'); if ($showVendors) { $results = \array_map(static function (string $name) : string { return $name . '/'; }, $results); // sort shorter results first to avoid auto-expanding the completion to a longer string than needed \usort($results, static function (string $a, string $b) { $lenA = \strlen($a); $lenB = \strlen($b); if ($lenA === $lenB) { return $a <=> $b; } return $lenA - $lenB; }); $pinned = []; // ensure if the input is an exact match that it is always in the result set $completionInput = $input->getCompletionValue() . '/'; if (\false !== ($exactIndex = \array_search($completionInput, $results, \true))) { $pinned[] = $completionInput; \array_splice($results, $exactIndex, 1); } return \array_merge($pinned, \array_slice($results, 0, $max - \count($pinned))); } return \array_slice($results, 0, $max); }; } /** * Suggest package names available on all configured repositories or * platform packages from the ones available on the currently-running PHP */ private function suggestAvailablePackageInclPlatform() : \Closure { return function (CompletionInput $input) : array { if (Preg::isMatch('{^(ext|lib|php)(-|$)|^com}', $input->getCompletionValue())) { $matches = $this->suggestPlatformPackage()($input); } else { $matches = []; } return \array_merge($matches, $this->suggestAvailablePackage(99 - \count($matches))($input)); }; } /** * Suggest platform packages from the ones available on the currently-running PHP */ private function suggestPlatformPackage() : \Closure { return function (CompletionInput $input) : array { $repos = new PlatformRepository([], $this->requireComposer()->getConfig()->get('platform')); $pattern = BasePackage::packageNameToRegexp($input->getCompletionValue() . '*'); return \array_filter(\array_map(static function (PackageInterface $package) { return $package->getName(); }, $repos->getPackages()), static function (string $name) use($pattern) : bool { return Preg::isMatch($pattern, $name); }); }; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Cache; use Composer\Factory; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author David Neilsen */ class ClearCacheCommand extends \Composer\Command\BaseCommand { protected function configure() : void { $this->setName('clear-cache')->setAliases(['clearcache', 'cc'])->setDescription('Clears composer\'s internal package cache')->setDefinition([new InputOption('gc', null, InputOption::VALUE_NONE, 'Only run garbage collection, not a full cache clear')])->setHelp(<<clear-cache deletes all cached packages from composer's cache directory. Read more at https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-cc EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->tryComposer(); if ($composer !== null) { $config = $composer->getConfig(); } else { $config = Factory::createConfig(); } $io = $this->getIO(); $cachePaths = ['cache-vcs-dir' => $config->get('cache-vcs-dir'), 'cache-repo-dir' => $config->get('cache-repo-dir'), 'cache-files-dir' => $config->get('cache-files-dir'), 'cache-dir' => $config->get('cache-dir')]; foreach ($cachePaths as $key => $cachePath) { // only individual dirs get garbage collected if ($key === 'cache-dir' && $input->getOption('gc')) { continue; } $cachePath = \realpath($cachePath); if (!$cachePath) { $io->writeError("Cache directory does not exist ({$key}): {$cachePath}"); continue; } $cache = new Cache($io, $cachePath); $cache->setReadOnly($config->get('cache-read-only')); if (!$cache->isEnabled()) { $io->writeError("Cache is not enabled ({$key}): {$cachePath}"); continue; } if ($input->getOption('gc')) { $io->writeError("Garbage-collecting cache ({$key}): {$cachePath}"); if ($key === 'cache-files-dir') { $cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize')); } elseif ($key === 'cache-repo-dir') { $cache->gc($config->get('cache-ttl'), 1024 * 1024 * 1024); } elseif ($key === 'cache-vcs-dir') { $cache->gcVcsCache($config->get('cache-ttl')); } } else { $io->writeError("Clearing cache ({$key}): {$cachePath}"); $cache->clear(); } } if ($input->getOption('gc')) { $io->writeError('All caches garbage-collected.'); } else { $io->writeError('All caches cleared.'); } return 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Advisory\Auditor; use Composer\Composer; use Composer\Factory; use Composer\Config; use Composer\Downloader\TransportException; use Composer\IO\BufferIO; use Composer\Json\JsonFile; use Composer\Json\JsonValidationException; use Composer\Package\Locker; use Composer\Package\RootPackage; use Composer\Package\Version\VersionParser; use Composer\Pcre\Preg; use Composer\Repository\ComposerRepository; use Composer\Repository\FilesystemRepository; use Composer\Repository\PlatformRepository; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\RepositorySet; use Composer\Repository\RootPackageRepository; use Composer\Util\ConfigValidator; use Composer\Util\Git; use Composer\Util\IniHelper; use Composer\Util\ProcessExecutor; use Composer\Util\HttpDownloader; use Composer\Util\StreamContextFactory; use Composer\Util\Platform; use Composer\SelfUpdate\Keys; use Composer\SelfUpdate\Versions; use Composer\IO\NullIO; use Composer\Package\CompletePackageInterface; use Composer\XdebugHandler\XdebugHandler; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Symfony\Component\Process\ExecutableFinder; use Composer\Util\Http\ProxyManager; use Composer\Util\Http\RequestProxy; /** * @author Jordi Boggiano */ class DiagnoseCommand extends \Composer\Command\BaseCommand { /** @var HttpDownloader */ protected $httpDownloader; /** @var ProcessExecutor */ protected $process; /** @var int */ protected $exitCode = 0; protected function configure() : void { $this->setName('diagnose')->setDescription('Diagnoses the system to identify common errors')->setHelp(<<diagnose command checks common errors to help debugging problems. The process exit code will be 1 in case of warnings and 2 for errors. Read more at https://getcomposer.org/doc/03-cli.md#diagnose EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->tryComposer(); $io = $this->getIO(); if ($composer) { $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $io->write('Checking composer.json: ', \false); $this->outputResult($this->checkComposerSchema()); if ($composer->getLocker()->isLocked()) { $io->write('Checking composer.lock: ', \false); $this->outputResult($this->checkComposerLockSchema($composer->getLocker())); } $this->process = $composer->getLoop()->getProcessExecutor() ?? new ProcessExecutor($io); } else { $this->process = new ProcessExecutor($io); } if ($composer) { $config = $composer->getConfig(); } else { $config = Factory::createConfig(); } $config->merge(['config' => ['secure-http' => \false]], Config::SOURCE_COMMAND); $config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO()); $this->httpDownloader = Factory::createHttpDownloader($io, $config); $io->write('Checking platform settings: ', \false); $this->outputResult($this->checkPlatform()); $io->write('Checking git settings: ', \false); $this->outputResult($this->checkGit()); $io->write('Checking http connectivity to packagist: ', \false); $this->outputResult($this->checkHttp('http', $config)); $io->write('Checking https connectivity to packagist: ', \false); $this->outputResult($this->checkHttp('https', $config)); foreach ($config->getRepositories() as $repo) { if (($repo['type'] ?? null) === 'composer' && isset($repo['url'])) { $composerRepo = new ComposerRepository($repo, $this->getIO(), $config, $this->httpDownloader); $reflMethod = new \ReflectionMethod($composerRepo, 'getPackagesJsonUrl'); if (\PHP_VERSION_ID < 80100) { $reflMethod->setAccessible(\true); } $url = $reflMethod->invoke($composerRepo); if (!\str_starts_with($url, 'http')) { continue; } if (\str_starts_with($url, 'https://repo.packagist.org')) { continue; } $io->write('Checking connectivity to ' . $repo['url'] . ': ', \false); $this->outputResult($this->checkComposerRepo($url, $config)); } } $proxyManager = ProxyManager::getInstance(); $protos = $config->get('disable-tls') === \true ? ['http'] : ['http', 'https']; try { foreach ($protos as $proto) { $proxy = $proxyManager->getProxyForRequest($proto . '://repo.packagist.org'); if ($proxy->getStatus() !== '') { $type = $proxy->isSecure() ? 'HTTPS' : 'HTTP'; $io->write('Checking ' . $type . ' proxy with ' . $proto . ': ', \false); $this->outputResult($this->checkHttpProxy($proxy, $proto)); } } } catch (TransportException $e) { $io->write('Checking HTTP proxy: ', \false); $status = $this->checkConnectivityAndComposerNetworkHttpEnablement(); $this->outputResult(\is_string($status) ? $status : $e); } if (\count($oauth = $config->get('github-oauth')) > 0) { foreach ($oauth as $domain => $token) { $io->write('Checking ' . $domain . ' oauth access: ', \false); $this->outputResult($this->checkGithubOauth($domain, $token)); } } else { $io->write('Checking github.com rate limit: ', \false); try { $rate = $this->getGithubRateLimit('github.com'); if (!\is_array($rate)) { $this->outputResult($rate); } elseif (10 > $rate['remaining']) { $io->write('WARNING'); $io->write(\sprintf('GitHub has a rate limit on their API. ' . 'You currently have %u ' . 'out of %u requests left.' . \PHP_EOL . 'See https://developer.github.com/v3/#rate-limiting and also' . \PHP_EOL . ' https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens', $rate['remaining'], $rate['limit'])); } else { $this->outputResult(\true); } } catch (\Exception $e) { if ($e instanceof TransportException && $e->getCode() === 401) { $this->outputResult('The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it'); } else { $this->outputResult($e); } } } $io->write('Checking disk free space: ', \false); $this->outputResult($this->checkDiskSpace($config)); if (\strpos(__FILE__, 'phar:') === 0) { $io->write('Checking pubkeys: ', \false); $this->outputResult($this->checkPubKeys($config)); $io->write('Checking Composer version: ', \false); $this->outputResult($this->checkVersion($config)); } $io->write('Checking Composer and its dependencies for vulnerabilities: ', \false); $this->outputResult($this->checkComposerAudit($config)); $io->write(\sprintf('Composer version: %s', Composer::getVersion())); $platformOverrides = $config->get('platform') ?: []; $platformRepo = new PlatformRepository([], $platformOverrides); $phpPkg = $platformRepo->findPackage('php', '*'); $phpVersion = $phpPkg->getPrettyVersion(); if ($phpPkg instanceof CompletePackageInterface && \str_contains((string) $phpPkg->getDescription(), 'overridden')) { $phpVersion .= ' - ' . $phpPkg->getDescription(); } $io->write(\sprintf('PHP version: %s', $phpVersion)); if (\defined('PHP_BINARY')) { $io->write(\sprintf('PHP binary path: %s', \PHP_BINARY)); } $io->write('OpenSSL version: ' . (\defined('OPENSSL_VERSION_TEXT') ? '' . \OPENSSL_VERSION_TEXT . '' : 'missing')); $io->write('curl version: ' . $this->getCurlVersion()); $finder = new ExecutableFinder(); $hasSystemUnzip = (bool) $finder->find('unzip'); $bin7zip = ''; if ($hasSystem7zip = (bool) $finder->find('7z', null, ['C:\\Program Files\\7-Zip'])) { $bin7zip = '7z'; } if (!Platform::isWindows() && !$hasSystem7zip && ($hasSystem7zip = (bool) $finder->find('7zz'))) { $bin7zip = '7zz'; } $io->write('zip: ' . (\extension_loaded('zip') ? 'extension present' : 'extension not loaded') . ', ' . ($hasSystemUnzip ? 'unzip present' : 'unzip not available') . ', ' . ($hasSystem7zip ? '7-Zip present (' . $bin7zip . ')' : '7-Zip not available') . (($hasSystem7zip || $hasSystemUnzip) && !\function_exists('proc_open') ? ', proc_open is disabled or not present, unzip/7-z will not be usable' : '')); return $this->exitCode; } /** * @return string|true */ private function checkComposerSchema() { $validator = new ConfigValidator($this->getIO()); [$errors, , $warnings] = $validator->validate(Factory::getComposerFile()); if ($errors || $warnings) { $messages = ['error' => $errors, 'warning' => $warnings]; $output = ''; foreach ($messages as $style => $msgs) { foreach ($msgs as $msg) { $output .= '<' . $style . '>' . $msg . '' . \PHP_EOL; } } return \rtrim($output); } return \true; } /** * @return string|true */ private function checkComposerLockSchema(Locker $locker) { $json = $locker->getJsonFile(); try { $json->validateSchema(JsonFile::LOCK_SCHEMA); } catch (JsonValidationException $e) { $output = ''; foreach ($e->getErrors() as $error) { $output .= '' . $error . '' . \PHP_EOL; } return \trim($output); } return \true; } private function checkGit() : string { if (!\function_exists('proc_open')) { return 'proc_open is not available, git cannot be used'; } $this->process->execute(['git', 'config', 'color.ui'], $output); if (\strtolower(\trim($output)) === 'always') { return 'Your git color.ui setting is set to always, this is known to create issues. Use "git config --global color.ui true" to set it correctly.'; } $gitVersion = Git::getVersion($this->process); if (null === $gitVersion) { return 'No git process found'; } if (\version_compare('2.24.0', $gitVersion, '>')) { return 'Your git version (' . $gitVersion . ') is too old and possibly will cause issues. Please upgrade to git 2.24 or above'; } return 'OK git version ' . $gitVersion . ''; } /** * @return string|string[]|true */ private function checkHttp(string $proto, Config $config) { $result = $this->checkConnectivityAndComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } $result = []; if ($proto === 'https' && $config->get('disable-tls') === \true) { $tlsWarning = 'Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.'; } try { $this->httpDownloader->get($proto . '://repo.packagist.org/packages.json'); } catch (TransportException $e) { $hints = HttpDownloader::getExceptionHints($e); if (null !== $hints && \count($hints) > 0) { foreach ($hints as $hint) { $result[] = $hint; } } $result[] = '[' . \get_class($e) . '] ' . $e->getMessage() . ''; } if (isset($tlsWarning)) { $result[] = $tlsWarning; } if (\count($result) > 0) { return $result; } return \true; } /** * @return string|string[]|true */ private function checkComposerRepo(string $url, Config $config) { $result = $this->checkConnectivityAndComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } $result = []; if (\str_starts_with($url, 'https://') && $config->get('disable-tls') === \true) { $tlsWarning = 'Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.'; } try { $this->httpDownloader->get($url); } catch (TransportException $e) { $hints = HttpDownloader::getExceptionHints($e); if (null !== $hints && \count($hints) > 0) { foreach ($hints as $hint) { $result[] = $hint; } } $result[] = '[' . \get_class($e) . '] ' . $e->getMessage() . ''; } if (isset($tlsWarning)) { $result[] = $tlsWarning; } if (\count($result) > 0) { return $result; } return \true; } /** * @return string|\Exception */ private function checkHttpProxy(RequestProxy $proxy, string $protocol) { $result = $this->checkConnectivityAndComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } try { $proxyStatus = $proxy->getStatus(); if ($proxy->isExcludedByNoProxy()) { return 'SKIP Because repo.packagist.org is ' . $proxyStatus . ''; } $json = $this->httpDownloader->get($protocol . '://repo.packagist.org/packages.json')->decodeJson(); if (isset($json['provider-includes'])) { $hash = \reset($json['provider-includes']); $hash = $hash['sha256']; $path = \str_replace('%hash%', $hash, \key($json['provider-includes'])); $provider = $this->httpDownloader->get($protocol . '://repo.packagist.org/' . $path)->getBody(); if (\hash('sha256', $provider) !== $hash) { return 'It seems that your proxy (' . $proxyStatus . ') is modifying ' . $protocol . ' traffic on the fly'; } } return 'OK ' . $proxyStatus . ''; } catch (\Exception $e) { return $e; } } /** * @return string|\Exception */ private function checkGithubOauth(string $domain, string $token) { $result = $this->checkConnectivityAndComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic'); try { $url = $domain === 'github.com' ? 'https://api.' . $domain . '/' : 'https://' . $domain . '/api/v3/'; $response = $this->httpDownloader->get($url, ['retry-auth-failure' => \false]); $expiration = $response->getHeader('github-authentication-token-expiration'); if ($expiration === null) { return 'OK does not expire'; } return 'OK expires on ' . $expiration . ''; } catch (\Exception $e) { if ($e instanceof TransportException && $e->getCode() === 401) { return 'The oauth token for ' . $domain . ' seems invalid, run "composer config --global --unset github-oauth.' . $domain . '" to remove it'; } return $e; } } /** * @param string $token * @throws TransportException * @return mixed|string */ private function getGithubRateLimit(string $domain, ?string $token = null) { $result = $this->checkConnectivityAndComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } if ($token) { $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic'); } $url = $domain === 'github.com' ? 'https://api.' . $domain . '/rate_limit' : 'https://' . $domain . '/api/rate_limit'; $data = $this->httpDownloader->get($url, ['retry-auth-failure' => \false])->decodeJson(); return $data['resources']['core']; } /** * @return string|true */ private function checkDiskSpace(Config $config) { if (!\function_exists('disk_free_space')) { return \true; } $minSpaceFree = 1024 * 1024; if (($df = @\disk_free_space($dir = $config->get('home'))) !== \false && $df < $minSpaceFree || ($df = @\disk_free_space($dir = $config->get('vendor-dir'))) !== \false && $df < $minSpaceFree) { return 'The disk hosting ' . $dir . ' is full'; } return \true; } /** * @return string[]|true */ private function checkPubKeys(Config $config) { $home = $config->get('home'); $errors = []; $io = $this->getIO(); if (\file_exists($home . '/keys.tags.pub') && \file_exists($home . '/keys.dev.pub')) { $io->write(''); } if (\file_exists($home . '/keys.tags.pub')) { $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home . '/keys.tags.pub')); } else { $errors[] = 'Missing pubkey for tags verification'; } if (\file_exists($home . '/keys.dev.pub')) { $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home . '/keys.dev.pub')); } else { $errors[] = 'Missing pubkey for dev verification'; } if ($errors) { $errors[] = 'Run composer self-update --update-keys to set them up'; } return $errors ?: \true; } /** * @return string|\Exception|true */ private function checkVersion(Config $config) { $result = $this->checkConnectivityAndComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } $versionsUtil = new Versions($config, $this->httpDownloader); try { $latest = $versionsUtil->getLatest(); } catch (\Exception $e) { return $e; } if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') { return 'You are not running the latest ' . $versionsUtil->getChannel() . ' version, run `composer self-update` to update (' . Composer::VERSION . ' => ' . $latest['version'] . ')'; } return \true; } /** * @return string|true */ private function checkComposerAudit(Config $config) { $result = $this->checkConnectivityAndComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } $auditor = new Auditor(); $repoSet = new RepositorySet(); $installedJson = new JsonFile(__DIR__ . '/../../../vendor/composer/installed.json'); if (!$installedJson->exists()) { return 'Could not find Composer\'s installed.json, this must be a non-standard Composer installation.'; } $localRepo = new FilesystemRepository($installedJson); $version = Composer::getVersion(); $packages = $localRepo->getCanonicalPackages(); if ($version !== '@package_version@') { $versionParser = new VersionParser(); $normalizedVersion = $versionParser->normalize($version); $rootPkg = new RootPackage('composer/composer', $normalizedVersion, $version); $packages[] = $rootPkg; } $repoSet->addRepository(new ComposerRepository(['type' => 'composer', 'url' => 'https://packagist.org'], new NullIO(), $config, $this->httpDownloader)); try { $io = new BufferIO(); $result = $auditor->audit($io, $repoSet, $packages, Auditor::FORMAT_TABLE, \true, [], Auditor::ABANDONED_IGNORE); } catch (\Throwable $e) { return 'Failed performing audit: ' . $e->getMessage() . ''; } if ($result > 0) { return 'Audit found some issues:' . \PHP_EOL . $io->getOutput(); } return \true; } private function getCurlVersion() : string { if (\extension_loaded('curl')) { if (!HttpDownloader::isCurlEnabled()) { return 'disabled via disable_functions, using php streams fallback, which reduces performance'; } $version = \curl_version(); return '' . $version['version'] . ' ' . 'libz ' . (!empty($version['libz_version']) ? $version['libz_version'] : 'missing') . ' ' . 'ssl ' . ($version['ssl_version'] ?? 'missing') . ''; } return 'missing, using php streams fallback, which reduces performance'; } /** * @param bool|string|string[]|\Exception $result */ private function outputResult($result) : void { $io = $this->getIO(); if (\true === $result) { $io->write('OK'); return; } $hadError = \false; $hadWarning = \false; if ($result instanceof \Exception) { $result = '[' . \get_class($result) . '] ' . $result->getMessage() . ''; } if (!$result) { // falsey results should be considered as an error, even if there is nothing to output $hadError = \true; } else { if (!\is_array($result)) { $result = [$result]; } foreach ($result as $message) { if (\false !== \strpos($message, '')) { $hadError = \true; } elseif (\false !== \strpos($message, '')) { $hadWarning = \true; } } } if ($hadError) { $io->write('FAIL'); $this->exitCode = \max($this->exitCode, 2); } elseif ($hadWarning) { $io->write('WARNING'); $this->exitCode = \max($this->exitCode, 1); } if ($result) { foreach ($result as $message) { $io->write(\trim($message)); } } } /** * @return string|true */ private function checkPlatform() { $output = ''; $out = static function ($msg, $style) use(&$output) : void { $output .= '<' . $style . '>' . $msg . '' . \PHP_EOL; }; // code below taken from getcomposer.org/installer, any changes should be made there and replicated here $errors = []; $warnings = []; $displayIniMessage = \false; $iniMessage = \PHP_EOL . \PHP_EOL . IniHelper::getMessage(); $iniMessage .= \PHP_EOL . 'If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.'; if (!\function_exists('json_decode')) { $errors['json'] = \true; } if (!\extension_loaded('Phar')) { $errors['phar'] = \true; } if (!\extension_loaded('filter')) { $errors['filter'] = \true; } if (!\extension_loaded('hash')) { $errors['hash'] = \true; } if (!\extension_loaded('iconv') && !\extension_loaded('mbstring')) { $errors['iconv_mbstring'] = \true; } if (!\filter_var(\ini_get('allow_url_fopen'), \FILTER_VALIDATE_BOOLEAN)) { $errors['allow_url_fopen'] = \true; } if (\extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) { $errors['ioncube'] = ioncube_loader_version(); } if (\PHP_VERSION_ID < 70205) { $errors['php'] = \PHP_VERSION; } if (!\extension_loaded('openssl')) { $errors['openssl'] = \true; } if (\extension_loaded('openssl') && \OPENSSL_VERSION_NUMBER < 0x1000100f) { $warnings['openssl_version'] = \true; } if (!\defined('_ContaoManager\\HHVM_VERSION') && !\extension_loaded('apcu') && \filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { $warnings['apc_cli'] = \true; } if (!\extension_loaded('zlib')) { $warnings['zlib'] = \true; } \ob_start(); \phpinfo(\INFO_GENERAL); $phpinfo = \ob_get_clean(); if (\is_string($phpinfo) && Preg::isMatchStrictGroups('{Configure Command(?: *| *=> *)(.*?)(?:|$)}m', $phpinfo, $match)) { $configure = $match[1]; if (\str_contains($configure, '--enable-sigchild')) { $warnings['sigchild'] = \true; } if (\str_contains($configure, '--with-curlwrappers')) { $warnings['curlwrappers'] = \true; } } if (\filter_var(\ini_get('xdebug.profiler_enabled'), \FILTER_VALIDATE_BOOLEAN)) { $warnings['xdebug_profile'] = \true; } elseif (XdebugHandler::isXdebugActive()) { $warnings['xdebug_loaded'] = \true; } if (\defined('PHP_WINDOWS_VERSION_BUILD') && (\version_compare(\PHP_VERSION, '7.2.23', '<') || \version_compare(\PHP_VERSION, '7.3.0', '>=') && \version_compare(\PHP_VERSION, '7.3.10', '<'))) { $warnings['onedrive'] = \PHP_VERSION; } if (\extension_loaded('uopz') && !(\filter_var(\ini_get('uopz.disable'), \FILTER_VALIDATE_BOOLEAN) || \filter_var(\ini_get('uopz.exit'), \FILTER_VALIDATE_BOOLEAN))) { $warnings['uopz'] = \true; } if (!empty($errors)) { foreach ($errors as $error => $current) { switch ($error) { case 'json': $text = \PHP_EOL . "The json extension is missing." . \PHP_EOL; $text .= "Install it or recompile php without --disable-json"; break; case 'phar': $text = \PHP_EOL . "The phar extension is missing." . \PHP_EOL; $text .= "Install it or recompile php without --disable-phar"; break; case 'filter': $text = \PHP_EOL . "The filter extension is missing." . \PHP_EOL; $text .= "Install it or recompile php without --disable-filter"; break; case 'hash': $text = \PHP_EOL . "The hash extension is missing." . \PHP_EOL; $text .= "Install it or recompile php without --disable-hash"; break; case 'iconv_mbstring': $text = \PHP_EOL . "The iconv OR mbstring extension is required and both are missing." . \PHP_EOL; $text .= "Install either of them or recompile php without --disable-iconv"; break; case 'php': $text = \PHP_EOL . "Your PHP ({$current}) is too old, you must upgrade to PHP 7.2.5 or higher."; break; case 'allow_url_fopen': $text = \PHP_EOL . "The allow_url_fopen setting is incorrect." . \PHP_EOL; $text .= "Add the following to the end of your `php.ini`:" . \PHP_EOL; $text .= " allow_url_fopen = On"; $displayIniMessage = \true; break; case 'ioncube': $text = \PHP_EOL . "Your ionCube Loader extension ({$current}) is incompatible with Phar files." . \PHP_EOL; $text .= "Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:" . \PHP_EOL; $text .= " zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so"; $displayIniMessage = \true; break; case 'openssl': $text = \PHP_EOL . "The openssl extension is missing, which means that secure HTTPS transfers are impossible." . \PHP_EOL; $text .= "If possible you should enable it or recompile php with --with-openssl"; break; default: throw new \InvalidArgumentException(\sprintf("DiagnoseCommand: Unknown error type \"%s\". Please report at https://github.com/composer/composer/issues/new.", $error)); } $out($text, 'error'); } $output .= \PHP_EOL; } if (!empty($warnings)) { foreach ($warnings as $warning => $current) { switch ($warning) { case 'apc_cli': $text = "The apc.enable_cli setting is incorrect." . \PHP_EOL; $text .= "Add the following to the end of your `php.ini`:" . \PHP_EOL; $text .= " apc.enable_cli = Off"; $displayIniMessage = \true; break; case 'zlib': $text = 'The zlib extension is not loaded, this can slow down Composer a lot.' . \PHP_EOL; $text .= 'If possible, enable it or recompile php with --with-zlib' . \PHP_EOL; $displayIniMessage = \true; break; case 'sigchild': $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms." . \PHP_EOL; $text .= "Recompile it without this flag if possible, see also:" . \PHP_EOL; $text .= " https://bugs.php.net/bug.php?id=22999"; break; case 'curlwrappers': $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub." . \PHP_EOL; $text .= " Recompile it without this flag if possible"; break; case 'openssl_version': // Attempt to parse version number out, fallback to whole string value. $opensslVersion = \strstr(\trim(\strstr(\OPENSSL_VERSION_TEXT, ' ')), ' ', \true); $opensslVersion = $opensslVersion ?: \OPENSSL_VERSION_TEXT; $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1." . \PHP_EOL; $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above."; break; case 'xdebug_loaded': $text = "The xdebug extension is loaded, this can slow down Composer a little." . \PHP_EOL; $text .= " Disabling it when using Composer is recommended."; break; case 'xdebug_profile': $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot." . \PHP_EOL; $text .= "Add the following to the end of your `php.ini` to disable it:" . \PHP_EOL; $text .= " xdebug.profiler_enabled = 0"; $displayIniMessage = \true; break; case 'onedrive': $text = "The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10." . \PHP_EOL; $text .= "Upgrade your PHP ({$current}) to use this location with Composer." . \PHP_EOL; break; case 'uopz': $text = "The uopz extension ignores exit calls and may not work with all Composer commands." . \PHP_EOL; $text .= "Disabling it when using Composer is recommended."; break; default: throw new \InvalidArgumentException(\sprintf("DiagnoseCommand: Unknown warning type \"%s\". Please report at https://github.com/composer/composer/issues/new.", $warning)); } $out($text, 'comment'); } } if ($displayIniMessage) { $out($iniMessage, 'comment'); } if (\in_array(Platform::getEnv('COMPOSER_IPRESOLVE'), ['4', '6'], \true)) { $warnings['ipresolve'] = \true; $out('The COMPOSER_IPRESOLVE env var is set to ' . Platform::getEnv('COMPOSER_IPRESOLVE') . ' which may result in network failures below.', 'comment'); } return \count($warnings) === 0 && \count($errors) === 0 ? \true : $output; } /** * Check if allow_url_fopen is ON * * @return string|true */ private function checkConnectivity() { if (!\ini_get('allow_url_fopen')) { return 'SKIP Because allow_url_fopen is missing.'; } return \true; } /** * @return string|true */ private function checkConnectivityAndComposerNetworkHttpEnablement() { $result = $this->checkConnectivity(); if ($result !== \true) { return $result; } $result = $this->checkComposerNetworkHttpEnablement(); if ($result !== \true) { return $result; } return \true; } /** * Check if Composer network is enabled for HTTP/S * * @return string|true */ private function checkComposerNetworkHttpEnablement() { if ((bool) Platform::getEnv('COMPOSER_DISABLE_NETWORK')) { return 'SKIP Network is disabled by COMPOSER_DISABLE_NETWORK.'; } return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Factory; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use _ContaoManager\Symfony\Component\Console\Command\Command; use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput; use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputArgument; use _ContaoManager\Symfony\Component\Console\Input\StringInput; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano */ class GlobalCommand extends \Composer\Command\BaseCommand { public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void { $application = $this->getApplication(); if ($input->mustSuggestArgumentValuesFor('command-name')) { $suggestions->suggestValues(\array_values(\array_filter(\array_map(static function (Command $command) { return $command->isHidden() ? null : $command->getName(); }, $application->all()), function (?string $cmd) { return $cmd !== null; }))); return; } if ($application->has($commandName = $input->getArgument('command-name'))) { $input = $this->prepareSubcommandInput($input, \true); $input = CompletionInput::fromString($input->__toString(), 2); $command = $application->find($commandName); $command->mergeApplicationDefinition(); $input->bind($command->getDefinition()); $command->complete($input, $suggestions); } } protected function configure() : void { $this->setName('global')->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME)')->setDefinition([new InputArgument('command-name', InputArgument::REQUIRED, ''), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, '')])->setHelp(<<\\AppData\\Roaming\\Composer on Windows and /home//.composer on unix systems. If your system uses freedesktop.org standards, then it will first check XDG_CONFIG_HOME or default to /home//.config/composer Note: This path may vary depending on customizations to bin-dir in composer.json or the environmental variable COMPOSER_BIN_DIR. Read more at https://getcomposer.org/doc/03-cli.md#global EOT ); } /** * @throws \Symfony\Component\Console\Exception\ExceptionInterface */ public function run(InputInterface $input, OutputInterface $output) : int { // TODO remove for Symfony 6+ as it is then in the interface if (!\method_exists($input, '__toString')) { // @phpstan-ignore-line throw new \LogicException('Expected an Input instance that is stringable, got ' . \get_class($input)); } // extract real command name $tokens = Preg::split('{\\s+}', $input->__toString()); $args = []; foreach ($tokens as $token) { if ($token && $token[0] !== '-') { $args[] = $token; if (\count($args) >= 2) { break; } } } // show help for this command if no command was found if (\count($args) < 2) { return parent::run($input, $output); } $input = $this->prepareSubcommandInput($input); return $this->getApplication()->run($input, $output); } private function prepareSubcommandInput(InputInterface $input, bool $quiet = \false) : StringInput { // TODO remove for Symfony 6+ as it is then in the interface if (!\method_exists($input, '__toString')) { // @phpstan-ignore-line throw new \LogicException('Expected an Input instance that is stringable, got ' . \get_class($input)); } // The COMPOSER env var should not apply to the global execution scope if (Platform::getEnv('COMPOSER')) { Platform::clearEnv('COMPOSER'); } // change to global dir $config = Factory::createConfig(); $home = $config->get('home'); if (!\is_dir($home)) { $fs = new Filesystem(); $fs->ensureDirectoryExists($home); if (!\is_dir($home)) { throw new \RuntimeException('Could not create home directory'); } } try { \chdir($home); } catch (\Exception $e) { throw new \RuntimeException('Could not switch to home directory "' . $home . '"', 0, $e); } if (!$quiet) { $this->getIO()->writeError('Changed current directory to ' . $home . ''); } // create new input without "global" command prefix $input = new StringInput(Preg::replace('{\\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\\b}', '', $input->__toString(), 1)); $this->getApplication()->resetComposer(); return $input; } /** * @inheritDoc */ public function isProxyCommand() : bool { return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; /** * @author Jordi Boggiano */ class AboutCommand extends \Composer\Command\BaseCommand { protected function configure() : void { $this->setName('about')->setDescription('Shows a short information about Composer')->setHelp(<<php composer.phar about EOT ); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composerVersion = Composer::getVersion(); $this->getIO()->write(<<Composer - Dependency Manager for PHP - version {$composerVersion} Composer is a dependency manager tracking local dependencies of your projects and libraries. See https://getcomposer.org/ for more information. EOT ); return 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use Composer\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use Composer\Console\Input\InputArgument; /** * @author Davey Shafik */ class ExecCommand extends \Composer\Command\BaseCommand { /** * @return void */ protected function configure() { $this->setName('exec')->setDescription('Executes a vendored binary/script')->setDefinition([new InputOption('list', 'l', InputOption::VALUE_NONE), new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit', null, function () { return $this->getBinaries(\false); }), new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Arguments to pass to the binary. Use -- to separate from composer arguments')])->setHelp(<<getBinaries(\false); if (\count($binaries) === 0) { return; } if ($input->getArgument('binary') !== null || $input->getOption('list')) { return; } $io = $this->getIO(); /** @var int $binary */ $binary = $io->select('Binary to run: ', $binaries, '', 1, 'Invalid binary name "%s"'); $input->setArgument('binary', $binaries[$binary]); } protected function execute(InputInterface $input, OutputInterface $output) : int { $composer = $this->requireComposer(); if ($input->getOption('list') || null === $input->getArgument('binary')) { $bins = $this->getBinaries(\true); if ([] === $bins) { $binDir = $composer->getConfig()->get('bin-dir'); throw new \RuntimeException("No binaries found in composer.json or in bin-dir ({$binDir})"); } $this->getIO()->write(<<Available binaries: EOT ); foreach ($bins as $bin) { $this->getIO()->write(<<- {$bin} EOT ); } return 0; } $binary = $input->getArgument('binary'); $dispatcher = $composer->getEventDispatcher(); $dispatcher->addListener('__exec_command', $binary); // If the CWD was modified, we restore it to what it was initially, as it was // most likely modified by the global command, and we want exec to run in the local working directory // not the global one if (\getcwd() !== $this->getApplication()->getInitialWorkingDirectory() && $this->getApplication()->getInitialWorkingDirectory() !== \false) { try { \chdir($this->getApplication()->getInitialWorkingDirectory()); } catch (\Exception $e) { throw new \RuntimeException('Could not switch back to working directory "' . $this->getApplication()->getInitialWorkingDirectory() . '"', 0, $e); } } return $dispatcher->dispatchScript('__exec_command', \true, $input->getArgument('args')); } /** * @return list */ private function getBinaries(bool $forDisplay) : array { $composer = $this->requireComposer(); $binDir = $composer->getConfig()->get('bin-dir'); $bins = \glob($binDir . '/*'); $localBins = $composer->getPackage()->getBinaries(); if ($forDisplay) { $localBins = \array_map(static function ($e) { return "{$e} (local)"; }, $localBins); } $binaries = []; foreach (\array_merge($bins, $localBins) as $bin) { // skip .bat copies if (isset($previousBin) && $bin === $previousBin . '.bat') { continue; } $previousBin = $bin; $binaries[] = \basename($bin); } return $binaries; } } * 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\AutoloadGenerator; use Composer\Console\GithubActionError; use Composer\DependencyResolver\DefaultPolicy; use Composer\DependencyResolver\LocalRepoTransaction; use Composer\DependencyResolver\LockTransaction; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UninstallOperation; use Composer\DependencyResolver\PoolOptimizer; use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Request; use Composer\DependencyResolver\Solver; use Composer\DependencyResolver\SolverProblemsException; use Composer\DependencyResolver\PolicyInterface; use Composer\Downloader\DownloadManager; use Composer\Downloader\TransportException; use Composer\EventDispatcher\EventDispatcher; use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\Installer\InstallationManager; use Composer\Installer\InstallerEvents; use Composer\Installer\SuggestedPackagesReporter; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; use Composer\Package\RootAliasPackage; use Composer\Package\BasePackage; use Composer\Package\CompletePackage; use Composer\Package\CompletePackageInterface; use Composer\Package\Link; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Version\VersionParser; use Composer\Package\Package; use Composer\Repository\ArrayRepository; use Composer\Repository\RepositorySet; use Composer\Repository\CompositeRepository; use Composer\Semver\Constraint\Constraint; use Composer\Package\Locker; use Composer\Package\RootPackageInterface; use Composer\Repository\InstalledArrayRepository; use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\InstalledRepository; use Composer\Repository\RootPackageRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryManager; use Composer\Repository\LockArrayRepository; use Composer\Script\ScriptEvents; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Advisory\Auditor; use Composer\Util\Platform; /** * @author Jordi Boggiano * @author Beau Simensen * @author Konstantin Kudryashov * @author Nils Adermann */ class Installer { public const ERROR_NONE = 0; // no error/success state public const ERROR_GENERIC_FAILURE = 1; public const ERROR_NO_LOCK_FILE_FOR_PARTIAL_UPDATE = 3; public const ERROR_LOCK_FILE_INVALID = 4; // used/declared in SolverProblemsException, carried over here for completeness public const ERROR_DEPENDENCY_RESOLUTION_FAILED = 2; public const ERROR_AUDIT_FAILED = 5; // technically exceptions are thrown with various status codes >400, but the process exit code is normalized to 100 public const ERROR_TRANSPORT_EXCEPTION = 100; /** * @var IOInterface */ protected $io; /** * @var Config */ protected $config; /** * @var RootPackageInterface&BasePackage */ protected $package; // TODO can we get rid of the below and just use the package itself? /** * @var RootPackageInterface&BasePackage */ protected $fixedRootPackage; /** * @var DownloadManager */ protected $downloadManager; /** * @var RepositoryManager */ protected $repositoryManager; /** * @var Locker */ protected $locker; /** * @var InstallationManager */ protected $installationManager; /** * @var EventDispatcher */ protected $eventDispatcher; /** * @var AutoloadGenerator */ protected $autoloadGenerator; /** @var bool */ protected $preferSource = \false; /** @var bool */ protected $preferDist = \false; /** @var bool */ protected $optimizeAutoloader = \false; /** @var bool */ protected $classMapAuthoritative = \false; /** @var bool */ protected $apcuAutoloader = \false; /** @var string|null */ protected $apcuAutoloaderPrefix = null; /** @var bool */ protected $devMode = \false; /** @var bool */ protected $dryRun = \false; /** @var bool */ protected $downloadOnly = \false; /** @var bool */ protected $verbose = \false; /** @var bool */ protected $update = \false; /** @var bool */ protected $install = \true; /** @var bool */ protected $dumpAutoloader = \true; /** @var bool */ protected $runScripts = \true; /** @var bool */ protected $preferStable = \false; /** @var bool */ protected $preferLowest = \false; /** @var bool */ protected $minimalUpdate = \false; /** @var bool */ protected $writeLock; /** @var bool */ protected $executeOperations = \true; /** @var bool */ protected $audit = \true; /** @var bool */ protected $errorOnAudit = \false; /** @var Auditor::FORMAT_* */ protected $auditFormat = Auditor::FORMAT_SUMMARY; /** @var list */ private $ignoredTypes = ['php-ext', 'php-ext-zend']; /** @var list|null */ private $allowedTypes = null; /** @var bool */ protected $updateMirrors = \false; /** * Array of package names/globs flagged for update * * @var non-empty-list|null */ protected $updateAllowList = null; /** @var Request::UPDATE_* */ protected $updateAllowTransitiveDependencies = Request::UPDATE_ONLY_LISTED; /** * @var SuggestedPackagesReporter */ protected $suggestedPackagesReporter; /** * @var PlatformRequirementFilterInterface */ protected $platformRequirementFilter; /** * @var ?RepositoryInterface */ protected $additionalFixedRepository; /** @var array */ protected $temporaryConstraints = []; /** * Constructor * * @param RootPackageInterface&BasePackage $package */ public function __construct(IOInterface $io, \Composer\Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator) { $this->io = $io; $this->config = $config; $this->package = $package; $this->downloadManager = $downloadManager; $this->repositoryManager = $repositoryManager; $this->locker = $locker; $this->installationManager = $installationManager; $this->eventDispatcher = $eventDispatcher; $this->autoloadGenerator = $autoloadGenerator; $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io); $this->platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing(); $this->writeLock = $config->get('lock'); } /** * Run installation (or update) * * @throws \Exception * @return int 0 on success or a positive error code on failure * @phpstan-return self::ERROR_* */ public function run() : int { // Disable GC to save CPU cycles, as the dependency solver can create hundreds of thousands // of PHP objects, the GC can spend quite some time walking the tree of references looking // for stuff to collect while there is nothing to collect. This slows things down dramatically // and turning it off results in much better performance. Do not try this at home however. \gc_collect_cycles(); \gc_disable(); if ($this->updateAllowList !== null && $this->updateMirrors) { throw new \RuntimeException("The installer options updateMirrors and updateAllowList are mutually exclusive."); } $isFreshInstall = $this->repositoryManager->getLocalRepository()->isFresh(); // Force update if there is no lock file present if (!$this->update && !$this->locker->isLocked()) { $this->io->writeError('No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.'); $this->update = \true; } if ($this->dryRun) { $this->verbose = \true; $this->runScripts = \false; $this->executeOperations = \false; $this->writeLock = \false; $this->dumpAutoloader = \false; $this->mockLocalRepositories($this->repositoryManager); } if ($this->downloadOnly) { $this->dumpAutoloader = \false; } if ($this->update && !$this->install) { $this->dumpAutoloader = \false; } if ($this->runScripts) { Platform::putEnv('COMPOSER_DEV_MODE', $this->devMode ? '1' : '0'); // dispatch pre event // should we treat this more strictly as running an update and then running an install, triggering events multiple times? $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD; $this->eventDispatcher->dispatchScript($eventName, $this->devMode); } $this->downloadManager->setPreferSource($this->preferSource); $this->downloadManager->setPreferDist($this->preferDist); $localRepo = $this->repositoryManager->getLocalRepository(); try { if ($this->update) { $res = $this->doUpdate($localRepo, $this->install); } else { $res = $this->doInstall($localRepo); } if ($res !== 0) { return $res; } } catch (\Exception $e) { if ($this->executeOperations && $this->install && $this->config->get('notify-on-install')) { $this->installationManager->notifyInstalls($this->io); } throw $e; } if ($this->executeOperations && $this->install && $this->config->get('notify-on-install')) { $this->installationManager->notifyInstalls($this->io); } if ($this->update) { $installedRepo = new InstalledRepository([$this->locker->getLockedRepository($this->devMode), $this->createPlatformRepo(\false), new RootPackageRepository(clone $this->package)]); if ($isFreshInstall) { $this->suggestedPackagesReporter->addSuggestionsFromPackage($this->package); } $this->suggestedPackagesReporter->outputMinimalistic($installedRepo); } // Find abandoned packages and warn user $lockedRepository = $this->locker->getLockedRepository(\true); foreach ($lockedRepository->getPackages() as $package) { if (!$package instanceof CompletePackage || !$package->isAbandoned()) { continue; } $replacement = \is_string($package->getReplacementPackage()) ? 'Use ' . $package->getReplacementPackage() . ' instead' : 'No replacement was suggested'; $this->io->writeError(\sprintf("Package %s is abandoned, you should avoid using it. %s.", $package->getPrettyName(), $replacement)); } if ($this->dumpAutoloader) { // write autoloader if ($this->optimizeAutoloader) { $this->io->writeError('Generating optimized autoload files'); } else { $this->io->writeError('Generating autoload files'); } $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative); $this->autoloadGenerator->setApcu($this->apcuAutoloader, $this->apcuAutoloaderPrefix); $this->autoloadGenerator->setRunScripts($this->runScripts); $this->autoloadGenerator->setPlatformRequirementFilter($this->platformRequirementFilter); $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader, null, $this->locker); } if ($this->install && $this->executeOperations) { // force binaries re-generation in case they are missing foreach ($localRepo->getPackages() as $package) { $this->installationManager->ensureBinariesPresence($package); } } $fundEnv = Platform::getEnv('COMPOSER_FUND'); $showFunding = \true; if (\is_numeric($fundEnv)) { $showFunding = \intval($fundEnv) !== 0; } if ($showFunding) { $fundingCount = 0; foreach ($localRepo->getPackages() as $package) { if ($package instanceof CompletePackageInterface && !$package instanceof AliasPackage && $package->getFunding()) { $fundingCount++; } } if ($fundingCount > 0) { $this->io->writeError([\sprintf("%d package%s you are using %s looking for funding.", $fundingCount, 1 === $fundingCount ? '' : 's', 1 === $fundingCount ? 'is' : 'are'), 'Use the `composer fund` command to find out more!']); } } if ($this->runScripts) { // dispatch post event $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchScript($eventName, $this->devMode); } // re-enable GC except on HHVM which triggers a warning here if (!\defined('_ContaoManager\\HHVM_VERSION')) { \gc_enable(); } if ($this->audit) { if ($this->update && !$this->install) { $packages = $lockedRepository->getCanonicalPackages(); $target = 'locked'; } else { $packages = $localRepo->getCanonicalPackages(); $target = 'installed'; } if (\count($packages) > 0) { try { $auditor = new Auditor(); $repoSet = new RepositorySet(); foreach ($this->repositoryManager->getRepositories() as $repo) { $repoSet->addRepository($repo); } $auditConfig = $this->config->get('audit'); return $auditor->audit($this->io, $repoSet, $packages, $this->auditFormat, \true, $auditConfig['ignore'] ?? [], $auditConfig['abandoned'] ?? Auditor::ABANDONED_FAIL) > 0 && $this->errorOnAudit ? self::ERROR_AUDIT_FAILED : 0; } catch (TransportException $e) { $this->io->error('Failed to audit ' . $target . ' packages.'); if ($this->io->isVerbose()) { $this->io->error('[' . \get_class($e) . '] ' . $e->getMessage()); } } } else { $this->io->writeError('No ' . $target . ' packages - skipping audit.'); } } return 0; } /** * @phpstan-return self::ERROR_* */ protected function doUpdate(InstalledRepositoryInterface $localRepo, bool $doInstall) : int { $platformRepo = $this->createPlatformRepo(\true); $aliases = $this->getRootAliases(\true); $lockedRepository = null; try { if ($this->locker->isLocked()) { $lockedRepository = $this->locker->getLockedRepository(\true); } } catch (\_ContaoManager\Seld\JsonLint\ParsingException $e) { if ($this->updateAllowList !== null || $this->updateMirrors) { // in case we are doing a partial update or updating mirrors, the lock file is needed so we error throw $e; } // otherwise, ignoring parse errors as the lock file will be regenerated from scratch when // doing a full update } if (($this->updateAllowList !== null || $this->updateMirrors) && !$lockedRepository) { $this->io->writeError('Cannot update ' . ($this->updateMirrors ? 'lock file information' : 'only a partial set of packages') . ' without a lock file present. Run `composer update` to generate a lock file.', \true, IOInterface::QUIET); return self::ERROR_NO_LOCK_FILE_FOR_PARTIAL_UPDATE; } $this->io->writeError('Loading composer repositories with package information'); // creating repository set $policy = $this->createPolicy(\true, $lockedRepository); $repositorySet = $this->createRepositorySet(\true, $platformRepo, $aliases); $repositories = $this->repositoryManager->getRepositories(); foreach ($repositories as $repository) { $repositorySet->addRepository($repository); } if ($lockedRepository) { $repositorySet->addRepository($lockedRepository); } $request = $this->createRequest($this->fixedRootPackage, $platformRepo, $lockedRepository); $this->requirePackagesForUpdate($request, $lockedRepository, \true); // pass the allow list into the request, so the pool builder can apply it if ($this->updateAllowList !== null) { $request->setUpdateAllowList($this->updateAllowList, $this->updateAllowTransitiveDependencies); } $pool = $repositorySet->createPool($request, $this->io, $this->eventDispatcher, $this->createPoolOptimizer($policy), $this->ignoredTypes, $this->allowedTypes); $this->io->writeError('Updating dependencies'); // solve dependencies $solver = new Solver($policy, $pool, $this->io); try { $lockTransaction = $solver->solve($request, $this->platformRequirementFilter); $ruleSetSize = $solver->getRuleSetSize(); $solver = null; } catch (SolverProblemsException $e) { $err = 'Your requirements could not be resolved to an installable set of packages.'; $prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io->isVerbose()); $this->io->writeError('' . $err . '', \true, IOInterface::QUIET); $this->io->writeError($prettyProblem); if (!$this->devMode) { $this->io->writeError('Running update with --no-dev does not mean require-dev is ignored, it just means the packages will not be installed. If dev requirements are blocking the update you have to resolve those problems.', \true, IOInterface::QUIET); } $ghe = new GithubActionError($this->io); $ghe->emit($err . "\n" . $prettyProblem); return \max(self::ERROR_GENERIC_FAILURE, $e->getCode()); } $this->io->writeError("Analyzed " . \count($pool) . " packages to resolve dependencies", \true, IOInterface::VERBOSE); $this->io->writeError("Analyzed " . $ruleSetSize . " rules to resolve dependencies", \true, IOInterface::VERBOSE); $pool = null; if (!$lockTransaction->getOperations()) { $this->io->writeError('Nothing to modify in lock file'); } $exitCode = $this->extractDevPackages($lockTransaction, $platformRepo, $aliases, $policy, $lockedRepository); if ($exitCode !== 0) { return $exitCode; } \Composer\Semver\CompilingMatcher::clear(); // write lock $platformReqs = $this->extractPlatformRequirements($this->package->getRequires()); $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires()); $installsUpdates = $uninstalls = []; if ($lockTransaction->getOperations()) { $installNames = $updateNames = $uninstallNames = []; foreach ($lockTransaction->getOperations() as $operation) { if ($operation instanceof InstallOperation) { $installsUpdates[] = $operation; $installNames[] = $operation->getPackage()->getPrettyName() . ':' . $operation->getPackage()->getFullPrettyVersion(); } elseif ($operation instanceof UpdateOperation) { // when mirrors/metadata from a package gets updated we do not want to list it as an // update in the output as it is only an internal lock file metadata update if ($this->updateMirrors && $operation->getInitialPackage()->getName() === $operation->getTargetPackage()->getName() && $operation->getInitialPackage()->getVersion() === $operation->getTargetPackage()->getVersion()) { continue; } $installsUpdates[] = $operation; $updateNames[] = $operation->getTargetPackage()->getPrettyName() . ':' . $operation->getTargetPackage()->getFullPrettyVersion(); } elseif ($operation instanceof UninstallOperation) { $uninstalls[] = $operation; $uninstallNames[] = $operation->getPackage()->getPrettyName(); } } if ($this->config->get('lock')) { $this->io->writeError(\sprintf("Lock file operations: %d install%s, %d update%s, %d removal%s", \count($installNames), 1 === \count($installNames) ? '' : 's', \count($updateNames), 1 === \count($updateNames) ? '' : 's', \count($uninstalls), 1 === \count($uninstalls) ? '' : 's')); if ($installNames) { $this->io->writeError("Installs: " . \implode(', ', $installNames), \true, IOInterface::VERBOSE); } if ($updateNames) { $this->io->writeError("Updates: " . \implode(', ', $updateNames), \true, IOInterface::VERBOSE); } if ($uninstalls) { $this->io->writeError("Removals: " . \implode(', ', $uninstallNames), \true, IOInterface::VERBOSE); } } } $sortByName = static function ($a, $b) : int { if ($a instanceof UpdateOperation) { $a = $a->getTargetPackage()->getName(); } else { $a = $a->getPackage()->getName(); } if ($b instanceof UpdateOperation) { $b = $b->getTargetPackage()->getName(); } else { $b = $b->getPackage()->getName(); } return \strcmp($a, $b); }; \usort($uninstalls, $sortByName); \usort($installsUpdates, $sortByName); foreach (\array_merge($uninstalls, $installsUpdates) as $operation) { // collect suggestions if ($operation instanceof InstallOperation) { $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage()); } // output op if lock file is enabled, but alias op only in debug verbosity if ($this->config->get('lock') && (\false === \strpos($operation->getOperationType(), 'Alias') || $this->io->isDebug())) { $sourceRepo = ''; if ($this->io->isVeryVerbose() && \false === \strpos($operation->getOperationType(), 'Alias')) { $operationPkg = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage(); if ($operationPkg->getRepository() !== null) { $sourceRepo = ' from ' . $operationPkg->getRepository()->getRepoName(); } } $this->io->writeError(' - ' . $operation->show(\true) . $sourceRepo); } } $updatedLock = $this->locker->setLockData($lockTransaction->getNewLockPackages(\false, $this->updateMirrors), $lockTransaction->getNewLockPackages(\true, $this->updateMirrors), $platformReqs, $platformDevReqs, $lockTransaction->getAliases($aliases), $this->package->getMinimumStability(), $this->package->getStabilityFlags(), $this->preferStable || $this->package->getPreferStable(), $this->preferLowest, $this->config->get('platform') ?: [], $this->writeLock && $this->executeOperations); if ($updatedLock && $this->writeLock && $this->executeOperations) { $this->io->writeError('Writing lock file'); } if ($doInstall) { // TODO ensure lock is used from locker as-is, since it may not have been written to disk in case of executeOperations == false return $this->doInstall($localRepo, \true); } return 0; } /** * Run the solver a second time on top of the existing update result with only the current result set in the pool * and see what packages would get removed if we only had the non-dev packages in the solver request * * @param array> $aliases * * @phpstan-param list $aliases * @phpstan-return self::ERROR_* */ protected function extractDevPackages(LockTransaction $lockTransaction, PlatformRepository $platformRepo, array $aliases, PolicyInterface $policy, ?LockArrayRepository $lockedRepository = null) : int { if (!$this->package->getDevRequires()) { return 0; } $resultRepo = new ArrayRepository([]); $loader = new ArrayLoader(null, \true); $dumper = new ArrayDumper(); foreach ($lockTransaction->getNewLockPackages(\false) as $pkg) { $resultRepo->addPackage($loader->load($dumper->dump($pkg))); } $repositorySet = $this->createRepositorySet(\true, $platformRepo, $aliases); $repositorySet->addRepository($resultRepo); $request = $this->createRequest($this->fixedRootPackage, $platformRepo); $this->requirePackagesForUpdate($request, $lockedRepository, \false); $pool = $repositorySet->createPoolWithAllPackages(); $solver = new Solver($policy, $pool, $this->io); try { $nonDevLockTransaction = $solver->solve($request, $this->platformRequirementFilter); $solver = null; } catch (SolverProblemsException $e) { $err = 'Unable to find a compatible set of packages based on your non-dev requirements alone.'; $prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io->isVerbose(), \true); $this->io->writeError('' . $err . '', \true, IOInterface::QUIET); $this->io->writeError('Your requirements can be resolved successfully when require-dev packages are present.'); $this->io->writeError('You may need to move packages from require-dev or some of their dependencies to require.'); $this->io->writeError($prettyProblem); $ghe = new GithubActionError($this->io); $ghe->emit($err . "\n" . $prettyProblem); return $e->getCode(); } $lockTransaction->setNonDevPackages($nonDevLockTransaction); return 0; } /** * @param bool $alreadySolved Whether the function is called as part of an update command or independently * @return int exit code * @phpstan-return self::ERROR_* */ protected function doInstall(InstalledRepositoryInterface $localRepo, bool $alreadySolved = \false) : int { if ($this->config->get('lock')) { $this->io->writeError('Installing dependencies from lock file' . ($this->devMode ? ' (including require-dev)' : '') . ''); } $lockedRepository = $this->locker->getLockedRepository($this->devMode); // verify that the lock file works with the current platform repository // we can skip this part if we're doing this as the second step after an update if (!$alreadySolved) { $this->io->writeError('Verifying lock file contents can be installed on current platform.'); $platformRepo = $this->createPlatformRepo(\false); // creating repository set $policy = $this->createPolicy(\false); // use aliases from lock file only, so empty root aliases here $repositorySet = $this->createRepositorySet(\false, $platformRepo, [], $lockedRepository); $repositorySet->addRepository($lockedRepository); // creating requirements request $request = $this->createRequest($this->fixedRootPackage, $platformRepo, $lockedRepository); if (!$this->locker->isFresh()) { $this->io->writeError('Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. It is recommended that you run `composer update` or `composer update `.', \true, IOInterface::QUIET); } $missingRequirementInfo = $this->locker->getMissingRequirementInfo($this->package, $this->devMode); if ($missingRequirementInfo !== []) { $this->io->writeError($missingRequirementInfo); if (!$this->config->get('allow-missing-requirements')) { return self::ERROR_LOCK_FILE_INVALID; } } foreach ($lockedRepository->getPackages() as $package) { $request->fixLockedPackage($package); } $rootRequires = $this->package->getRequires(); if ($this->devMode) { $rootRequires = \array_merge($rootRequires, $this->package->getDevRequires()); } foreach ($rootRequires as $link) { if (PlatformRepository::isPlatformPackage($link->getTarget())) { $request->requireName($link->getTarget(), $link->getConstraint()); } } foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) { if (!isset($rootRequires[$link->getTarget()])) { $request->requireName($link->getTarget(), $link->getConstraint()); } } unset($rootRequires, $link); $pool = $repositorySet->createPool($request, $this->io, $this->eventDispatcher, null, $this->ignoredTypes, $this->allowedTypes); // solve dependencies $solver = new Solver($policy, $pool, $this->io); try { $lockTransaction = $solver->solve($request, $this->platformRequirementFilter); $solver = null; // installing the locked packages on this platform resulted in lock modifying operations, there wasn't a conflict, but the lock file as-is seems to not work on this system if (0 !== \count($lockTransaction->getOperations())) { $this->io->writeError('Your lock file cannot be installed on this system without changes. Please run composer update.', \true, IOInterface::QUIET); return self::ERROR_LOCK_FILE_INVALID; } } catch (SolverProblemsException $e) { $err = 'Your lock file does not contain a compatible set of packages. Please run composer update.'; $prettyProblem = $e->getPrettyString($repositorySet, $request, $pool, $this->io->isVerbose()); $this->io->writeError('' . $err . '', \true, IOInterface::QUIET); $this->io->writeError($prettyProblem); $ghe = new GithubActionError($this->io); $ghe->emit($err . "\n" . $prettyProblem); return \max(self::ERROR_GENERIC_FAILURE, $e->getCode()); } } // TODO in how far do we need to do anything here to ensure dev packages being updated to latest in lock without version change are treated correctly? $localRepoTransaction = new LocalRepoTransaction($lockedRepository, $localRepo); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_OPERATIONS_EXEC, $this->devMode, $this->executeOperations, $localRepoTransaction); $installs = $updates = $uninstalls = []; foreach ($localRepoTransaction->getOperations() as $operation) { if ($operation instanceof InstallOperation) { $installs[] = $operation->getPackage()->getPrettyName() . ':' . $operation->getPackage()->getFullPrettyVersion(); } elseif ($operation instanceof UpdateOperation) { $updates[] = $operation->getTargetPackage()->getPrettyName() . ':' . $operation->getTargetPackage()->getFullPrettyVersion(); } elseif ($operation instanceof UninstallOperation) { $uninstalls[] = $operation->getPackage()->getPrettyName(); } } if ($installs === [] && $updates === [] && $uninstalls === []) { $this->io->writeError('Nothing to install, update or remove'); } else { $this->io->writeError(\sprintf("Package operations: %d install%s, %d update%s, %d removal%s", \count($installs), 1 === \count($installs) ? '' : 's', \count($updates), 1 === \count($updates) ? '' : 's', \count($uninstalls), 1 === \count($uninstalls) ? '' : 's')); if ($installs) { $this->io->writeError("Installs: " . \implode(', ', $installs), \true, IOInterface::VERBOSE); } if ($updates) { $this->io->writeError("Updates: " . \implode(', ', $updates), \true, IOInterface::VERBOSE); } if ($uninstalls) { $this->io->writeError("Removals: " . \implode(', ', $uninstalls), \true, IOInterface::VERBOSE); } } if ($this->executeOperations) { $localRepo->setDevPackageNames($this->locker->getDevPackageNames()); $this->installationManager->execute($localRepo, $localRepoTransaction->getOperations(), $this->devMode, $this->runScripts, $this->downloadOnly); // see https://github.com/composer/composer/issues/2764 if (\count($localRepoTransaction->getOperations()) > 0) { $vendorDir = $this->config->get('vendor-dir'); if (\is_dir($vendorDir)) { // suppress errors as this fails sometimes on OSX for no apparent reason // see https://github.com/composer/composer/issues/4070#issuecomment-129792748 @\touch($vendorDir); } } } else { foreach ($localRepoTransaction->getOperations() as $operation) { // output op, but alias op only in debug verbosity if (\false === \strpos($operation->getOperationType(), 'Alias') || $this->io->isDebug()) { $this->io->writeError(' - ' . $operation->show(\false)); } } } return 0; } protected function createPlatformRepo(bool $forUpdate) : PlatformRepository { if ($forUpdate) { $platformOverrides = $this->config->get('platform') ?: []; } else { $platformOverrides = $this->locker->getPlatformOverrides(); } return new PlatformRepository([], $platformOverrides); } /** * @param array> $rootAliases * * @phpstan-param list $rootAliases */ private function createRepositorySet(bool $forUpdate, PlatformRepository $platformRepo, array $rootAliases = [], ?RepositoryInterface $lockedRepository = null) : RepositorySet { if ($forUpdate) { $minimumStability = $this->package->getMinimumStability(); $stabilityFlags = $this->package->getStabilityFlags(); $requires = \array_merge($this->package->getRequires(), $this->package->getDevRequires()); } else { $minimumStability = $this->locker->getMinimumStability(); $stabilityFlags = $this->locker->getStabilityFlags(); $requires = []; foreach ($lockedRepository->getPackages() as $package) { $constraint = new Constraint('=', $package->getVersion()); $constraint->setPrettyString($package->getPrettyVersion()); $requires[$package->getName()] = $constraint; } } $rootRequires = []; foreach ($requires as $req => $constraint) { if ($constraint instanceof Link) { $constraint = $constraint->getConstraint(); } // skip platform requirements from the root package to avoid filtering out existing platform packages if ($this->platformRequirementFilter->isIgnored($req)) { continue; } elseif ($this->platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter) { $constraint = $this->platformRequirementFilter->filterConstraint($req, $constraint); } $rootRequires[$req] = $constraint; } $this->fixedRootPackage = clone $this->package; $this->fixedRootPackage->setRequires([]); $this->fixedRootPackage->setDevRequires([]); $stabilityFlags[$this->package->getName()] = BasePackage::STABILITIES[VersionParser::parseStability($this->package->getVersion())]; $repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases, $this->package->getReferences(), $rootRequires, $this->temporaryConstraints); $repositorySet->addRepository(new RootPackageRepository($this->fixedRootPackage)); $repositorySet->addRepository($platformRepo); if ($this->additionalFixedRepository) { // allow using installed repos if needed to avoid warnings about installed repositories being used in the RepositorySet // see https://github.com/composer/composer/pull/9574 $additionalFixedRepositories = $this->additionalFixedRepository; if ($additionalFixedRepositories instanceof CompositeRepository) { $additionalFixedRepositories = $additionalFixedRepositories->getRepositories(); } else { $additionalFixedRepositories = [$additionalFixedRepositories]; } foreach ($additionalFixedRepositories as $additionalFixedRepository) { if ($additionalFixedRepository instanceof InstalledRepository || $additionalFixedRepository instanceof InstalledRepositoryInterface) { $repositorySet->allowInstalledRepositories(); break; } } $repositorySet->addRepository($this->additionalFixedRepository); } return $repositorySet; } private function createPolicy(bool $forUpdate, ?LockArrayRepository $lockedRepo = null) : DefaultPolicy { $preferStable = null; $preferLowest = null; if (!$forUpdate) { $preferStable = $this->locker->getPreferStable(); $preferLowest = $this->locker->getPreferLowest(); } // old lock file without prefer stable/lowest will return null // so in this case we use the composer.json info if (null === $preferStable) { $preferStable = $this->preferStable || $this->package->getPreferStable(); } if (null === $preferLowest) { $preferLowest = $this->preferLowest; } $preferredVersions = null; if ($forUpdate && $this->minimalUpdate && $this->updateAllowList !== null && $lockedRepo !== null) { $preferredVersions = []; foreach ($lockedRepo->getPackages() as $pkg) { if ($pkg instanceof AliasPackage || \in_array($pkg->getName(), $this->updateAllowList, \true)) { continue; } $preferredVersions[$pkg->getName()] = $pkg->getVersion(); } } return new DefaultPolicy($preferStable, $preferLowest, $preferredVersions); } /** * @param RootPackageInterface&BasePackage $rootPackage */ private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo, ?LockArrayRepository $lockedRepository = null) : Request { $request = new Request($lockedRepository); $request->fixPackage($rootPackage); if ($rootPackage instanceof RootAliasPackage) { $request->fixPackage($rootPackage->getAliasOf()); } $fixedPackages = $platformRepo->getPackages(); if ($this->additionalFixedRepository) { $fixedPackages = \array_merge($fixedPackages, $this->additionalFixedRepository->getPackages()); } // fix the version of all platform packages + additionally installed packages // to prevent the solver trying to remove or update those // TODO why not replaces? $provided = $rootPackage->getProvides(); foreach ($fixedPackages as $package) { // skip platform packages that are provided by the root package if ($package->getRepository() !== $platformRepo || !isset($provided[$package->getName()]) || !$provided[$package->getName()]->getConstraint()->matches(new Constraint('=', $package->getVersion()))) { $request->fixPackage($package); } } return $request; } private function requirePackagesForUpdate(Request $request, ?LockArrayRepository $lockedRepository = null, bool $includeDevRequires = \true) : void { // if we're updating mirrors we want to keep exactly the same versions installed which are in the lock file, but we want current remote metadata if ($this->updateMirrors) { $excludedPackages = []; if (!$includeDevRequires) { $excludedPackages = \array_flip($this->locker->getDevPackageNames()); } foreach ($lockedRepository->getPackages() as $lockedPackage) { // exclude alias packages here as for root aliases, both alias and aliased are // present in the lock repo and we only want to require the aliased version if (!$lockedPackage instanceof AliasPackage && !isset($excludedPackages[$lockedPackage->getName()])) { $request->requireName($lockedPackage->getName(), new Constraint('==', $lockedPackage->getVersion())); } } } else { $links = $this->package->getRequires(); if ($includeDevRequires) { $links = \array_merge($links, $this->package->getDevRequires()); } foreach ($links as $link) { $request->requireName($link->getTarget(), $link->getConstraint()); } } } /** * @return array> * * @phpstan-return list */ private function getRootAliases(bool $forUpdate) : array { if ($forUpdate) { $aliases = $this->package->getAliases(); } else { $aliases = $this->locker->getAliases(); } return $aliases; } /** * @param Link[] $links * * @return array */ private function extractPlatformRequirements(array $links) : array { $platformReqs = []; foreach ($links as $link) { if (PlatformRepository::isPlatformPackage($link->getTarget())) { $platformReqs[$link->getTarget()] = $link->getPrettyConstraint(); } } return $platformReqs; } /** * Replace local repositories with InstalledArrayRepository instances * * This is to prevent any accidental modification of the existing repos on disk */ private function mockLocalRepositories(RepositoryManager $rm) : void { $packages = []; foreach ($rm->getLocalRepository()->getPackages() as $package) { $packages[(string) $package] = clone $package; } foreach ($packages as $key => $package) { if ($package instanceof AliasPackage) { $alias = (string) $package->getAliasOf(); $className = \get_class($package); $packages[$key] = new $className($packages[$alias], $package->getVersion(), $package->getPrettyVersion()); } } $rm->setLocalRepository(new InstalledArrayRepository($packages)); } private function createPoolOptimizer(PolicyInterface $policy) : ?PoolOptimizer { // Not the best architectural decision here, would need to be able // to configure from the outside of Installer but this is only // a debugging tool and should never be required in any other use case if ('0' === Platform::getEnv('COMPOSER_POOL_OPTIMIZER')) { $this->io->write('Pool Optimizer was disabled for debugging purposes.', \true, IOInterface::DEBUG); return null; } return new PoolOptimizer($policy); } /** * Create Installer * * @return Installer */ public static function create(IOInterface $io, \Composer\Composer $composer) : self { return new static($io, $composer->getConfig(), $composer->getPackage(), $composer->getDownloadManager(), $composer->getRepositoryManager(), $composer->getLocker(), $composer->getInstallationManager(), $composer->getEventDispatcher(), $composer->getAutoloadGenerator()); } /** * Packages of those types are ignored, by default php-ext and php-ext-zend are ignored * * @param list $types * @return $this */ public function setIgnoredTypes(array $types) : self { $this->ignoredTypes = $types; return $this; } /** * Only packages of those types are allowed if set to non-null * * @param list|null $types * @return $this */ public function setAllowedTypes(?array $types) : self { $this->allowedTypes = $types; return $this; } /** * @return $this */ public function setAdditionalFixedRepository(RepositoryInterface $additionalFixedRepository) : self { $this->additionalFixedRepository = $additionalFixedRepository; return $this; } /** * @param array $constraints * @return Installer */ public function setTemporaryConstraints(array $constraints) : self { $this->temporaryConstraints = $constraints; return $this; } /** * Whether to run in drymode or not * * @return Installer */ public function setDryRun(bool $dryRun = \true) : self { $this->dryRun = $dryRun; return $this; } /** * Checks, if this is a dry run (simulation mode). */ public function isDryRun() : bool { return $this->dryRun; } /** * Whether to download only or not. * * @return Installer */ public function setDownloadOnly(bool $downloadOnly = \true) : self { $this->downloadOnly = $downloadOnly; return $this; } /** * prefer source installation * * @return Installer */ public function setPreferSource(bool $preferSource = \true) : self { $this->preferSource = $preferSource; return $this; } /** * prefer dist installation * * @return Installer */ public function setPreferDist(bool $preferDist = \true) : self { $this->preferDist = $preferDist; return $this; } /** * Whether or not generated autoloader are optimized * * @return Installer */ public function setOptimizeAutoloader(bool $optimizeAutoloader) : self { $this->optimizeAutoloader = $optimizeAutoloader; if (!$this->optimizeAutoloader) { // Force classMapAuthoritative off when not optimizing the // autoloader $this->setClassMapAuthoritative(\false); } return $this; } /** * Whether or not generated autoloader considers the class map * authoritative. * * @return Installer */ public function setClassMapAuthoritative(bool $classMapAuthoritative) : self { $this->classMapAuthoritative = $classMapAuthoritative; if ($this->classMapAuthoritative) { // Force optimizeAutoloader when classmap is authoritative $this->setOptimizeAutoloader(\true); } return $this; } /** * Whether or not generated autoloader considers APCu caching. * * @return Installer */ public function setApcuAutoloader(bool $apcuAutoloader, ?string $apcuAutoloaderPrefix = null) : self { $this->apcuAutoloader = $apcuAutoloader; $this->apcuAutoloaderPrefix = $apcuAutoloaderPrefix; return $this; } /** * update packages * * @return Installer */ public function setUpdate(bool $update) : self { $this->update = $update; return $this; } /** * Allows disabling the install step after an update * * @return Installer */ public function setInstall(bool $install) : self { $this->install = $install; return $this; } /** * enables dev packages * * @return Installer */ public function setDevMode(bool $devMode = \true) : self { $this->devMode = $devMode; return $this; } /** * set whether to run autoloader or not * * This is disabled implicitly when enabling dryRun * * @return Installer */ public function setDumpAutoloader(bool $dumpAutoloader = \true) : self { $this->dumpAutoloader = $dumpAutoloader; return $this; } /** * set whether to run scripts or not * * This is disabled implicitly when enabling dryRun * * @return Installer * @deprecated Use setRunScripts(false) on the EventDispatcher instance being injected instead */ public function setRunScripts(bool $runScripts = \true) : self { $this->runScripts = $runScripts; return $this; } /** * set the config instance * * @return Installer */ public function setConfig(\Composer\Config $config) : self { $this->config = $config; return $this; } /** * run in verbose mode * * @return Installer */ public function setVerbose(bool $verbose = \true) : self { $this->verbose = $verbose; return $this; } /** * Checks, if running in verbose mode. */ public function isVerbose() : bool { return $this->verbose; } /** * set ignore Platform Package requirements * * If this is set to true, all platform requirements are ignored * If this is set to false, no platform requirements are ignored * If this is set to string[], those packages will be ignored * * @param bool|string[] $ignorePlatformReqs * * @return Installer * * @deprecated use setPlatformRequirementFilter instead */ public function setIgnorePlatformRequirements($ignorePlatformReqs) : self { \trigger_error('Installer::setIgnorePlatformRequirements is deprecated since Composer 2.2, use setPlatformRequirementFilter instead.', \E_USER_DEPRECATED); return $this->setPlatformRequirementFilter(PlatformRequirementFilterFactory::fromBoolOrList($ignorePlatformReqs)); } /** * @return Installer */ public function setPlatformRequirementFilter(PlatformRequirementFilterInterface $platformRequirementFilter) : self { $this->platformRequirementFilter = $platformRequirementFilter; return $this; } /** * Update the lock file to the exact same versions and references but use current remote metadata like URLs and mirror info * * @return Installer */ public function setUpdateMirrors(bool $updateMirrors) : self { $this->updateMirrors = $updateMirrors; return $this; } /** * restrict the update operation to a few packages, all other packages * that are already installed will be kept at their current version * * @param string[] $packages * * @return Installer */ public function setUpdateAllowList(array $packages) : self { if (\count($packages) === 0) { $this->updateAllowList = null; } else { $this->updateAllowList = \array_values(\array_unique(\array_map('strtolower', $packages))); } return $this; } /** * Should dependencies of packages marked for update be updated? * * Depending on the chosen constant this will either only update the directly named packages, all transitive * dependencies which are not root requirement or all transitive dependencies including root requirements * * @param int $updateAllowTransitiveDependencies One of the UPDATE_ constants on the Request class * @return Installer */ public function setUpdateAllowTransitiveDependencies(int $updateAllowTransitiveDependencies) : self { if (!\in_array($updateAllowTransitiveDependencies, [Request::UPDATE_ONLY_LISTED, Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE, Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS], \true)) { throw new \RuntimeException("Invalid value for updateAllowTransitiveDependencies supplied"); } $this->updateAllowTransitiveDependencies = $updateAllowTransitiveDependencies; return $this; } /** * Should packages be preferred in a stable version when updating? * * @return Installer */ public function setPreferStable(bool $preferStable = \true) : self { $this->preferStable = $preferStable; return $this; } /** * Should packages be preferred in a lowest version when updating? * * @return Installer */ public function setPreferLowest(bool $preferLowest = \true) : self { $this->preferLowest = $preferLowest; return $this; } /** * Only relevant for partial updates (with setUpdateAllowList), if this is enabled currently locked versions will be preferred for packages which are not in the allowlist * * This reduces the update to * * @return Installer */ public function setMinimalUpdate(bool $minimalUpdate = \true) : self { $this->minimalUpdate = $minimalUpdate; return $this; } /** * Should the lock file be updated when updating? * * This is disabled implicitly when enabling dryRun * * @return Installer */ public function setWriteLock(bool $writeLock = \true) : self { $this->writeLock = $writeLock; return $this; } /** * Should the operations (package install, update and removal) be executed on disk? * * This is disabled implicitly when enabling dryRun * * @return Installer */ public function setExecuteOperations(bool $executeOperations = \true) : self { $this->executeOperations = $executeOperations; return $this; } /** * Should an audit be run after installation is complete? * * @return Installer */ public function setAudit(bool $audit) : self { $this->audit = $audit; return $this; } /** * Should exit with status code 5 on audit error * * @param bool $errorOnAudit * @return Installer */ public function setErrorOnAudit(bool $errorOnAudit) : self { $this->errorOnAudit = $errorOnAudit; return $this; } /** * What format should be used for audit output? * * @param Auditor::FORMAT_* $auditFormat * @return Installer */ public function setAuditFormat(string $auditFormat) : self { $this->auditFormat = $auditFormat; return $this; } /** * Disables plugins. * * Call this if you want to ensure that third-party code never gets * executed. The default is to automatically install, and execute * custom third-party installers. * * @return Installer */ public function disablePlugins() : self { $this->installationManager->disablePlugins(); return $this; } /** * @return Installer */ public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter) : self { $this->suggestedPackagesReporter = $suggestedPackagesReporter; return $this; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Filter\PlatformRequirementFilter; interface PlatformRequirementFilterInterface { public function isIgnored(string $req) : bool; public function isUpperBoundIgnored(string $req) : bool; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Filter\PlatformRequirementFilter; use Composer\Repository\PlatformRepository; final class IgnoreAllPlatformRequirementFilter implements \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface { public function isIgnored(string $req) : bool { return PlatformRepository::isPlatformPackage($req); } public function isUpperBoundIgnored(string $req) : bool { return $this->isIgnored($req); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Filter\PlatformRequirementFilter; use Composer\Package\BasePackage; use Composer\Pcre\Preg; use Composer\Repository\PlatformRepository; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Semver\Constraint\MultiConstraint; use Composer\Semver\Interval; use Composer\Semver\Intervals; final class IgnoreListPlatformRequirementFilter implements \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface { /** * @var non-empty-string */ private $ignoreRegex; /** * @var non-empty-string */ private $ignoreUpperBoundRegex; /** * @param string[] $reqList */ public function __construct(array $reqList) { $ignoreAll = $ignoreUpperBound = []; foreach ($reqList as $req) { if (\substr($req, -1) === '+') { $ignoreUpperBound[] = \substr($req, 0, -1); } else { $ignoreAll[] = $req; } } $this->ignoreRegex = BasePackage::packageNamesToRegexp($ignoreAll); $this->ignoreUpperBoundRegex = BasePackage::packageNamesToRegexp($ignoreUpperBound); } public function isIgnored(string $req) : bool { if (!PlatformRepository::isPlatformPackage($req)) { return \false; } return Preg::isMatch($this->ignoreRegex, $req); } public function isUpperBoundIgnored(string $req) : bool { if (!PlatformRepository::isPlatformPackage($req)) { return \false; } return $this->isIgnored($req) || Preg::isMatch($this->ignoreUpperBoundRegex, $req); } /** * @param bool $allowUpperBoundOverride For conflicts we do not want the upper bound to be skipped */ public function filterConstraint(string $req, ConstraintInterface $constraint, bool $allowUpperBoundOverride = \true) : ConstraintInterface { if (!PlatformRepository::isPlatformPackage($req)) { return $constraint; } if (!$allowUpperBoundOverride || !Preg::isMatch($this->ignoreUpperBoundRegex, $req)) { return $constraint; } if (Preg::isMatch($this->ignoreRegex, $req)) { return new MatchAllConstraint(); } $intervals = Intervals::get($constraint); $last = \end($intervals['numeric']); if ($last !== \false && (string) $last->getEnd() !== (string) Interval::untilPositiveInfinity()) { $constraint = new MultiConstraint([$constraint, new Constraint('>=', $last->getEnd()->getVersion())], \false); } return $constraint; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Filter\PlatformRequirementFilter; final class IgnoreNothingPlatformRequirementFilter implements \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface { /** * @return false */ public function isIgnored(string $req) : bool { return \false; } /** * @return false */ public function isUpperBoundIgnored(string $req) : bool { return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Filter\PlatformRequirementFilter; final class PlatformRequirementFilterFactory { /** * @param mixed $boolOrList */ public static function fromBoolOrList($boolOrList) : \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface { if (\is_bool($boolOrList)) { return $boolOrList ? self::ignoreAll() : self::ignoreNothing(); } if (\is_array($boolOrList)) { return new \Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter($boolOrList); } throw new \InvalidArgumentException(\sprintf('PlatformRequirementFilter: Unknown $boolOrList parameter %s. Please report at https://github.com/composer/composer/issues/new.', \gettype($boolOrList))); } public static function ignoreAll() : \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface { return new \Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter(); } public static function ignoreNothing() : \Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface { return new \Composer\Filter\PlatformRequirementFilter\IgnoreNothingPlatformRequirementFilter(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; /** * Package Events. * * @author Jordi Boggiano */ class PackageEvents { /** * The PRE_PACKAGE_INSTALL event occurs before a package is installed. * * The event listener method receives a Composer\Installer\PackageEvent instance. * * @var string */ public const PRE_PACKAGE_INSTALL = 'pre-package-install'; /** * The POST_PACKAGE_INSTALL event occurs after a package is installed. * * The event listener method receives a Composer\Installer\PackageEvent instance. * * @var string */ public const POST_PACKAGE_INSTALL = 'post-package-install'; /** * The PRE_PACKAGE_UPDATE event occurs before a package is updated. * * The event listener method receives a Composer\Installer\PackageEvent instance. * * @var string */ public const PRE_PACKAGE_UPDATE = 'pre-package-update'; /** * The POST_PACKAGE_UPDATE event occurs after a package is updated. * * The event listener method receives a Composer\Installer\PackageEvent instance. * * @var string */ public const POST_PACKAGE_UPDATE = 'post-package-update'; /** * The PRE_PACKAGE_UNINSTALL event occurs before a package has been uninstalled. * * The event listener method receives a Composer\Installer\PackageEvent instance. * * @var string */ public const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall'; /** * The POST_PACKAGE_UNINSTALL event occurs after a package has been uninstalled. * * The event listener method receives a Composer\Installer\PackageEvent instance. * * @var string */ public const POST_PACKAGE_UNINSTALL = 'post-package-uninstall'; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Util\Silencer; /** * Utility to handle installation of package "bin"/binaries * * @author Jordi Boggiano * @author Konstantin Kudryashov * @author Helmut Hummel */ class BinaryInstaller { /** @var string */ protected $binDir; /** @var string */ protected $binCompat; /** @var IOInterface */ protected $io; /** @var Filesystem */ protected $filesystem; /** @var string|null */ private $vendorDir; /** * @param Filesystem $filesystem */ public function __construct(IOInterface $io, string $binDir, string $binCompat, ?Filesystem $filesystem = null, ?string $vendorDir = null) { $this->binDir = $binDir; $this->binCompat = $binCompat; $this->io = $io; $this->filesystem = $filesystem ?: new Filesystem(); $this->vendorDir = $vendorDir; } public function installBinaries(PackageInterface $package, string $installPath, bool $warnOnOverwrite = \true) : void { $binaries = $this->getBinaries($package); if (!$binaries) { return; } Platform::workaroundFilesystemIssues(); foreach ($binaries as $bin) { $binPath = $installPath . '/' . $bin; if (!\file_exists($binPath)) { $this->io->writeError(' Skipped installation of bin ' . $bin . ' for package ' . $package->getName() . ': file not found in package'); continue; } if (\is_dir($binPath)) { $this->io->writeError(' Skipped installation of bin ' . $bin . ' for package ' . $package->getName() . ': found a directory at that path'); continue; } if (!$this->filesystem->isAbsolutePath($binPath)) { // in case a custom installer returned a relative path for the // $package, we can now safely turn it into a absolute path (as we // already checked the binary's existence). The following helpers // will require absolute paths to work properly. $binPath = \realpath($binPath); } $this->initializeBinDir(); $link = $this->binDir . '/' . \basename($bin); if (\file_exists($link)) { if (!\is_link($link)) { if ($warnOnOverwrite) { $this->io->writeError(' Skipped installation of bin ' . $bin . ' for package ' . $package->getName() . ': name conflicts with an existing file'); } continue; } if (\realpath($link) === \realpath($binPath)) { // It is a linked binary from a previous installation, which can be replaced with a proxy file $this->filesystem->unlink($link); } } $binCompat = $this->binCompat; if ($binCompat === "auto" && (Platform::isWindows() || Platform::isWindowsSubsystemForLinux())) { $binCompat = 'full'; } if ($binCompat === "full") { $this->installFullBinaries($binPath, $link, $bin, $package); } else { $this->installUnixyProxyBinaries($binPath, $link); } Silencer::call('chmod', $binPath, 0777 & ~\umask()); } } public function removeBinaries(PackageInterface $package) : void { $this->initializeBinDir(); $binaries = $this->getBinaries($package); if (!$binaries) { return; } foreach ($binaries as $bin) { $link = $this->binDir . '/' . \basename($bin); if (\is_link($link) || \file_exists($link)) { // still checking for symlinks here for legacy support $this->filesystem->unlink($link); } if (\is_file($link . '.bat')) { $this->filesystem->unlink($link . '.bat'); } } // attempt removing the bin dir in case it is left empty if (\is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) { Silencer::call('rmdir', $this->binDir); } } public static function determineBinaryCaller(string $bin) : string { if ('.bat' === \substr($bin, -4) || '.exe' === \substr($bin, -4)) { return 'call'; } $handle = \fopen($bin, 'r'); $line = \fgets($handle); \fclose($handle); if (Preg::isMatchStrictGroups('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', (string) $line, $match)) { return \trim($match[1]); } return 'php'; } /** * @return string[] */ protected function getBinaries(PackageInterface $package) : array { return $package->getBinaries(); } protected function installFullBinaries(string $binPath, string $link, string $bin, PackageInterface $package) : void { // add unixy support for cygwin and similar environments if ('.bat' !== \substr($binPath, -4)) { $this->installUnixyProxyBinaries($binPath, $link); $link .= '.bat'; if (\file_exists($link)) { $this->io->writeError(' Skipped installation of bin ' . $bin . '.bat proxy for package ' . $package->getName() . ': a .bat proxy was already installed'); } } if (!\file_exists($link)) { \file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link)); Silencer::call('chmod', $link, 0777 & ~\umask()); } } protected function installUnixyProxyBinaries(string $binPath, string $link) : void { \file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link)); Silencer::call('chmod', $link, 0777 & ~\umask()); } protected function initializeBinDir() : void { $this->filesystem->ensureDirectoryExists($this->binDir); $this->binDir = \realpath($this->binDir); } protected function generateWindowsProxyCode(string $bin, string $link) : string { $binPath = $this->filesystem->findShortestPath($link, $bin); $caller = self::determineBinaryCaller($bin); // if the target is a php file, we run the unixy proxy file // to ensure that _composer_autoload_path gets defined, instead // of running the binary directly if ($caller === 'php') { return "@ECHO OFF\r\n" . "setlocal DISABLEDELAYEDEXPANSION\r\n" . "SET BIN_TARGET=%~dp0/" . \trim(ProcessExecutor::escape(\basename($link, '.bat')), '"\'') . "\r\n" . "SET COMPOSER_RUNTIME_BIN_DIR=%~dp0\r\n" . "{$caller} \"%BIN_TARGET%\" %*\r\n"; } return "@ECHO OFF\r\n" . "setlocal DISABLEDELAYEDEXPANSION\r\n" . "SET BIN_TARGET=%~dp0/" . \trim(ProcessExecutor::escape($binPath), '"\'') . "\r\n" . "SET COMPOSER_RUNTIME_BIN_DIR=%~dp0\r\n" . "{$caller} \"%BIN_TARGET%\" %*\r\n"; } protected function generateUnixyProxyCode(string $bin, string $link) : string { $binPath = $this->filesystem->findShortestPath($link, $bin); $binDir = ProcessExecutor::escape(\dirname($binPath)); $binFile = \basename($binPath); $binContents = (string) \file_get_contents($bin, \false, null, 0, 500); // For php files, we generate a PHP proxy instead of a shell one, // which allows calling the proxy with a custom php process if (Preg::isMatch('{^(#!.*\\r?\\n)?[\\r\\n\\t ]*<\\?php}', $binContents, $match)) { // carry over the existing shebang if present, otherwise add our own $proxyCode = $match[1] === null ? '#!/usr/bin/env php' : \trim($match[1]); $binPathExported = $this->filesystem->findShortestPathCode($link, $bin, \false, \true); $streamProxyCode = $streamHint = ''; $globalsCode = '$GLOBALS[\'_composer_bin_dir\'] = __DIR__;' . "\n"; $phpunitHack1 = $phpunitHack2 = ''; // Don't expose autoload path when vendor dir was not set in custom installers if ($this->vendorDir !== null) { // ensure comparisons work accurately if the CWD is a symlink, as $link is realpath'd already $vendorDirReal = \realpath($this->vendorDir); if ($vendorDirReal === \false) { $vendorDirReal = $this->vendorDir; } $globalsCode .= '$GLOBALS[\'_composer_autoload_path\'] = ' . $this->filesystem->findShortestPathCode($link, $vendorDirReal . '/autoload.php', \false, \true) . ";\n"; } // Add workaround for PHPUnit process isolation if ($this->filesystem->normalizePath($bin) === $this->filesystem->normalizePath($this->vendorDir . '/phpunit/phpunit/phpunit')) { // workaround issue on PHPUnit 6.5+ running on PHP 8+ $globalsCode .= '$GLOBALS[\'__PHPUNIT_ISOLATION_EXCLUDE_LIST\'] = $GLOBALS[\'__PHPUNIT_ISOLATION_BLACKLIST\'] = array(realpath(' . $binPathExported . '));' . "\n"; // workaround issue on all PHPUnit versions running on PHP <8 $phpunitHack1 = "'phpvfscomposer://'."; $phpunitHack2 = ' $data = str_replace(\'__DIR__\', var_export(dirname($this->realpath), true), $data); $data = str_replace(\'__FILE__\', var_export($this->realpath, true), $data);'; } if (\trim($match[0]) !== 'realpath = realpath(\$opened_path) ?: \$opened_path; \$opened_path = {$phpunitHack1}\$this->realpath; \$this->handle = fopen(\$this->realpath, \$mode); \$this->position = 0; return (bool) \$this->handle; } public function stream_read(\$count) { \$data = fread(\$this->handle, \$count); if (\$this->position === 0) { \$data = preg_replace('{^#!.*\\r?\\n}', '', \$data); }{$phpunitHack2} \$this->position += strlen(\$data); return \$data; } public function stream_cast(\$castAs) { return \$this->handle; } public function stream_close() { fclose(\$this->handle); } public function stream_lock(\$operation) { return \$operation ? flock(\$this->handle, \$operation) : true; } public function stream_seek(\$offset, \$whence) { if (0 === fseek(\$this->handle, \$offset, \$whence)) { \$this->position = ftell(\$this->handle); return true; } return false; } public function stream_tell() { return \$this->position; } public function stream_eof() { return feof(\$this->handle); } public function stream_stat() { return array(); } public function stream_set_option(\$option, \$arg1, \$arg2) { return true; } public function url_stat(\$path, \$flags) { \$path = substr(\$path, 17); if (file_exists(\$path)) { return stat(\$path); } return false; } } } if ( (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper')) ) { return include("phpvfscomposer://" . {$binPathExported}); } } STREAMPROXY; } return $proxyCode . "\n" . << /dev/null) if [ -z "\$self" ]; then self="\$selfArg" fi dir=\$(cd "\${self%[/\\\\]*}" > /dev/null; cd {$binDir} && pwd) if [ -d /proc/cygdrive ]; then case \$(which php) in \$(readlink -n /proc/cygdrive)/*) # We are in Cygwin using Windows php, so the path must be translated dir=\$(cygpath -m "\$dir"); ;; esac fi export COMPOSER_RUNTIME_BIN_DIR="\$(cd "\${self%[/\\\\]*}" > /dev/null; pwd)" # If bash is sourcing this file, we have to source the target as well bashSource="\$BASH_SOURCE" if [ -n "\$bashSource" ]; then if [ "\$bashSource" != "\$0" ]; then source "\${dir}/{$binFile}" "\$@" return fi fi exec "\${dir}/{$binFile}" "\$@" PROXY; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Composer; use Composer\IO\IOInterface; use Composer\PartialComposer; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\Plugin\PluginManager; use Composer\Util\Filesystem; use Composer\Util\Platform; use React\Promise\PromiseInterface; /** * Installer for plugin packages * * @author Jordi Boggiano * @author Nils Adermann */ class PluginInstaller extends \Composer\Installer\LibraryInstaller { public function __construct(IOInterface $io, PartialComposer $composer, ?Filesystem $fs = null, ?\Composer\Installer\BinaryInstaller $binaryInstaller = null) { parent::__construct($io, $composer, 'composer-plugin', $fs, $binaryInstaller); } /** * @inheritDoc */ public function supports(string $packageType) { return $packageType === 'composer-plugin' || $packageType === 'composer-installer'; } public function disablePlugins() : void { $this->getPluginManager()->disablePlugins(); } /** * @inheritDoc */ public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null) { // fail install process early if it is going to fail due to a plugin not being allowed if (($type === 'install' || $type === 'update') && !$this->getPluginManager()->arePluginsDisabled('local')) { $this->getPluginManager()->isPluginAllowed($package->getName(), \false, \true === ($package->getExtra()['plugin-optional'] ?? \false)); } return parent::prepare($type, $package, $prevPackage); } /** * @inheritDoc */ public function download(PackageInterface $package, ?PackageInterface $prevPackage = null) { $extra = $package->getExtra(); if (empty($extra['class'])) { throw new \UnexpectedValueException('Error while installing ' . $package->getPrettyName() . ', composer-plugin packages should have a class defined in their extra key to be usable.'); } return parent::download($package, $prevPackage); } /** * @inheritDoc */ public function install(InstalledRepositoryInterface $repo, PackageInterface $package) { $promise = parent::install($repo, $package); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } return $promise->then(function () use($package, $repo) : void { try { Platform::workaroundFilesystemIssues(); $this->getPluginManager()->registerPackage($package, \true); } catch (\Exception $e) { $this->rollbackInstall($e, $repo, $package); } }); } /** * @inheritDoc */ public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) { $promise = parent::update($repo, $initial, $target); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } return $promise->then(function () use($initial, $target, $repo) : void { try { Platform::workaroundFilesystemIssues(); $this->getPluginManager()->deactivatePackage($initial); $this->getPluginManager()->registerPackage($target, \true); } catch (\Exception $e) { $this->rollbackInstall($e, $repo, $target); } }); } public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) { $this->getPluginManager()->uninstallPackage($package); return parent::uninstall($repo, $package); } private function rollbackInstall(\Exception $e, InstalledRepositoryInterface $repo, PackageInterface $package) : void { $this->io->writeError('Plugin initialization failed (' . $e->getMessage() . '), uninstalling plugin'); parent::uninstall($repo, $package); throw $e; } protected function getPluginManager() : PluginManager { \assert($this->composer instanceof Composer, new \LogicException(self::class . ' should be initialized with a fully loaded Composer instance.')); $pluginManager = $this->composer->getPluginManager(); return $pluginManager; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Package\PackageInterface; /** * Interface for the package installation manager that handle binary installation. * * @author Jordi Boggiano */ interface BinaryPresenceInterface { /** * Make sure binaries are installed for a given package. * * @param PackageInterface $package package instance * * @return void */ public function ensureBinariesPresence(PackageInterface $package); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; class InstallerEvents { /** * The PRE_OPERATIONS_EXEC event occurs before the lock file gets * installed and operations are executed. * * The event listener method receives an Composer\Installer\InstallerEvent instance. * * @var string */ public const PRE_OPERATIONS_EXEC = 'pre-operations-exec'; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Composer; use Composer\IO\IOInterface; use Composer\DependencyResolver\Operation\OperationInterface; use Composer\Repository\RepositoryInterface; use Composer\EventDispatcher\Event; /** * The Package Event. * * @author Jordi Boggiano */ class PackageEvent extends Event { /** * @var Composer */ private $composer; /** * @var IOInterface */ private $io; /** * @var bool */ private $devMode; /** * @var RepositoryInterface */ private $localRepo; /** * @var OperationInterface[] */ private $operations; /** * @var OperationInterface The operation instance which is being executed */ private $operation; /** * Constructor. * * @param OperationInterface[] $operations */ public function __construct(string $eventName, Composer $composer, IOInterface $io, bool $devMode, RepositoryInterface $localRepo, array $operations, OperationInterface $operation) { parent::__construct($eventName); $this->composer = $composer; $this->io = $io; $this->devMode = $devMode; $this->localRepo = $localRepo; $this->operations = $operations; $this->operation = $operation; } public function getComposer() : Composer { return $this->composer; } public function getIO() : IOInterface { return $this->io; } public function isDevMode() : bool { return $this->devMode; } public function getLocalRepo() : RepositoryInterface { return $this->localRepo; } /** * @return OperationInterface[] */ public function getOperations() : array { return $this->operations; } /** * Returns the package instance. */ public function getOperation() : OperationInterface { return $this->operation; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Composer; use Composer\DependencyResolver\Transaction; use Composer\EventDispatcher\Event; use Composer\IO\IOInterface; class InstallerEvent extends Event { /** * @var Composer */ private $composer; /** * @var IOInterface */ private $io; /** * @var bool */ private $devMode; /** * @var bool */ private $executeOperations; /** * @var Transaction */ private $transaction; /** * Constructor. */ public function __construct(string $eventName, Composer $composer, IOInterface $io, bool $devMode, bool $executeOperations, Transaction $transaction) { parent::__construct($eventName); $this->composer = $composer; $this->io = $io; $this->devMode = $devMode; $this->executeOperations = $executeOperations; $this->transaction = $transaction; } public function getComposer() : Composer { return $this->composer; } public function getIO() : IOInterface { return $this->io; } public function isDevMode() : bool { return $this->devMode; } public function isExecutingOperations() : bool { return $this->executeOperations; } public function getTransaction() : ?Transaction { return $this->transaction; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Composer; use Composer\IO\IOInterface; use Composer\PartialComposer; use Composer\Pcre\Preg; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\Util\Filesystem; use Composer\Util\Silencer; use Composer\Util\Platform; use React\Promise\PromiseInterface; use Composer\Downloader\DownloadManager; /** * Package installation manager. * * @author Jordi Boggiano * @author Konstantin Kudryashov */ class LibraryInstaller implements \Composer\Installer\InstallerInterface, \Composer\Installer\BinaryPresenceInterface { /** @var PartialComposer */ protected $composer; /** @var string */ protected $vendorDir; /** @var DownloadManager|null */ protected $downloadManager; /** @var IOInterface */ protected $io; /** @var string */ protected $type; /** @var Filesystem */ protected $filesystem; /** @var BinaryInstaller */ protected $binaryInstaller; /** * Initializes library installer. * * @param Filesystem $filesystem * @param BinaryInstaller $binaryInstaller */ public function __construct(IOInterface $io, PartialComposer $composer, ?string $type = 'library', ?Filesystem $filesystem = null, ?\Composer\Installer\BinaryInstaller $binaryInstaller = null) { $this->composer = $composer; $this->downloadManager = $composer instanceof Composer ? $composer->getDownloadManager() : null; $this->io = $io; $this->type = $type; $this->filesystem = $filesystem ?: new Filesystem(); $this->vendorDir = \rtrim($composer->getConfig()->get('vendor-dir'), '/'); $this->binaryInstaller = $binaryInstaller ?: new \Composer\Installer\BinaryInstaller($this->io, \rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem, $this->vendorDir); } /** * @inheritDoc */ public function supports(string $packageType) { return $packageType === $this->type || null === $this->type; } /** * @inheritDoc */ public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package) { if (!$repo->hasPackage($package)) { return \false; } $installPath = $this->getInstallPath($package); if (Filesystem::isReadable($installPath)) { return \true; } if (Platform::isWindows() && $this->filesystem->isJunction($installPath)) { return \true; } if (\is_link($installPath)) { if (\realpath($installPath) === \false) { return \false; } return \true; } return \false; } /** * @inheritDoc */ public function download(PackageInterface $package, ?PackageInterface $prevPackage = null) { $this->initializeVendorDir(); $downloadPath = $this->getInstallPath($package); return $this->getDownloadManager()->download($package, $downloadPath, $prevPackage); } /** * @inheritDoc */ public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null) { $this->initializeVendorDir(); $downloadPath = $this->getInstallPath($package); return $this->getDownloadManager()->prepare($type, $package, $downloadPath, $prevPackage); } /** * @inheritDoc */ public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null) { $this->initializeVendorDir(); $downloadPath = $this->getInstallPath($package); return $this->getDownloadManager()->cleanup($type, $package, $downloadPath, $prevPackage); } /** * @inheritDoc */ public function install(InstalledRepositoryInterface $repo, PackageInterface $package) { $this->initializeVendorDir(); $downloadPath = $this->getInstallPath($package); // remove the binaries if it appears the package files are missing if (!Filesystem::isReadable($downloadPath) && $repo->hasPackage($package)) { $this->binaryInstaller->removeBinaries($package); } $promise = $this->installCode($package); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } $binaryInstaller = $this->binaryInstaller; $installPath = $this->getInstallPath($package); return $promise->then(static function () use($binaryInstaller, $installPath, $package, $repo) : void { $binaryInstaller->installBinaries($package, $installPath); if (!$repo->hasPackage($package)) { $repo->addPackage(clone $package); } }); } /** * @inheritDoc */ public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) { if (!$repo->hasPackage($initial)) { throw new \InvalidArgumentException('Package is not installed: ' . $initial); } $this->initializeVendorDir(); $this->binaryInstaller->removeBinaries($initial); $promise = $this->updateCode($initial, $target); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } $binaryInstaller = $this->binaryInstaller; $installPath = $this->getInstallPath($target); return $promise->then(static function () use($binaryInstaller, $installPath, $target, $initial, $repo) : void { $binaryInstaller->installBinaries($target, $installPath); $repo->removePackage($initial); if (!$repo->hasPackage($target)) { $repo->addPackage(clone $target); } }); } /** * @inheritDoc */ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) { if (!$repo->hasPackage($package)) { throw new \InvalidArgumentException('Package is not installed: ' . $package); } $promise = $this->removeCode($package); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } $binaryInstaller = $this->binaryInstaller; $downloadPath = $this->getPackageBasePath($package); $filesystem = $this->filesystem; return $promise->then(static function () use($binaryInstaller, $filesystem, $downloadPath, $package, $repo) : void { $binaryInstaller->removeBinaries($package); $repo->removePackage($package); if (\strpos($package->getName(), '/')) { $packageVendorDir = \dirname($downloadPath); if (\is_dir($packageVendorDir) && $filesystem->isDirEmpty($packageVendorDir)) { Silencer::call('rmdir', $packageVendorDir); } } }); } /** * @inheritDoc * * @return string */ public function getInstallPath(PackageInterface $package) { $this->initializeVendorDir(); $basePath = ($this->vendorDir ? $this->vendorDir . '/' : '') . $package->getPrettyName(); $targetDir = $package->getTargetDir(); return $basePath . ($targetDir ? '/' . $targetDir : ''); } /** * Make sure binaries are installed for a given package. * * @param PackageInterface $package Package instance */ public function ensureBinariesPresence(PackageInterface $package) { $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), \false); } /** * Returns the base path of the package without target-dir path * * It is used for BC as getInstallPath tends to be overridden by * installer plugins but not getPackageBasePath * * @return string */ protected function getPackageBasePath(PackageInterface $package) { $installPath = $this->getInstallPath($package); $targetDir = $package->getTargetDir(); if ($targetDir) { return Preg::replace('{/*' . \str_replace('/', '/+', \preg_quote($targetDir)) . '/?$}', '', $installPath); } return $installPath; } /** * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ protected function installCode(PackageInterface $package) { $downloadPath = $this->getInstallPath($package); return $this->getDownloadManager()->install($package, $downloadPath); } /** * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ protected function updateCode(PackageInterface $initial, PackageInterface $target) { $initialDownloadPath = $this->getInstallPath($initial); $targetDownloadPath = $this->getInstallPath($target); if ($targetDownloadPath !== $initialDownloadPath) { // if the target and initial dirs intersect, we force a remove + install // to avoid the rename wiping the target dir as part of the initial dir cleanup if (\strpos($initialDownloadPath, $targetDownloadPath) === 0 || \strpos($targetDownloadPath, $initialDownloadPath) === 0) { $promise = $this->removeCode($initial); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } return $promise->then(function () use($target) : PromiseInterface { $promise = $this->installCode($target); if ($promise instanceof PromiseInterface) { return $promise; } return \React\Promise\resolve(null); }); } $this->filesystem->rename($initialDownloadPath, $targetDownloadPath); } return $this->getDownloadManager()->update($initial, $target, $targetDownloadPath); } /** * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ protected function removeCode(PackageInterface $package) { $downloadPath = $this->getPackageBasePath($package); return $this->getDownloadManager()->remove($package, $downloadPath); } /** * @return void */ protected function initializeVendorDir() { $this->filesystem->ensureDirectoryExists($this->vendorDir); $this->vendorDir = \realpath($this->vendorDir); } protected function getDownloadManager() : DownloadManager { \assert($this->downloadManager instanceof DownloadManager, new \LogicException(self::class . ' should be initialized with a fully loaded Composer instance to be able to install/... packages')); return $this->downloadManager; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use InvalidArgumentException; use React\Promise\PromiseInterface; /** * Interface for the package installation manager. * * @author Konstantin Kudryashov * @author Jordi Boggiano */ interface InstallerInterface { /** * Decides if the installer supports the given type * * @return bool */ public function supports(string $packageType); /** * Checks that provided package is installed. * * @param InstalledRepositoryInterface $repo repository in which to check * @param PackageInterface $package package instance * * @return bool */ public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package); /** * Downloads the files needed to later install the given package. * * @param PackageInterface $package package instance * @param PackageInterface $prevPackage previous package instance in case of an update * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ public function download(PackageInterface $package, ?PackageInterface $prevPackage = null); /** * Do anything that needs to be done between all downloads have been completed and the actual operation is executed * * All packages get first downloaded, then all together prepared, then all together installed/updated/uninstalled. Therefore * for error recovery it is important to avoid failing during install/update/uninstall as much as possible, and risky things or * user prompts should happen in the prepare step rather. In case of failure, cleanup() will be called so that changes can * be undone as much as possible. * * @param string $type one of install/update/uninstall * @param PackageInterface $package package instance * @param PackageInterface $prevPackage previous package instance in case of an update * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ public function prepare(string $type, PackageInterface $package, ?PackageInterface $prevPackage = null); /** * Installs specific package. * * @param InstalledRepositoryInterface $repo repository in which to check * @param PackageInterface $package package instance * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ public function install(InstalledRepositoryInterface $repo, PackageInterface $package); /** * Updates specific package. * * @param InstalledRepositoryInterface $repo repository in which to check * @param PackageInterface $initial already installed package version * @param PackageInterface $target updated version * @throws InvalidArgumentException if $initial package is not installed * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target); /** * Uninstalls specific package. * * @param InstalledRepositoryInterface $repo repository in which to check * @param PackageInterface $package package instance * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package); /** * Do anything to cleanup changes applied in the prepare or install/update/uninstall steps * * Note that cleanup will be called for all packages regardless if they failed an operation or not, to give * all installers a change to cleanup things they did previously, so you need to keep track of changes * applied in the installer/downloader themselves. * * @param string $type one of install/update/uninstall * @param PackageInterface $package package instance * @param PackageInterface $prevPackage previous package instance in case of an update * @return PromiseInterface|null * @phpstan-return PromiseInterface|null */ public function cleanup(string $type, PackageInterface $package, ?PackageInterface $prevPackage = null); /** * Returns the absolute installation path of a package. * * @return string|null absolute path to install to, which MUST not end with a slash, or null if the package does not have anything installed on disk */ public function getInstallPath(PackageInterface $package); } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\IO\IOInterface; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UninstallOperation; /** * Metapackage installation manager. * * @author Martin Hasoň */ class MetapackageInstaller implements \Composer\Installer\InstallerInterface { /** @var IOInterface */ private $io; public function __construct(IOInterface $io) { $this->io = $io; } /** * @inheritDoc */ public function supports(string $packageType) { return $packageType === 'metapackage'; } /** * @inheritDoc */ public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package) { return $repo->hasPackage($package); } /** * @inheritDoc */ public function download(PackageInterface $package, ?PackageInterface $prevPackage = null) { // noop return \React\Promise\resolve(null); } /** * @inheritDoc */ public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null) { // noop return \React\Promise\resolve(null); } /** * @inheritDoc */ public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null) { // noop return \React\Promise\resolve(null); } /** * @inheritDoc */ public function install(InstalledRepositoryInterface $repo, PackageInterface $package) { $this->io->writeError(" - " . InstallOperation::format($package)); $repo->addPackage(clone $package); return \React\Promise\resolve(null); } /** * @inheritDoc */ public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) { if (!$repo->hasPackage($initial)) { throw new \InvalidArgumentException('Package is not installed: ' . $initial); } $this->io->writeError(" - " . UpdateOperation::format($initial, $target)); $repo->removePackage($initial); $repo->addPackage(clone $target); return \React\Promise\resolve(null); } /** * @inheritDoc */ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) { if (!$repo->hasPackage($package)) { throw new \InvalidArgumentException('Package is not installed: ' . $package); } $this->io->writeError(" - " . UninstallOperation::format($package)); $repo->removePackage($package); return \React\Promise\resolve(null); } /** * @inheritDoc * * @return null */ public function getInstallPath(PackageInterface $package) { return null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use React\Promise\PromiseInterface; use Composer\Package\PackageInterface; use Composer\Downloader\DownloadManager; use Composer\Repository\InstalledRepositoryInterface; use Composer\Util\Filesystem; /** * Project Installer is used to install a single package into a directory as * root project. * * @author Benjamin Eberlei */ class ProjectInstaller implements \Composer\Installer\InstallerInterface { /** @var string */ private $installPath; /** @var DownloadManager */ private $downloadManager; /** @var Filesystem */ private $filesystem; public function __construct(string $installPath, DownloadManager $dm, Filesystem $fs) { $this->installPath = \rtrim(\strtr($installPath, '\\', '/'), '/') . '/'; $this->downloadManager = $dm; $this->filesystem = $fs; } /** * Decides if the installer supports the given type */ public function supports(string $packageType) : bool { return \true; } /** * @inheritDoc */ public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package) : bool { return \false; } /** * @inheritDoc */ public function download(PackageInterface $package, ?PackageInterface $prevPackage = null) : ?PromiseInterface { $installPath = $this->installPath; if (\file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) { throw new \InvalidArgumentException("Project directory {$installPath} is not empty."); } if (!\is_dir($installPath)) { \mkdir($installPath, 0777, \true); } return $this->downloadManager->download($package, $installPath, $prevPackage); } /** * @inheritDoc */ public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null) : ?PromiseInterface { return $this->downloadManager->prepare($type, $package, $this->installPath, $prevPackage); } /** * @inheritDoc */ public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null) : ?PromiseInterface { return $this->downloadManager->cleanup($type, $package, $this->installPath, $prevPackage); } /** * @inheritDoc */ public function install(InstalledRepositoryInterface $repo, PackageInterface $package) : ?PromiseInterface { return $this->downloadManager->install($package, $this->installPath); } /** * @inheritDoc */ public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) : ?PromiseInterface { throw new \InvalidArgumentException("not supported"); } /** * @inheritDoc */ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) : ?PromiseInterface { throw new \InvalidArgumentException("not supported"); } /** * Returns the installation path of a package * * @return string configured install path */ public function getInstallPath(PackageInterface $package) : string { return $this->installPath; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; use Composer\Pcre\Preg; use Composer\Repository\InstalledRepository; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; /** * Add suggested packages from different places to output them in the end. * * @author Haralan Dobrev */ class SuggestedPackagesReporter { public const MODE_LIST = 1; public const MODE_BY_PACKAGE = 2; public const MODE_BY_SUGGESTION = 4; /** * @var array */ protected $suggestedPackages = []; /** * @var IOInterface */ private $io; public function __construct(IOInterface $io) { $this->io = $io; } /** * @return array Suggested packages with source, target and reason keys. */ public function getPackages() : array { return $this->suggestedPackages; } /** * Add suggested packages to be listed after install * * Could be used to add suggested packages both from the installer * or from CreateProjectCommand. * * @param string $source Source package which made the suggestion * @param string $target Target package to be suggested * @param string $reason Reason the target package to be suggested */ public function addPackage(string $source, string $target, string $reason) : \Composer\Installer\SuggestedPackagesReporter { $this->suggestedPackages[] = ['source' => $source, 'target' => $target, 'reason' => $reason]; return $this; } /** * Add all suggestions from a package. */ public function addSuggestionsFromPackage(PackageInterface $package) : \Composer\Installer\SuggestedPackagesReporter { $source = $package->getPrettyName(); foreach ($package->getSuggests() as $target => $reason) { $this->addPackage($source, $target, $reason); } return $this; } /** * Output suggested packages. * * Do not list the ones already installed if installed repository provided. * * @param int $mode One of the MODE_* constants from this class * @param InstalledRepository|null $installedRepo If passed in, suggested packages which are installed already will be skipped * @param PackageInterface|null $onlyDependentsOf If passed in, only the suggestions from direct dependents of that package, or from the package itself, will be shown */ public function output(int $mode, ?InstalledRepository $installedRepo = null, ?PackageInterface $onlyDependentsOf = null) : void { $suggestedPackages = $this->getFilteredSuggestions($installedRepo, $onlyDependentsOf); $suggesters = []; $suggested = []; foreach ($suggestedPackages as $suggestion) { $suggesters[$suggestion['source']][$suggestion['target']] = $suggestion['reason']; $suggested[$suggestion['target']][$suggestion['source']] = $suggestion['reason']; } \ksort($suggesters); \ksort($suggested); // Simple mode if ($mode & self::MODE_LIST) { foreach (\array_keys($suggested) as $name) { $this->io->write(\sprintf('%s', $name)); } return; } // Grouped by package if ($mode & self::MODE_BY_PACKAGE) { foreach ($suggesters as $suggester => $suggestions) { $this->io->write(\sprintf('%s suggests:', $suggester)); foreach ($suggestions as $suggestion => $reason) { $this->io->write(\sprintf(' - %s' . ($reason ? ': %s' : ''), $suggestion, $this->escapeOutput($reason))); } $this->io->write(''); } } // Grouped by suggestion if ($mode & self::MODE_BY_SUGGESTION) { // Improve readability in full mode if ($mode & self::MODE_BY_PACKAGE) { $this->io->write(\str_repeat('-', 78)); } foreach ($suggested as $suggestion => $suggesters) { $this->io->write(\sprintf('%s is suggested by:', $suggestion)); foreach ($suggesters as $suggester => $reason) { $this->io->write(\sprintf(' - %s' . ($reason ? ': %s' : ''), $suggester, $this->escapeOutput($reason))); } $this->io->write(''); } } if ($onlyDependentsOf) { $allSuggestedPackages = $this->getFilteredSuggestions($installedRepo); $diff = \count($allSuggestedPackages) - \count($suggestedPackages); if ($diff) { $this->io->write('' . $diff . ' additional suggestions by transitive dependencies can be shown with --all'); } } } /** * Output number of new suggested packages and a hint to use suggest command. * * @param InstalledRepository|null $installedRepo If passed in, suggested packages which are installed already will be skipped * @param PackageInterface|null $onlyDependentsOf If passed in, only the suggestions from direct dependents of that package, or from the package itself, will be shown */ public function outputMinimalistic(?InstalledRepository $installedRepo = null, ?PackageInterface $onlyDependentsOf = null) : void { $suggestedPackages = $this->getFilteredSuggestions($installedRepo, $onlyDependentsOf); if ($suggestedPackages) { $this->io->writeError('' . \count($suggestedPackages) . ' package suggestions were added by new dependencies, use `composer suggest` to see details.'); } } /** * @param InstalledRepository|null $installedRepo If passed in, suggested packages which are installed already will be skipped * @param PackageInterface|null $onlyDependentsOf If passed in, only the suggestions from direct dependents of that package, or from the package itself, will be shown * @return mixed[] */ private function getFilteredSuggestions(?InstalledRepository $installedRepo = null, ?PackageInterface $onlyDependentsOf = null) : array { $suggestedPackages = $this->getPackages(); $installedNames = []; if (null !== $installedRepo && !empty($suggestedPackages)) { foreach ($installedRepo->getPackages() as $package) { $installedNames = \array_merge($installedNames, $package->getNames()); } } $sourceFilter = []; if ($onlyDependentsOf) { $sourceFilter = \array_map(static function ($link) : string { return $link->getTarget(); }, \array_merge($onlyDependentsOf->getRequires(), $onlyDependentsOf->getDevRequires())); $sourceFilter[] = $onlyDependentsOf->getName(); } $suggestions = []; foreach ($suggestedPackages as $suggestion) { if (\in_array($suggestion['target'], $installedNames) || $sourceFilter && !\in_array($suggestion['source'], $sourceFilter)) { continue; } $suggestions[] = $suggestion; } return $suggestions; } private function escapeOutput(string $string) : string { return OutputFormatter::escape($this->removeControlCharacters($string)); } private function removeControlCharacters(string $string) : string { return Preg::replace('/[[:cntrl:]]/', '', \str_replace("\n", ' ', $string)); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\IO\IOInterface; use Composer\IO\ConsoleIO; use Composer\Package\PackageInterface; use Composer\Package\AliasPackage; use Composer\Repository\InstalledRepositoryInterface; use Composer\DependencyResolver\Operation\OperationInterface; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\UninstallOperation; use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation; use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation; use Composer\Downloader\FileDownloader; use Composer\EventDispatcher\EventDispatcher; use Composer\Util\Loop; use Composer\Util\Platform; use React\Promise\PromiseInterface; use _ContaoManager\Seld\Signal\SignalHandler; /** * Package operation manager. * * @author Konstantin Kudryashov * @author Jordi Boggiano * @author Nils Adermann */ class InstallationManager { /** @var list */ private $installers = []; /** @var array */ private $cache = []; /** @var array> */ private $notifiablePackages = []; /** @var Loop */ private $loop; /** @var IOInterface */ private $io; /** @var ?EventDispatcher */ private $eventDispatcher; /** @var bool */ private $outputProgress; public function __construct(Loop $loop, IOInterface $io, ?EventDispatcher $eventDispatcher = null) { $this->loop = $loop; $this->io = $io; $this->eventDispatcher = $eventDispatcher; } public function reset() : void { $this->notifiablePackages = []; FileDownloader::$downloadMetadata = []; } /** * Adds installer * * @param InstallerInterface $installer installer instance */ public function addInstaller(\Composer\Installer\InstallerInterface $installer) : void { \array_unshift($this->installers, $installer); $this->cache = []; } /** * Removes installer * * @param InstallerInterface $installer installer instance */ public function removeInstaller(\Composer\Installer\InstallerInterface $installer) : void { if (\false !== ($key = \array_search($installer, $this->installers, \true))) { \array_splice($this->installers, $key, 1); $this->cache = []; } } /** * Disables plugins. * * We prevent any plugins from being instantiated by * disabling the PluginManager. This ensures that no third-party * code is ever executed. */ public function disablePlugins() : void { foreach ($this->installers as $i => $installer) { if (!$installer instanceof \Composer\Installer\PluginInstaller) { continue; } $installer->disablePlugins(); } } /** * Returns installer for a specific package type. * * @param string $type package type * * @throws \InvalidArgumentException if installer for provided type is not registered */ public function getInstaller(string $type) : \Composer\Installer\InstallerInterface { $type = \strtolower($type); if (isset($this->cache[$type])) { return $this->cache[$type]; } foreach ($this->installers as $installer) { if ($installer->supports($type)) { return $this->cache[$type] = $installer; } } throw new \InvalidArgumentException('Unknown installer type: ' . $type); } /** * Checks whether provided package is installed in one of the registered installers. * * @param InstalledRepositoryInterface $repo repository in which to check * @param PackageInterface $package package instance */ public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package) : bool { if ($package instanceof AliasPackage) { return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf()); } return $this->getInstaller($package->getType())->isInstalled($repo, $package); } /** * Install binary for the given package. * If the installer associated to this package doesn't handle that function, it'll do nothing. * * @param PackageInterface $package Package instance */ public function ensureBinariesPresence(PackageInterface $package) : void { try { $installer = $this->getInstaller($package->getType()); } catch (\InvalidArgumentException $e) { // no installer found for the current package type (@see `getInstaller()`) return; } // if the given installer support installing binaries if ($installer instanceof \Composer\Installer\BinaryPresenceInterface) { $installer->ensureBinariesPresence($package); } } /** * Executes solver operation. * * @param InstalledRepositoryInterface $repo repository in which to add/remove/update packages * @param OperationInterface[] $operations operations to execute * @param bool $devMode whether the install is being run in dev mode * @param bool $runScripts whether to dispatch script events * @param bool $downloadOnly whether to only download packages */ public function execute(InstalledRepositoryInterface $repo, array $operations, bool $devMode = \true, bool $runScripts = \true, bool $downloadOnly = \false) : void { /** @var array> $cleanupPromises */ $cleanupPromises = []; $signalHandler = SignalHandler::create([SignalHandler::SIGINT, SignalHandler::SIGTERM, SignalHandler::SIGHUP], function (string $signal, SignalHandler $handler) use(&$cleanupPromises) { $this->io->writeError('Received ' . $signal . ', aborting', \true, IOInterface::DEBUG); $this->runCleanup($cleanupPromises); $handler->exitWithLastSignal(); }); try { // execute operations in batches to make sure download-modifying-plugins are installed // before the other packages get downloaded $batches = []; $batch = []; foreach ($operations as $index => $operation) { if ($operation instanceof UpdateOperation || $operation instanceof InstallOperation) { $package = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage(); if ($package->getType() === 'composer-plugin') { $extra = $package->getExtra(); if (isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === \true) { if (\count($batch) > 0) { $batches[] = $batch; } $batches[] = [$index => $operation]; $batch = []; continue; } } } $batch[$index] = $operation; } if (\count($batch) > 0) { $batches[] = $batch; } foreach ($batches as $batchToExecute) { $this->downloadAndExecuteBatch($repo, $batchToExecute, $cleanupPromises, $devMode, $runScripts, $downloadOnly, $operations); } } catch (\Exception $e) { $this->runCleanup($cleanupPromises); throw $e; } finally { $signalHandler->unregister(); } if ($downloadOnly) { return; } // do a last write so that we write the repository even if nothing changed // as that can trigger an update of some files like InstalledVersions.php if // running a new composer version $repo->write($devMode, $this); } /** * @param OperationInterface[] $operations List of operations to execute in this batch * @param OperationInterface[] $allOperations Complete list of operations to be executed in the install job, used for event listeners * @phpstan-param array> $cleanupPromises */ private function downloadAndExecuteBatch(InstalledRepositoryInterface $repo, array $operations, array &$cleanupPromises, bool $devMode, bool $runScripts, bool $downloadOnly, array $allOperations) : void { $promises = []; foreach ($operations as $index => $operation) { $opType = $operation->getOperationType(); // ignoring alias ops as they don't need to execute anything at this stage if (!\in_array($opType, ['update', 'install', 'uninstall'], \true)) { continue; } if ($opType === 'update') { /** @var UpdateOperation $operation */ $package = $operation->getTargetPackage(); $initialPackage = $operation->getInitialPackage(); } else { /** @var InstallOperation|MarkAliasInstalledOperation|MarkAliasUninstalledOperation|UninstallOperation $operation */ $package = $operation->getPackage(); $initialPackage = null; } $installer = $this->getInstaller($package->getType()); $cleanupPromises[$index] = static function () use($opType, $installer, $package, $initialPackage) : ?PromiseInterface { // avoid calling cleanup if the download was not even initialized for a package // as without installation source configured nothing will work if (null === $package->getInstallationSource()) { return \React\Promise\resolve(null); } return $installer->cleanup($opType, $package, $initialPackage); }; if ($opType !== 'uninstall') { $promise = $installer->download($package, $initialPackage); if (null !== $promise) { $promises[] = $promise; } } } // execute all downloads first if (\count($promises) > 0) { $this->waitOnPromises($promises); } if ($downloadOnly) { $this->runCleanup($cleanupPromises); return; } // execute operations in batches to make sure every plugin is installed in the // right order and activated before the packages depending on it are installed $batches = []; $batch = []; foreach ($operations as $index => $operation) { if ($operation instanceof InstallOperation || $operation instanceof UpdateOperation) { $package = $operation instanceof UpdateOperation ? $operation->getTargetPackage() : $operation->getPackage(); if ($package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer') { if (\count($batch) > 0) { $batches[] = $batch; } $batches[] = [$index => $operation]; $batch = []; continue; } } $batch[$index] = $operation; } if (\count($batch) > 0) { $batches[] = $batch; } foreach ($batches as $batchToExecute) { $this->executeBatch($repo, $batchToExecute, $cleanupPromises, $devMode, $runScripts, $allOperations); } } /** * @param OperationInterface[] $operations List of operations to execute in this batch * @param OperationInterface[] $allOperations Complete list of operations to be executed in the install job, used for event listeners * @phpstan-param array> $cleanupPromises */ private function executeBatch(InstalledRepositoryInterface $repo, array $operations, array $cleanupPromises, bool $devMode, bool $runScripts, array $allOperations) : void { $promises = []; $postExecCallbacks = []; foreach ($operations as $index => $operation) { $opType = $operation->getOperationType(); // ignoring alias ops as they don't need to execute anything if (!\in_array($opType, ['update', 'install', 'uninstall'], \true)) { // output alias ops in debug verbosity as they have no output otherwise if ($this->io->isDebug()) { $this->io->writeError(' - ' . $operation->show(\false)); } $this->{$opType}($repo, $operation); continue; } if ($opType === 'update') { /** @var UpdateOperation $operation */ $package = $operation->getTargetPackage(); $initialPackage = $operation->getInitialPackage(); } else { /** @var InstallOperation|MarkAliasInstalledOperation|MarkAliasUninstalledOperation|UninstallOperation $operation */ $package = $operation->getPackage(); $initialPackage = null; } $installer = $this->getInstaller($package->getType()); $eventName = ['install' => \Composer\Installer\PackageEvents::PRE_PACKAGE_INSTALL, 'update' => \Composer\Installer\PackageEvents::PRE_PACKAGE_UPDATE, 'uninstall' => \Composer\Installer\PackageEvents::PRE_PACKAGE_UNINSTALL][$opType]; if ($runScripts && $this->eventDispatcher !== null) { $this->eventDispatcher->dispatchPackageEvent($eventName, $devMode, $repo, $allOperations, $operation); } $dispatcher = $this->eventDispatcher; $io = $this->io; $promise = $installer->prepare($opType, $package, $initialPackage); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } $promise = $promise->then(function () use($opType, $repo, $operation) { return $this->{$opType}($repo, $operation); })->then($cleanupPromises[$index])->then(function () use($devMode, $repo) : void { $repo->write($devMode, $this); }, static function ($e) use($opType, $package, $io) : void { $io->writeError(' ' . \ucfirst($opType) . ' of ' . $package->getPrettyName() . ' failed'); throw $e; }); $eventName = ['install' => \Composer\Installer\PackageEvents::POST_PACKAGE_INSTALL, 'update' => \Composer\Installer\PackageEvents::POST_PACKAGE_UPDATE, 'uninstall' => \Composer\Installer\PackageEvents::POST_PACKAGE_UNINSTALL][$opType]; if ($runScripts && $dispatcher !== null) { $postExecCallbacks[] = static function () use($dispatcher, $eventName, $devMode, $repo, $allOperations, $operation) : void { $dispatcher->dispatchPackageEvent($eventName, $devMode, $repo, $allOperations, $operation); }; } $promises[] = $promise; } // execute all prepare => installs/updates/removes => cleanup steps if (\count($promises) > 0) { $this->waitOnPromises($promises); } Platform::workaroundFilesystemIssues(); foreach ($postExecCallbacks as $cb) { $cb(); } } /** * @param array> $promises */ private function waitOnPromises(array $promises) : void { $progress = null; if ($this->outputProgress && $this->io instanceof ConsoleIO && !(bool) Platform::getEnv('CI') && !$this->io->isDebug() && \count($promises) > 1) { $progress = $this->io->getProgressBar(); } $this->loop->wait($promises, $progress); if ($progress !== null) { $progress->clear(); // ProgressBar in non-decorated output does not output a final line-break and clear() does nothing if (!$this->io->isDecorated()) { $this->io->writeError(''); } } } /** * Executes download operation. * * @phpstan-return PromiseInterface|null */ public function download(PackageInterface $package) : ?PromiseInterface { $installer = $this->getInstaller($package->getType()); $promise = $installer->cleanup("install", $package); return $promise; } /** * Executes install operation. * * @param InstalledRepositoryInterface $repo repository in which to check * @param InstallOperation $operation operation instance * @phpstan-return PromiseInterface|null */ public function install(InstalledRepositoryInterface $repo, InstallOperation $operation) : ?PromiseInterface { $package = $operation->getPackage(); $installer = $this->getInstaller($package->getType()); $promise = $installer->install($repo, $package); $this->markForNotification($package); return $promise; } /** * Executes update operation. * * @param InstalledRepositoryInterface $repo repository in which to check * @param UpdateOperation $operation operation instance * @phpstan-return PromiseInterface|null */ public function update(InstalledRepositoryInterface $repo, UpdateOperation $operation) : ?PromiseInterface { $initial = $operation->getInitialPackage(); $target = $operation->getTargetPackage(); $initialType = $initial->getType(); $targetType = $target->getType(); if ($initialType === $targetType) { $installer = $this->getInstaller($initialType); $promise = $installer->update($repo, $initial, $target); $this->markForNotification($target); } else { $promise = $this->getInstaller($initialType)->uninstall($repo, $initial); if (!$promise instanceof PromiseInterface) { $promise = \React\Promise\resolve(null); } $installer = $this->getInstaller($targetType); $promise = $promise->then(static function () use($installer, $repo, $target) : PromiseInterface { $promise = $installer->install($repo, $target); if ($promise instanceof PromiseInterface) { return $promise; } return \React\Promise\resolve(null); }); } return $promise; } /** * Uninstalls package. * * @param InstalledRepositoryInterface $repo repository in which to check * @param UninstallOperation $operation operation instance * @phpstan-return PromiseInterface|null */ public function uninstall(InstalledRepositoryInterface $repo, UninstallOperation $operation) : ?PromiseInterface { $package = $operation->getPackage(); $installer = $this->getInstaller($package->getType()); return $installer->uninstall($repo, $package); } /** * Executes markAliasInstalled operation. * * @param InstalledRepositoryInterface $repo repository in which to check * @param MarkAliasInstalledOperation $operation operation instance */ public function markAliasInstalled(InstalledRepositoryInterface $repo, MarkAliasInstalledOperation $operation) : void { $package = $operation->getPackage(); if (!$repo->hasPackage($package)) { $repo->addPackage(clone $package); } } /** * Executes markAlias operation. * * @param InstalledRepositoryInterface $repo repository in which to check * @param MarkAliasUninstalledOperation $operation operation instance */ public function markAliasUninstalled(InstalledRepositoryInterface $repo, MarkAliasUninstalledOperation $operation) : void { $package = $operation->getPackage(); $repo->removePackage($package); } /** * Returns the installation path of a package * * @return string|null absolute path to install to, which does not end with a slash, or null if the package does not have anything installed on disk */ public function getInstallPath(PackageInterface $package) : ?string { $installer = $this->getInstaller($package->getType()); return $installer->getInstallPath($package); } public function setOutputProgress(bool $outputProgress) : void { $this->outputProgress = $outputProgress; } public function notifyInstalls(IOInterface $io) : void { $promises = []; try { foreach ($this->notifiablePackages as $repoUrl => $packages) { // non-batch API, deprecated if (\str_contains($repoUrl, '%package%')) { foreach ($packages as $package) { $url = \str_replace('%package%', $package->getPrettyName(), $repoUrl); $params = ['version' => $package->getPrettyVersion(), 'version_normalized' => $package->getVersion()]; $opts = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => ['Content-type: application/x-www-form-urlencoded'], 'content' => \http_build_query($params, '', '&'), 'timeout' => 3]]; $promises[] = $this->loop->getHttpDownloader()->add($url, $opts); } continue; } $postData = ['downloads' => []]; foreach ($packages as $package) { $packageNotification = ['name' => $package->getPrettyName(), 'version' => $package->getVersion()]; if (\strpos($repoUrl, 'packagist.org/') !== \false) { if (isset(FileDownloader::$downloadMetadata[$package->getName()])) { $packageNotification['downloaded'] = FileDownloader::$downloadMetadata[$package->getName()]; } else { $packageNotification['downloaded'] = \false; } } $postData['downloads'][] = $packageNotification; } $opts = ['retry-auth-failure' => \false, 'http' => ['method' => 'POST', 'header' => ['Content-Type: application/json'], 'content' => \json_encode($postData), 'timeout' => 6]]; $promises[] = $this->loop->getHttpDownloader()->add($repoUrl, $opts); } $this->loop->wait($promises); } catch (\Exception $e) { } $this->reset(); } private function markForNotification(PackageInterface $package) : void { if ($package->getNotificationUrl() !== null) { $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package; } } /** * @return void * @phpstan-param array> $cleanupPromises */ private function runCleanup(array $cleanupPromises) : void { $promises = []; $this->loop->abortJobs(); foreach ($cleanupPromises as $cleanup) { $promises[] = new \React\Promise\Promise(static function ($resolve) use($cleanup) : void { $promise = $cleanup(); if (!$promise instanceof PromiseInterface) { $resolve(null); } else { $promise->then(static function () use($resolve) : void { $resolve(null); }); } }); } if (\count($promises) > 0) { $this->loop->wait($promises); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Installer; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; /** * Does not install anything but marks packages installed in the repo * * Useful for dry runs * * @author Jordi Boggiano */ class NoopInstaller implements \Composer\Installer\InstallerInterface { /** * @inheritDoc */ public function supports(string $packageType) { return \true; } /** * @inheritDoc */ public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package) { return $repo->hasPackage($package); } /** * @inheritDoc */ public function download(PackageInterface $package, ?PackageInterface $prevPackage = null) { return \React\Promise\resolve(null); } /** * @inheritDoc */ public function prepare($type, PackageInterface $package, ?PackageInterface $prevPackage = null) { return \React\Promise\resolve(null); } /** * @inheritDoc */ public function cleanup($type, PackageInterface $package, ?PackageInterface $prevPackage = null) { return \React\Promise\resolve(null); } /** * @inheritDoc */ public function install(InstalledRepositoryInterface $repo, PackageInterface $package) { if (!$repo->hasPackage($package)) { $repo->addPackage(clone $package); } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) { if (!$repo->hasPackage($initial)) { throw new \InvalidArgumentException('Package is not installed: ' . $initial); } $repo->removePackage($initial); if (!$repo->hasPackage($target)) { $repo->addPackage(clone $target); } return \React\Promise\resolve(null); } /** * @inheritDoc */ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) { if (!$repo->hasPackage($package)) { throw new \InvalidArgumentException('Package is not installed: ' . $package); } $repo->removePackage($package); return \React\Promise\resolve(null); } /** * @inheritDoc */ public function getInstallPath(PackageInterface $package) { $targetDir = $package->getTargetDir(); return $package->getPrettyName() . ($targetDir ? '/' . $targetDir : ''); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Advisory; use Composer\Semver\Constraint\ConstraintInterface; use DateTimeImmutable; class SecurityAdvisory extends \Composer\Advisory\PartialSecurityAdvisory { /** * @var string * @readonly */ public $title; /** * @var string|null * @readonly */ public $cve; /** * @var string|null * @readonly */ public $link; /** * @var DateTimeImmutable * @readonly */ public $reportedAt; /** * @var non-empty-array * @readonly */ public $sources; /** * @var string|null * @readonly */ public $severity; /** * @param non-empty-array $sources */ public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null, ?string $severity = null) { parent::__construct($packageName, $advisoryId, $affectedVersions); $this->title = $title; $this->sources = $sources; $this->reportedAt = $reportedAt; $this->cve = $cve; $this->link = $link; $this->severity = $severity; } /** * @internal */ public function toIgnoredAdvisory(?string $ignoreReason) : \Composer\Advisory\IgnoredSecurityAdvisory { return new \Composer\Advisory\IgnoredSecurityAdvisory($this->packageName, $this->advisoryId, $this->affectedVersions, $this->title, $this->sources, $this->reportedAt, $this->cve, $this->link, $ignoreReason, $this->severity); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { $data = parent::jsonSerialize(); $data['reportedAt'] = $data['reportedAt']->format(\DATE_RFC3339); return $data; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Advisory; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\VersionParser; use JsonSerializable; class PartialSecurityAdvisory implements JsonSerializable { /** * @var string * @readonly */ public $advisoryId; /** * @var string * @readonly */ public $packageName; /** * @var ConstraintInterface * @readonly */ public $affectedVersions; /** * @param array $data * @return SecurityAdvisory|PartialSecurityAdvisory */ public static function create(string $packageName, array $data, VersionParser $parser) : self { $constraint = $parser->parseConstraints($data['affectedVersions']); if (isset($data['title'], $data['sources'], $data['reportedAt'])) { return new \Composer\Advisory\SecurityAdvisory($packageName, $data['advisoryId'], $constraint, $data['title'], $data['sources'], new \DateTimeImmutable($data['reportedAt'], new \DateTimeZone('UTC')), $data['cve'] ?? null, $data['link'] ?? null, $data['severity'] ?? null); } return new self($packageName, $data['advisoryId'], $constraint); } public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions) { $this->advisoryId = $advisoryId; $this->packageName = $packageName; $this->affectedVersions = $affectedVersions; } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { $data = (array) $this; $data['affectedVersions'] = $data['affectedVersions']->getPrettyString(); return $data; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Advisory; use Composer\IO\ConsoleIO; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\CompletePackageInterface; use Composer\Package\PackageInterface; use Composer\Repository\RepositorySet; use Composer\Util\PackageInfo; use InvalidArgumentException; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; /** * @internal */ class Auditor { public const FORMAT_TABLE = 'table'; public const FORMAT_PLAIN = 'plain'; public const FORMAT_JSON = 'json'; public const FORMAT_SUMMARY = 'summary'; public const FORMATS = [self::FORMAT_TABLE, self::FORMAT_PLAIN, self::FORMAT_JSON, self::FORMAT_SUMMARY]; public const ABANDONED_IGNORE = 'ignore'; public const ABANDONED_REPORT = 'report'; public const ABANDONED_FAIL = 'fail'; /** @internal */ public const ABANDONEDS = [self::ABANDONED_IGNORE, self::ABANDONED_REPORT, self::ABANDONED_FAIL]; /** Values to determine the audit result. */ public const STATUS_OK = 0; public const STATUS_VULNERABLE = 1; public const STATUS_ABANDONED = 2; /** * @param PackageInterface[] $packages * @param self::FORMAT_* $format The format that will be used to output audit results. * @param bool $warningOnly If true, outputs a warning. If false, outputs an error. * @param string[] $ignoreList List of advisory IDs, remote IDs or CVE IDs that reported but not listed as vulnerabilities. * @param self::ABANDONED_* $abandoned * @param array $ignoredSeverities List of ignored severity levels * * @return int-mask A bitmask of STATUS_* constants or 0 on success * @throws InvalidArgumentException If no packages are passed in */ public function audit(IOInterface $io, RepositorySet $repoSet, array $packages, string $format, bool $warningOnly = \true, array $ignoreList = [], string $abandoned = self::ABANDONED_FAIL, array $ignoredSeverities = []) : int { $allAdvisories = $repoSet->getMatchingSecurityAdvisories($packages, $format === self::FORMAT_SUMMARY); // we need the CVE & remote IDs set to filter ignores correctly so if we have any matches using the optimized codepath above // and ignores are set then we need to query again the full data to make sure it can be filtered if (\count($allAdvisories) > 0 && $ignoreList !== [] && $format === self::FORMAT_SUMMARY) { $allAdvisories = $repoSet->getMatchingSecurityAdvisories($packages, \false); } ['advisories' => $advisories, 'ignoredAdvisories' => $ignoredAdvisories] = $this->processAdvisories($allAdvisories, $ignoreList, $ignoredSeverities); $abandonedCount = 0; $affectedPackagesCount = \count($advisories); if ($abandoned === self::ABANDONED_IGNORE) { $abandonedPackages = []; } else { $abandonedPackages = $this->filterAbandonedPackages($packages); if ($abandoned === self::ABANDONED_FAIL) { $abandonedCount = \count($abandonedPackages); } } $auditBitmask = $this->calculateBitmask(0 < $affectedPackagesCount, 0 < $abandonedCount); if (self::FORMAT_JSON === $format) { $json = ['advisories' => $advisories]; if ($ignoredAdvisories !== []) { $json['ignored-advisories'] = $ignoredAdvisories; } $json['abandoned'] = \array_reduce($abandonedPackages, static function (array $carry, CompletePackageInterface $package) : array { $carry[$package->getPrettyName()] = $package->getReplacementPackage(); return $carry; }, []); $io->write(JsonFile::encode($json)); return $auditBitmask; } $errorOrWarn = $warningOnly ? 'warning' : 'error'; if ($affectedPackagesCount > 0 || \count($ignoredAdvisories) > 0) { $passes = [[$ignoredAdvisories, "Found %d ignored security vulnerability advisor%s affecting %d package%s%s"], [$advisories, "<{$errorOrWarn}>Found %d security vulnerability advisor%s affecting %d package%s%s"]]; foreach ($passes as [$advisoriesToOutput, $message]) { [$pkgCount, $totalAdvisoryCount] = $this->countAdvisories($advisoriesToOutput); if ($pkgCount > 0) { $plurality = $totalAdvisoryCount === 1 ? 'y' : 'ies'; $pkgPlurality = $pkgCount === 1 ? '' : 's'; $punctuation = $format === 'summary' ? '.' : ':'; $io->writeError(\sprintf($message, $totalAdvisoryCount, $plurality, $pkgCount, $pkgPlurality, $punctuation)); $this->outputAdvisories($io, $advisoriesToOutput, $format); } } if ($format === self::FORMAT_SUMMARY) { $io->writeError('Run "composer audit" for a full list of advisories.'); } } else { $io->writeError('No security vulnerability advisories found.'); } if (\count($abandonedPackages) > 0 && $format !== self::FORMAT_SUMMARY) { $this->outputAbandonedPackages($io, $abandonedPackages, $format); } return $auditBitmask; } /** * @param array $packages * @return array */ private function filterAbandonedPackages(array $packages) : array { return \array_filter($packages, static function (PackageInterface $pkg) : bool { return $pkg instanceof CompletePackageInterface && $pkg->isAbandoned(); }); } /** * @phpstan-param array> $allAdvisories * @param array|array $ignoreList List of advisory IDs, remote IDs or CVE IDs that reported but not listed as vulnerabilities. * @param array $ignoredSeverities List of ignored severity levels * @phpstan-return array{advisories: array>, ignoredAdvisories: array>} */ private function processAdvisories(array $allAdvisories, array $ignoreList, array $ignoredSeverities) : array { if ($ignoreList === [] && $ignoredSeverities === []) { return ['advisories' => $allAdvisories, 'ignoredAdvisories' => []]; } if (\count($ignoreList) > 0 && !\array_is_list($ignoreList)) { $ignoredIds = \array_keys($ignoreList); } else { $ignoredIds = $ignoreList; } $advisories = []; $ignored = []; $ignoreReason = null; foreach ($allAdvisories as $package => $pkgAdvisories) { foreach ($pkgAdvisories as $advisory) { $isActive = \true; if (\in_array($advisory->advisoryId, $ignoredIds, \true)) { $isActive = \false; $ignoreReason = $ignoreList[$advisory->advisoryId] ?? null; } if ($advisory instanceof \Composer\Advisory\SecurityAdvisory) { if (\in_array($advisory->severity, $ignoredSeverities, \true)) { $isActive = \false; $ignoreReason = "Ignored via --ignore-severity={$advisory->severity}"; } if (\in_array($advisory->cve, $ignoredIds, \true)) { $isActive = \false; $ignoreReason = $ignoreList[$advisory->cve] ?? null; } foreach ($advisory->sources as $source) { if (\in_array($source['remoteId'], $ignoredIds, \true)) { $isActive = \false; $ignoreReason = $ignoreList[$source['remoteId']] ?? null; break; } } } if ($isActive) { $advisories[$package][] = $advisory; continue; } // Partial security advisories only used in summary mode // and in that case we do not need to cast the object. if ($advisory instanceof \Composer\Advisory\SecurityAdvisory) { $advisory = $advisory->toIgnoredAdvisory($ignoreReason); } $ignored[$package][] = $advisory; } } return ['advisories' => $advisories, 'ignoredAdvisories' => $ignored]; } /** * @param array> $advisories * @return array{int, int} Count of affected packages and total count of advisories */ private function countAdvisories(array $advisories) : array { $count = 0; foreach ($advisories as $packageAdvisories) { $count += \count($packageAdvisories); } return [\count($advisories), $count]; } /** * @param array> $advisories * @param self::FORMAT_* $format The format that will be used to output audit results. */ private function outputAdvisories(IOInterface $io, array $advisories, string $format) : void { switch ($format) { case self::FORMAT_TABLE: if (!$io instanceof ConsoleIO) { throw new InvalidArgumentException('Cannot use table format with ' . \get_class($io)); } $this->outputAdvisoriesTable($io, $advisories); return; case self::FORMAT_PLAIN: $this->outputAdvisoriesPlain($io, $advisories); return; case self::FORMAT_SUMMARY: return; default: throw new InvalidArgumentException('Invalid format "' . $format . '".'); } } /** * @param array> $advisories */ private function outputAdvisoriesTable(ConsoleIO $io, array $advisories) : void { foreach ($advisories as $packageAdvisories) { foreach ($packageAdvisories as $advisory) { $headers = ['Package', 'Severity', 'CVE', 'Title', 'URL', 'Affected versions', 'Reported at']; $row = [$advisory->packageName, $this->getSeverity($advisory), $this->getCVE($advisory), $advisory->title, $this->getURL($advisory), $advisory->affectedVersions->getPrettyString(), $advisory->reportedAt->format(\DATE_ATOM)]; if ($advisory->cve === null) { $headers[] = 'Advisory ID'; $row[] = $advisory->advisoryId; } if ($advisory instanceof \Composer\Advisory\IgnoredSecurityAdvisory) { $headers[] = 'Ignore reason'; $row[] = $advisory->ignoreReason ?? 'None specified'; } $io->getTable()->setHorizontal()->setHeaders($headers)->addRow($row)->setColumnWidth(1, 80)->setColumnMaxWidth(1, 80)->render(); } } } /** * @param array> $advisories */ private function outputAdvisoriesPlain(IOInterface $io, array $advisories) : void { $error = []; $firstAdvisory = \true; foreach ($advisories as $packageAdvisories) { foreach ($packageAdvisories as $advisory) { if (!$firstAdvisory) { $error[] = '--------'; } $error[] = "Package: " . $advisory->packageName; $error[] = "Severity: " . $this->getSeverity($advisory); $error[] = "CVE: " . $this->getCVE($advisory); if ($advisory->cve === null) { $error[] = "Advisory ID: " . $advisory->advisoryId; } $error[] = "Title: " . OutputFormatter::escape($advisory->title); $error[] = "URL: " . $this->getURL($advisory); $error[] = "Affected versions: " . OutputFormatter::escape($advisory->affectedVersions->getPrettyString()); $error[] = "Reported at: " . $advisory->reportedAt->format(\DATE_ATOM); if ($advisory instanceof \Composer\Advisory\IgnoredSecurityAdvisory) { $error[] = "Ignore reason: " . ($advisory->ignoreReason ?? 'None specified'); } $firstAdvisory = \false; } } $io->writeError($error); } /** * @param array $packages * @param self::FORMAT_PLAIN|self::FORMAT_TABLE $format */ private function outputAbandonedPackages(IOInterface $io, array $packages, string $format) : void { $io->writeError(\sprintf('Found %d abandoned package%s:', \count($packages), \count($packages) > 1 ? 's' : '')); if ($format === self::FORMAT_PLAIN) { foreach ($packages as $pkg) { $replacement = $pkg->getReplacementPackage() !== null ? 'Use ' . $pkg->getReplacementPackage() . ' instead' : 'No replacement was suggested'; $io->writeError(\sprintf('%s is abandoned. %s.', $this->getPackageNameWithLink($pkg), $replacement)); } return; } if (!$io instanceof ConsoleIO) { throw new InvalidArgumentException('Cannot use table format with ' . \get_class($io)); } $table = $io->getTable()->setHeaders(['Abandoned Package', 'Suggested Replacement'])->setColumnWidth(1, 80)->setColumnMaxWidth(1, 80); foreach ($packages as $pkg) { $replacement = $pkg->getReplacementPackage() !== null ? $pkg->getReplacementPackage() : 'none'; $table->addRow([$this->getPackageNameWithLink($pkg), $replacement]); } $table->render(); } private function getPackageNameWithLink(PackageInterface $package) : string { $packageUrl = PackageInfo::getViewSourceOrHomepageUrl($package); return $packageUrl !== null ? '' . $package->getPrettyName() . '' : $package->getPrettyName(); } private function getSeverity(\Composer\Advisory\SecurityAdvisory $advisory) : string { if ($advisory->severity === null) { return ''; } return $advisory->severity; } private function getCVE(\Composer\Advisory\SecurityAdvisory $advisory) : string { if ($advisory->cve === null) { return 'NO CVE'; } return '' . $advisory->cve . ''; } private function getURL(\Composer\Advisory\SecurityAdvisory $advisory) : string { if ($advisory->link === null) { return ''; } return 'link) . '>' . OutputFormatter::escape($advisory->link) . ''; } /** * @return int-mask */ private function calculateBitmask(bool $hasVulnerablePackages, bool $hasAbandonedPackages) : int { $bitmask = self::STATUS_OK; if ($hasVulnerablePackages) { $bitmask |= self::STATUS_VULNERABLE; } if ($hasAbandonedPackages) { $bitmask |= self::STATUS_ABANDONED; } return $bitmask; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Advisory; use Composer\Semver\Constraint\ConstraintInterface; use DateTimeImmutable; class IgnoredSecurityAdvisory extends \Composer\Advisory\SecurityAdvisory { /** * @var string|null * @readonly */ public $ignoreReason; /** * @param non-empty-array $sources */ public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null, ?string $ignoreReason = null, ?string $severity = null) { parent::__construct($packageName, $advisoryId, $affectedVersions, $title, $sources, $reportedAt, $cve, $link, $severity); $this->ignoreReason = $ignoreReason; } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { $data = parent::jsonSerialize(); if ($this->ignoreReason === NULL) { unset($data['ignoreReason']); } return $data; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Exception; /** * @author Jordi Boggiano */ class IrrecoverableDownloadException extends \RuntimeException { } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Exception; /** * Specific exception for Composer\Util\HttpDownloader creation. * * @author Jordi Boggiano */ class NoSslException extends \RuntimeException { } * 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\Json\JsonFile; use Composer\CaBundle\CaBundle; use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use _ContaoManager\Symfony\Component\Finder\Finder; use _ContaoManager\Symfony\Component\Process\Process; use _ContaoManager\Seld\PharUtils\Timestamps; use _ContaoManager\Seld\PharUtils\Linter; /** * The Compiler class compiles composer into a phar * * @author Fabien Potencier * @author Jordi Boggiano */ class Compiler { /** @var string */ private $version; /** @var string */ private $branchAliasVersion = ''; /** @var \DateTime */ private $versionDate; /** * Compiles composer into a single phar file * * @param string $pharFile The full path to the file to create * * @throws \RuntimeException */ public function compile(string $pharFile = 'composer.phar') : void { if (\file_exists($pharFile)) { \unlink($pharFile); } $process = new ProcessExecutor(); if (0 !== $process->execute(['git', 'log', '--pretty=%H', '-n1', 'HEAD'], $output, \dirname(\dirname(__DIR__)))) { throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.'); } $this->version = \trim($output); if (0 !== $process->execute(['git', 'log', '-n1', '--pretty=%ci', 'HEAD'], $output, \dirname(\dirname(__DIR__)))) { throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.'); } $this->versionDate = new \DateTime(\trim($output)); $this->versionDate->setTimezone(new \DateTimeZone('UTC')); if (0 === $process->execute(['git', 'describe', '--tags', '--exact-match', 'HEAD'], $output, \dirname(\dirname(__DIR__)))) { $this->version = \trim($output); } else { // get branch-alias defined in composer.json for dev-main (if any) $localConfig = __DIR__ . '/../../composer.json'; $file = new JsonFile($localConfig); $localConfig = $file->read(); if (isset($localConfig['extra']['branch-alias']['dev-main'])) { $this->branchAliasVersion = $localConfig['extra']['branch-alias']['dev-main']; } } if ('' === $this->version) { throw new \UnexpectedValueException('Version detection failed'); } $phar = new \Phar($pharFile, 0, 'composer.phar'); $phar->setSignatureAlgorithm(\Phar::SHA512); $phar->startBuffering(); $finderSort = static function ($a, $b) : int { return \strcmp(\strtr($a->getRealPath(), '\\', '/'), \strtr($b->getRealPath(), '\\', '/')); }; // Add Composer sources $finder = new Finder(); $finder->files()->ignoreVCS(\true)->name('*.php')->notName('Compiler.php')->notName('ClassLoader.php')->notName('InstalledVersions.php')->in(__DIR__ . '/..')->sort($finderSort); foreach ($finder as $file) { $this->addFile($phar, $file); } // Add runtime utilities separately to make sure they retains the docblocks as these will get copied into projects $this->addFile($phar, new \SplFileInfo(__DIR__ . '/Autoload/ClassLoader.php'), \false); $this->addFile($phar, new \SplFileInfo(__DIR__ . '/InstalledVersions.php'), \false); // Add Composer resources $finder = new Finder(); $finder->files()->in(__DIR__ . '/../../res')->sort($finderSort); foreach ($finder as $file) { $this->addFile($phar, $file, \false); } // Add vendor files $finder = new Finder(); $finder->files()->ignoreVCS(\true)->notPath('/\\/(composer\\.(json|lock)|[A-Z]+\\.md(?:own)?|\\.gitignore|appveyor.yml|phpunit\\.xml\\.dist|phpstan\\.neon\\.dist|phpstan-config\\.neon|phpstan-baseline\\.neon)$/')->notPath('/bin\\/(jsonlint|validate-json|simple-phpunit|phpstan|phpstan\\.phar)(\\.bat)?$/')->notPath('justinrainbow/json-schema/demo/')->notPath('justinrainbow/json-schema/dist/')->notPath('composer/pcre/extension.neon')->notPath('composer/LICENSE')->exclude('Tests')->exclude('tests')->exclude('docs')->in(__DIR__ . '/../../vendor/')->sort($finderSort); $extraFiles = []; foreach ([__DIR__ . '/../../vendor/composer/installed.json', __DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-exceptions.json', __DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-licenses.json', CaBundle::getBundledCaBundlePath(), __DIR__ . '/../../vendor/symfony/console/Resources/bin/hiddeninput.exe', __DIR__ . '/../../vendor/symfony/console/Resources/completion.bash'] as $file) { $extraFiles[$file] = \realpath($file); if (!\file_exists($file)) { throw new \RuntimeException('Extra file listed is missing from the filesystem: ' . $file); } } $unexpectedFiles = []; foreach ($finder as $file) { if (\false !== ($index = \array_search($file->getRealPath(), $extraFiles, \true))) { unset($extraFiles[$index]); } elseif (!Preg::isMatch('{(^LICENSE$|\\.php$)}', $file->getFilename())) { $unexpectedFiles[] = (string) $file; } if (Preg::isMatch('{\\.php[\\d.]*$}', $file->getFilename())) { $this->addFile($phar, $file); } else { $this->addFile($phar, $file, \false); } } if (\count($extraFiles) > 0) { throw new \RuntimeException('These files were expected but not added to the phar, they might be excluded or gone from the source package:' . \PHP_EOL . \var_export($extraFiles, \true)); } if (\count($unexpectedFiles) > 0) { throw new \RuntimeException('These files were unexpectedly added to the phar, make sure they are excluded or listed in $extraFiles:' . \PHP_EOL . \var_export($unexpectedFiles, \true)); } // Add bin/composer $this->addComposerBin($phar); // Stubs $phar->setStub($this->getStub()); $phar->stopBuffering(); // disabled for interoperability with systems without gzip ext // $phar->compressFiles(\Phar::GZ); $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../../LICENSE'), \false); unset($phar); // re-sign the phar with reproducible timestamp / signature $util = new Timestamps($pharFile); $util->updateTimestamps($this->versionDate); $util->save($pharFile, \Phar::SHA512); Linter::lint($pharFile, ['vendor/symfony/console/Attribute/AsCommand.php', 'vendor/symfony/polyfill-intl-grapheme/bootstrap80.php', 'vendor/symfony/polyfill-intl-normalizer/bootstrap80.php', 'vendor/symfony/polyfill-mbstring/bootstrap80.php', 'vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'vendor/symfony/service-contracts/Attribute/SubscribedService.php']); } private function getRelativeFilePath(\SplFileInfo $file) : string { $realPath = $file->getRealPath(); $pathPrefix = \dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR; $pos = \strpos($realPath, $pathPrefix); $relativePath = $pos !== \false ? \substr_replace($realPath, '', $pos, \strlen($pathPrefix)) : $realPath; return \strtr($relativePath, '\\', '/'); } private function addFile(\Phar $phar, \SplFileInfo $file, bool $strip = \true) : void { $path = $this->getRelativeFilePath($file); $content = \file_get_contents((string) $file); if ($strip) { $content = $this->stripWhitespace($content); } elseif ('LICENSE' === $file->getFilename()) { $content = "\n" . $content . "\n"; } if ($path === 'src/Composer/Composer.php') { $content = \strtr($content, ['@package_version@' => $this->version, '@package_branch_alias_version@' => $this->branchAliasVersion, '@release_date@' => $this->versionDate->format('Y-m-d H:i:s')]); $content = Preg::replace('{SOURCE_VERSION = \'[^\']+\';}', 'SOURCE_VERSION = \'\';', $content); } $phar->addFromString($path, $content); } private function addComposerBin(\Phar $phar) : void { $content = \file_get_contents(__DIR__ . '/../../bin/composer'); $content = Preg::replace('{^#!/usr/bin/env php\\s*}', '', $content); $phar->addFromString('bin/composer', $content); } /** * Removes whitespace from a PHP source string while preserving line numbers. * * @param string $source A PHP string * @return string The PHP string with the whitespace removed */ private function stripWhitespace(string $source) : string { if (!\function_exists('token_get_all')) { return $source; } $output = ''; foreach (\token_get_all($source) as $token) { if (\is_string($token)) { $output .= $token; } elseif (\in_array($token[0], [\T_COMMENT, \T_DOC_COMMENT])) { $output .= \str_repeat("\n", \substr_count($token[1], "\n")); } elseif (\T_WHITESPACE === $token[0]) { // reduce wide spaces $whitespace = Preg::replace('{[ \\t]+}', ' ', $token[1]); // normalize newlines to \n $whitespace = Preg::replace('{(?:\\r\\n|\\r|\\n)}', "\n", $whitespace); // trim leading spaces $whitespace = Preg::replace('{\\n +}', "\n", $whitespace); $output .= $whitespace; } else { $output .= $token[1]; } } return $output; } private function getStub() : string { $stub = <<<'EOF' #!/usr/bin/env php * Jordi Boggiano * * For the full copyright and license information, please view * the license that is located at the bottom of this file. */ // Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264 if (extension_loaded('apc') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN) && filter_var(ini_get('apc.cache_by_default'), FILTER_VALIDATE_BOOLEAN)) { if (version_compare(phpversion('apc'), '3.0.12', '>=')) { ini_set('apc.cache_by_default', 0); } else { fwrite(STDERR, 'Warning: APC <= 3.0.12 may cause fatal errors when running composer commands.'.PHP_EOL); fwrite(STDERR, 'Update APC, or set apc.enable_cli or apc.cache_by_default to 0 in your php.ini.'.PHP_EOL); } } if (!class_exists('Phar')) { echo 'PHP\'s phar extension is missing. Composer requires it to run. Enable the extension or recompile php without --disable-phar then try again.' . PHP_EOL; exit(1); } Phar::mapPhar('composer.phar'); EOF; // add warning once the phar is older than 60 days if (Preg::isMatch('{^[a-f0-9]+$}', $this->version)) { $warningTime = (int) $this->versionDate->format('U') + 60 * 86400; $stub .= "define('COMPOSER_DEV_WARNING_TIME', {$warningTime});\n"; } return $stub . <<<'EOF' require 'phar://composer.phar/bin/composer'; __HALT_COMPILER(); EOF; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; use Composer\Package\Version\VersionParser; use Composer\Pcre\Preg; use Composer\Util\ComposerMirror; /** * Core package definitions that are needed to resolve dependencies and install packages * * @author Nils Adermann * * @phpstan-import-type AutoloadRules from PackageInterface * @phpstan-import-type DevAutoloadRules from PackageInterface * @phpstan-import-type PhpExtConfig from PackageInterface */ class Package extends \Composer\Package\BasePackage { /** @var string */ protected $type; /** @var ?string */ protected $targetDir; /** @var 'source'|'dist'|null */ protected $installationSource; /** @var ?string */ protected $sourceType; /** @var ?string */ protected $sourceUrl; /** @var ?string */ protected $sourceReference; /** @var ?list */ protected $sourceMirrors; /** @var ?non-empty-string */ protected $distType; /** @var ?non-empty-string */ protected $distUrl; /** @var ?string */ protected $distReference; /** @var ?string */ protected $distSha1Checksum; /** @var ?list */ protected $distMirrors; /** @var string */ protected $version; /** @var string */ protected $prettyVersion; /** @var ?\DateTimeInterface */ protected $releaseDate; /** @var mixed[] */ protected $extra = []; /** @var string[] */ protected $binaries = []; /** @var bool */ protected $dev; /** * @var string * @phpstan-var 'stable'|'RC'|'beta'|'alpha'|'dev' */ protected $stability; /** @var ?string */ protected $notificationUrl; /** @var array */ protected $requires = []; /** @var array */ protected $conflicts = []; /** @var array */ protected $provides = []; /** @var array */ protected $replaces = []; /** @var array */ protected $devRequires = []; /** @var array */ protected $suggests = []; /** * @var array * @phpstan-var AutoloadRules */ protected $autoload = []; /** * @var array * @phpstan-var DevAutoloadRules */ protected $devAutoload = []; /** @var string[] */ protected $includePaths = []; /** @var bool */ protected $isDefaultBranch = \false; /** @var mixed[] */ protected $transportOptions = []; /** * @var array|null * @phpstan-var PhpExtConfig|null */ protected $phpExt = null; /** * Creates a new in memory package. * * @param string $name The package's name * @param string $version The package's version * @param string $prettyVersion The package's non-normalized version */ public function __construct(string $name, string $version, string $prettyVersion) { parent::__construct($name); $this->version = $version; $this->prettyVersion = $prettyVersion; $this->stability = VersionParser::parseStability($version); $this->dev = $this->stability === 'dev'; } /** * @inheritDoc */ public function isDev() : bool { return $this->dev; } public function setType(string $type) : void { $this->type = $type; } /** * @inheritDoc */ public function getType() : string { return $this->type ?: 'library'; } /** * @inheritDoc */ public function getStability() : string { return $this->stability; } public function setTargetDir(?string $targetDir) : void { $this->targetDir = $targetDir; } /** * @inheritDoc */ public function getTargetDir() : ?string { if (null === $this->targetDir) { return null; } return \ltrim(Preg::replace('{ (?:^|[\\\\/]+) \\.\\.? (?:[\\\\/]+|$) (?:\\.\\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/'); } /** * @param mixed[] $extra */ public function setExtra(array $extra) : void { $this->extra = $extra; } /** * @inheritDoc */ public function getExtra() : array { return $this->extra; } /** * @param string[] $binaries */ public function setBinaries(array $binaries) : void { $this->binaries = $binaries; } /** * @inheritDoc */ public function getBinaries() : array { return $this->binaries; } /** * @inheritDoc */ public function setInstallationSource(?string $type) : void { $this->installationSource = $type; } /** * @inheritDoc */ public function getInstallationSource() : ?string { return $this->installationSource; } public function setSourceType(?string $type) : void { $this->sourceType = $type; } /** * @inheritDoc */ public function getSourceType() : ?string { return $this->sourceType; } public function setSourceUrl(?string $url) : void { $this->sourceUrl = $url; } /** * @inheritDoc */ public function getSourceUrl() : ?string { return $this->sourceUrl; } public function setSourceReference(?string $reference) : void { $this->sourceReference = $reference; } /** * @inheritDoc */ public function getSourceReference() : ?string { return $this->sourceReference; } public function setSourceMirrors(?array $mirrors) : void { $this->sourceMirrors = $mirrors; } /** * @inheritDoc */ public function getSourceMirrors() : ?array { return $this->sourceMirrors; } /** * @inheritDoc */ public function getSourceUrls() : array { return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source'); } /** * @param string $type */ public function setDistType(?string $type) : void { $this->distType = $type === '' ? null : $type; } /** * @inheritDoc */ public function getDistType() : ?string { return $this->distType; } /** * @param string|null $url */ public function setDistUrl(?string $url) : void { $this->distUrl = $url === '' ? null : $url; } /** * @inheritDoc */ public function getDistUrl() : ?string { return $this->distUrl; } /** * @param string $reference */ public function setDistReference(?string $reference) : void { $this->distReference = $reference; } /** * @inheritDoc */ public function getDistReference() : ?string { return $this->distReference; } /** * @param string $sha1checksum */ public function setDistSha1Checksum(?string $sha1checksum) : void { $this->distSha1Checksum = $sha1checksum; } /** * @inheritDoc */ public function getDistSha1Checksum() : ?string { return $this->distSha1Checksum; } public function setDistMirrors(?array $mirrors) : void { $this->distMirrors = $mirrors; } /** * @inheritDoc */ public function getDistMirrors() : ?array { return $this->distMirrors; } /** * @inheritDoc */ public function getDistUrls() : array { return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist'); } /** * @inheritDoc */ public function getTransportOptions() : array { return $this->transportOptions; } /** * @inheritDoc */ public function setTransportOptions(array $options) : void { $this->transportOptions = $options; } /** * @inheritDoc */ public function getVersion() : string { return $this->version; } /** * @inheritDoc */ public function getPrettyVersion() : string { return $this->prettyVersion; } public function setReleaseDate(?\DateTimeInterface $releaseDate) : void { $this->releaseDate = $releaseDate; } /** * @inheritDoc */ public function getReleaseDate() : ?\DateTimeInterface { return $this->releaseDate; } /** * Set the required packages * * @param array $requires A set of package links */ public function setRequires(array $requires) : void { if (isset($requires[0])) { // @phpstan-ignore-line $requires = $this->convertLinksToMap($requires, 'setRequires'); } $this->requires = $requires; } /** * @inheritDoc */ public function getRequires() : array { return $this->requires; } /** * Set the conflicting packages * * @param array $conflicts A set of package links */ public function setConflicts(array $conflicts) : void { if (isset($conflicts[0])) { // @phpstan-ignore-line $conflicts = $this->convertLinksToMap($conflicts, 'setConflicts'); } $this->conflicts = $conflicts; } /** * @inheritDoc * @return array */ public function getConflicts() : array { return $this->conflicts; } /** * Set the provided virtual packages * * @param array $provides A set of package links */ public function setProvides(array $provides) : void { if (isset($provides[0])) { // @phpstan-ignore-line $provides = $this->convertLinksToMap($provides, 'setProvides'); } $this->provides = $provides; } /** * @inheritDoc * @return array */ public function getProvides() : array { return $this->provides; } /** * Set the packages this one replaces * * @param array $replaces A set of package links */ public function setReplaces(array $replaces) : void { if (isset($replaces[0])) { // @phpstan-ignore-line $replaces = $this->convertLinksToMap($replaces, 'setReplaces'); } $this->replaces = $replaces; } /** * @inheritDoc * @return array */ public function getReplaces() : array { return $this->replaces; } /** * Set the recommended packages * * @param array $devRequires A set of package links */ public function setDevRequires(array $devRequires) : void { if (isset($devRequires[0])) { // @phpstan-ignore-line $devRequires = $this->convertLinksToMap($devRequires, 'setDevRequires'); } $this->devRequires = $devRequires; } /** * @inheritDoc */ public function getDevRequires() : array { return $this->devRequires; } /** * Set the suggested packages * * @param array $suggests A set of package names/comments */ public function setSuggests(array $suggests) : void { $this->suggests = $suggests; } /** * @inheritDoc */ public function getSuggests() : array { return $this->suggests; } /** * Set the autoload mapping * * @param array $autoload Mapping of autoloading rules * * @phpstan-param AutoloadRules $autoload */ public function setAutoload(array $autoload) : void { $this->autoload = $autoload; } /** * @inheritDoc */ public function getAutoload() : array { return $this->autoload; } /** * Set the dev autoload mapping * * @param array $devAutoload Mapping of dev autoloading rules * * @phpstan-param DevAutoloadRules $devAutoload */ public function setDevAutoload(array $devAutoload) : void { $this->devAutoload = $devAutoload; } /** * @inheritDoc */ public function getDevAutoload() : array { return $this->devAutoload; } /** * Sets the list of paths added to PHP's include path. * * @param string[] $includePaths List of directories. */ public function setIncludePaths(array $includePaths) : void { $this->includePaths = $includePaths; } /** * @inheritDoc */ public function getIncludePaths() : array { return $this->includePaths; } /** * Sets the settings for php extension packages * * @param array|null $phpExt * * @phpstan-param PhpExtConfig|null $phpExt */ public function setPhpExt(?array $phpExt) : void { $this->phpExt = $phpExt; } /** * @inheritDoc */ public function getPhpExt() : ?array { return $this->phpExt; } /** * Sets the notification URL */ public function setNotificationUrl(string $notificationUrl) : void { $this->notificationUrl = $notificationUrl; } /** * @inheritDoc */ public function getNotificationUrl() : ?string { return $this->notificationUrl; } public function setIsDefaultBranch(bool $defaultBranch) : void { $this->isDefaultBranch = $defaultBranch; } /** * @inheritDoc */ public function isDefaultBranch() : bool { return $this->isDefaultBranch; } /** * @inheritDoc */ public function setSourceDistReferences(string $reference) : void { $this->setSourceReference($reference); // only bitbucket, github and gitlab have auto generated dist URLs that easily allow replacing the reference in the dist URL // TODO generalize this a bit for self-managed/on-prem versions? Some kind of replace token in dist urls which allow this? if ($this->getDistUrl() !== null && Preg::isMatch('{^https?://(?:(?:www\\.)?bitbucket\\.org|(api\\.)?github\\.com|(?:www\\.)?gitlab\\.com)/}i', $this->getDistUrl())) { $this->setDistReference($reference); $this->setDistUrl(Preg::replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $this->getDistUrl())); } elseif ($this->getDistReference()) { // update the dist reference if there was one, but if none was provided ignore it $this->setDistReference($reference); } } /** * Replaces current version and pretty version with passed values. * It also sets stability. * * @param string $version The package's normalized version * @param string $prettyVersion The package's non-normalized version */ public function replaceVersion(string $version, string $prettyVersion) : void { $this->version = $version; $this->prettyVersion = $prettyVersion; $this->stability = VersionParser::parseStability($version); $this->dev = $this->stability === 'dev'; } /** * @param mixed[]|null $mirrors * * @return list * * @phpstan-param list|null $mirrors */ protected function getUrls(?string $url, ?array $mirrors, ?string $ref, ?string $type, string $urlType) : array { if (!$url) { return []; } if ($urlType === 'dist' && \false !== \strpos($url, '%')) { $url = ComposerMirror::processUrl($url, $this->name, $this->version, $ref, $type, $this->prettyVersion); } $urls = [$url]; if ($mirrors) { foreach ($mirrors as $mirror) { if ($urlType === 'dist') { $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type, $this->prettyVersion); } elseif ($urlType === 'source' && $type === 'git') { $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type); } elseif ($urlType === 'source' && $type === 'hg') { $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type); } else { continue; } if (!\in_array($mirrorUrl, $urls)) { $func = $mirror['preferred'] ? 'array_unshift' : 'array_push'; $func($urls, $mirrorUrl); } } } return $urls; } /** * @param array $links * @return array */ private function convertLinksToMap(array $links, string $source) : array { \trigger_error('Package::' . $source . ' must be called with a map of lowercased package name => Link object, got a indexed array, this is deprecated and you should fix your usage.'); $newLinks = []; foreach ($links as $link) { $newLinks[$link->getTarget()] = $link; } return $newLinks; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; use Composer\Semver\Constraint\ConstraintInterface; /** * Represents a link between two packages, represented by their names * * @author Nils Adermann */ class Link { public const TYPE_REQUIRE = 'requires'; public const TYPE_DEV_REQUIRE = 'devRequires'; public const TYPE_PROVIDE = 'provides'; public const TYPE_CONFLICT = 'conflicts'; public const TYPE_REPLACE = 'replaces'; /** * Special type * @internal */ public const TYPE_DOES_NOT_REQUIRE = 'does not require'; private const TYPE_UNKNOWN = 'relates to'; /** * Will be converted into a constant once the min PHP version allows this * * @internal * @var string[] * @phpstan-var array */ public static $TYPES = [self::TYPE_REQUIRE, self::TYPE_DEV_REQUIRE, self::TYPE_PROVIDE, self::TYPE_CONFLICT, self::TYPE_REPLACE]; /** * @var string */ protected $source; /** * @var string */ protected $target; /** * @var ConstraintInterface */ protected $constraint; /** * @var string * @phpstan-var string $description */ protected $description; /** * @var ?string */ protected $prettyConstraint; /** * Creates a new package link. * * @param ConstraintInterface $constraint Constraint applying to the target of this link * @param self::TYPE_* $description Used to create a descriptive string representation */ public function __construct(string $source, string $target, ConstraintInterface $constraint, $description = self::TYPE_UNKNOWN, ?string $prettyConstraint = null) { $this->source = \strtolower($source); $this->target = \strtolower($target); $this->constraint = $constraint; $this->description = self::TYPE_DEV_REQUIRE === $description ? 'requires (for development)' : $description; $this->prettyConstraint = $prettyConstraint; } public function getDescription() : string { return $this->description; } public function getSource() : string { return $this->source; } public function getTarget() : string { return $this->target; } public function getConstraint() : ConstraintInterface { return $this->constraint; } /** * @throws \UnexpectedValueException If no pretty constraint was provided */ public function getPrettyConstraint() : string { if (null === $this->prettyConstraint) { throw new \UnexpectedValueException(\sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this)); } return $this->prettyConstraint; } public function __toString() : string { return $this->source . ' ' . $this->description . ' ' . $this->target . ' (' . $this->constraint . ')'; } public function getPrettyString(\Composer\Package\PackageInterface $sourcePackage) : string { return $sourcePackage->getPrettyString() . ' ' . $this->description . ' ' . $this->target . ' ' . $this->constraint->getPrettyString(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; /** * Defines package metadata that is not necessarily needed for solving and installing packages * * PackageInterface & derivatives are considered internal, you may use them in type hints but extending/implementing them is not recommended and not supported. Things may change without notice. * * @author Nils Adermann */ interface CompletePackageInterface extends \Composer\Package\PackageInterface { /** * Returns the scripts of this package * * @return array Map of script name to array of handlers */ public function getScripts() : array; /** * @param array $scripts */ public function setScripts(array $scripts) : void; /** * Returns an array of repositories * * @return mixed[] Repositories */ public function getRepositories() : array; /** * Set the repositories * * @param mixed[] $repositories */ public function setRepositories(array $repositories) : void; /** * Returns the package license, e.g. MIT, BSD, GPL * * @return string[] The package licenses */ public function getLicense() : array; /** * Set the license * * @param string[] $license */ public function setLicense(array $license) : void; /** * Returns an array of keywords relating to the package * * @return string[] */ public function getKeywords() : array; /** * Set the keywords * * @param string[] $keywords */ public function setKeywords(array $keywords) : void; /** * Returns the package description * * @return ?string */ public function getDescription() : ?string; /** * Set the description */ public function setDescription(string $description) : void; /** * Returns the package homepage * * @return ?string */ public function getHomepage() : ?string; /** * Set the homepage */ public function setHomepage(string $homepage) : void; /** * Returns an array of authors of the package * * Each item can contain name/homepage/email keys * * @return array */ public function getAuthors() : array; /** * Set the authors * * @param array $authors */ public function setAuthors(array $authors) : void; /** * Returns the support information * * @return array{issues?: string, forum?: string, wiki?: string, source?: string, email?: string, irc?: string, docs?: string, rss?: string, chat?: string, security?: string} */ public function getSupport() : array; /** * Set the support information * * @param array{issues?: string, forum?: string, wiki?: string, source?: string, email?: string, irc?: string, docs?: string, rss?: string, chat?: string, security?: string} $support */ public function setSupport(array $support) : void; /** * Returns an array of funding options for the package * * Each item will contain type and url keys * * @return array */ public function getFunding() : array; /** * Set the funding * * @param array $funding */ public function setFunding(array $funding) : void; /** * Returns if the package is abandoned or not */ public function isAbandoned() : bool; /** * If the package is abandoned and has a suggested replacement, this method returns it */ public function getReplacementPackage() : ?string; /** * @param bool|string $abandoned */ public function setAbandoned($abandoned) : void; /** * Returns default base filename for archive * * @return ?string */ public function getArchiveName() : ?string; /** * Sets default base filename for archive */ public function setArchiveName(string $name) : void; /** * Returns a list of patterns to exclude from package archives * * @return string[] */ public function getArchiveExcludes() : array; /** * Sets a list of patterns to be excluded from archives * * @param string[] $excludes */ public function setArchiveExcludes(array $excludes) : void; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; use Composer\Downloader\DownloadManager; use Composer\Package\RootPackageInterface; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Loop; use Composer\Util\SyncHelper; use Composer\Json\JsonFile; use Composer\Package\CompletePackageInterface; /** * @author Matthieu Moquet * @author Till Klampaeckel */ class ArchiveManager { /** @var DownloadManager */ protected $downloadManager; /** @var Loop */ protected $loop; /** * @var ArchiverInterface[] */ protected $archivers = []; /** * @var bool */ protected $overwriteFiles = \true; /** * @param DownloadManager $downloadManager A manager used to download package sources */ public function __construct(DownloadManager $downloadManager, Loop $loop) { $this->downloadManager = $downloadManager; $this->loop = $loop; } public function addArchiver(\Composer\Package\Archiver\ArchiverInterface $archiver) : void { $this->archivers[] = $archiver; } /** * Set whether existing archives should be overwritten * * @param bool $overwriteFiles New setting * * @return $this */ public function setOverwriteFiles(bool $overwriteFiles) : self { $this->overwriteFiles = $overwriteFiles; return $this; } /** * @return array * @internal */ public function getPackageFilenameParts(CompletePackageInterface $package) : array { $baseName = $package->getArchiveName(); if (null === $baseName) { $baseName = Preg::replace('#[^a-z0-9-_]#i', '-', $package->getName()); } $parts = ['base' => $baseName]; $distReference = $package->getDistReference(); if (null !== $distReference && Preg::isMatch('{^[a-f0-9]{40}$}', $distReference)) { $parts['dist_reference'] = $distReference; $parts['dist_type'] = $package->getDistType(); } else { $parts['version'] = $package->getPrettyVersion(); $parts['dist_reference'] = $distReference; } $sourceReference = $package->getSourceReference(); if (null !== $sourceReference) { $parts['source_reference'] = \substr(\hash('sha1', $sourceReference), 0, 6); } $parts = \array_filter($parts, function (?string $part) { return $part !== null; }); foreach ($parts as $key => $part) { $parts[$key] = \str_replace('/', '-', $part); } return $parts; } /** * @param array $parts * * @return string * @internal */ public function getPackageFilenameFromParts(array $parts) : string { return \implode('-', $parts); } /** * Generate a distinct filename for a particular version of a package. * * @param CompletePackageInterface $package The package to get a name for * * @return string A filename without an extension */ public function getPackageFilename(CompletePackageInterface $package) : string { return $this->getPackageFilenameFromParts($this->getPackageFilenameParts($package)); } /** * Create an archive of the specified package. * * @param CompletePackageInterface $package The package to archive * @param string $format The format of the archive (zip, tar, ...) * @param string $targetDir The directory where to build the archive * @param string|null $fileName The relative file name to use for the archive, or null to generate * the package name. Note that the format will be appended to this name * @param bool $ignoreFilters Ignore filters when looking for files in the package * @throws \InvalidArgumentException * @throws \RuntimeException * @return string The path of the created archive */ public function archive(CompletePackageInterface $package, string $format, string $targetDir, ?string $fileName = null, bool $ignoreFilters = \false) : string { if (empty($format)) { throw new \InvalidArgumentException('Format must be specified'); } // Search for the most appropriate archiver $usableArchiver = null; foreach ($this->archivers as $archiver) { if ($archiver->supports($format, $package->getSourceType())) { $usableArchiver = $archiver; break; } } // Checks the format/source type are supported before downloading the package if (null === $usableArchiver) { throw new \RuntimeException(\sprintf('No archiver found to support %s format', $format)); } $filesystem = new Filesystem(); if ($package instanceof RootPackageInterface) { $sourcePath = \realpath('.'); } else { // Directory used to download the sources $sourcePath = \sys_get_temp_dir() . '/composer_archive' . \bin2hex(\random_bytes(5)); $filesystem->ensureDirectoryExists($sourcePath); try { // Download sources $promise = $this->downloadManager->download($package, $sourcePath); SyncHelper::await($this->loop, $promise); $promise = $this->downloadManager->install($package, $sourcePath); SyncHelper::await($this->loop, $promise); } catch (\Exception $e) { $filesystem->removeDirectory($sourcePath); throw $e; } // Check exclude from downloaded composer.json if (\file_exists($composerJsonPath = $sourcePath . '/composer.json')) { $jsonFile = new JsonFile($composerJsonPath); $jsonData = $jsonFile->read(); if (!empty($jsonData['archive']['name'])) { $package->setArchiveName($jsonData['archive']['name']); } if (!empty($jsonData['archive']['exclude'])) { $package->setArchiveExcludes($jsonData['archive']['exclude']); } } } $supportedFormats = $this->getSupportedFormats(); $packageNameParts = null === $fileName ? $this->getPackageFilenameParts($package) : ['base' => $fileName]; $packageName = $this->getPackageFilenameFromParts($packageNameParts); $excludePatterns = $this->buildExcludePatterns($packageNameParts, $supportedFormats); // Archive filename $filesystem->ensureDirectoryExists($targetDir); $target = \realpath($targetDir) . '/' . $packageName . '.' . $format; $filesystem->ensureDirectoryExists(\dirname($target)); if (!$this->overwriteFiles && \file_exists($target)) { return $target; } // Create the archive $tempTarget = \sys_get_temp_dir() . '/composer_archive' . \bin2hex(\random_bytes(5)) . '.' . $format; $filesystem->ensureDirectoryExists(\dirname($tempTarget)); $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, \array_merge($excludePatterns, $package->getArchiveExcludes()), $ignoreFilters); $filesystem->rename($archivePath, $target); // cleanup temporary download if (!$package instanceof RootPackageInterface) { $filesystem->removeDirectory($sourcePath); } $filesystem->remove($tempTarget); return $target; } /** * @param string[] $parts * @param string[] $formats * * @return string[] */ private function buildExcludePatterns(array $parts, array $formats) : array { $base = $parts['base']; if (\count($parts) > 1) { $base .= '-*'; } $patterns = []; foreach ($formats as $format) { $patterns[] = "{$base}.{$format}"; } return $patterns; } /** * @return string[] */ private function getSupportedFormats() : array { // The problem is that the \Composer\Package\Archiver\ArchiverInterface // doesn't provide method to get the supported formats. // Supported formats are also hard-coded into the description of the // --format option. // See \Composer\Command\ArchiveCommand::configure(). $formats = []; foreach ($this->archivers as $archiver) { $items = []; switch (\get_class($archiver)) { case \Composer\Package\Archiver\ZipArchiver::class: $items = ['zip']; break; case \Composer\Package\Archiver\PharArchiver::class: $items = ['zip', 'tar', 'tar.gz', 'tar.bz2']; break; } $formats = \array_merge($formats, $items); } return \array_unique($formats); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; use Composer\Pcre\Preg; use Composer\Util\Filesystem; use FilesystemIterator; use FilterIterator; use Iterator; use _ContaoManager\Symfony\Component\Finder\Finder; use _ContaoManager\Symfony\Component\Finder\SplFileInfo; /** * A Symfony Finder wrapper which locates files that should go into archives * * Handles .gitignore, .gitattributes and .hgignore files as well as composer's * own exclude rules from composer.json * * @author Nils Adermann * @phpstan-extends FilterIterator> */ class ArchivableFilesFinder extends FilterIterator { /** * @var Finder */ protected $finder; /** * Initializes the internal Symfony Finder with appropriate filters * * @param string $sources Path to source files to be archived * @param string[] $excludes Composer's own exclude rules from composer.json * @param bool $ignoreFilters Ignore filters when looking for files */ public function __construct(string $sources, array $excludes, bool $ignoreFilters = \false) { $fs = new Filesystem(); $sourcesRealPath = \realpath($sources); if ($sourcesRealPath === \false) { throw new \RuntimeException('Could not realpath() the source directory "' . $sources . '"'); } $sources = $fs->normalizePath($sourcesRealPath); if ($ignoreFilters) { $filters = []; } else { $filters = [new \Composer\Package\Archiver\GitExcludeFilter($sources), new \Composer\Package\Archiver\ComposerExcludeFilter($sources, $excludes)]; } $this->finder = new Finder(); $filter = static function (\SplFileInfo $file) use($sources, $filters, $fs) : bool { $realpath = $file->getRealPath(); if ($realpath === \false) { return \false; } if ($file->isLink() && \strpos($realpath, $sources) !== 0) { return \false; } $relativePath = Preg::replace('#^' . \preg_quote($sources, '#') . '#', '', $fs->normalizePath($realpath)); $exclude = \false; foreach ($filters as $filter) { $exclude = $filter->filter($relativePath, $exclude); } return !$exclude; }; $this->finder->in($sources)->filter($filter)->ignoreVCS(\true)->ignoreDotFiles(\false)->sortByName(); parent::__construct($this->finder->getIterator()); } public function accept() : bool { /** @var SplFileInfo $current */ $current = $this->getInnerIterator()->current(); if (!$current->isDir()) { return \true; } $iterator = new FilesystemIterator((string) $current, FilesystemIterator::SKIP_DOTS); return !$iterator->valid(); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; /** * @author Till Klampaeckel * @author Nils Adermann * @author Matthieu Moquet */ class PharArchiver implements \Composer\Package\Archiver\ArchiverInterface { /** @var array */ protected static $formats = ['zip' => \Phar::ZIP, 'tar' => \Phar::TAR, 'tar.gz' => \Phar::TAR, 'tar.bz2' => \Phar::TAR]; /** @var array */ protected static $compressFormats = ['tar.gz' => \Phar::GZ, 'tar.bz2' => \Phar::BZ2]; /** * @inheritDoc */ public function archive(string $sources, string $target, string $format, array $excludes = [], bool $ignoreFilters = \false) : string { $sources = \realpath($sources); // Phar would otherwise load the file which we don't want if (\file_exists($target)) { \unlink($target); } try { $filename = \substr($target, 0, \strrpos($target, $format) - 1); // Check if compress format if (isset(static::$compressFormats[$format])) { // Current compress format supported base on tar $target = $filename . '.tar'; } $phar = new \PharData($target, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO, '', static::$formats[$format]); $files = new \Composer\Package\Archiver\ArchivableFilesFinder($sources, $excludes, $ignoreFilters); $filesOnly = new \Composer\Package\Archiver\ArchivableFilesFilter($files); $phar->buildFromIterator($filesOnly, $sources); $filesOnly->addEmptyDir($phar, $sources); if (isset(static::$compressFormats[$format])) { // Check can be compressed? if (!$phar->canCompress(static::$compressFormats[$format])) { throw new \RuntimeException(\sprintf('Can not compress to %s format', $format)); } // Delete old tar \unlink($target); // Compress the new tar $phar->compress(static::$compressFormats[$format]); // Make the correct filename $target = $filename . '.' . $format; } return $target; } catch (\UnexpectedValueException $e) { $message = \sprintf("Could not create archive '%s' from '%s': %s", $target, $sources, $e->getMessage()); throw new \RuntimeException($message, $e->getCode(), $e); } } /** * @inheritDoc */ public function supports(string $format, ?string $sourceType) : bool { return isset(static::$formats[$format]); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; use Composer\Pcre\Preg; use _ContaoManager\Symfony\Component\Finder; /** * @author Nils Adermann */ abstract class BaseExcludeFilter { /** * @var string */ protected $sourcePath; /** * @var array array of [$pattern, $negate, $stripLeadingSlash] arrays */ protected $excludePatterns; /** * @param string $sourcePath Directory containing sources to be filtered */ public function __construct(string $sourcePath) { $this->sourcePath = $sourcePath; $this->excludePatterns = []; } /** * Checks the given path against all exclude patterns in this filter * * Negated patterns overwrite exclude decisions of previous filters. * * @param string $relativePath The file's path relative to the sourcePath * @param bool $exclude Whether a previous filter wants to exclude this file * * @return bool Whether the file should be excluded */ public function filter(string $relativePath, bool $exclude) : bool { foreach ($this->excludePatterns as $patternData) { [$pattern, $negate, $stripLeadingSlash] = $patternData; if ($stripLeadingSlash) { $path = \substr($relativePath, 1); } else { $path = $relativePath; } try { if (Preg::isMatch($pattern, $path)) { $exclude = !$negate; } } catch (\RuntimeException $e) { // suppressed } } return $exclude; } /** * Processes a file containing exclude rules of different formats per line * * @param string[] $lines A set of lines to be parsed * @param callable $lineParser The parser to be used on each line * * @return array Exclude patterns to be used in filter() */ protected function parseLines(array $lines, callable $lineParser) : array { return \array_filter(\array_map(static function ($line) use($lineParser) { $line = \trim($line); if (!$line || 0 === \strpos($line, '#')) { return null; } return $lineParser($line); }, $lines), static function ($pattern) : bool { return $pattern !== null; }); } /** * Generates a set of exclude patterns for filter() from gitignore rules * * @param string[] $rules A list of exclude rules in gitignore syntax * * @return array Exclude patterns */ protected function generatePatterns(array $rules) : array { $patterns = []; foreach ($rules as $rule) { $patterns[] = $this->generatePattern($rule); } return $patterns; } /** * Generates an exclude pattern for filter() from a gitignore rule * * @param string $rule An exclude rule in gitignore syntax * * @return array{0: non-empty-string, 1: bool, 2: bool} An exclude pattern */ protected function generatePattern(string $rule) : array { $negate = \false; $pattern = ''; if ($rule !== '' && $rule[0] === '!') { $negate = \true; $rule = \ltrim($rule, '!'); } $firstSlashPosition = \strpos($rule, '/'); if (0 === $firstSlashPosition) { $pattern = '^/'; } elseif (\false === $firstSlashPosition || \strlen($rule) - 1 === $firstSlashPosition) { $pattern = '/'; } $rule = \trim($rule, '/'); // remove delimiters as well as caret (^) and dollar sign ($) from the regex $rule = \substr(Finder\Glob::toRegex($rule), 2, -2); return ['{' . $pattern . $rule . '(?=$|/)}', $negate, \false]; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; use FilterIterator; use Iterator; use PharData; use SplFileInfo; /** * @phpstan-extends FilterIterator> */ class ArchivableFilesFilter extends FilterIterator { /** @var string[] */ private $dirs = []; /** * @return bool true if the current element is acceptable, otherwise false. */ public function accept() : bool { $file = $this->getInnerIterator()->current(); if ($file->isDir()) { $this->dirs[] = (string) $file; return \false; } return \true; } public function addEmptyDir(PharData $phar, string $sources) : void { foreach ($this->dirs as $filepath) { $localname = \str_replace($sources . "/", '', $filepath); $phar->addEmptyDir($localname); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; use Composer\Pcre\Preg; /** * An exclude filter that processes gitattributes * * It respects export-ignore git attributes * * @author Nils Adermann */ class GitExcludeFilter extends \Composer\Package\Archiver\BaseExcludeFilter { /** * Parses .gitattributes if it exists */ public function __construct(string $sourcePath) { parent::__construct($sourcePath); if (\file_exists($sourcePath . '/.gitattributes')) { $this->excludePatterns = \array_merge($this->excludePatterns, $this->parseLines(\file($sourcePath . '/.gitattributes'), [$this, 'parseGitAttributesLine'])); } } /** * Callback parser which finds export-ignore rules in git attribute lines * * @param string $line A line from .gitattributes * * @return array{0: string, 1: bool, 2: bool}|null An exclude pattern for filter() */ public function parseGitAttributesLine(string $line) : ?array { $parts = Preg::split('#\\s+#', $line); if (\count($parts) === 2 && $parts[1] === 'export-ignore') { return $this->generatePattern($parts[0]); } if (\count($parts) === 2 && $parts[1] === '-export-ignore') { return $this->generatePattern('!' . $parts[0]); } return null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; /** * An exclude filter which processes composer's own exclude rules * * @author Nils Adermann */ class ComposerExcludeFilter extends \Composer\Package\Archiver\BaseExcludeFilter { /** * @param string $sourcePath Directory containing sources to be filtered * @param string[] $excludeRules An array of exclude rules from composer.json */ public function __construct(string $sourcePath, array $excludeRules) { parent::__construct($sourcePath); $this->excludePatterns = $this->generatePatterns($excludeRules); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; /** * @author Till Klampaeckel * @author Matthieu Moquet * @author Nils Adermann */ interface ArchiverInterface { /** * Create an archive from the sources. * * @param string $sources The sources directory * @param string $target The target file * @param string $format The format used for archive * @param string[] $excludes A list of patterns for files to exclude * @param bool $ignoreFilters Whether to ignore filters when looking for files * * @return string The path to the written archive file */ public function archive(string $sources, string $target, string $format, array $excludes = [], bool $ignoreFilters = \false) : string; /** * Format supported by the archiver. * * @param string $format The archive format * @param ?string $sourceType The source type (git, svn, hg, etc.) * * @return bool true if the format is supported by the archiver */ public function supports(string $format, ?string $sourceType) : bool; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Archiver; use ZipArchive; use Composer\Util\Filesystem; /** * @author Jan Prieser */ class ZipArchiver implements \Composer\Package\Archiver\ArchiverInterface { /** @var array */ protected static $formats = ['zip' => \true]; /** * @inheritDoc */ public function archive(string $sources, string $target, string $format, array $excludes = [], bool $ignoreFilters = \false) : string { $fs = new Filesystem(); $sourcesRealpath = \realpath($sources); if (\false !== $sourcesRealpath) { $sources = $sourcesRealpath; } unset($sourcesRealpath); $sources = $fs->normalizePath($sources); $zip = new ZipArchive(); $res = $zip->open($target, ZipArchive::CREATE); if ($res === \true) { $files = new \Composer\Package\Archiver\ArchivableFilesFinder($sources, $excludes, $ignoreFilters); foreach ($files as $file) { /** @var \Symfony\Component\Finder\SplFileInfo $file */ $filepath = \strtr($file->getPath() . "/" . $file->getFilename(), '\\', '/'); $localname = $filepath; if (\strpos($localname, $sources . '/') === 0) { $localname = \substr($localname, \strlen($sources . '/')); } if ($file->isDir()) { $zip->addEmptyDir($localname); } else { $zip->addFile($filepath, $localname); } /** * setExternalAttributesName() is only available with libzip 0.11.2 or above */ if (\method_exists($zip, 'setExternalAttributesName')) { $perms = \fileperms($filepath); /** * Ensure to preserve the permission umasks for the filepath in the archive. */ $zip->setExternalAttributesName($localname, ZipArchive::OPSYS_UNIX, $perms << 16); } } if ($zip->close()) { return $target; } } $message = \sprintf("Could not create archive '%s' from '%s': %s", $target, $sources, $zip->getStatusString()); throw new \RuntimeException($message); } /** * @inheritDoc */ public function supports(string $format, ?string $sourceType) : bool { return isset(static::$formats[$format]) && $this->compressionAvailable(); } private function compressionAvailable() : bool { return \class_exists('ZipArchive'); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; /** * @author Jordi Boggiano */ class CompleteAliasPackage extends \Composer\Package\AliasPackage implements \Composer\Package\CompletePackageInterface { /** @var CompletePackage */ protected $aliasOf; /** * All descendants' constructors should call this parent constructor * * @param CompletePackage $aliasOf The package this package is an alias of * @param string $version The version the alias must report * @param string $prettyVersion The alias's non-normalized version */ public function __construct(\Composer\Package\CompletePackage $aliasOf, string $version, string $prettyVersion) { parent::__construct($aliasOf, $version, $prettyVersion); } /** * @return CompletePackage */ public function getAliasOf() { return $this->aliasOf; } public function getScripts() : array { return $this->aliasOf->getScripts(); } public function setScripts(array $scripts) : void { $this->aliasOf->setScripts($scripts); } public function getRepositories() : array { return $this->aliasOf->getRepositories(); } public function setRepositories(array $repositories) : void { $this->aliasOf->setRepositories($repositories); } public function getLicense() : array { return $this->aliasOf->getLicense(); } public function setLicense(array $license) : void { $this->aliasOf->setLicense($license); } public function getKeywords() : array { return $this->aliasOf->getKeywords(); } public function setKeywords(array $keywords) : void { $this->aliasOf->setKeywords($keywords); } public function getDescription() : ?string { return $this->aliasOf->getDescription(); } public function setDescription(?string $description) : void { $this->aliasOf->setDescription($description); } public function getHomepage() : ?string { return $this->aliasOf->getHomepage(); } public function setHomepage(?string $homepage) : void { $this->aliasOf->setHomepage($homepage); } public function getAuthors() : array { return $this->aliasOf->getAuthors(); } public function setAuthors(array $authors) : void { $this->aliasOf->setAuthors($authors); } public function getSupport() : array { return $this->aliasOf->getSupport(); } public function setSupport(array $support) : void { $this->aliasOf->setSupport($support); } public function getFunding() : array { return $this->aliasOf->getFunding(); } public function setFunding(array $funding) : void { $this->aliasOf->setFunding($funding); } public function isAbandoned() : bool { return $this->aliasOf->isAbandoned(); } public function getReplacementPackage() : ?string { return $this->aliasOf->getReplacementPackage(); } public function setAbandoned($abandoned) : void { $this->aliasOf->setAbandoned($abandoned); } public function getArchiveName() : ?string { return $this->aliasOf->getArchiveName(); } public function setArchiveName(?string $name) : void { $this->aliasOf->setArchiveName($name); } public function getArchiveExcludes() : array { return $this->aliasOf->getArchiveExcludes(); } public function setArchiveExcludes(array $excludes) : void { $this->aliasOf->setArchiveExcludes($excludes); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; use Composer\Semver\Constraint\Constraint; use Composer\Package\Version\VersionParser; /** * @author Jordi Boggiano */ class AliasPackage extends \Composer\Package\BasePackage { /** @var string */ protected $version; /** @var string */ protected $prettyVersion; /** @var bool */ protected $dev; /** @var bool */ protected $rootPackageAlias = \false; /** * @var string * @phpstan-var 'stable'|'RC'|'beta'|'alpha'|'dev' */ protected $stability; /** @var bool */ protected $hasSelfVersionRequires = \false; /** @var BasePackage */ protected $aliasOf; /** @var Link[] */ protected $requires; /** @var Link[] */ protected $devRequires; /** @var Link[] */ protected $conflicts; /** @var Link[] */ protected $provides; /** @var Link[] */ protected $replaces; /** * All descendants' constructors should call this parent constructor * * @param BasePackage $aliasOf The package this package is an alias of * @param string $version The version the alias must report * @param string $prettyVersion The alias's non-normalized version */ public function __construct(\Composer\Package\BasePackage $aliasOf, string $version, string $prettyVersion) { parent::__construct($aliasOf->getName()); $this->version = $version; $this->prettyVersion = $prettyVersion; $this->aliasOf = $aliasOf; $this->stability = VersionParser::parseStability($version); $this->dev = $this->stability === 'dev'; foreach (\Composer\Package\Link::$TYPES as $type) { $links = $aliasOf->{'get' . \ucfirst($type)}(); $this->{$type} = $this->replaceSelfVersionDependencies($links, $type); } } /** * @return BasePackage */ public function getAliasOf() { return $this->aliasOf; } /** * @inheritDoc */ public function getVersion() : string { return $this->version; } /** * @inheritDoc */ public function getStability() : string { return $this->stability; } /** * @inheritDoc */ public function getPrettyVersion() : string { return $this->prettyVersion; } /** * @inheritDoc */ public function isDev() : bool { return $this->dev; } /** * @inheritDoc */ public function getRequires() : array { return $this->requires; } /** * @inheritDoc * @return array */ public function getConflicts() : array { return $this->conflicts; } /** * @inheritDoc * @return array */ public function getProvides() : array { return $this->provides; } /** * @inheritDoc * @return array */ public function getReplaces() : array { return $this->replaces; } /** * @inheritDoc */ public function getDevRequires() : array { return $this->devRequires; } /** * Stores whether this is an alias created by an aliasing in the requirements of the root package or not * * Use by the policy for sorting manually aliased packages first, see #576 */ public function setRootPackageAlias(bool $value) : void { $this->rootPackageAlias = $value; } /** * @see setRootPackageAlias */ public function isRootPackageAlias() : bool { return $this->rootPackageAlias; } /** * @param Link[] $links * @param Link::TYPE_* $linkType * * @return Link[] */ protected function replaceSelfVersionDependencies(array $links, $linkType) : array { // for self.version requirements, we use the original package's branch name instead, to avoid leaking the magic dev-master-alias to users $prettyVersion = $this->prettyVersion; if ($prettyVersion === VersionParser::DEFAULT_BRANCH_ALIAS) { $prettyVersion = $this->aliasOf->getPrettyVersion(); } if (\in_array($linkType, [\Composer\Package\Link::TYPE_CONFLICT, \Composer\Package\Link::TYPE_PROVIDE, \Composer\Package\Link::TYPE_REPLACE], \true)) { $newLinks = []; foreach ($links as $link) { // link is self.version, but must be replacing also the replaced version if ('self.version' === $link->getPrettyConstraint()) { $newLinks[] = new \Composer\Package\Link($link->getSource(), $link->getTarget(), $constraint = new Constraint('=', $this->version), $linkType, $prettyVersion); $constraint->setPrettyString($prettyVersion); } } $links = \array_merge($links, $newLinks); } else { foreach ($links as $index => $link) { if ('self.version' === $link->getPrettyConstraint()) { if ($linkType === \Composer\Package\Link::TYPE_REQUIRE) { $this->hasSelfVersionRequires = \true; } $links[$index] = new \Composer\Package\Link($link->getSource(), $link->getTarget(), $constraint = new Constraint('=', $this->version), $linkType, $prettyVersion); $constraint->setPrettyString($prettyVersion); } } } return $links; } public function hasSelfVersionRequires() : bool { return $this->hasSelfVersionRequires; } public function __toString() : string { return parent::__toString() . ' (' . ($this->rootPackageAlias ? 'root ' : '') . 'alias of ' . $this->aliasOf->getVersion() . ')'; } /*************************************** * Wrappers around the aliased package * ***************************************/ public function getType() : string { return $this->aliasOf->getType(); } public function getTargetDir() : ?string { return $this->aliasOf->getTargetDir(); } public function getExtra() : array { return $this->aliasOf->getExtra(); } public function setInstallationSource(?string $type) : void { $this->aliasOf->setInstallationSource($type); } public function getInstallationSource() : ?string { return $this->aliasOf->getInstallationSource(); } public function getSourceType() : ?string { return $this->aliasOf->getSourceType(); } public function getSourceUrl() : ?string { return $this->aliasOf->getSourceUrl(); } public function getSourceUrls() : array { return $this->aliasOf->getSourceUrls(); } public function getSourceReference() : ?string { return $this->aliasOf->getSourceReference(); } public function setSourceReference(?string $reference) : void { $this->aliasOf->setSourceReference($reference); } public function setSourceMirrors(?array $mirrors) : void { $this->aliasOf->setSourceMirrors($mirrors); } public function getSourceMirrors() : ?array { return $this->aliasOf->getSourceMirrors(); } public function getDistType() : ?string { return $this->aliasOf->getDistType(); } public function getDistUrl() : ?string { return $this->aliasOf->getDistUrl(); } public function getDistUrls() : array { return $this->aliasOf->getDistUrls(); } public function getDistReference() : ?string { return $this->aliasOf->getDistReference(); } public function setDistReference(?string $reference) : void { $this->aliasOf->setDistReference($reference); } public function getDistSha1Checksum() : ?string { return $this->aliasOf->getDistSha1Checksum(); } public function setTransportOptions(array $options) : void { $this->aliasOf->setTransportOptions($options); } public function getTransportOptions() : array { return $this->aliasOf->getTransportOptions(); } public function setDistMirrors(?array $mirrors) : void { $this->aliasOf->setDistMirrors($mirrors); } public function getDistMirrors() : ?array { return $this->aliasOf->getDistMirrors(); } public function getAutoload() : array { return $this->aliasOf->getAutoload(); } public function getDevAutoload() : array { return $this->aliasOf->getDevAutoload(); } public function getIncludePaths() : array { return $this->aliasOf->getIncludePaths(); } public function getPhpExt() : ?array { return $this->aliasOf->getPhpExt(); } public function getReleaseDate() : ?\DateTimeInterface { return $this->aliasOf->getReleaseDate(); } public function getBinaries() : array { return $this->aliasOf->getBinaries(); } public function getSuggests() : array { return $this->aliasOf->getSuggests(); } public function getNotificationUrl() : ?string { return $this->aliasOf->getNotificationUrl(); } public function isDefaultBranch() : bool { return $this->aliasOf->isDefaultBranch(); } public function setDistUrl(?string $url) : void { $this->aliasOf->setDistUrl($url); } public function setDistType(?string $type) : void { $this->aliasOf->setDistType($type); } public function setSourceDistReferences(string $reference) : void { $this->aliasOf->setSourceDistReferences($reference); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; use Composer\Json\JsonFile; use Composer\Installer\InstallationManager; use Composer\Pcre\Preg; use Composer\Repository\InstalledRepository; use Composer\Repository\LockArrayRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RootPackageRepository; use Composer\Util\ProcessExecutor; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Version\VersionParser; use Composer\Plugin\PluginInterface; use Composer\Util\Git as GitUtil; use Composer\IO\IOInterface; use _ContaoManager\Seld\JsonLint\ParsingException; /** * Reads/writes project lockfile (composer.lock). * * @author Konstantin Kudryashiv * @author Jordi Boggiano */ class Locker { /** @var JsonFile */ private $lockFile; /** @var InstallationManager */ private $installationManager; /** @var string */ private $hash; /** @var string */ private $contentHash; /** @var ArrayLoader */ private $loader; /** @var ArrayDumper */ private $dumper; /** @var ProcessExecutor */ private $process; /** @var mixed[]|null */ private $lockDataCache = null; /** @var bool */ private $virtualFileWritten = \false; /** * Initializes packages locker. * * @param JsonFile $lockFile lockfile loader * @param InstallationManager $installationManager installation manager instance * @param string $composerFileContents The contents of the composer file */ public function __construct(IOInterface $io, JsonFile $lockFile, InstallationManager $installationManager, string $composerFileContents, ?ProcessExecutor $process = null) { $this->lockFile = $lockFile; $this->installationManager = $installationManager; $this->hash = \hash('md5', $composerFileContents); $this->contentHash = self::getContentHash($composerFileContents); $this->loader = new ArrayLoader(null, \true); $this->dumper = new ArrayDumper(); $this->process = $process ?? new ProcessExecutor($io); } /** * @internal */ public function getJsonFile() : JsonFile { return $this->lockFile; } /** * Returns the md5 hash of the sorted content of the composer file. * * @param string $composerFileContents The contents of the composer file. */ public static function getContentHash(string $composerFileContents) : string { $content = JsonFile::parseJson($composerFileContents, 'composer.json'); $relevantKeys = ['name', 'version', 'require', 'require-dev', 'conflict', 'replace', 'provide', 'minimum-stability', 'prefer-stable', 'repositories', 'extra']; $relevantContent = []; foreach (\array_intersect($relevantKeys, \array_keys($content)) as $key) { $relevantContent[$key] = $content[$key]; } if (isset($content['config']['platform'])) { $relevantContent['config']['platform'] = $content['config']['platform']; } \ksort($relevantContent); return \hash('md5', JsonFile::encode($relevantContent, 0)); } /** * Checks whether locker has been locked (lockfile found). */ public function isLocked() : bool { if (!$this->virtualFileWritten && !$this->lockFile->exists()) { return \false; } $data = $this->getLockData(); return isset($data['packages']); } /** * Checks whether the lock file is still up to date with the current hash */ public function isFresh() : bool { $lock = $this->lockFile->read(); if (!empty($lock['content-hash'])) { // There is a content hash key, use that instead of the file hash return $this->contentHash === $lock['content-hash']; } // BC support for old lock files without content-hash if (!empty($lock['hash'])) { return $this->hash === $lock['hash']; } // should not be reached unless the lock file is corrupted, so assume it's out of date return \false; } /** * Searches and returns an array of locked packages, retrieved from registered repositories. * * @param bool $withDevReqs true to retrieve the locked dev packages * @throws \RuntimeException */ public function getLockedRepository(bool $withDevReqs = \false) : LockArrayRepository { $lockData = $this->getLockData(); $packages = new LockArrayRepository(); $lockedPackages = $lockData['packages']; if ($withDevReqs) { if (isset($lockData['packages-dev'])) { $lockedPackages = \array_merge($lockedPackages, $lockData['packages-dev']); } else { throw new \RuntimeException('The lock file does not contain require-dev information, run install with the --no-dev option or delete it and run composer update to generate a new lock file.'); } } if (empty($lockedPackages)) { return $packages; } if (isset($lockedPackages[0]['name'])) { $packageByName = []; foreach ($lockedPackages as $info) { $package = $this->loader->load($info); $packages->addPackage($package); $packageByName[$package->getName()] = $package; if ($package instanceof \Composer\Package\AliasPackage) { $packageByName[$package->getAliasOf()->getName()] = $package->getAliasOf(); } } if (isset($lockData['aliases'])) { foreach ($lockData['aliases'] as $alias) { if (isset($packageByName[$alias['package']])) { $aliasPkg = new \Composer\Package\CompleteAliasPackage($packageByName[$alias['package']], $alias['alias_normalized'], $alias['alias']); $aliasPkg->setRootPackageAlias(\true); $packages->addPackage($aliasPkg); } } } return $packages; } throw new \RuntimeException('Your composer.lock is invalid. Run "composer update" to generate a new one.'); } /** * @return string[] Names of dependencies installed through require-dev */ public function getDevPackageNames() : array { $names = []; $lockData = $this->getLockData(); if (isset($lockData['packages-dev'])) { foreach ($lockData['packages-dev'] as $package) { $names[] = \strtolower($package['name']); } } return $names; } /** * Returns the platform requirements stored in the lock file * * @param bool $withDevReqs if true, the platform requirements from the require-dev block are also returned * @return \Composer\Package\Link[] */ public function getPlatformRequirements(bool $withDevReqs = \false) : array { $lockData = $this->getLockData(); $requirements = []; if (!empty($lockData['platform'])) { $requirements = $this->loader->parseLinks('__root__', '1.0.0', \Composer\Package\Link::TYPE_REQUIRE, $lockData['platform'] ?? []); } if ($withDevReqs && !empty($lockData['platform-dev'])) { $devRequirements = $this->loader->parseLinks('__root__', '1.0.0', \Composer\Package\Link::TYPE_REQUIRE, $lockData['platform-dev'] ?? []); $requirements = \array_merge($requirements, $devRequirements); } return $requirements; } /** * @return key-of */ public function getMinimumStability() : string { $lockData = $this->getLockData(); return $lockData['minimum-stability'] ?? 'stable'; } /** * @return array */ public function getStabilityFlags() : array { $lockData = $this->getLockData(); return $lockData['stability-flags'] ?? []; } public function getPreferStable() : ?bool { $lockData = $this->getLockData(); // return null if not set to allow caller logic to choose the // right behavior since old lock files have no prefer-stable return $lockData['prefer-stable'] ?? null; } public function getPreferLowest() : ?bool { $lockData = $this->getLockData(); // return null if not set to allow caller logic to choose the // right behavior since old lock files have no prefer-lowest return $lockData['prefer-lowest'] ?? null; } /** * @return array */ public function getPlatformOverrides() : array { $lockData = $this->getLockData(); return $lockData['platform-overrides'] ?? []; } /** * @return string[][] * * @phpstan-return list */ public function getAliases() : array { $lockData = $this->getLockData(); return $lockData['aliases'] ?? []; } /** * @return string */ public function getPluginApi() { $lockData = $this->getLockData(); return $lockData['plugin-api-version'] ?? '1.1.0'; } /** * @return array */ public function getLockData() : array { if (null !== $this->lockDataCache) { return $this->lockDataCache; } if (!$this->lockFile->exists()) { throw new \LogicException('No lockfile found. Unable to read locked packages'); } return $this->lockDataCache = $this->lockFile->read(); } /** * Locks provided data into lockfile. * * @param PackageInterface[] $packages array of packages * @param PackageInterface[]|null $devPackages array of dev packages or null if installed without --dev * @param array $platformReqs array of package name => constraint for required platform packages * @param array $platformDevReqs array of package name => constraint for dev-required platform packages * @param string[][] $aliases array of aliases * @param array $stabilityFlags * @param array $platformOverrides * @param bool $write Whether to actually write data to disk, useful in tests and for --dry-run * * @phpstan-param list $aliases */ public function setLockData(array $packages, ?array $devPackages, array $platformReqs, array $platformDevReqs, array $aliases, string $minimumStability, array $stabilityFlags, bool $preferStable, bool $preferLowest, array $platformOverrides, bool $write = \true) : bool { // keep old default branch names normalized to DEFAULT_BRANCH_ALIAS for BC as that is how Composer 1 outputs the lock file // when loading the lock file the version is anyway ignored in Composer 2, so it has no adverse effect $aliases = \array_map(static function ($alias) : array { if (\in_array($alias['version'], ['dev-master', 'dev-trunk', 'dev-default'], \true)) { $alias['version'] = VersionParser::DEFAULT_BRANCH_ALIAS; } return $alias; }, $aliases); $lock = ['_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 @gener' . 'ated automatically'], 'content-hash' => $this->contentHash, 'packages' => $this->lockPackages($packages), 'packages-dev' => null, 'aliases' => $aliases, 'minimum-stability' => $minimumStability, 'stability-flags' => $stabilityFlags, 'prefer-stable' => $preferStable, 'prefer-lowest' => $preferLowest]; if (null !== $devPackages) { $lock['packages-dev'] = $this->lockPackages($devPackages); } $lock['platform'] = $platformReqs; $lock['platform-dev'] = $platformDevReqs; if (\count($platformOverrides) > 0) { $lock['platform-overrides'] = $platformOverrides; } $lock['plugin-api-version'] = PluginInterface::PLUGIN_API_VERSION; $lock = $this->fixupJsonDataType($lock); try { $isLocked = $this->isLocked(); } catch (ParsingException $e) { $isLocked = \false; } if (!$isLocked || $lock !== $this->getLockData()) { if ($write) { $this->lockFile->write($lock); $this->lockDataCache = null; $this->virtualFileWritten = \false; } else { $this->virtualFileWritten = \true; $this->lockDataCache = JsonFile::parseJson(JsonFile::encode($lock)); } return \true; } return \false; } /** * Updates the lock file's hash in-place from a given composer.json's JsonFile * * This does not reload or require any packages, and retains the filemtime of the lock file. * * Use this only to update the lock file hash after updating a composer.json in ways that are guaranteed NOT to impact the dependency resolution. * * This is a risky method, use carefully. * * @param (callable(array): array)|null $dataProcessor Receives the lock data and can process it before it gets written to disk */ public function updateHash(JsonFile $composerJson, ?callable $dataProcessor = null) : void { $contents = \file_get_contents($composerJson->getPath()); if (\false === $contents) { throw new \RuntimeException('Unable to read ' . $composerJson->getPath() . ' contents to update the lock file hash.'); } $lockMtime = \filemtime($this->lockFile->getPath()); $lockData = $this->lockFile->read(); $lockData['content-hash'] = \Composer\Package\Locker::getContentHash($contents); if ($dataProcessor !== null) { $lockData = $dataProcessor($lockData); } $this->lockFile->write($this->fixupJsonDataType($lockData)); $this->lockDataCache = null; $this->virtualFileWritten = \false; if (\is_int($lockMtime)) { @\touch($this->lockFile->getPath(), $lockMtime); } } /** * Ensures correct data types and ordering for the JSON lock format * * @param array $lockData * @return array */ private function fixupJsonDataType(array $lockData) : array { foreach (['stability-flags', 'platform', 'platform-dev'] as $key) { if (isset($lockData[$key]) && \is_array($lockData[$key]) && \count($lockData[$key]) === 0) { $lockData[$key] = new \stdClass(); } } if (\is_array($lockData['stability-flags'])) { \ksort($lockData['stability-flags']); } return $lockData; } /** * @param PackageInterface[] $packages * * @return mixed[][] * * @phpstan-return list> */ private function lockPackages(array $packages) : array { $locked = []; foreach ($packages as $package) { if ($package instanceof \Composer\Package\AliasPackage) { continue; } $name = $package->getPrettyName(); $version = $package->getPrettyVersion(); if (!$name || !$version) { throw new \LogicException(\sprintf('Package "%s" has no version or name and can not be locked', $package)); } $spec = $this->dumper->dump($package); unset($spec['version_normalized']); // always move time to the end of the package definition $time = $spec['time'] ?? null; unset($spec['time']); if ($package->isDev() && $package->getInstallationSource() === 'source') { // use the exact commit time of the current reference if it's a dev package $time = $this->getPackageTime($package) ?: $time; } if (null !== $time) { $spec['time'] = $time; } unset($spec['installation-source']); $locked[] = $spec; } \usort($locked, static function ($a, $b) { $comparison = \strcmp($a['name'], $b['name']); if (0 !== $comparison) { return $comparison; } // If it is the same package, compare the versions to make the order deterministic return \strcmp($a['version'], $b['version']); }); return $locked; } /** * Returns the packages's datetime for its source reference. * * @param PackageInterface $package The package to scan. * @return string|null The formatted datetime or null if none was found. */ private function getPackageTime(\Composer\Package\PackageInterface $package) : ?string { if (!\function_exists('proc_open')) { return null; } $path = $this->installationManager->getInstallPath($package); if ($path === null) { return null; } $path = \realpath($path); $sourceType = $package->getSourceType(); $datetime = null; if ($path && \in_array($sourceType, ['git', 'hg'])) { $sourceRef = $package->getSourceReference() ?: $package->getDistReference(); switch ($sourceType) { case 'git': GitUtil::cleanEnv(); $command = \array_merge(['git', 'log', '-n1', '--pretty=%ct', (string) $sourceRef], GitUtil::getNoShowSignatureFlags($this->process)); if (0 === $this->process->execute($command, $output, $path) && Preg::isMatch('{^\\s*\\d+\\s*$}', $output)) { $datetime = new \DateTime('@' . \trim($output), new \DateTimeZone('UTC')); } break; case 'hg': if (0 === $this->process->execute(['hg', 'log', '--template', '{date|hgdate}', '-r', (string) $sourceRef], $output, $path) && Preg::isMatch('{^\\s*(\\d+)\\s*}', $output, $match)) { $datetime = new \DateTime('@' . $match[1], new \DateTimeZone('UTC')); } break; } } return $datetime ? $datetime->format(\DATE_RFC3339) : null; } /** * @return array */ public function getMissingRequirementInfo(\Composer\Package\RootPackageInterface $package, bool $includeDev) : array { $missingRequirementInfo = []; $missingRequirements = \false; $sets = [['repo' => $this->getLockedRepository(\false), 'method' => 'getRequires', 'description' => 'Required']]; if ($includeDev === \true) { $sets[] = ['repo' => $this->getLockedRepository(\true), 'method' => 'getDevRequires', 'description' => 'Required (in require-dev)']; } $rootRepo = new RootPackageRepository(clone $package); foreach ($sets as $set) { $installedRepo = new InstalledRepository([$set['repo'], $rootRepo]); foreach (\call_user_func([$package, $set['method']]) as $link) { if (PlatformRepository::isPlatformPackage($link->getTarget())) { continue; } if ($link->getPrettyConstraint() === 'self.version') { continue; } if ($installedRepo->findPackagesWithReplacersAndProviders($link->getTarget(), $link->getConstraint()) === []) { $results = $installedRepo->findPackagesWithReplacersAndProviders($link->getTarget()); if ($results !== []) { $provider = \reset($results); $description = $provider->getPrettyVersion(); if ($provider->getName() !== $link->getTarget()) { foreach (['getReplaces' => 'replaced as %s by %s', 'getProvides' => 'provided as %s by %s'] as $method => $text) { foreach (\call_user_func([$provider, $method]) as $providerLink) { if ($providerLink->getTarget() === $link->getTarget()) { $description = \sprintf($text, $providerLink->getPrettyConstraint(), $provider->getPrettyName() . ' ' . $provider->getPrettyVersion()); break 2; } } } } $missingRequirementInfo[] = '- ' . $set['description'] . ' package "' . $link->getTarget() . '" is in the lock file as "' . $description . '" but that does not satisfy your constraint "' . $link->getPrettyConstraint() . '".'; } else { $missingRequirementInfo[] = '- ' . $set['description'] . ' package "' . $link->getTarget() . '" is not present in the lock file.'; } $missingRequirements = \true; } } } if ($missingRequirements) { $missingRequirementInfo[] = 'This usually happens when composer files are incorrectly merged or the composer.json file is manually edited.'; $missingRequirementInfo[] = 'Read more about correctly resolving merge conflicts https://getcomposer.org/doc/articles/resolving-merge-conflicts.md'; $missingRequirementInfo[] = 'and prefer using the "require" command over editing the composer.json file directly https://getcomposer.org/doc/03-cli.md#require-r'; } return $missingRequirementInfo; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; use Composer\Repository\RepositoryInterface; /** * Defines the essential information a package has that is used during solving/installation * * PackageInterface & derivatives are considered internal, you may use them in type hints but extending/implementing them is not recommended and not supported. Things may change without notice. * * @author Jordi Boggiano * * @phpstan-type AutoloadRules array{psr-0?: array, psr-4?: array, classmap?: list, files?: list, exclude-from-classmap?: list} * @phpstan-type DevAutoloadRules array{psr-0?: array, psr-4?: array, classmap?: list, files?: list} * @phpstan-type PhpExtConfig array{extension-name?: string, priority?: int, support-zts?: bool, support-nts?: bool, build-path?: string|null, os-families?: non-empty-list, os-families-exclude?: non-empty-list, configure-options?: list} */ interface PackageInterface { public const DISPLAY_SOURCE_REF_IF_DEV = 0; public const DISPLAY_SOURCE_REF = 1; public const DISPLAY_DIST_REF = 2; /** * Returns the package's name without version info, thus not a unique identifier * * @return string package name */ public function getName() : string; /** * Returns the package's pretty (i.e. with proper case) name * * @return string package name */ public function getPrettyName() : string; /** * Returns a set of names that could refer to this package * * No version or release type information should be included in any of the * names. Provided or replaced package names need to be returned as well. * * @param bool $provides Whether provided names should be included * * @return string[] An array of strings referring to this package */ public function getNames(bool $provides = \true) : array; /** * Allows the solver to set an id for this package to refer to it. */ public function setId(int $id) : void; /** * Retrieves the package's id set through setId * * @return int The previously set package id */ public function getId() : int; /** * Returns whether the package is a development virtual package or a concrete one */ public function isDev() : bool; /** * Returns the package type, e.g. library * * @return string The package type */ public function getType() : string; /** * Returns the package targetDir property * * @return ?string The package targetDir */ public function getTargetDir() : ?string; /** * Returns the package extra data * * @return mixed[] The package extra data */ public function getExtra() : array; /** * Sets source from which this package was installed (source/dist). * * @param ?string $type source/dist * @phpstan-param 'source'|'dist'|null $type */ public function setInstallationSource(?string $type) : void; /** * Returns source from which this package was installed (source/dist). * * @return ?string source/dist * @phpstan-return 'source'|'dist'|null */ public function getInstallationSource() : ?string; /** * Returns the repository type of this package, e.g. git, svn * * @return ?string The repository type */ public function getSourceType() : ?string; /** * Returns the repository url of this package, e.g. git://github.com/naderman/composer.git * * @return ?string The repository url */ public function getSourceUrl() : ?string; /** * Returns the repository urls of this package including mirrors, e.g. git://github.com/naderman/composer.git * * @return list */ public function getSourceUrls() : array; /** * Returns the repository reference of this package, e.g. master, 1.0.0 or a commit hash for git * * @return ?string The repository reference */ public function getSourceReference() : ?string; /** * Returns the source mirrors of this package * * @return ?list */ public function getSourceMirrors() : ?array; /** * @param null|list $mirrors */ public function setSourceMirrors(?array $mirrors) : void; /** * Returns the type of the distribution archive of this version, e.g. zip, tarball * * @return ?string The repository type */ public function getDistType() : ?string; /** * Returns the url of the distribution archive of this version * * @return ?non-empty-string */ public function getDistUrl() : ?string; /** * Returns the urls of the distribution archive of this version, including mirrors * * @return non-empty-string[] */ public function getDistUrls() : array; /** * Returns the reference of the distribution archive of this version, e.g. master, 1.0.0 or a commit hash for git * * @return ?string */ public function getDistReference() : ?string; /** * Returns the sha1 checksum for the distribution archive of this version * * Can be an empty string which should be treated as null * * @return ?string */ public function getDistSha1Checksum() : ?string; /** * Returns the dist mirrors of this package * * @return ?list */ public function getDistMirrors() : ?array; /** * @param null|list $mirrors */ public function setDistMirrors(?array $mirrors) : void; /** * Returns the version of this package * * @return string version */ public function getVersion() : string; /** * Returns the pretty (i.e. non-normalized) version string of this package * * @return string version */ public function getPrettyVersion() : string; /** * Returns the pretty version string plus a git or hg commit hash of this package * * @see getPrettyVersion * * @param bool $truncate If the source reference is a sha1 hash, truncate it * @param int $displayMode One of the DISPLAY_ constants on this interface determining display of references * @return string version * * @phpstan-param self::DISPLAY_SOURCE_REF_IF_DEV|self::DISPLAY_SOURCE_REF|self::DISPLAY_DIST_REF $displayMode */ public function getFullPrettyVersion(bool $truncate = \true, int $displayMode = self::DISPLAY_SOURCE_REF_IF_DEV) : string; /** * Returns the release date of the package * * @return ?\DateTimeInterface */ public function getReleaseDate() : ?\DateTimeInterface; /** * Returns the stability of this package: one of (dev, alpha, beta, RC, stable) * * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev' */ public function getStability() : string; /** * Returns a set of links to packages which need to be installed before * this package can be installed * * @return array A map of package links defining required packages, indexed by the require package's name */ public function getRequires() : array; /** * Returns a set of links to packages which must not be installed at the * same time as this package * * @return Link[] An array of package links defining conflicting packages */ public function getConflicts() : array; /** * Returns a set of links to virtual packages that are provided through * this package * * @return Link[] An array of package links defining provided packages */ public function getProvides() : array; /** * Returns a set of links to packages which can alternatively be * satisfied by installing this package * * @return Link[] An array of package links defining replaced packages */ public function getReplaces() : array; /** * Returns a set of links to packages which are required to develop * this package. These are installed if in dev mode. * * @return array A map of package links defining packages required for development, indexed by the require package's name */ public function getDevRequires() : array; /** * Returns a set of package names and reasons why they are useful in * combination with this package. * * @return array An array of package suggestions with descriptions * @phpstan-return array */ public function getSuggests() : array; /** * Returns an associative array of autoloading rules * * {"": {""}} * * Type is either "psr-4", "psr-0", "classmap" or "files". Namespaces are mapped to * directories for autoloading using the type specified. * * @return array Mapping of autoloading rules * @phpstan-return AutoloadRules */ public function getAutoload() : array; /** * Returns an associative array of dev autoloading rules * * {"": {""}} * * Type is either "psr-4", "psr-0", "classmap" or "files". Namespaces are mapped to * directories for autoloading using the type specified. * * @return array Mapping of dev autoloading rules * @phpstan-return DevAutoloadRules */ public function getDevAutoload() : array; /** * Returns a list of directories which should get added to PHP's * include path. * * @return string[] */ public function getIncludePaths() : array; /** * Returns the settings for php extension packages * * @return array|null * * @phpstan-return PhpExtConfig|null */ public function getPhpExt() : ?array; /** * Stores a reference to the repository that owns the package */ public function setRepository(RepositoryInterface $repository) : void; /** * Returns a reference to the repository that owns the package * * @return ?RepositoryInterface */ public function getRepository() : ?RepositoryInterface; /** * Returns the package binaries * * @return string[] */ public function getBinaries() : array; /** * Returns package unique name, constructed from name and version. */ public function getUniqueName() : string; /** * Returns the package notification url * * @return ?string */ public function getNotificationUrl() : ?string; /** * Converts the package into a readable and unique string */ public function __toString() : string; /** * Converts the package into a pretty readable string */ public function getPrettyString() : string; public function isDefaultBranch() : bool; /** * Returns a list of options to download package dist files * * @return mixed[] */ public function getTransportOptions() : array; /** * Configures the list of options to download package dist files * * @param mixed[] $options */ public function setTransportOptions(array $options) : void; public function setSourceReference(?string $reference) : void; public function setDistUrl(?string $url) : void; public function setDistType(?string $type) : void; public function setDistReference(?string $reference) : void; /** * Set dist and source references and update dist URL for ones that contain a reference */ public function setSourceDistReferences(string $reference) : void; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Version; use Composer\Package\PackageInterface; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; use Composer\Pcre\Preg; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Intervals; use Composer\Util\Platform; /** * @author Jordi Boggiano * @internal */ class VersionBumper { /** * Given a constraint, this returns a new constraint with * the lower bound bumped to match the given package's version. * * For example: * * ^1.0 + 1.2.1 -> ^1.2.1 * * ^1.2 + 1.2.0 -> ^1.2 * * ^1.2.0 + 1.3.0 -> ^1.3.0 * * ^1.2 || ^2.3 + 1.3.0 -> ^1.3 || ^2.3 * * ^1.2 || ^2.3 + 2.4.0 -> ^1.2 || ^2.4 * * ^3@dev + 3.2.99999-dev -> ^3.2@dev * * ~2 + 2.0-beta.1 -> ~2 * * ~2.0.0 + 2.0.3 -> ~2.0.3 * * ~2.0 + 2.0.3 -> ^2.0.3 * * dev-master + dev-master -> dev-master * * * + 1.2.3 -> >=1.2.3 */ public function bumpRequirement(ConstraintInterface $constraint, PackageInterface $package) : string { $parser = new \Composer\Package\Version\VersionParser(); $prettyConstraint = $constraint->getPrettyString(); if (\str_starts_with($constraint->getPrettyString(), 'dev-')) { return $prettyConstraint; } $version = $package->getVersion(); if (\str_starts_with($package->getVersion(), 'dev-')) { $loader = new ArrayLoader($parser); $dumper = new ArrayDumper(); $extra = $loader->getBranchAlias($dumper->dump($package)); // dev packages without branch alias cannot be processed if (null === $extra || $extra === \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS) { return $prettyConstraint; } $version = $extra; } $intervals = Intervals::get($constraint); // complex constraints with branch names are not bumped if (\count($intervals['branches']['names']) > 0) { return $prettyConstraint; } $major = Preg::replace('{^(\\d+).*}', '$1', $version); $versionWithoutSuffix = Preg::replace('{(?:\\.(?:0|9999999))+(-dev)?$}', '', $version); $newPrettyConstraint = '^' . $versionWithoutSuffix; // not a simple stable version, abort if (!Preg::isMatch('{^\\^\\d+(\\.\\d+)*$}', $newPrettyConstraint)) { return $prettyConstraint; } $pattern = '{ (?<=,|\\ |\\||^) # leading separator (?P \\^v?' . $major . '(?:\\.\\d+)* # e.g. ^2.anything | ~v?' . $major . '(?:\\.\\d+){1,3} # e.g. ~2.2 or ~2.2.2 or ~2.2.2.2 | v?' . $major . '(?:\\.[*x])+ # e.g. 2.* or 2.*.* or 2.x.x.x etc | >=v?\\d(?:\\.\\d+)* # e.g. >=2 or >=1.2 etc | \\* # full wildcard ) (?=,|$|\\ |\\||@) # trailing separator }x'; if (Preg::isMatchAllWithOffsets($pattern, $prettyConstraint, $matches)) { $modified = $prettyConstraint; foreach (\array_reverse($matches['constraint']) as $match) { \assert(\is_string($match[0])); $suffix = ''; if (\substr_count($match[0], '.') === 2 && \substr_count($versionWithoutSuffix, '.') === 1) { $suffix = '.0'; } if (\str_starts_with($match[0], '~') && \substr_count($match[0], '.') !== 1) { // take as many version bits from the current version as we have in the constraint to bump it without making it more specific $versionBits = \explode('.', $versionWithoutSuffix); $versionBits = \array_pad($versionBits, \substr_count($match[0], '.') + 1, '0'); $replacement = '~' . \implode('.', \array_slice($versionBits, 0, \substr_count($match[0], '.') + 1)); } elseif ($match[0] === '*' || \str_starts_with($match[0], '>=')) { $replacement = '>=' . $versionWithoutSuffix . $suffix; } else { $replacement = $newPrettyConstraint . $suffix; } $modified = \substr_replace($modified, $replacement, $match[1], Platform::strlen($match[0])); } // if it is strictly equal to the previous one then no need to change anything $newConstraint = $parser->parseConstraints($modified); if (Intervals::isSubsetOf($newConstraint, $constraint) && Intervals::isSubsetOf($constraint, $newConstraint)) { return $prettyConstraint; } return $modified; } return $prettyConstraint; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Version; use Composer\Package\BasePackage; /** * @author Jordi Boggiano */ class StabilityFilter { /** * Checks if any of the provided package names in the given stability match the configured acceptable stability and flags * * @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value * @phpstan-param array, BasePackage::STABILITY_*> $acceptableStabilities * @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value * @phpstan-param array $stabilityFlags * @param string[] $names The package name(s) to check for stability flags * @param key-of $stability one of 'stable', 'RC', 'beta', 'alpha' or 'dev' * @return bool true if any package name is acceptable */ public static function isPackageAcceptable(array $acceptableStabilities, array $stabilityFlags, array $names, string $stability) : bool { foreach ($names as $name) { // allow if package matches the package-specific stability flag if (isset($stabilityFlags[$name])) { if (BasePackage::STABILITIES[$stability] <= $stabilityFlags[$name]) { return \true; } } elseif (isset($acceptableStabilities[$stability])) { // allow if package matches the global stability requirement and has no exception return \true; } } return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Version; use Composer\Config; use Composer\IO\IOInterface; use Composer\Pcre\Preg; use Composer\Repository\Vcs\HgDriver; use Composer\IO\NullIO; use Composer\Semver\VersionParser as SemverVersionParser; use Composer\Util\Git as GitUtil; use Composer\Util\HttpDownloader; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Util\Svn as SvnUtil; use React\Promise\CancellablePromiseInterface; use _ContaoManager\Symfony\Component\Process\Process; /** * Try to guess the current version number based on different VCS configuration. * * @author Jordi Boggiano * @author Samuel Roze * * @phpstan-type Version array{version: string, commit: string|null, pretty_version: string|null}|array{version: string, commit: string|null, pretty_version: string|null, feature_version: string|null, feature_pretty_version: string|null} */ class VersionGuesser { /** * @var Config */ private $config; /** * @var ProcessExecutor */ private $process; /** * @var SemverVersionParser */ private $versionParser; /** * @var IOInterface|null */ private $io; public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser, ?IOInterface $io = null) { $this->config = $config; $this->process = $process; $this->versionParser = $versionParser; $this->io = $io; } /** * @param array $packageConfig * @param string $path Path to guess into * * @phpstan-return Version|null */ public function guessVersion(array $packageConfig, string $path) : ?array { if (!\function_exists('proc_open')) { return null; } // bypass version guessing in bash completions as it takes time to create // new processes and the root version is usually not that important if (Platform::isInputCompletionProcess()) { return null; } $versionData = $this->guessGitVersion($packageConfig, $path); if (null !== $versionData['version']) { return $this->postprocess($versionData); } $versionData = $this->guessHgVersion($packageConfig, $path); if (null !== $versionData && null !== $versionData['version']) { return $this->postprocess($versionData); } $versionData = $this->guessFossilVersion($path); if (null !== $versionData['version']) { return $this->postprocess($versionData); } $versionData = $this->guessSvnVersion($packageConfig, $path); if (null !== $versionData && null !== $versionData['version']) { return $this->postprocess($versionData); } return null; } /** * @phpstan-param Version $versionData * * @phpstan-return Version */ private function postprocess(array $versionData) : array { if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version'] && $versionData['feature_pretty_version'] === $versionData['pretty_version']) { unset($versionData['feature_version'], $versionData['feature_pretty_version']); } if ('-dev' === \substr($versionData['version'], -4) && Preg::isMatch('{\\.9{7}}', $versionData['version'])) { $versionData['pretty_version'] = Preg::replace('{(\\.9{7})+}', '.x', $versionData['version']); } if (!empty($versionData['feature_version']) && '-dev' === \substr($versionData['feature_version'], -4) && Preg::isMatch('{\\.9{7}}', $versionData['feature_version'])) { $versionData['feature_pretty_version'] = Preg::replace('{(\\.9{7})+}', '.x', $versionData['feature_version']); } return $versionData; } /** * @param array $packageConfig * * @return array{version: string|null, commit: string|null, pretty_version: string|null, feature_version?: string|null, feature_pretty_version?: string|null} */ private function guessGitVersion(array $packageConfig, string $path) : array { GitUtil::cleanEnv(); $commit = null; $version = null; $prettyVersion = null; $featureVersion = null; $featurePrettyVersion = null; $isDetached = \false; // try to fetch current version from git branch if (0 === $this->process->execute(['git', 'branch', '-a', '--no-color', '--no-abbrev', '-v'], $output, $path)) { $branches = []; $isFeatureBranch = \false; // find current branch and collect all branch names foreach ($this->process->splitLines($output) as $branch) { if ($branch && Preg::isMatchStrictGroups('{^(?:\\* ) *(\\(no branch\\)|\\(detached from \\S+\\)|\\(HEAD detached at \\S+\\)|\\S+) *([a-f0-9]+) .*$}', $branch, $match)) { if ($match[1] === '(no branch)' || \strpos($match[1], '(detached ') === 0 || \strpos($match[1], '(HEAD detached at') === 0) { $version = 'dev-' . $match[2]; $prettyVersion = $version; $isFeatureBranch = \true; $isDetached = \true; } else { $version = $this->versionParser->normalizeBranch($match[1]); $prettyVersion = 'dev-' . $match[1]; $isFeatureBranch = $this->isFeatureBranch($packageConfig, $match[1]); } $commit = $match[2]; } if ($branch && !Preg::isMatchStrictGroups('{^ *.+/HEAD }', $branch)) { if (Preg::isMatchStrictGroups('{^(?:\\* )? *((?:remotes/(?:origin|upstream)/)?[^\\s/]+) *([a-f0-9]+) .*$}', $branch, $match)) { $branches[] = $match[1]; } } } if ($isFeatureBranch) { $featureVersion = $version; $featurePrettyVersion = $prettyVersion; // try to find the best (nearest) version branch to assume this feature's version $result = $this->guessFeatureVersion($packageConfig, $version, $branches, ['git', 'rev-list', '%candidate%..%branch%'], $path); $version = $result['version']; $prettyVersion = $result['pretty_version']; } } GitUtil::checkForRepoOwnershipError($this->process->getErrorOutput(), $path, $this->io); if (!$version || $isDetached) { $result = $this->versionFromGitTags($path); if ($result) { $version = $result['version']; $prettyVersion = $result['pretty_version']; $featureVersion = null; $featurePrettyVersion = null; } } if (null === $commit) { $command = \array_merge(['git', 'log', '--pretty=%H', '-n1', 'HEAD'], GitUtil::getNoShowSignatureFlags($this->process)); if (0 === $this->process->execute($command, $output, $path)) { $commit = \trim($output) ?: null; } } if ($featureVersion) { return ['version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion, 'feature_version' => $featureVersion, 'feature_pretty_version' => $featurePrettyVersion]; } return ['version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion]; } /** * @return array{version: string, pretty_version: string}|null */ private function versionFromGitTags(string $path) : ?array { // try to fetch current version from git tags if (0 === $this->process->execute(['git', 'describe', '--exact-match', '--tags'], $output, $path)) { try { $version = $this->versionParser->normalize(\trim($output)); return ['version' => $version, 'pretty_version' => \trim($output)]; } catch (\Exception $e) { } } return null; } /** * @param array $packageConfig * * @return array{version: string|null, commit: ''|null, pretty_version: string|null, feature_version?: string|null, feature_pretty_version?: string|null}|null */ private function guessHgVersion(array $packageConfig, string $path) : ?array { // try to fetch current version from hg branch if (0 === $this->process->execute(['hg', 'branch'], $output, $path)) { $branch = \trim($output); $version = $this->versionParser->normalizeBranch($branch); $isFeatureBranch = 0 === \strpos($version, 'dev-'); if (\Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS === $version) { return ['version' => $version, 'commit' => null, 'pretty_version' => 'dev-' . $branch]; } if (!$isFeatureBranch) { return ['version' => $version, 'commit' => null, 'pretty_version' => $version]; } // re-use the HgDriver to fetch branches (this properly includes bookmarks) $io = new NullIO(); $driver = new HgDriver(['url' => $path], $io, $this->config, new HttpDownloader($io, $this->config), $this->process); $branches = \array_map('strval', \array_keys($driver->getBranches())); // try to find the best (nearest) version branch to assume this feature's version $result = $this->guessFeatureVersion($packageConfig, $version, $branches, ['hg', 'log', '-r', 'not ancestors(\'%candidate%\') and ancestors(\'%branch%\')', '--template', '"{node}\\n"'], $path); $result['commit'] = ''; $result['feature_version'] = $version; $result['feature_pretty_version'] = $version; return $result; } return null; } /** * @param array $packageConfig * @param list $branches * @param list $scmCmdline * * @return array{version: string|null, pretty_version: string|null} */ private function guessFeatureVersion(array $packageConfig, ?string $version, array $branches, array $scmCmdline, string $path) : array { $prettyVersion = $version; // ignore feature branches if they have no branch-alias or self.version is used // and find the branch they came from to use as a version instead if (!isset($packageConfig['extra']['branch-alias'][$version]) || \strpos(\json_encode($packageConfig), '"self.version"')) { $branch = Preg::replace('{^dev-}', '', $version); $length = \PHP_INT_MAX; // return directly, if branch is configured to be non-feature branch if (!$this->isFeatureBranch($packageConfig, $branch)) { return ['version' => $version, 'pretty_version' => $prettyVersion]; } // sort local branches first then remote ones // and sort numeric branches below named ones, to make sure if the branch has the same distance from main and 1.10 and 1.9 for example, 1.9 is picked // and sort using natural sort so that 1.10 will appear before 1.9 \usort($branches, static function ($a, $b) : int { $aRemote = 0 === \strpos($a, 'remotes/'); $bRemote = 0 === \strpos($b, 'remotes/'); if ($aRemote !== $bRemote) { return $aRemote ? 1 : -1; } return \strnatcasecmp($b, $a); }); $promises = []; $this->process->setMaxJobs(30); try { $lastIndex = -1; foreach ($branches as $index => $candidate) { $candidateVersion = Preg::replace('{^remotes/\\S+/}', '', $candidate); // do not compare against itself or other feature branches if ($candidate === $branch || $this->isFeatureBranch($packageConfig, $candidateVersion)) { continue; } $cmdLine = \array_map(static function (string $component) use($candidate, $branch) { return \str_replace(['%candidate%', '%branch%'], [$candidate, $branch], $component); }, $scmCmdline); $promises[] = $this->process->executeAsync($cmdLine, $path)->then(function (Process $process) use(&$lastIndex, $index, &$length, &$version, &$prettyVersion, $candidateVersion, &$promises) : void { if (!$process->isSuccessful()) { return; } $output = $process->getOutput(); // overwrite existing if we have a shorter diff, or we have an equal diff and an index that comes later in the array (i.e. older version) // as newer versions typically have more commits, if the feature branch is based on a newer branch it should have a longer diff to the old version // but if it doesn't and they have equal diffs, then it probably is based on the old version if (\strlen($output) < $length || \strlen($output) === $length && $lastIndex < $index) { $lastIndex = $index; $length = \strlen($output); $version = $this->versionParser->normalizeBranch($candidateVersion); $prettyVersion = 'dev-' . $candidateVersion; if ($length === 0) { foreach ($promises as $promise) { // to support react/promise 2.x we wrap the promise in a resolve() call for safety \React\Promise\resolve($promise)->cancel(); } } } }); } $this->process->wait(); } finally { $this->process->resetMaxJobs(); } } return ['version' => $version, 'pretty_version' => $prettyVersion]; } /** * @param array $packageConfig */ private function isFeatureBranch(array $packageConfig, ?string $branchName) : bool { $nonFeatureBranches = ''; if (!empty($packageConfig['non-feature-branches'])) { $nonFeatureBranches = \implode('|', $packageConfig['non-feature-branches']); } return !Preg::isMatch('{^(' . $nonFeatureBranches . '|master|main|latest|next|current|support|tip|trunk|default|develop|\\d+\\..+)$}', $branchName, $match); } /** * @return array{version: string|null, commit: '', pretty_version: string|null} */ private function guessFossilVersion(string $path) : array { $version = null; $prettyVersion = null; // try to fetch current version from fossil if (0 === $this->process->execute(['fossil', 'branch', 'list'], $output, $path)) { $branch = \trim($output); $version = $this->versionParser->normalizeBranch($branch); $prettyVersion = 'dev-' . $branch; } // try to fetch current version from fossil tags if (0 === $this->process->execute(['fossil', 'tag', 'list'], $output, $path)) { try { $version = $this->versionParser->normalize(\trim($output)); $prettyVersion = \trim($output); } catch (\Exception $e) { } } return ['version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion]; } /** * @param array $packageConfig * * @return array{version: string, commit: '', pretty_version: string}|null */ private function guessSvnVersion(array $packageConfig, string $path) : ?array { SvnUtil::cleanEnv(); // try to fetch current version from svn if (0 === $this->process->execute(['svn', 'info', '--xml'], $output, $path)) { $trunkPath = isset($packageConfig['trunk-path']) ? \preg_quote($packageConfig['trunk-path'], '#') : 'trunk'; $branchesPath = isset($packageConfig['branches-path']) ? \preg_quote($packageConfig['branches-path'], '#') : 'branches'; $tagsPath = isset($packageConfig['tags-path']) ? \preg_quote($packageConfig['tags-path'], '#') : 'tags'; $urlPattern = '#.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))#'; if (Preg::isMatch($urlPattern, $output, $matches)) { if (isset($matches[2], $matches[3]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) { // we are in a branches path $version = $this->versionParser->normalizeBranch($matches[3]); $prettyVersion = 'dev-' . $matches[3]; return ['version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion]; } \assert(\is_string($matches[1])); $prettyVersion = \trim($matches[1]); if ($prettyVersion === 'trunk') { $version = 'dev-trunk'; } else { $version = $this->versionParser->normalize($prettyVersion); } return ['version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion]; } } return null; } public function getRootVersionFromEnv() : string { $version = Platform::getEnv('COMPOSER_ROOT_VERSION'); if (!\is_string($version) || $version === '') { throw new \RuntimeException('COMPOSER_ROOT_VERSION not set or empty'); } if (Preg::isMatch('{^(\\d+(?:\\.\\d+)*)-dev$}i', $version, $match)) { $version = $match[1] . '.x-dev'; } return $version; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Version; use Composer\Filter\PlatformRequirementFilter\IgnoreAllPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\IgnoreListPlatformRequirementFilter; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterInterface; use Composer\IO\IOInterface; use Composer\Package\BasePackage; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Composer; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; use Composer\Pcre\Preg; use Composer\Repository\RepositorySet; use Composer\Repository\PlatformRepository; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; /** * Selects the best possible version for a package * * @author Ryan Weaver * @author Jordi Boggiano */ class VersionSelector { /** @var RepositorySet */ private $repositorySet; /** @var array */ private $platformConstraints = []; /** @var VersionParser */ private $parser; /** * @param PlatformRepository $platformRepo If passed in, the versions found will be filtered against their requirements to eliminate any not matching the current platform packages */ public function __construct(RepositorySet $repositorySet, ?PlatformRepository $platformRepo = null) { $this->repositorySet = $repositorySet; if ($platformRepo) { foreach ($platformRepo->getPackages() as $package) { $this->platformConstraints[$package->getName()][] = new Constraint('==', $package->getVersion()); } } } /** * Given a package name and optional version, returns the latest PackageInterface * that matches. * * @param string $targetPackageVersion * @param PlatformRequirementFilterInterface|bool|string[] $platformRequirementFilter * @param IOInterface|null $io If passed, warnings will be output there in case versions cannot be selected due to platform requirements * @param callable(PackageInterface):bool|bool $showWarnings * @return PackageInterface|false */ public function findBestCandidate(string $packageName, ?string $targetPackageVersion = null, string $preferredStability = 'stable', $platformRequirementFilter = null, int $repoSetFlags = 0, ?IOInterface $io = null, $showWarnings = \true) { if (!isset(BasePackage::STABILITIES[$preferredStability])) { // If you get this, maybe you are still relying on the Composer 1.x signature where the 3rd arg was the php version throw new \UnexpectedValueException('Expected a valid stability name as 3rd argument, got ' . $preferredStability); } if (null === $platformRequirementFilter) { $platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing(); } elseif (!$platformRequirementFilter instanceof PlatformRequirementFilterInterface) { \trigger_error('VersionSelector::findBestCandidate with ignored platform reqs as bool|array is deprecated since Composer 2.2, use an instance of PlatformRequirementFilterInterface instead.', \E_USER_DEPRECATED); $platformRequirementFilter = PlatformRequirementFilterFactory::fromBoolOrList($platformRequirementFilter); } $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null; $candidates = $this->repositorySet->findPackages(\strtolower($packageName), $constraint, $repoSetFlags); $minPriority = BasePackage::STABILITIES[$preferredStability]; \usort($candidates, static function (PackageInterface $a, PackageInterface $b) use($minPriority) { $aPriority = $a->getStabilityPriority(); $bPriority = $b->getStabilityPriority(); // A is less stable than our preferred stability, // and B is more stable than A, select B if ($minPriority < $aPriority && $bPriority < $aPriority) { return 1; } // A is less stable than our preferred stability, // and B is less stable than A, select A if ($minPriority < $aPriority && $aPriority < $bPriority) { return -1; } // A is more stable than our preferred stability, // and B is less stable than preferred stability, select A if ($minPriority >= $aPriority && $minPriority < $bPriority) { return -1; } // select highest version of the two return \version_compare($b->getVersion(), $a->getVersion()); }); if (\count($this->platformConstraints) > 0 && !$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter) { /** @var array $alreadyWarnedNames */ $alreadyWarnedNames = []; /** @var array $alreadySeenNames */ $alreadySeenNames = []; foreach ($candidates as $pkg) { $reqs = $pkg->getRequires(); $skip = \false; foreach ($reqs as $name => $link) { if (!PlatformRepository::isPlatformPackage($name) || $platformRequirementFilter->isIgnored($name)) { continue; } if (isset($this->platformConstraints[$name])) { foreach ($this->platformConstraints[$name] as $providedConstraint) { if ($link->getConstraint()->matches($providedConstraint)) { // constraint satisfied, go to next require continue 2; } if ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter && $platformRequirementFilter->isUpperBoundIgnored($name)) { $filteredConstraint = $platformRequirementFilter->filterConstraint($name, $link->getConstraint()); if ($filteredConstraint->matches($providedConstraint)) { // constraint satisfied with the upper bound ignored, go to next require continue 2; } } } // constraint not satisfied $reason = 'is not satisfied by your platform'; } else { // Package requires a platform package that is unknown on current platform. // It means that current platform cannot validate this constraint and so package is not installable. $reason = 'is missing from your platform'; } $isLatestVersion = !isset($alreadySeenNames[$pkg->getName()]); $alreadySeenNames[$pkg->getName()] = \true; if ($io !== null && ($showWarnings === \true || \is_callable($showWarnings) && $showWarnings($pkg))) { $isFirstWarning = !isset($alreadyWarnedNames[$pkg->getName() . '/' . $link->getTarget()]); $alreadyWarnedNames[$pkg->getName() . '/' . $link->getTarget()] = \true; $latest = $isLatestVersion ? "'s latest version" : ''; $io->writeError('Cannot use ' . $pkg->getPrettyName() . $latest . ' ' . $pkg->getPrettyVersion() . ' as it ' . $link->getDescription() . ' ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' which ' . $reason . '.', \true, $isFirstWarning ? IOInterface::NORMAL : IOInterface::VERBOSE); } // skip candidate $skip = \true; } if ($skip) { continue; } $package = $pkg; break; } } else { $package = \count($candidates) > 0 ? $candidates[0] : null; } if (!isset($package)) { return \false; } // if we end up with 9999999-dev as selected package, make sure we use the original version instead of the alias if ($package instanceof AliasPackage && $package->getVersion() === \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS) { $package = $package->getAliasOf(); } return $package; } /** * Given a concrete version, this returns a ^ constraint (when possible) * that should be used, for example, in composer.json. * * For example: * * 1.2.1 -> ^1.2 * * 1.2.1.2 -> ^1.2 * * 1.2 -> ^1.2 * * v3.2.1 -> ^3.2 * * 2.0-beta.1 -> ^2.0@beta * * dev-master -> ^2.1@dev (dev version with alias) * * dev-master -> dev-master (dev versions are untouched) */ public function findRecommendedRequireVersion(PackageInterface $package) : string { // Extensions which are versioned in sync with PHP should rather be required as "*" to simplify // the requires and have only one required version to change when bumping the php requirement if (0 === \strpos($package->getName(), 'ext-')) { $phpVersion = \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION; $extVersion = \implode('.', \array_slice(\explode('.', $package->getVersion()), 0, 3)); if ($phpVersion === $extVersion) { return '*'; } } $version = $package->getVersion(); if (!$package->isDev()) { return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability()); } $loader = new ArrayLoader($this->getParser()); $dumper = new ArrayDumper(); $extra = $loader->getBranchAlias($dumper->dump($package)); if ($extra && $extra !== \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS) { $extra = Preg::replace('{^(\\d+\\.\\d+\\.\\d+)(\\.9999999)-dev$}', '$1.0', $extra, -1, $count); if ($count > 0) { $extra = \str_replace('.9999999', '.0', $extra); return $this->transformVersion($extra, $extra, 'dev'); } } return $package->getPrettyVersion(); } private function transformVersion(string $version, string $prettyVersion, string $stability) : string { // attempt to transform 2.1.1 to 2.1 // this allows you to upgrade through minor versions $semanticVersionParts = \explode('.', $version); // check to see if we have a semver-looking version if (\count($semanticVersionParts) === 4 && Preg::isMatch('{^\\d+\\D?}', $semanticVersionParts[3])) { // remove the last parts (i.e. the patch version number and any extra) if ($semanticVersionParts[0] === '0') { unset($semanticVersionParts[3]); } else { unset($semanticVersionParts[2], $semanticVersionParts[3]); } $version = \implode('.', $semanticVersionParts); } else { return $prettyVersion; } // append stability flag if not default if ($stability !== 'stable') { $version .= '@' . $stability; } // 2.1 -> ^2.1 return '^' . $version; } private function getParser() : \Composer\Package\Version\VersionParser { if ($this->parser === null) { $this->parser = new \Composer\Package\Version\VersionParser(); } return $this->parser; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Version; use Composer\Pcre\Preg; use Composer\Repository\PlatformRepository; use Composer\Semver\VersionParser as SemverVersionParser; use Composer\Semver\Semver; use Composer\Semver\Constraint\ConstraintInterface; class VersionParser extends SemverVersionParser { public const DEFAULT_BRANCH_ALIAS = '9999999-dev'; /** @var array Constraint parsing cache */ private static $constraints = []; /** * @inheritDoc */ public function parseConstraints($constraints) : ConstraintInterface { if (!isset(self::$constraints[$constraints])) { self::$constraints[$constraints] = parent::parseConstraints($constraints); } return self::$constraints[$constraints]; } /** * Parses an array of strings representing package/version pairs. * * The parsing results in an array of arrays, each of which * contain a 'name' key with value and optionally a 'version' key with value. * * @param string[] $pairs a set of package/version pairs separated by ":", "=" or " " * * @return list */ public function parseNameVersionPairs(array $pairs) : array { $pairs = \array_values($pairs); $result = []; for ($i = 0, $count = \count($pairs); $i < $count; $i++) { $pair = Preg::replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', \trim($pairs[$i])); if (\false === \strpos($pair, ' ') && isset($pairs[$i + 1]) && \false === \strpos($pairs[$i + 1], '/') && !Preg::isMatch('{(?<=[a-z0-9_/-])\\*|\\*(?=[a-z0-9_/-])}i', $pairs[$i + 1]) && !PlatformRepository::isPlatformPackage($pairs[$i + 1])) { $pair .= ' ' . $pairs[$i + 1]; $i++; } if (\strpos($pair, ' ')) { [$name, $version] = \explode(' ', $pair, 2); $result[] = ['name' => $name, 'version' => $version]; } else { $result[] = ['name' => $pair]; } } return $result; } public static function isUpgrade(string $normalizedFrom, string $normalizedTo) : bool { if ($normalizedFrom === $normalizedTo) { return \true; } if (\in_array($normalizedFrom, ['dev-master', 'dev-trunk', 'dev-default'], \true)) { $normalizedFrom = \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS; } if (\in_array($normalizedTo, ['dev-master', 'dev-trunk', 'dev-default'], \true)) { $normalizedTo = \Composer\Package\Version\VersionParser::DEFAULT_BRANCH_ALIAS; } if (\strpos($normalizedFrom, 'dev-') === 0 || \strpos($normalizedTo, 'dev-') === 0) { return \true; } $sorted = Semver::sort([$normalizedTo, $normalizedFrom]); return $sorted[0] === $normalizedFrom; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Loader; use Composer\Package\BasePackage; use Composer\Pcre\Preg; use Composer\Semver\Constraint\Constraint; use Composer\Package\Version\VersionParser; use Composer\Repository\PlatformRepository; use Composer\Semver\Constraint\MatchNoneConstraint; use Composer\Semver\Intervals; use Composer\Spdx\SpdxLicenses; /** * @author Jordi Boggiano */ class ValidatingArrayLoader implements \Composer\Package\Loader\LoaderInterface { public const CHECK_ALL = 3; public const CHECK_UNBOUND_CONSTRAINTS = 1; public const CHECK_STRICT_CONSTRAINTS = 2; /** @var LoaderInterface */ private $loader; /** @var VersionParser */ private $versionParser; /** @var list */ private $errors; /** @var list */ private $warnings; /** @var mixed[] */ private $config; /** @var int One or more of self::CHECK_* constants */ private $flags; /** * @param true $strictName */ public function __construct(\Composer\Package\Loader\LoaderInterface $loader, bool $strictName = \true, ?VersionParser $parser = null, int $flags = 0) { $this->loader = $loader; $this->versionParser = $parser ?? new VersionParser(); $this->flags = $flags; if ($strictName !== \true) { // @phpstan-ignore-line \trigger_error('$strictName must be set to true in ValidatingArrayLoader\'s constructor as of 2.2, and it will be removed in 3.0', \E_USER_DEPRECATED); } } /** * @inheritDoc */ public function load(array $config, string $class = 'Composer\\Package\\CompletePackage') : BasePackage { $this->errors = []; $this->warnings = []; $this->config = $config; $this->validateString('name', \true); if (isset($config['name']) && null !== ($err = self::hasPackageNamingError($config['name']))) { $this->errors[] = 'name : ' . $err; } if (isset($this->config['version'])) { if (!\is_scalar($this->config['version'])) { $this->validateString('version'); } else { if (!\is_string($this->config['version'])) { $this->config['version'] = (string) $this->config['version']; } try { $this->versionParser->normalize($this->config['version']); } catch (\Exception $e) { $this->errors[] = 'version : invalid value (' . $this->config['version'] . '): ' . $e->getMessage(); unset($this->config['version']); } } } if (isset($this->config['config']['platform'])) { foreach ((array) $this->config['config']['platform'] as $key => $platform) { if (\false === $platform) { continue; } if (!\is_string($platform)) { $this->errors[] = 'config.platform.' . $key . ' : invalid value (' . \gettype($platform) . ' ' . \var_export($platform, \true) . '): expected string or false'; continue; } try { $this->versionParser->normalize($platform); } catch (\Exception $e) { $this->errors[] = 'config.platform.' . $key . ' : invalid value (' . $platform . '): ' . $e->getMessage(); } } } $this->validateRegex('type', '[A-Za-z0-9-]+'); $this->validateString('target-dir'); $this->validateArray('extra'); if (isset($this->config['bin'])) { if (\is_string($this->config['bin'])) { $this->validateString('bin'); } else { $this->validateFlatArray('bin'); } } $this->validateArray('scripts'); // TODO validate event names & listener syntax $this->validateString('description'); $this->validateUrl('homepage'); $this->validateFlatArray('keywords', '[\\p{N}\\p{L} ._-]+'); $releaseDate = null; $this->validateString('time'); if (isset($this->config['time'])) { try { $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC')); } catch (\Exception $e) { $this->errors[] = 'time : invalid value (' . $this->config['time'] . '): ' . $e->getMessage(); unset($this->config['time']); } } if (isset($this->config['license'])) { // validate main data types if (\is_array($this->config['license']) || \is_string($this->config['license'])) { $licenses = (array) $this->config['license']; foreach ($licenses as $index => $license) { if (!\is_string($license)) { $this->warnings[] = \sprintf('License %s should be a string.', \json_encode($license)); unset($licenses[$index]); } } // check for license validity on newly updated branches/tags if (null === $releaseDate || $releaseDate->getTimestamp() >= \strtotime('-8days')) { $licenseValidator = new SpdxLicenses(); foreach ($licenses as $license) { // replace proprietary by MIT for validation purposes since it's not a valid SPDX identifier, but is accepted by composer if ('proprietary' === $license) { continue; } $licenseToValidate = \str_replace('proprietary', 'MIT', $license); if (!$licenseValidator->validate($licenseToValidate)) { if ($licenseValidator->validate(\trim($licenseToValidate))) { $this->warnings[] = \sprintf('License %s must not contain extra spaces, make sure to trim it.', \json_encode($license)); } else { $this->warnings[] = \sprintf('License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . \PHP_EOL . 'If the software is closed-source, you may use "proprietary" as license.', \json_encode($license)); } } } } $this->config['license'] = \array_values($licenses); } else { $this->warnings[] = \sprintf('License must be a string or array of strings, got %s.', \json_encode($this->config['license'])); unset($this->config['license']); } } if ($this->validateArray('authors')) { foreach ($this->config['authors'] as $key => $author) { if (!\is_array($author)) { $this->errors[] = 'authors.' . $key . ' : should be an array, ' . \gettype($author) . ' given'; unset($this->config['authors'][$key]); continue; } foreach (['homepage', 'email', 'name', 'role'] as $authorData) { if (isset($author[$authorData]) && !\is_string($author[$authorData])) { $this->errors[] = 'authors.' . $key . '.' . $authorData . ' : invalid value, must be a string'; unset($this->config['authors'][$key][$authorData]); } } if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) { $this->warnings[] = 'authors.' . $key . '.homepage : invalid value (' . $author['homepage'] . '), must be an http/https URL'; unset($this->config['authors'][$key]['homepage']); } if (isset($author['email']) && \false === \filter_var($author['email'], \FILTER_VALIDATE_EMAIL)) { $this->warnings[] = 'authors.' . $key . '.email : invalid value (' . $author['email'] . '), must be a valid email address'; unset($this->config['authors'][$key]['email']); } if (\count($this->config['authors'][$key]) === 0) { unset($this->config['authors'][$key]); } } if (\count($this->config['authors']) === 0) { unset($this->config['authors']); } } if ($this->validateArray('support') && !empty($this->config['support'])) { foreach (['issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss', 'chat', 'security'] as $key) { if (isset($this->config['support'][$key]) && !\is_string($this->config['support'][$key])) { $this->errors[] = 'support.' . $key . ' : invalid value, must be a string'; unset($this->config['support'][$key]); } } if (isset($this->config['support']['email']) && !\filter_var($this->config['support']['email'], \FILTER_VALIDATE_EMAIL)) { $this->warnings[] = 'support.email : invalid value (' . $this->config['support']['email'] . '), must be a valid email address'; unset($this->config['support']['email']); } if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], ['irc', 'ircs'])) { $this->warnings[] = 'support.irc : invalid value (' . $this->config['support']['irc'] . '), must be a irc:/// or ircs:// URL'; unset($this->config['support']['irc']); } foreach (['issues', 'forum', 'wiki', 'source', 'docs', 'chat', 'security'] as $key) { if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) { $this->warnings[] = 'support.' . $key . ' : invalid value (' . $this->config['support'][$key] . '), must be an http/https URL'; unset($this->config['support'][$key]); } } if (empty($this->config['support'])) { unset($this->config['support']); } } if ($this->validateArray('funding') && !empty($this->config['funding'])) { foreach ($this->config['funding'] as $key => $fundingOption) { if (!\is_array($fundingOption)) { $this->errors[] = 'funding.' . $key . ' : should be an array, ' . \gettype($fundingOption) . ' given'; unset($this->config['funding'][$key]); continue; } foreach (['type', 'url'] as $fundingData) { if (isset($fundingOption[$fundingData]) && !\is_string($fundingOption[$fundingData])) { $this->errors[] = 'funding.' . $key . '.' . $fundingData . ' : invalid value, must be a string'; unset($this->config['funding'][$key][$fundingData]); } } if (isset($fundingOption['url']) && !$this->filterUrl($fundingOption['url'])) { $this->warnings[] = 'funding.' . $key . '.url : invalid value (' . $fundingOption['url'] . '), must be an http/https URL'; unset($this->config['funding'][$key]['url']); } if (empty($this->config['funding'][$key])) { unset($this->config['funding'][$key]); } } if (empty($this->config['funding'])) { unset($this->config['funding']); } } $this->validateArray('php-ext'); if (isset($this->config['php-ext']) && !\in_array($this->config['type'] ?? '', ['php-ext', 'php-ext-zend'], \true)) { $this->errors[] = 'php-ext can only be set by packages of type "php-ext" or "php-ext-zend" which must be C extensions'; unset($this->config['php-ext']); } $unboundConstraint = new Constraint('=', '10000000-dev'); foreach (\array_keys(BasePackage::$supportedLinkTypes) as $linkType) { if ($this->validateArray($linkType) && isset($this->config[$linkType])) { foreach ($this->config[$linkType] as $package => $constraint) { $package = (string) $package; if (isset($this->config['name']) && 0 === \strcasecmp($package, $this->config['name'])) { $this->errors[] = $linkType . '.' . $package . ' : a package cannot set a ' . $linkType . ' on itself'; unset($this->config[$linkType][$package]); continue; } if ($err = self::hasPackageNamingError($package, \true)) { $this->warnings[] = $linkType . '.' . $err; } elseif (!Preg::isMatch('{^[A-Za-z0-9_./-]+$}', $package)) { $this->errors[] = $linkType . '.' . $package . ' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]'; } if (!\is_string($constraint)) { $this->errors[] = $linkType . '.' . $package . ' : invalid value, must be a string containing a version constraint'; unset($this->config[$linkType][$package]); } elseif ('self.version' !== $constraint) { try { $linkConstraint = $this->versionParser->parseConstraints($constraint); } catch (\Exception $e) { $this->errors[] = $linkType . '.' . $package . ' : invalid version constraint (' . $e->getMessage() . ')'; unset($this->config[$linkType][$package]); continue; } // check requires for unbound constraints on non-platform packages if ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS && 'require' === $linkType && $linkConstraint->matches($unboundConstraint) && !PlatformRepository::isPlatformPackage($package)) { $this->warnings[] = $linkType . '.' . $package . ' : unbound version constraints (' . $constraint . ') should be avoided'; } elseif ($this->flags & self::CHECK_STRICT_CONSTRAINTS && 'require' === $linkType && $linkConstraint instanceof Constraint && \in_array($linkConstraint->getOperator(), ['==', '='], \true) && (new Constraint('>=', '1.0.0.0-dev'))->matches($linkConstraint)) { $this->warnings[] = $linkType . '.' . $package . ' : exact version constraints (' . $constraint . ') should be avoided if the package follows semantic versioning'; } $compacted = Intervals::compactConstraint($linkConstraint); if ($compacted instanceof MatchNoneConstraint) { $this->warnings[] = $linkType . '.' . $package . ' : this version constraint cannot possibly match anything (' . $constraint . ')'; } } if ($linkType === 'conflict' && isset($this->config['replace']) && ($keys = \array_intersect_key($this->config['replace'], $this->config['conflict']))) { $this->errors[] = $linkType . '.' . $package . ' : you cannot conflict with a package that is also replaced, as replace already creates an implicit conflict rule'; unset($this->config[$linkType][$package]); } } } } if ($this->validateArray('suggest') && isset($this->config['suggest'])) { foreach ($this->config['suggest'] as $package => $description) { if (!\is_string($description)) { $this->errors[] = 'suggest.' . $package . ' : invalid value, must be a string describing why the package is suggested'; unset($this->config['suggest'][$package]); } } } if ($this->validateString('minimum-stability') && isset($this->config['minimum-stability'])) { if (!isset(BasePackage::STABILITIES[\strtolower($this->config['minimum-stability'])]) && $this->config['minimum-stability'] !== 'RC') { $this->errors[] = 'minimum-stability : invalid value (' . $this->config['minimum-stability'] . '), must be one of ' . \implode(', ', \array_keys(BasePackage::STABILITIES)); unset($this->config['minimum-stability']); } } if ($this->validateArray('autoload') && isset($this->config['autoload'])) { $types = ['psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap']; foreach ($this->config['autoload'] as $type => $typeConfig) { if (!\in_array($type, $types)) { $this->errors[] = 'autoload : invalid value (' . $type . '), must be one of ' . \implode(', ', $types); unset($this->config['autoload'][$type]); } if ($type === 'psr-4') { foreach ($typeConfig as $namespace => $dirs) { if ($namespace !== '' && '\\' !== \substr((string) $namespace, -1)) { $this->errors[] = 'autoload.psr-4 : invalid value (' . $namespace . '), namespaces must end with a namespace separator, should be ' . $namespace . '\\\\'; } } } } } if (isset($this->config['autoload']['psr-4']) && isset($this->config['target-dir'])) { $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4'; // Unset the psr-4 setting, since unsetting target-dir might // interfere with other settings. unset($this->config['autoload']['psr-4']); } foreach (['source', 'dist'] as $srcType) { if ($this->validateArray($srcType) && !empty($this->config[$srcType])) { if (!isset($this->config[$srcType]['type'])) { $this->errors[] = $srcType . '.type : must be present'; } if (!isset($this->config[$srcType]['url'])) { $this->errors[] = $srcType . '.url : must be present'; } if ($srcType === 'source' && !isset($this->config[$srcType]['reference'])) { $this->errors[] = $srcType . '.reference : must be present'; } if (isset($this->config[$srcType]['type']) && !\is_string($this->config[$srcType]['type'])) { $this->errors[] = $srcType . '.type : should be a string, ' . \gettype($this->config[$srcType]['type']) . ' given'; } if (isset($this->config[$srcType]['url']) && !\is_string($this->config[$srcType]['url'])) { $this->errors[] = $srcType . '.url : should be a string, ' . \gettype($this->config[$srcType]['url']) . ' given'; } if (isset($this->config[$srcType]['reference']) && !\is_string($this->config[$srcType]['reference']) && !\is_int($this->config[$srcType]['reference'])) { $this->errors[] = $srcType . '.reference : should be a string or int, ' . \gettype($this->config[$srcType]['reference']) . ' given'; } if (isset($this->config[$srcType]['reference']) && Preg::isMatch('{^\\s*-}', (string) $this->config[$srcType]['reference'])) { $this->errors[] = $srcType . '.reference : must not start with a "-", "' . $this->config[$srcType]['reference'] . '" given'; } if (isset($this->config[$srcType]['url']) && Preg::isMatch('{^\\s*-}', (string) $this->config[$srcType]['url'])) { $this->errors[] = $srcType . '.url : must not start with a "-", "' . $this->config[$srcType]['url'] . '" given'; } } } // TODO validate repositories // TODO validate package repositories' packages using this recursively $this->validateFlatArray('include-path'); $this->validateArray('transport-options'); // branch alias validation if (isset($this->config['extra']['branch-alias'])) { if (!\is_array($this->config['extra']['branch-alias'])) { $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases'; } else { foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) { if (!\is_string($targetBranch)) { $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . \json_encode($targetBranch) . ') must be a string, "' . \gettype($targetBranch) . '" received.'; unset($this->config['extra']['branch-alias'][$sourceBranch]); continue; } // ensure it is an alias to a -dev package if ('-dev' !== \substr($targetBranch, -4)) { $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . $targetBranch . ') must end in -dev'; unset($this->config['extra']['branch-alias'][$sourceBranch]); continue; } // normalize without -dev and ensure it's a numeric branch that is parseable $validatedTargetBranch = $this->versionParser->normalizeBranch(\substr($targetBranch, 0, -4)); if ('-dev' !== \substr($validatedTargetBranch, -4)) { $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . $targetBranch . ') must be a parseable number like 2.0-dev'; unset($this->config['extra']['branch-alias'][$sourceBranch]); continue; } // If using numeric aliases ensure the alias is a valid subversion if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch)) && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch)) && \stripos($targetPrefix, $sourcePrefix) !== 0) { $this->warnings[] = 'extra.branch-alias.' . $sourceBranch . ' : the target branch (' . $targetBranch . ') is not a valid numeric alias for this version'; unset($this->config['extra']['branch-alias'][$sourceBranch]); } } } } if ($this->errors) { throw new \Composer\Package\Loader\InvalidPackageException($this->errors, $this->warnings, $config); } $package = $this->loader->load($this->config, $class); $this->config = []; return $package; } /** * @return list */ public function getWarnings() : array { return $this->warnings; } /** * @return list */ public function getErrors() : array { return $this->errors; } public static function hasPackageNamingError(string $name, bool $isLink = \false) : ?string { if (PlatformRepository::isPlatformPackage($name)) { return null; } if (!Preg::isMatch('{^[a-z0-9](?:[_.-]?[a-z0-9]++)*+/[a-z0-9](?:(?:[_.]|-{1,2})?[a-z0-9]++)*+$}iD', $name)) { return $name . ' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".'; } $reservedNames = ['nul', 'con', 'prn', 'aux', 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9', 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9']; $bits = \explode('/', \strtolower($name)); if (\in_array($bits[0], $reservedNames, \true) || \in_array($bits[1], $reservedNames, \true)) { return $name . ' is reserved, package and vendor names can not match any of: ' . \implode(', ', $reservedNames) . '.'; } if (Preg::isMatch('{\\.json$}', $name)) { return $name . ' is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.'; } if (Preg::isMatch('{[A-Z]}', $name)) { if ($isLink) { return $name . ' is invalid, it should not contain uppercase characters. Please use ' . \strtolower($name) . ' instead.'; } $suggestName = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '1\\3-\\2\\4', $name); $suggestName = \strtolower($suggestName); return $name . ' is invalid, it should not contain uppercase characters. We suggest using ' . $suggestName . ' instead.'; } return null; } /** * @phpstan-param non-empty-string $property * @phpstan-param non-empty-string $regex */ private function validateRegex(string $property, string $regex, bool $mandatory = \false) : bool { if (!$this->validateString($property, $mandatory)) { return \false; } if (!Preg::isMatch('{^' . $regex . '$}u', $this->config[$property])) { $message = $property . ' : invalid value (' . $this->config[$property] . '), must match ' . $regex; if ($mandatory) { $this->errors[] = $message; } else { $this->warnings[] = $message; } unset($this->config[$property]); return \false; } return \true; } /** * @phpstan-param non-empty-string $property */ private function validateString(string $property, bool $mandatory = \false) : bool { if (isset($this->config[$property]) && !\is_string($this->config[$property])) { $this->errors[] = $property . ' : should be a string, ' . \gettype($this->config[$property]) . ' given'; unset($this->config[$property]); return \false; } if (!isset($this->config[$property]) || \trim($this->config[$property]) === '') { if ($mandatory) { $this->errors[] = $property . ' : must be present'; } unset($this->config[$property]); return \false; } return \true; } /** * @phpstan-param non-empty-string $property */ private function validateArray(string $property, bool $mandatory = \false) : bool { if (isset($this->config[$property]) && !\is_array($this->config[$property])) { $this->errors[] = $property . ' : should be an array, ' . \gettype($this->config[$property]) . ' given'; unset($this->config[$property]); return \false; } if (!isset($this->config[$property]) || !\count($this->config[$property])) { if ($mandatory) { $this->errors[] = $property . ' : must be present and contain at least one element'; } unset($this->config[$property]); return \false; } return \true; } /** * @phpstan-param non-empty-string $property * @phpstan-param non-empty-string|null $regex */ private function validateFlatArray(string $property, ?string $regex = null, bool $mandatory = \false) : bool { if (!$this->validateArray($property, $mandatory)) { return \false; } $pass = \true; foreach ($this->config[$property] as $key => $value) { if (!\is_string($value) && !\is_numeric($value)) { $this->errors[] = $property . '.' . $key . ' : must be a string or int, ' . \gettype($value) . ' given'; unset($this->config[$property][$key]); $pass = \false; continue; } if ($regex && !Preg::isMatch('{^' . $regex . '$}u', (string) $value)) { $this->warnings[] = $property . '.' . $key . ' : invalid value (' . $value . '), must match ' . $regex; unset($this->config[$property][$key]); $pass = \false; } } return $pass; } /** * @phpstan-param non-empty-string $property */ private function validateUrl(string $property, bool $mandatory = \false) : bool { if (!$this->validateString($property, $mandatory)) { return \false; } if (!$this->filterUrl($this->config[$property])) { $this->warnings[] = $property . ' : invalid value (' . $this->config[$property] . '), must be an http/https URL'; unset($this->config[$property]); return \false; } return \true; } /** * @param mixed $value * @param string[] $schemes */ private function filterUrl($value, array $schemes = ['http', 'https']) : bool { if ($value === '') { return \true; } $bits = \parse_url($value); if (empty($bits['scheme']) || empty($bits['host'])) { return \false; } if (!\in_array($bits['scheme'], $schemes, \true)) { return \false; } return \true; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Loader; /** * @author Jordi Boggiano */ class InvalidPackageException extends \Exception { /** @var list */ private $errors; /** @var list */ private $warnings; /** @var mixed[] package config */ private $data; /** * @param list $errors * @param list $warnings * @param mixed[] $data */ public function __construct(array $errors, array $warnings, array $data) { $this->errors = $errors; $this->warnings = $warnings; $this->data = $data; parent::__construct("Invalid package information: \n" . \implode("\n", \array_merge($errors, $warnings))); } /** * @return mixed[] */ public function getData() : array { return $this->data; } /** * @return list */ public function getErrors() : array { return $this->errors; } /** * @return list */ public function getWarnings() : array { return $this->warnings; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Loader; use Composer\Package\BasePackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\CompletePackage; use Composer\Package\RootPackage; use Composer\Package\PackageInterface; use Composer\Package\CompletePackageInterface; use Composer\Package\Link; use Composer\Package\RootAliasPackage; use Composer\Package\Version\VersionParser; use Composer\Pcre\Preg; /** * @author Konstantin Kudryashiv * @author Jordi Boggiano */ class ArrayLoader implements \Composer\Package\Loader\LoaderInterface { /** @var VersionParser */ protected $versionParser; /** @var bool */ protected $loadOptions; public function __construct(?VersionParser $parser = null, bool $loadOptions = \false) { if (!$parser) { $parser = new VersionParser(); } $this->versionParser = $parser; $this->loadOptions = $loadOptions; } /** * @inheritDoc */ public function load(array $config, string $class = 'Composer\\Package\\CompletePackage') : BasePackage { if ($class !== 'Composer\\Package\\CompletePackage' && $class !== 'Composer\\Package\\RootPackage') { \trigger_error('The $class arg is deprecated, please reach out to Composer maintainers ASAP if you still need this.', \E_USER_DEPRECATED); } $package = $this->createObject($config, $class); foreach (BasePackage::$supportedLinkTypes as $type => $opts) { if (!isset($config[$type]) || !\is_array($config[$type])) { continue; } $method = 'set' . \ucfirst($opts['method']); $package->{$method}($this->parseLinks($package->getName(), $package->getPrettyVersion(), $opts['method'], $config[$type])); } $package = $this->configureObject($package, $config); return $package; } /** * @param array> $versions * * @return list */ public function loadPackages(array $versions) : array { $packages = []; $linkCache = []; foreach ($versions as $version) { $package = $this->createObject($version, 'Composer\\Package\\CompletePackage'); $this->configureCachedLinks($linkCache, $package, $version); $package = $this->configureObject($package, $version); $packages[] = $package; } return $packages; } /** * @template PackageClass of CompletePackage * * @param mixed[] $config package data * @param string $class FQCN to be instantiated * * @return CompletePackage|RootPackage * * @phpstan-param class-string $class */ private function createObject(array $config, string $class) : CompletePackage { if (!isset($config['name'])) { throw new \UnexpectedValueException('Unknown package has no name defined (' . \json_encode($config) . ').'); } if (!isset($config['version']) || !\is_scalar($config['version'])) { throw new \UnexpectedValueException('Package ' . $config['name'] . ' has no version defined.'); } if (!\is_string($config['version'])) { $config['version'] = (string) $config['version']; } // handle already normalized versions if (isset($config['version_normalized']) && \is_string($config['version_normalized'])) { $version = $config['version_normalized']; // handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it if ($version === VersionParser::DEFAULT_BRANCH_ALIAS) { $version = $this->versionParser->normalize($config['version']); } } else { $version = $this->versionParser->normalize($config['version']); } return new $class($config['name'], $version, $config['version']); } /** * @param CompletePackage $package * @param mixed[] $config package data * * @return RootPackage|RootAliasPackage|CompletePackage|CompleteAliasPackage */ private function configureObject(PackageInterface $package, array $config) : BasePackage { if (!$package instanceof CompletePackage) { throw new \LogicException('ArrayLoader expects instances of the Composer\\Package\\CompletePackage class to function correctly'); } $package->setType(isset($config['type']) ? \strtolower($config['type']) : 'library'); if (isset($config['target-dir'])) { $package->setTargetDir($config['target-dir']); } if (isset($config['extra']) && \is_array($config['extra'])) { $package->setExtra($config['extra']); } if (isset($config['bin'])) { if (!\is_array($config['bin'])) { $config['bin'] = [$config['bin']]; } foreach ($config['bin'] as $key => $bin) { $config['bin'][$key] = \ltrim($bin, '/'); } $package->setBinaries($config['bin']); } if (isset($config['installation-source'])) { $package->setInstallationSource($config['installation-source']); } if (isset($config['default-branch']) && $config['default-branch'] === \true) { $package->setIsDefaultBranch(\true); } if (isset($config['source'])) { if (!isset($config['source']['type'], $config['source']['url'], $config['source']['reference'])) { throw new \UnexpectedValueException(\sprintf("Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.", $config['name'], \json_encode($config['source']))); } $package->setSourceType($config['source']['type']); $package->setSourceUrl($config['source']['url']); $package->setSourceReference(isset($config['source']['reference']) ? (string) $config['source']['reference'] : null); if (isset($config['source']['mirrors'])) { $package->setSourceMirrors($config['source']['mirrors']); } } if (isset($config['dist'])) { if (!isset($config['dist']['type'], $config['dist']['url'])) { throw new \UnexpectedValueException(\sprintf("Package %s's dist key should be specified as " . "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.", $config['name'], \json_encode($config['dist']))); } $package->setDistType($config['dist']['type']); $package->setDistUrl($config['dist']['url']); $package->setDistReference(isset($config['dist']['reference']) ? (string) $config['dist']['reference'] : null); $package->setDistSha1Checksum($config['dist']['shasum'] ?? null); if (isset($config['dist']['mirrors'])) { $package->setDistMirrors($config['dist']['mirrors']); } } if (isset($config['suggest']) && \is_array($config['suggest'])) { foreach ($config['suggest'] as $target => $reason) { if ('self.version' === \trim($reason)) { $config['suggest'][$target] = $package->getPrettyVersion(); } } $package->setSuggests($config['suggest']); } if (isset($config['autoload'])) { $package->setAutoload($config['autoload']); } if (isset($config['autoload-dev'])) { $package->setDevAutoload($config['autoload-dev']); } if (isset($config['include-path'])) { $package->setIncludePaths($config['include-path']); } if (isset($config['php-ext'])) { $package->setPhpExt($config['php-ext']); } if (!empty($config['time'])) { $time = Preg::isMatch('/^\\d++$/D', $config['time']) ? '@' . $config['time'] : $config['time']; try { $date = new \DateTime($time, new \DateTimeZone('UTC')); $package->setReleaseDate($date); } catch (\Exception $e) { } } if (!empty($config['notification-url'])) { $package->setNotificationUrl($config['notification-url']); } if ($package instanceof CompletePackageInterface) { if (!empty($config['archive']['name'])) { $package->setArchiveName($config['archive']['name']); } if (!empty($config['archive']['exclude'])) { $package->setArchiveExcludes($config['archive']['exclude']); } if (isset($config['scripts']) && \is_array($config['scripts'])) { foreach ($config['scripts'] as $event => $listeners) { $config['scripts'][$event] = (array) $listeners; } foreach (['composer', 'php', 'putenv'] as $reserved) { if (isset($config['scripts'][$reserved])) { \trigger_error('The `' . $reserved . '` script name is reserved for internal use, please avoid defining it', \E_USER_DEPRECATED); } } $package->setScripts($config['scripts']); } if (!empty($config['description']) && \is_string($config['description'])) { $package->setDescription($config['description']); } if (!empty($config['homepage']) && \is_string($config['homepage'])) { $package->setHomepage($config['homepage']); } if (!empty($config['keywords']) && \is_array($config['keywords'])) { $package->setKeywords(\array_map('strval', $config['keywords'])); } if (!empty($config['license'])) { $package->setLicense(\is_array($config['license']) ? $config['license'] : [$config['license']]); } if (!empty($config['authors']) && \is_array($config['authors'])) { $package->setAuthors($config['authors']); } if (isset($config['support']) && \is_array($config['support'])) { $package->setSupport($config['support']); } if (!empty($config['funding']) && \is_array($config['funding'])) { $package->setFunding($config['funding']); } if (isset($config['abandoned'])) { $package->setAbandoned($config['abandoned']); } } if ($this->loadOptions && isset($config['transport-options'])) { $package->setTransportOptions($config['transport-options']); } if ($aliasNormalized = $this->getBranchAlias($config)) { $prettyAlias = Preg::replace('{(\\.9{7})+}', '.x', $aliasNormalized); if ($package instanceof RootPackage) { return new RootAliasPackage($package, $aliasNormalized, $prettyAlias); } return new CompleteAliasPackage($package, $aliasNormalized, $prettyAlias); } return $package; } /** * @param array>>> $linkCache * @param mixed[] $config */ private function configureCachedLinks(array &$linkCache, PackageInterface $package, array $config) : void { $name = $package->getName(); $prettyVersion = $package->getPrettyVersion(); foreach (BasePackage::$supportedLinkTypes as $type => $opts) { if (isset($config[$type])) { $method = 'set' . \ucfirst($opts['method']); $links = []; foreach ($config[$type] as $prettyTarget => $constraint) { $target = \strtolower($prettyTarget); // recursive links are not supported if ($target === $name) { continue; } if ($constraint === 'self.version') { $links[$target] = $this->createLink($name, $prettyVersion, $opts['method'], $target, $constraint); } else { if (!isset($linkCache[$name][$type][$target][$constraint])) { $linkCache[$name][$type][$target][$constraint] = [$target, $this->createLink($name, $prettyVersion, $opts['method'], $target, $constraint)]; } [$target, $link] = $linkCache[$name][$type][$target][$constraint]; $links[$target] = $link; } } $package->{$method}($links); } } } /** * @param string $source source package name * @param string $sourceVersion source package version (pretty version ideally) * @param string $description link description (e.g. requires, replaces, ..) * @param array $links array of package name => constraint mappings * * @return Link[] * * @phpstan-param Link::TYPE_* $description */ public function parseLinks(string $source, string $sourceVersion, string $description, array $links) : array { $res = []; foreach ($links as $target => $constraint) { if (!\is_string($constraint)) { continue; } $target = \strtolower((string) $target); $res[$target] = $this->createLink($source, $sourceVersion, $description, $target, $constraint); } return $res; } /** * @param string $source source package name * @param string $sourceVersion source package version (pretty version ideally) * @param Link::TYPE_* $description link description (e.g. requires, replaces, ..) * @param string $target target package name * @param string $prettyConstraint constraint string */ private function createLink(string $source, string $sourceVersion, string $description, string $target, string $prettyConstraint) : Link { if (!\is_string($prettyConstraint)) { throw new \UnexpectedValueException('Link constraint in ' . $source . ' ' . $description . ' > ' . $target . ' should be a string, got ' . \gettype($prettyConstraint) . ' (' . \var_export($prettyConstraint, \true) . ')'); } if ('self.version' === $prettyConstraint) { $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion); } else { $parsedConstraint = $this->versionParser->parseConstraints($prettyConstraint); } return new Link($source, $target, $parsedConstraint, $description, $prettyConstraint); } /** * Retrieves a branch alias (dev-master => 1.0.x-dev for example) if it exists * * @param mixed[] $config the entire package config * * @return string|null normalized version of the branch alias or null if there is none */ public function getBranchAlias(array $config) : ?string { if (!isset($config['version']) || !\is_scalar($config['version'])) { throw new \UnexpectedValueException('no/invalid version defined'); } if (!\is_string($config['version'])) { $config['version'] = (string) $config['version']; } if (\strpos($config['version'], 'dev-') !== 0 && '-dev' !== \substr($config['version'], -4)) { return null; } if (isset($config['extra']['branch-alias']) && \is_array($config['extra']['branch-alias'])) { foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) { $sourceBranch = (string) $sourceBranch; // ensure it is an alias to a -dev package if ('-dev' !== \substr($targetBranch, -4)) { continue; } // normalize without -dev and ensure it's a numeric branch that is parseable if ($targetBranch === VersionParser::DEFAULT_BRANCH_ALIAS) { $validatedTargetBranch = VersionParser::DEFAULT_BRANCH_ALIAS; } else { $validatedTargetBranch = $this->versionParser->normalizeBranch(\substr($targetBranch, 0, -4)); } if ('-dev' !== \substr($validatedTargetBranch, -4)) { continue; } // ensure that it is the current branch aliasing itself if (\strtolower($config['version']) !== \strtolower($sourceBranch)) { continue; } // If using numeric aliases ensure the alias is a valid subversion if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch)) && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch)) && \stripos($targetPrefix, $sourcePrefix) !== 0) { continue; } return $validatedTargetBranch; } } if (isset($config['default-branch']) && $config['default-branch'] === \true && \false === $this->versionParser->parseNumericAliasPrefix(Preg::replace('{^v}', '', $config['version']))) { return VersionParser::DEFAULT_BRANCH_ALIAS; } return null; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Loader; use Composer\Package\CompletePackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\RootAliasPackage; use Composer\Package\RootPackage; use Composer\Package\BasePackage; /** * Defines a loader that takes an array to create package instances * * @author Jordi Boggiano */ interface LoaderInterface { /** * Converts a package from an array to a real instance * * @param mixed[] $config package data * @param string $class FQCN to be instantiated * * @return CompletePackage|CompleteAliasPackage|RootPackage|RootAliasPackage * * @phpstan-param class-string $class */ public function load(array $config, string $class = 'Composer\\Package\\CompletePackage') : BasePackage; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Loader; use Composer\Package\BasePackage; use Composer\Config; use Composer\IO\IOInterface; use Composer\Package\RootAliasPackage; use Composer\Pcre\Preg; use Composer\Repository\RepositoryFactory; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; use Composer\Package\RootPackage; use Composer\Repository\RepositoryManager; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; /** * ArrayLoader built for the sole purpose of loading the root package * * Sets additional defaults and loads repositories * * @author Jordi Boggiano */ class RootPackageLoader extends \Composer\Package\Loader\ArrayLoader { /** * @var RepositoryManager */ private $manager; /** * @var Config */ private $config; /** * @var VersionGuesser */ private $versionGuesser; /** * @var IOInterface|null */ private $io; public function __construct(RepositoryManager $manager, Config $config, ?VersionParser $parser = null, ?VersionGuesser $versionGuesser = null, ?IOInterface $io = null) { parent::__construct($parser); $this->manager = $manager; $this->config = $config; $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor($io), $this->versionParser, $io); $this->io = $io; } /** * @inheritDoc * * @return RootPackage|RootAliasPackage * * @phpstan-param class-string $class */ public function load(array $config, string $class = 'Composer\\Package\\RootPackage', ?string $cwd = null) : BasePackage { if ($class !== 'Composer\\Package\\RootPackage') { \trigger_error('The $class arg is deprecated, please reach out to Composer maintainers ASAP if you still need this.', \E_USER_DEPRECATED); } if (!isset($config['name'])) { $config['name'] = '__root__'; } elseif ($err = \Composer\Package\Loader\ValidatingArrayLoader::hasPackageNamingError($config['name'])) { throw new \RuntimeException('Your package name ' . $err); } $autoVersioned = \false; if (!isset($config['version'])) { $commit = null; // override with env var if available if (Platform::getEnv('COMPOSER_ROOT_VERSION')) { $config['version'] = $this->versionGuesser->getRootVersionFromEnv(); } else { $versionData = $this->versionGuesser->guessVersion($config, $cwd ?? Platform::getCwd(\true)); if ($versionData) { $config['version'] = $versionData['pretty_version']; $config['version_normalized'] = $versionData['version']; $commit = $versionData['commit']; } } if (!isset($config['version'])) { if ($this->io !== null && $config['name'] !== '__root__' && 'project' !== ($config['type'] ?? '')) { $this->io->warning(\sprintf("Composer could not detect the root package (%s) version, defaulting to '1.0.0'. See https://getcomposer.org/root-version", $config['name'])); } $config['version'] = '1.0.0'; $autoVersioned = \true; } if ($commit) { $config['source'] = ['type' => '', 'url' => '', 'reference' => $commit]; $config['dist'] = ['type' => '', 'url' => '', 'reference' => $commit]; } } /** @var RootPackage|RootAliasPackage $package */ $package = parent::load($config, $class); if ($package instanceof RootAliasPackage) { $realPackage = $package->getAliasOf(); } else { $realPackage = $package; } if (!$realPackage instanceof RootPackage) { throw new \LogicException('Expecting a Composer\\Package\\RootPackage at this point'); } if ($autoVersioned) { $realPackage->replaceVersion($realPackage->getVersion(), RootPackage::DEFAULT_PRETTY_VERSION); } if (isset($config['minimum-stability'])) { $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability'])); } $aliases = []; $stabilityFlags = []; $references = []; foreach (['require', 'require-dev'] as $linkType) { if (isset($config[$linkType])) { $linkInfo = BasePackage::$supportedLinkTypes[$linkType]; $method = 'get' . \ucfirst($linkInfo['method']); $links = []; foreach ($realPackage->{$method}() as $link) { $links[$link->getTarget()] = $link->getConstraint()->getPrettyString(); } $aliases = $this->extractAliases($links, $aliases); $stabilityFlags = self::extractStabilityFlags($links, $realPackage->getMinimumStability(), $stabilityFlags); $references = self::extractReferences($links, $references); if (isset($links[$config['name']])) { throw new \RuntimeException(\sprintf('Root package \'%s\' cannot require itself in its composer.json' . \PHP_EOL . 'Did you accidentally name your root package after an external package?', $config['name'])); } } } foreach (\array_keys(BasePackage::$supportedLinkTypes) as $linkType) { if (isset($config[$linkType])) { foreach ($config[$linkType] as $linkName => $constraint) { if ($err = \Composer\Package\Loader\ValidatingArrayLoader::hasPackageNamingError($linkName, \true)) { throw new \RuntimeException($linkType . '.' . $err); } } } } $realPackage->setAliases($aliases); $realPackage->setStabilityFlags($stabilityFlags); $realPackage->setReferences($references); if (isset($config['prefer-stable'])) { $realPackage->setPreferStable((bool) $config['prefer-stable']); } if (isset($config['config'])) { $realPackage->setConfig($config['config']); } $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager); foreach ($repos as $repo) { $this->manager->addRepository($repo); } $realPackage->setRepositories($this->config->getRepositories()); return $package; } /** * @param array $requires * @param list $aliases * * @return list */ private function extractAliases(array $requires, array $aliases) : array { foreach ($requires as $reqName => $reqVersion) { if (Preg::isMatchStrictGroups('{(?:^|\\| *|, *)([^,\\s#|]+)(?:#[^ ]+)? +as +([^,\\s|]+)(?:$| *\\|| *,)}', $reqVersion, $match)) { $aliases[] = ['package' => \strtolower($reqName), 'version' => $this->versionParser->normalize($match[1], $reqVersion), 'alias' => $match[2], 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion)]; } elseif (\strpos($reqVersion, ' as ') !== \false) { throw new \UnexpectedValueException('Invalid alias definition in "' . $reqName . '": "' . $reqVersion . '". Aliases should be in the form "exact-version as other-exact-version".'); } } return $aliases; } /** * @internal * * @param array $requires * @param array $stabilityFlags * @param key-of $minimumStability * * @return array * * @phpstan-param array $stabilityFlags * @phpstan-return array */ public static function extractStabilityFlags(array $requires, string $minimumStability, array $stabilityFlags) : array { $stabilities = BasePackage::STABILITIES; $minimumStability = $stabilities[$minimumStability]; foreach ($requires as $reqName => $reqVersion) { $constraints = []; // extract all sub-constraints in case it is an OR/AND multi-constraint $orSplit = Preg::split('{\\s*\\|\\|?\\s*}', \trim($reqVersion)); foreach ($orSplit as $orConstraint) { $andSplit = Preg::split('{(?< ,]) *(? $stability) { continue; } $stabilityFlags[$name] = $stability; $matched = \true; } } if ($matched) { continue; } foreach ($constraints as $constraint) { // infer flags for requirements that have an explicit -dev or -beta version specified but only // for those that are more unstable than the minimumStability or existing flags $reqVersion = Preg::replace('{^([^,\\s@]+) as .+$}', '$1', $constraint); if (Preg::isMatch('{^[^,\\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) { $name = \strtolower($reqName); $stability = $stabilities[$stabilityName]; if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability || $minimumStability > $stability) { continue; } $stabilityFlags[$name] = $stability; } } } return $stabilityFlags; } /** * @internal * * @param array $requires * @param array $references * * @return array */ public static function extractReferences(array $requires, array $references) : array { foreach ($requires as $reqName => $reqVersion) { $reqVersion = Preg::replace('{^([^,\\s@]+) as .+$}', '$1', $reqVersion); if (Preg::isMatchStrictGroups('{^[^,\\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) { $name = \strtolower($reqName); $references[$name] = $match[1]; } } return $references; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Loader; use Composer\Json\JsonFile; use Composer\Package\BasePackage; use Composer\Package\CompletePackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\RootPackage; use Composer\Package\RootAliasPackage; /** * @author Konstantin Kudryashiv */ class JsonLoader { /** @var LoaderInterface */ private $loader; public function __construct(\Composer\Package\Loader\LoaderInterface $loader) { $this->loader = $loader; } /** * @param string|JsonFile $json A filename, json string or JsonFile instance to load the package from * @return CompletePackage|CompleteAliasPackage|RootPackage|RootAliasPackage */ public function load($json) : BasePackage { if ($json instanceof JsonFile) { $config = $json->read(); } elseif (\file_exists($json)) { $config = JsonFile::parseJson(\file_get_contents($json), $json); } elseif (\is_string($json)) { $config = JsonFile::parseJson($json); } else { throw new \InvalidArgumentException(\sprintf("JsonLoader: Unknown \$json parameter %s. Please report at https://github.com/composer/composer/issues/new.", \gettype($json))); } return $this->loader->load($config); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; use Composer\Repository\RepositoryInterface; use Composer\Repository\PlatformRepository; /** * Base class for packages providing name storage and default match implementation * * @author Nils Adermann */ abstract class BasePackage implements \Composer\Package\PackageInterface { /** * @phpstan-var array * @internal */ public static $supportedLinkTypes = ['require' => ['description' => 'requires', 'method' => \Composer\Package\Link::TYPE_REQUIRE], 'conflict' => ['description' => 'conflicts', 'method' => \Composer\Package\Link::TYPE_CONFLICT], 'provide' => ['description' => 'provides', 'method' => \Composer\Package\Link::TYPE_PROVIDE], 'replace' => ['description' => 'replaces', 'method' => \Composer\Package\Link::TYPE_REPLACE], 'require-dev' => ['description' => 'requires (for development)', 'method' => \Composer\Package\Link::TYPE_DEV_REQUIRE]]; public const STABILITY_STABLE = 0; public const STABILITY_RC = 5; public const STABILITY_BETA = 10; public const STABILITY_ALPHA = 15; public const STABILITY_DEV = 20; public const STABILITIES = ['stable' => self::STABILITY_STABLE, 'RC' => self::STABILITY_RC, 'beta' => self::STABILITY_BETA, 'alpha' => self::STABILITY_ALPHA, 'dev' => self::STABILITY_DEV]; /** * @deprecated * @readonly * @var array, self::STABILITY_*> * @phpstan-ignore property.readOnlyByPhpDocDefaultValue */ public static $stabilities = self::STABILITIES; /** * READ-ONLY: The package id, public for fast access in dependency solver * @var int * @internal */ public $id; /** @var string */ protected $name; /** @var string */ protected $prettyName; /** @var ?RepositoryInterface */ protected $repository = null; /** * All descendants' constructors should call this parent constructor * * @param string $name The package's name */ public function __construct(string $name) { $this->prettyName = $name; $this->name = \strtolower($name); $this->id = -1; } /** * @inheritDoc */ public function getName() : string { return $this->name; } /** * @inheritDoc */ public function getPrettyName() : string { return $this->prettyName; } /** * @inheritDoc */ public function getNames($provides = \true) : array { $names = [$this->getName() => \true]; if ($provides) { foreach ($this->getProvides() as $link) { $names[$link->getTarget()] = \true; } } foreach ($this->getReplaces() as $link) { $names[$link->getTarget()] = \true; } return \array_keys($names); } /** * @inheritDoc */ public function setId(int $id) : void { $this->id = $id; } /** * @inheritDoc */ public function getId() : int { return $this->id; } /** * @inheritDoc */ public function setRepository(RepositoryInterface $repository) : void { if ($this->repository && $repository !== $this->repository) { throw new \LogicException(\sprintf('Package "%s" cannot be added to repository "%s" as it is already in repository "%s".', $this->getPrettyName(), $repository->getRepoName(), $this->repository->getRepoName())); } $this->repository = $repository; } /** * @inheritDoc */ public function getRepository() : ?RepositoryInterface { return $this->repository; } /** * checks if this package is a platform package */ public function isPlatform() : bool { return $this->getRepository() instanceof PlatformRepository; } /** * Returns package unique name, constructed from name, version and release type. */ public function getUniqueName() : string { return $this->getName() . '-' . $this->getVersion(); } public function equals(\Composer\Package\PackageInterface $package) : bool { $self = $this; if ($this instanceof \Composer\Package\AliasPackage) { $self = $this->getAliasOf(); } if ($package instanceof \Composer\Package\AliasPackage) { $package = $package->getAliasOf(); } return $package === $self; } /** * Converts the package into a readable and unique string */ public function __toString() : string { return $this->getUniqueName(); } public function getPrettyString() : string { return $this->getPrettyName() . ' ' . $this->getPrettyVersion(); } /** * @inheritDoc */ public function getFullPrettyVersion(bool $truncate = \true, int $displayMode = \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF_IF_DEV) : string { if ($displayMode === \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF_IF_DEV && (!$this->isDev() || !\in_array($this->getSourceType(), ['hg', 'git']))) { return $this->getPrettyVersion(); } switch ($displayMode) { case \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF_IF_DEV: case \Composer\Package\PackageInterface::DISPLAY_SOURCE_REF: $reference = $this->getSourceReference(); break; case \Composer\Package\PackageInterface::DISPLAY_DIST_REF: $reference = $this->getDistReference(); break; default: throw new \UnexpectedValueException('Display mode ' . $displayMode . ' is not supported'); } if (null === $reference) { return $this->getPrettyVersion(); } // if source reference is a sha1 hash -- truncate if ($truncate && \strlen($reference) === 40 && $this->getSourceType() !== 'svn') { return $this->getPrettyVersion() . ' ' . \substr($reference, 0, 7); } return $this->getPrettyVersion() . ' ' . $reference; } /** * @phpstan-return self::STABILITY_* */ public function getStabilityPriority() : int { return self::STABILITIES[$this->getStability()]; } public function __clone() { $this->repository = null; $this->id = -1; } /** * Build a regexp from a package name, expanding * globs as required * * @param non-empty-string $wrap Wrap the cleaned string by the given string * @return non-empty-string */ public static function packageNameToRegexp(string $allowPattern, string $wrap = '{^%s$}i') : string { $cleanedAllowPattern = \str_replace('\\*', '.*', \preg_quote($allowPattern)); return \sprintf($wrap, $cleanedAllowPattern); } /** * Build a regexp from package names, expanding * globs as required * * @param string[] $packageNames * @param non-empty-string $wrap * @return non-empty-string */ public static function packageNamesToRegexp(array $packageNames, string $wrap = '{^(?:%s)$}iD') : string { $packageNames = \array_map(static function ($packageName) : string { return \Composer\Package\BasePackage::packageNameToRegexp($packageName, '%s'); }, $packageNames); return \sprintf($wrap, \implode('|', $packageNames)); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Comparer; use Composer\Util\Platform; /** * class Comparer * * @author Hector Prats */ class Comparer { /** @var string Source directory */ private $source; /** @var string Target directory */ private $update; /** @var array{changed?: string[], removed?: string[], added?: string[]} */ private $changed; public function setSource(string $source) : void { $this->source = $source; } public function setUpdate(string $update) : void { $this->update = $update; } /** * @return array{changed?: string[], removed?: string[], added?: string[]}|false false if no change */ public function getChanged(bool $explicated = \false) { $changed = $this->changed; if (!\count($changed)) { return \false; } if ($explicated) { foreach ($changed as $sectionKey => $itemSection) { foreach ($itemSection as $itemKey => $item) { $changed[$sectionKey][$itemKey] = $item . ' (' . $sectionKey . ')'; } } } return $changed; } /** * @return string empty string if no changes */ public function getChangedAsString(bool $toString = \false, bool $explicated = \false) : string { $changed = $this->getChanged($explicated); if (\false === $changed) { return ''; } $strings = []; foreach ($changed as $sectionKey => $itemSection) { foreach ($itemSection as $itemKey => $item) { $strings[] = $item . "\r\n"; } } return \trim(\implode("\r\n", $strings)); } public function doCompare() : void { $source = []; $destination = []; $this->changed = []; $currentDirectory = Platform::getCwd(); \chdir($this->source); $source = $this->doTree('.', $source); if (!\is_array($source)) { return; } \chdir($currentDirectory); \chdir($this->update); $destination = $this->doTree('.', $destination); if (!\is_array($destination)) { exit; } \chdir($currentDirectory); foreach ($source as $dir => $value) { foreach ($value as $file => $hash) { if (isset($destination[$dir][$file])) { if ($hash !== $destination[$dir][$file]) { $this->changed['changed'][] = $dir . '/' . $file; } } else { $this->changed['removed'][] = $dir . '/' . $file; } } } foreach ($destination as $dir => $value) { foreach ($value as $file => $hash) { if (!isset($source[$dir][$file])) { $this->changed['added'][] = $dir . '/' . $file; } } } } /** * @param mixed[] $array * * @return array>|false */ private function doTree(string $dir, array &$array) { if ($dh = \opendir($dir)) { while ($file = \readdir($dh)) { if ($file !== '.' && $file !== '..') { if (\is_link($dir . '/' . $file)) { $array[$dir][$file] = \readlink($dir . '/' . $file); } elseif (\is_dir($dir . '/' . $file)) { if (!\count($array)) { $array[0] = 'Temp'; } if (!$this->doTree($dir . '/' . $file, $array)) { return \false; } } elseif (\is_file($dir . '/' . $file) && \filesize($dir . '/' . $file)) { $array[$dir][$file] = \hash_file(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', $dir . '/' . $file); } } } if (\count($array) > 1 && isset($array['0'])) { unset($array['0']); } return $array; } return \false; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; /** * @author Jordi Boggiano */ class RootAliasPackage extends \Composer\Package\CompleteAliasPackage implements \Composer\Package\RootPackageInterface { /** @var RootPackage */ protected $aliasOf; /** * All descendants' constructors should call this parent constructor * * @param RootPackage $aliasOf The package this package is an alias of * @param string $version The version the alias must report * @param string $prettyVersion The alias's non-normalized version */ public function __construct(\Composer\Package\RootPackage $aliasOf, string $version, string $prettyVersion) { parent::__construct($aliasOf, $version, $prettyVersion); } /** * @return RootPackage */ public function getAliasOf() { return $this->aliasOf; } /** * @inheritDoc */ public function getAliases() : array { return $this->aliasOf->getAliases(); } /** * @inheritDoc */ public function getMinimumStability() : string { return $this->aliasOf->getMinimumStability(); } /** * @inheritDoc */ public function getStabilityFlags() : array { return $this->aliasOf->getStabilityFlags(); } /** * @inheritDoc */ public function getReferences() : array { return $this->aliasOf->getReferences(); } /** * @inheritDoc */ public function getPreferStable() : bool { return $this->aliasOf->getPreferStable(); } /** * @inheritDoc */ public function getConfig() : array { return $this->aliasOf->getConfig(); } /** * @inheritDoc */ public function setRequires(array $requires) : void { $this->requires = $this->replaceSelfVersionDependencies($requires, \Composer\Package\Link::TYPE_REQUIRE); $this->aliasOf->setRequires($requires); } /** * @inheritDoc */ public function setDevRequires(array $devRequires) : void { $this->devRequires = $this->replaceSelfVersionDependencies($devRequires, \Composer\Package\Link::TYPE_DEV_REQUIRE); $this->aliasOf->setDevRequires($devRequires); } /** * @inheritDoc */ public function setConflicts(array $conflicts) : void { $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, \Composer\Package\Link::TYPE_CONFLICT); $this->aliasOf->setConflicts($conflicts); } /** * @inheritDoc */ public function setProvides(array $provides) : void { $this->provides = $this->replaceSelfVersionDependencies($provides, \Composer\Package\Link::TYPE_PROVIDE); $this->aliasOf->setProvides($provides); } /** * @inheritDoc */ public function setReplaces(array $replaces) : void { $this->replaces = $this->replaceSelfVersionDependencies($replaces, \Composer\Package\Link::TYPE_REPLACE); $this->aliasOf->setReplaces($replaces); } /** * @inheritDoc */ public function setAutoload(array $autoload) : void { $this->aliasOf->setAutoload($autoload); } /** * @inheritDoc */ public function setDevAutoload(array $devAutoload) : void { $this->aliasOf->setDevAutoload($devAutoload); } /** * @inheritDoc */ public function setStabilityFlags(array $stabilityFlags) : void { $this->aliasOf->setStabilityFlags($stabilityFlags); } /** * @inheritDoc */ public function setMinimumStability(string $minimumStability) : void { $this->aliasOf->setMinimumStability($minimumStability); } /** * @inheritDoc */ public function setPreferStable(bool $preferStable) : void { $this->aliasOf->setPreferStable($preferStable); } /** * @inheritDoc */ public function setConfig(array $config) : void { $this->aliasOf->setConfig($config); } /** * @inheritDoc */ public function setReferences(array $references) : void { $this->aliasOf->setReferences($references); } /** * @inheritDoc */ public function setAliases(array $aliases) : void { $this->aliasOf->setAliases($aliases); } /** * @inheritDoc */ public function setSuggests(array $suggests) : void { $this->aliasOf->setSuggests($suggests); } /** * @inheritDoc */ public function setExtra(array $extra) : void { $this->aliasOf->setExtra($extra); } public function __clone() { parent::__clone(); $this->aliasOf = clone $this->aliasOf; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; /** * Package containing additional metadata that is not used by the solver * * @author Nils Adermann */ class CompletePackage extends \Composer\Package\Package implements \Composer\Package\CompletePackageInterface { /** @var mixed[] */ protected $repositories = []; /** @var string[] */ protected $license = []; /** @var string[] */ protected $keywords = []; /** @var array */ protected $authors = []; /** @var ?string */ protected $description = null; /** @var ?string */ protected $homepage = null; /** @var array Map of script name to array of handlers */ protected $scripts = []; /** @var array{issues?: string, forum?: string, wiki?: string, source?: string, email?: string, irc?: string, docs?: string, rss?: string, chat?: string, security?: string} */ protected $support = []; /** @var array */ protected $funding = []; /** @var bool|string */ protected $abandoned = \false; /** @var ?string */ protected $archiveName = null; /** @var string[] */ protected $archiveExcludes = []; /** * @inheritDoc */ public function setScripts(array $scripts) : void { $this->scripts = $scripts; } /** * @inheritDoc */ public function getScripts() : array { return $this->scripts; } /** * @inheritDoc */ public function setRepositories(array $repositories) : void { $this->repositories = $repositories; } /** * @inheritDoc */ public function getRepositories() : array { return $this->repositories; } /** * @inheritDoc */ public function setLicense(array $license) : void { $this->license = $license; } /** * @inheritDoc */ public function getLicense() : array { return $this->license; } /** * @inheritDoc */ public function setKeywords(array $keywords) : void { $this->keywords = $keywords; } /** * @inheritDoc */ public function getKeywords() : array { return $this->keywords; } /** * @inheritDoc */ public function setAuthors(array $authors) : void { $this->authors = $authors; } /** * @inheritDoc */ public function getAuthors() : array { return $this->authors; } /** * @inheritDoc */ public function setDescription(?string $description) : void { $this->description = $description; } /** * @inheritDoc */ public function getDescription() : ?string { return $this->description; } /** * @inheritDoc */ public function setHomepage(?string $homepage) : void { $this->homepage = $homepage; } /** * @inheritDoc */ public function getHomepage() : ?string { return $this->homepage; } /** * @inheritDoc */ public function setSupport(array $support) : void { $this->support = $support; } /** * @inheritDoc */ public function getSupport() : array { return $this->support; } /** * @inheritDoc */ public function setFunding(array $funding) : void { $this->funding = $funding; } /** * @inheritDoc */ public function getFunding() : array { return $this->funding; } /** * @inheritDoc */ public function isAbandoned() : bool { return (bool) $this->abandoned; } /** * @inheritDoc */ public function setAbandoned($abandoned) : void { $this->abandoned = $abandoned; } /** * @inheritDoc */ public function getReplacementPackage() : ?string { return \is_string($this->abandoned) ? $this->abandoned : null; } /** * @inheritDoc */ public function setArchiveName(?string $name) : void { $this->archiveName = $name; } /** * @inheritDoc */ public function getArchiveName() : ?string { return $this->archiveName; } /** * @inheritDoc */ public function setArchiveExcludes(array $excludes) : void { $this->archiveExcludes = $excludes; } /** * @inheritDoc */ public function getArchiveExcludes() : array { return $this->archiveExcludes; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; /** * Defines additional fields that are only needed for the root package * * PackageInterface & derivatives are considered internal, you may use them in type hints but extending/implementing them is not recommended and not supported. Things may change without notice. * * @author Jordi Boggiano * * @phpstan-import-type AutoloadRules from PackageInterface * @phpstan-import-type DevAutoloadRules from PackageInterface */ interface RootPackageInterface extends \Composer\Package\CompletePackageInterface { /** * Returns a set of package names and their aliases * * @return list */ public function getAliases() : array; /** * Returns the minimum stability of the package * * @return key-of */ public function getMinimumStability() : string; /** * Returns the stability flags to apply to dependencies * * array('foo/bar' => 'dev') * * @return array */ public function getStabilityFlags() : array; /** * Returns a set of package names and source references that must be enforced on them * * array('foo/bar' => 'abcd1234') * * @return array */ public function getReferences() : array; /** * Returns true if the root package prefers picking stable packages over unstable ones */ public function getPreferStable() : bool; /** * Returns the root package's configuration * * @return mixed[] */ public function getConfig() : array; /** * Set the required packages * * @param Link[] $requires A set of package links */ public function setRequires(array $requires) : void; /** * Set the recommended packages * * @param Link[] $devRequires A set of package links */ public function setDevRequires(array $devRequires) : void; /** * Set the conflicting packages * * @param Link[] $conflicts A set of package links */ public function setConflicts(array $conflicts) : void; /** * Set the provided virtual packages * * @param Link[] $provides A set of package links */ public function setProvides(array $provides) : void; /** * Set the packages this one replaces * * @param Link[] $replaces A set of package links */ public function setReplaces(array $replaces) : void; /** * Set the autoload mapping * * @param array $autoload Mapping of autoloading rules * @phpstan-param AutoloadRules $autoload */ public function setAutoload(array $autoload) : void; /** * Set the dev autoload mapping * * @param array $devAutoload Mapping of dev autoloading rules * @phpstan-param DevAutoloadRules $devAutoload */ public function setDevAutoload(array $devAutoload) : void; /** * Set the stabilityFlags * * @phpstan-param array $stabilityFlags */ public function setStabilityFlags(array $stabilityFlags) : void; /** * Set the minimumStability * * @phpstan-param key-of $minimumStability */ public function setMinimumStability(string $minimumStability) : void; /** * Set the preferStable */ public function setPreferStable(bool $preferStable) : void; /** * Set the config * * @param mixed[] $config */ public function setConfig(array $config) : void; /** * Set the references * * @param array $references */ public function setReferences(array $references) : void; /** * Set the aliases * * @param list $aliases */ public function setAliases(array $aliases) : void; /** * Set the suggested packages * * @param array $suggests A set of package names/comments */ public function setSuggests(array $suggests) : void; /** * @param mixed[] $extra */ public function setExtra(array $extra) : void; } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package; /** * The root package represents the project's composer.json and contains additional metadata * * @author Jordi Boggiano */ class RootPackage extends \Composer\Package\CompletePackage implements \Composer\Package\RootPackageInterface { public const DEFAULT_PRETTY_VERSION = '1.0.0+no-version-set'; /** @var key-of */ protected $minimumStability = 'stable'; /** @var bool */ protected $preferStable = \false; /** @var array Map of package name to stability constant */ protected $stabilityFlags = []; /** @var mixed[] */ protected $config = []; /** @var array Map of package name to reference/commit hash */ protected $references = []; /** @var list */ protected $aliases = []; /** * @inheritDoc */ public function setMinimumStability(string $minimumStability) : void { $this->minimumStability = $minimumStability; } /** * @inheritDoc */ public function getMinimumStability() : string { return $this->minimumStability; } /** * @inheritDoc */ public function setStabilityFlags(array $stabilityFlags) : void { $this->stabilityFlags = $stabilityFlags; } /** * @inheritDoc */ public function getStabilityFlags() : array { return $this->stabilityFlags; } /** * @inheritDoc */ public function setPreferStable(bool $preferStable) : void { $this->preferStable = $preferStable; } /** * @inheritDoc */ public function getPreferStable() : bool { return $this->preferStable; } /** * @inheritDoc */ public function setConfig(array $config) : void { $this->config = $config; } /** * @inheritDoc */ public function getConfig() : array { return $this->config; } /** * @inheritDoc */ public function setReferences(array $references) : void { $this->references = $references; } /** * @inheritDoc */ public function getReferences() : array { return $this->references; } /** * @inheritDoc */ public function setAliases(array $aliases) : void { $this->aliases = $aliases; } /** * @inheritDoc */ public function getAliases() : array { return $this->aliases; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Package\Dumper; use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Package\CompletePackageInterface; use Composer\Package\RootPackageInterface; /** * @author Konstantin Kudryashiv * @author Jordi Boggiano */ class ArrayDumper { /** * @return array */ public function dump(PackageInterface $package) : array { $keys = ['binaries' => 'bin', 'type', 'extra', 'installationSource' => 'installation-source', 'autoload', 'devAutoload' => 'autoload-dev', 'notificationUrl' => 'notification-url', 'includePaths' => 'include-path', 'phpExt' => 'php-ext']; $data = []; $data['name'] = $package->getPrettyName(); $data['version'] = $package->getPrettyVersion(); $data['version_normalized'] = $package->getVersion(); if ($package->getTargetDir() !== null) { $data['target-dir'] = $package->getTargetDir(); } if ($package->getSourceType() !== null) { $data['source']['type'] = $package->getSourceType(); $data['source']['url'] = $package->getSourceUrl(); if (null !== ($value = $package->getSourceReference())) { $data['source']['reference'] = $value; } if ($mirrors = $package->getSourceMirrors()) { $data['source']['mirrors'] = $mirrors; } } if ($package->getDistType() !== null) { $data['dist']['type'] = $package->getDistType(); $data['dist']['url'] = $package->getDistUrl(); if (null !== ($value = $package->getDistReference())) { $data['dist']['reference'] = $value; } if (null !== ($value = $package->getDistSha1Checksum())) { $data['dist']['shasum'] = $value; } if ($mirrors = $package->getDistMirrors()) { $data['dist']['mirrors'] = $mirrors; } } foreach (BasePackage::$supportedLinkTypes as $type => $opts) { $links = $package->{'get' . \ucfirst($opts['method'])}(); if (\count($links) === 0) { continue; } foreach ($links as $link) { $data[$type][$link->getTarget()] = $link->getPrettyConstraint(); } \ksort($data[$type]); } $packages = $package->getSuggests(); if (\count($packages) > 0) { \ksort($packages); $data['suggest'] = $packages; } if ($package->getReleaseDate() instanceof \DateTimeInterface) { $data['time'] = $package->getReleaseDate()->format(\DATE_RFC3339); } if ($package->isDefaultBranch()) { $data['default-branch'] = \true; } $data = $this->dumpValues($package, $keys, $data); if ($package instanceof CompletePackageInterface) { if ($package->getArchiveName()) { $data['archive']['name'] = $package->getArchiveName(); } if ($package->getArchiveExcludes()) { $data['archive']['exclude'] = $package->getArchiveExcludes(); } $keys = ['scripts', 'license', 'authors', 'description', 'homepage', 'keywords', 'repositories', 'support', 'funding']; $data = $this->dumpValues($package, $keys, $data); if (isset($data['keywords']) && \is_array($data['keywords'])) { \sort($data['keywords']); } if ($package->isAbandoned()) { $data['abandoned'] = $package->getReplacementPackage() ?: \true; } } if ($package instanceof RootPackageInterface) { $minimumStability = $package->getMinimumStability(); if ($minimumStability !== '') { $data['minimum-stability'] = $minimumStability; } } if (\count($package->getTransportOptions()) > 0) { $data['transport-options'] = $package->getTransportOptions(); } return $data; } /** * @param array $keys * @param array $data * * @return array */ private function dumpValues(PackageInterface $package, array $keys, array $data) : array { foreach ($keys as $method => $key) { if (\is_numeric($method)) { $method = $key; } $getter = 'get' . \ucfirst($method); $value = $package->{$getter}(); if (null !== $value && !(\is_array($value) && 0 === \count($value))) { $data[$key] = $value; } } return $data; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Console; use Composer\Installer; use Composer\IO\NullIO; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\Silencer; use LogicException; use RuntimeException; use _ContaoManager\Symfony\Component\Console\Application as BaseApplication; use _ContaoManager\Symfony\Component\Console\Exception\CommandNotFoundException; use _ContaoManager\Symfony\Component\Console\Exception\ExceptionInterface; use _ContaoManager\Symfony\Component\Console\Helper\HelperSet; use _ContaoManager\Symfony\Component\Console\Helper\QuestionHelper; use _ContaoManager\Symfony\Component\Console\Input\InputDefinition; use _ContaoManager\Symfony\Component\Console\Input\InputInterface; use _ContaoManager\Symfony\Component\Console\Input\InputOption; use _ContaoManager\Symfony\Component\Console\Output\ConsoleOutputInterface; use _ContaoManager\Symfony\Component\Console\Output\OutputInterface; use _ContaoManager\Seld\JsonLint\ParsingException; use Composer\Command; use Composer\Composer; use Composer\Factory; use Composer\Downloader\TransportException; use Composer\IO\IOInterface; use Composer\IO\ConsoleIO; use Composer\Json\JsonValidationException; use Composer\Util\ErrorHandler; use Composer\Util\HttpDownloader; use Composer\EventDispatcher\ScriptExecutionException; use Composer\Exception\NoSslException; use Composer\XdebugHandler\XdebugHandler; use _ContaoManager\Symfony\Component\Process\Exception\ProcessTimedOutException; /** * The console application that handles the commands * * @author Ryan Weaver * @author Jordi Boggiano * @author François Pluchino */ class Application extends BaseApplication { /** * @var ?Composer */ protected $composer; /** * @var IOInterface */ protected $io; /** @var string */ private static $logo = ' ______ / ____/___ ____ ___ ____ ____ ________ _____ / / / __ \\/ __ `__ \\/ __ \\/ __ \\/ ___/ _ \\/ ___/ / /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ / \\____/\\____/_/ /_/ /_/ .___/\\____/____/\\___/_/ /_/ '; /** @var bool */ private $hasPluginCommands = \false; /** @var bool */ private $disablePluginsByDefault = \false; /** @var bool */ private $disableScriptsByDefault = \false; /** * @var string|false Store the initial working directory at startup time */ private $initialWorkingDirectory; public function __construct(string $name = 'Composer', string $version = '') { if (\method_exists($this, 'setCatchErrors')) { $this->setCatchErrors(\true); } static $shutdownRegistered = \false; if ($version === '') { $version = Composer::getVersion(); } if (\function_exists('ini_set') && \extension_loaded('xdebug')) { \ini_set('xdebug.show_exception_trace', '0'); \ini_set('xdebug.scream', '0'); } if (\function_exists('date_default_timezone_set') && \function_exists('date_default_timezone_get')) { \date_default_timezone_set(Silencer::call('date_default_timezone_get')); } $this->io = new NullIO(); if (!$shutdownRegistered) { $shutdownRegistered = \true; \register_shutdown_function(static function () : void { $lastError = \error_get_last(); if ($lastError && $lastError['message'] && (\strpos($lastError['message'], 'Allowed memory') !== \false || \strpos($lastError['message'], 'exceeded memory') !== \false)) { echo "\n" . 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.'; } }); } $this->initialWorkingDirectory = \getcwd(); parent::__construct($name, $version); } public function __destruct() { } public function run(?InputInterface $input = null, ?OutputInterface $output = null) : int { if (null === $output) { $output = Factory::createOutput(); } return parent::run($input, $output); } public function doRun(InputInterface $input, OutputInterface $output) : int { $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins'); $this->disableScriptsByDefault = $input->hasParameterOption('--no-scripts'); static $stdin = null; if (null === $stdin) { $stdin = \defined('STDIN') ? \STDIN : \fopen('php://stdin', 'r'); } if (Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING') !== '1' && (Platform::getEnv('COMPOSER_NO_INTERACTION') || $stdin === \false || !Platform::isTty($stdin))) { $input->setInteractive(\false); } $io = $this->io = new ConsoleIO($input, $output, new HelperSet([new QuestionHelper()])); // Register error handler again to pass it the IO instance ErrorHandler::register($io); if ($input->hasParameterOption('--no-cache')) { $io->writeError('Disabling cache usage', \true, IOInterface::DEBUG); Platform::putEnv('COMPOSER_CACHE_DIR', Platform::isWindows() ? 'nul' : '/dev/null'); } // switch working dir $newWorkDir = $this->getNewWorkingDir($input); if (null !== $newWorkDir) { $oldWorkingDir = Platform::getCwd(\true); \chdir($newWorkDir); $this->initialWorkingDirectory = $newWorkDir; $cwd = Platform::getCwd(\true); $io->writeError('Changed CWD to ' . ($cwd !== '' ? $cwd : $newWorkDir), \true, IOInterface::DEBUG); } // determine command name to be executed without including plugin commands $commandName = ''; if ($name = $this->getCommandNameBeforeBinding($input)) { try { $commandName = $this->find($name)->getName(); } catch (CommandNotFoundException $e) { // we'll check command validity again later after plugins are loaded $commandName = \false; } catch (\InvalidArgumentException $e) { } } // prompt user for dir change if no composer.json is present in current dir if (null === $newWorkDir && !\in_array($commandName, ['', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project', 'outdated'], \true) && !\file_exists(Factory::getComposerFile()) && ($useParentDirIfNoJsonAvailable = $this->getUseParentDirConfigValue()) !== \false && ($commandName !== 'config' || $input->hasParameterOption('--file', \true) === \false && $input->hasParameterOption('-f', \true) === \false) && $input->hasParameterOption('--help', \true) === \false && $input->hasParameterOption('-h', \true) === \false) { $dir = \dirname(Platform::getCwd(\true)); $home = \realpath((Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE')) ?: '/'); // abort when we reach the home dir or top of the filesystem while (\dirname($dir) !== $dir && $dir !== $home) { if (\file_exists($dir . '/' . Factory::getComposerFile())) { if ($useParentDirIfNoJsonAvailable !== \true && !$io->isInteractive()) { $io->writeError('No composer.json in current directory, to use the one at ' . $dir . ' run interactively or set config.use-parent-dir to true'); break; } if ($useParentDirIfNoJsonAvailable === \true || $io->askConfirmation('No composer.json in current directory, do you want to use the one at ' . $dir . '? [Y,n]? ')) { if ($useParentDirIfNoJsonAvailable === \true) { $io->writeError('No composer.json in current directory, changing working directory to ' . $dir . ''); } else { $io->writeError('Always want to use the parent dir? Use "composer config --global use-parent-dir true" to change the default.'); } $oldWorkingDir = Platform::getCwd(\true); \chdir($dir); } break; } $dir = \dirname($dir); } unset($dir, $home); } $needsSudoCheck = !Platform::isWindows() && \function_exists('exec') && !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER') && !Platform::isDocker(); $isNonAllowedRoot = \false; // Clobber sudo credentials if COMPOSER_ALLOW_SUPERUSER is not set before loading plugins if ($needsSudoCheck) { $isNonAllowedRoot = $this->isRunningAsRoot(); if ($isNonAllowedRoot) { if ($uid = (int) Platform::getEnv('SUDO_UID')) { // Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on // ref. https://github.com/composer/composer/issues/5119 Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1"); } } // Silently clobber any remaining sudo leases on the current user as well to avoid privilege escalations Silencer::call('exec', 'sudo -K > /dev/null 2>&1'); } // avoid loading plugins/initializing the Composer instance earlier than necessary if no plugin command is needed // if showing the version, we never need plugin commands $mayNeedPluginCommand = \false === $input->hasParameterOption(['--version', '-V']) && (\false === $commandName || \in_array($commandName, ['', 'list', 'help'], \true) || $commandName === '_complete' && !$isNonAllowedRoot); if ($mayNeedPluginCommand && !$this->disablePluginsByDefault && !$this->hasPluginCommands) { // at this point plugins are needed, so if we are running as root and it is not allowed we need to prompt // if interactive, and abort otherwise if ($isNonAllowedRoot) { $io->writeError('Do not run Composer as root/super user! See https://getcomposer.org/root for details'); if ($io->isInteractive() && $io->askConfirmation('Continue as root/super user [yes]? ')) { // avoid a second prompt later $isNonAllowedRoot = \false; } else { $io->writeError('Aborting as no plugin should be loaded if running as super user is not explicitly allowed'); return 1; } } try { foreach ($this->getPluginCommands() as $command) { if ($this->has($command->getName())) { $io->writeError('Plugin command ' . $command->getName() . ' (' . \get_class($command) . ') would override a Composer command and has been skipped'); } else { $this->add($command); } } } catch (NoSslException $e) { // suppress these as they are not relevant at this point } catch (ParsingException $e) { $details = $e->getDetails(); $file = \realpath(Factory::getComposerFile()); $line = null; if ($details && isset($details['line'])) { $line = $details['line']; } $ghe = new \Composer\Console\GithubActionError($this->io); $ghe->emit($e->getMessage(), $file, $line); throw $e; } $this->hasPluginCommands = \true; } if (!$this->disablePluginsByDefault && $isNonAllowedRoot && !$io->isInteractive()) { $io->writeError('Composer plugins have been disabled for safety in this non-interactive session.'); $io->writeError('Set COMPOSER_ALLOW_SUPERUSER=1 if you want to allow plugins to run as root/super user.'); $this->disablePluginsByDefault = \true; } // determine command name to be executed incl plugin commands, and check if it's a proxy command $isProxyCommand = \false; if ($name = $this->getCommandNameBeforeBinding($input)) { try { $command = $this->find($name); $commandName = $command->getName(); $isProxyCommand = $command instanceof Command\BaseCommand && $command->isProxyCommand(); } catch (\InvalidArgumentException $e) { } } if (!$isProxyCommand) { $io->writeError(\sprintf('Running %s (%s) with %s on %s', Composer::getVersion(), Composer::RELEASE_DATE, \defined('_ContaoManager\\HHVM_VERSION') ? 'HHVM ' . HHVM_VERSION : 'PHP ' . \PHP_VERSION, \function_exists('php_uname') ? \php_uname('s') . ' / ' . \php_uname('r') : 'Unknown OS'), \true, IOInterface::DEBUG); if (\PHP_VERSION_ID < 70205) { $io->writeError('Composer supports PHP 7.2.5 and above, you will most likely encounter problems with your PHP ' . \PHP_VERSION . '. Upgrading is strongly recommended but you can use Composer 2.2.x LTS as a fallback.'); } if (XdebugHandler::isXdebugActive() && !Platform::getEnv('COMPOSER_DISABLE_XDEBUG_WARN')) { $io->writeError('Composer is operating slower than normal because you have Xdebug enabled. See https://getcomposer.org/xdebug'); } if (\defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && \time() > \COMPOSER_DEV_WARNING_TIME) { $io->writeError(\sprintf('Warning: This development build of Composer is over 60 days old. It is recommended to update it by running "%s self-update" to get the latest version.', $_SERVER['PHP_SELF'])); } if ($isNonAllowedRoot) { if ($commandName !== 'self-update' && $commandName !== 'selfupdate' && $commandName !== '_complete') { $io->writeError('Do not run Composer as root/super user! See https://getcomposer.org/root for details'); if ($io->isInteractive()) { if (!$io->askConfirmation('Continue as root/super user [yes]? ')) { return 1; } } } } // Check system temp folder for usability as it can cause weird runtime issues otherwise Silencer::call(static function () use($io) : void { $pid = \function_exists('getmypid') ? \getmypid() . '-' : ''; $tempfile = \sys_get_temp_dir() . '/temp-' . $pid . \bin2hex(\random_bytes(5)); if (!(\file_put_contents($tempfile, __FILE__) && \file_get_contents($tempfile) === __FILE__ && \unlink($tempfile) && !\file_exists($tempfile))) { $io->writeError(\sprintf('PHP temp directory (%s) does not exist or is not writable to Composer. Set sys_temp_dir in your php.ini', \sys_get_temp_dir())); } }); // add non-standard scripts as own commands $file = Factory::getComposerFile(); if (\is_file($file) && Filesystem::isReadable($file) && \is_array($composer = \json_decode(\file_get_contents($file), \true))) { if (isset($composer['scripts']) && \is_array($composer['scripts'])) { foreach ($composer['scripts'] as $script => $dummy) { if (!\defined('Composer\\Script\\ScriptEvents::' . \str_replace('-', '_', \strtoupper($script)))) { if ($this->has($script)) { $io->writeError('A script named ' . $script . ' would override a Composer command and has been skipped'); } else { $description = null; if (isset($composer['scripts-descriptions'][$script])) { $description = $composer['scripts-descriptions'][$script]; } $aliases = $composer['scripts-aliases'][$script] ?? []; $this->add(new Command\ScriptAliasCommand($script, $description, $aliases)); } } } } } } try { if ($input->hasParameterOption('--profile')) { $startTime = \microtime(\true); $this->io->enableDebugging($startTime); } $result = parent::doRun($input, $output); if (\true === $input->hasParameterOption(['--version', '-V'], \true)) { $io->writeError(\sprintf('PHP version %s (%s)', \PHP_VERSION, \PHP_BINARY)); $io->writeError('Run the "diagnose" command to get more detailed diagnostics output.'); } // chdir back to $oldWorkingDir if set if (isset($oldWorkingDir) && '' !== $oldWorkingDir) { Silencer::call('chdir', $oldWorkingDir); } if (isset($startTime)) { $io->writeError('Memory usage: ' . \round(\memory_get_usage() / 1024 / 1024, 2) . 'MiB (peak: ' . \round(\memory_get_peak_usage() / 1024 / 1024, 2) . 'MiB), time: ' . \round(\microtime(\true) - $startTime, 2) . 's'); } return $result; } catch (ScriptExecutionException $e) { if ($this->getDisablePluginsByDefault() && $this->isRunningAsRoot() && !$this->io->isInteractive()) { $io->writeError('Plugins have been disabled automatically as you are running as root, this may be the cause of the script failure.', \true, IOInterface::QUIET); $io->writeError('See also https://getcomposer.org/root', \true, IOInterface::QUIET); } return $e->getCode(); } catch (\Throwable $e) { $ghe = new \Composer\Console\GithubActionError($this->io); $ghe->emit($e->getMessage()); $this->hintCommonErrors($e, $output); // symfony/console <6.4 does not handle \Error subtypes so we have to renderThrowable ourselves // instead of rethrowing those for consumption by the parent class // can be removed when Composer supports PHP 8.1+ if (!\method_exists($this, 'setCatchErrors') && !$e instanceof \Exception) { if ($output instanceof ConsoleOutputInterface) { $this->renderThrowable($e, $output->getErrorOutput()); } else { $this->renderThrowable($e, $output); } return \max(1, $e->getCode()); } // override TransportException's code for the purpose of parent::run() using it as process exit code // as http error codes are all beyond the 255 range of permitted exit codes if ($e instanceof TransportException) { $reflProp = new \ReflectionProperty($e, 'code'); $reflProp->setAccessible(\true); $reflProp->setValue($e, Installer::ERROR_TRANSPORT_EXCEPTION); } throw $e; } finally { \restore_error_handler(); } } /** * @throws \RuntimeException * @return ?string */ private function getNewWorkingDir(InputInterface $input) : ?string { /** @var string|null $workingDir */ $workingDir = $input->getParameterOption(['--working-dir', '-d'], null, \true); if (null !== $workingDir && !\is_dir($workingDir)) { throw new \RuntimeException('Invalid working directory specified, ' . $workingDir . ' does not exist.'); } return $workingDir; } private function hintCommonErrors(\Throwable $exception, OutputInterface $output) : void { $io = $this->getIO(); if ((\get_class($exception) === LogicException::class || $exception instanceof \Error) && $output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE) { $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); } Silencer::suppress(); try { $composer = $this->getComposer(\false, \true); if (null !== $composer && \function_exists('disk_free_space')) { $config = $composer->getConfig(); $minSpaceFree = 100 * 1024 * 1024; if (($df = \disk_free_space($dir = $config->get('home'))) !== \false && $df < $minSpaceFree || ($df = \disk_free_space($dir = $config->get('vendor-dir'))) !== \false && $df < $minSpaceFree || ($df = \disk_free_space($dir = \sys_get_temp_dir())) !== \false && $df < $minSpaceFree) { $io->writeError('The disk hosting ' . $dir . ' has less than 100MiB of free space, this may be the cause of the following exception', \true, IOInterface::QUIET); } } } catch (\Exception $e) { } Silencer::restore(); if ($exception instanceof TransportException && \str_contains($exception->getMessage(), 'Unable to use a proxy')) { $io->writeError('The following exception indicates your proxy is misconfigured', \true, IOInterface::QUIET); $io->writeError('Check https://getcomposer.org/doc/faqs/how-to-use-composer-behind-a-proxy.md for details', \true, IOInterface::QUIET); } if (Platform::isWindows() && \false !== \strpos($exception->getMessage(), 'The system cannot find the path specified')) { $io->writeError('The following exception may be caused by a stale entry in your cmd.exe AutoRun', \true, IOInterface::QUIET); $io->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details', \true, IOInterface::QUIET); } if (\false !== \strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) { $io->writeError('The following exception is caused by a lack of memory or swap, or not having swap configured', \true, IOInterface::QUIET); $io->writeError('Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details', \true, IOInterface::QUIET); } if ($exception instanceof ProcessTimedOutException) { $io->writeError('The following exception is caused by a process timeout', \true, IOInterface::QUIET); $io->writeError('Check https://getcomposer.org/doc/06-config.md#process-timeout for details', \true, IOInterface::QUIET); } if ($this->getDisablePluginsByDefault() && $this->isRunningAsRoot() && !$this->io->isInteractive()) { $io->writeError('Plugins have been disabled automatically as you are running as root, this may be the cause of the following exception. See also https://getcomposer.org/root', \true, IOInterface::QUIET); } elseif ($exception instanceof CommandNotFoundException && $this->getDisablePluginsByDefault()) { $io->writeError('Plugins have been disabled, which may be why some commands are missing, unless you made a typo', \true, IOInterface::QUIET); } $hints = HttpDownloader::getExceptionHints($exception); if (null !== $hints && \count($hints) > 0) { foreach ($hints as $hint) { $io->writeError($hint, \true, IOInterface::QUIET); } } } /** * @throws JsonValidationException * @throws \InvalidArgumentException * @return ?Composer If $required is true then the return value is guaranteed */ public function getComposer(bool $required = \true, ?bool $disablePlugins = null, ?bool $disableScripts = null) : ?Composer { if (null === $disablePlugins) { $disablePlugins = $this->disablePluginsByDefault; } if (null === $disableScripts) { $disableScripts = $this->disableScriptsByDefault; } if (null === $this->composer) { try { $this->composer = Factory::create(Platform::isInputCompletionProcess() ? new NullIO() : $this->io, null, $disablePlugins, $disableScripts); } catch (\InvalidArgumentException $e) { if ($required) { $this->io->writeError($e->getMessage()); if ($this->areExceptionsCaught()) { exit(1); } throw $e; } } catch (JsonValidationException $e) { if ($required) { throw $e; } } catch (RuntimeException $e) { if ($required) { throw $e; } } } return $this->composer; } /** * Removes the cached composer instance */ public function resetComposer() : void { $this->composer = null; if (\method_exists($this->getIO(), 'resetAuthentications')) { $this->getIO()->resetAuthentications(); } } public function getIO() : IOInterface { return $this->io; } public function getHelp() : string { return self::$logo . parent::getHelp(); } /** * Initializes all the composer commands. * @return \Symfony\Component\Console\Command\Command[] */ protected function getDefaultCommands() : array { $commands = \array_merge(parent::getDefaultCommands(), [new Command\AboutCommand(), new Command\ConfigCommand(), new Command\DependsCommand(), new Command\ProhibitsCommand(), new Command\InitCommand(), new Command\InstallCommand(), new Command\CreateProjectCommand(), new Command\UpdateCommand(), new Command\SearchCommand(), new Command\ValidateCommand(), new Command\AuditCommand(), new Command\ShowCommand(), new Command\SuggestsCommand(), new Command\RequireCommand(), new Command\DumpAutoloadCommand(), new Command\StatusCommand(), new Command\ArchiveCommand(), new Command\DiagnoseCommand(), new Command\RunScriptCommand(), new Command\LicensesCommand(), new Command\GlobalCommand(), new Command\ClearCacheCommand(), new Command\RemoveCommand(), new Command\HomeCommand(), new Command\ExecCommand(), new Command\OutdatedCommand(), new Command\CheckPlatformReqsCommand(), new Command\FundCommand(), new Command\ReinstallCommand(), new Command\BumpCommand()]); if (\strpos(__FILE__, 'phar:') === 0 || '1' === Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING')) { $commands[] = new Command\SelfUpdateCommand(); } return $commands; } /** * This ensures we can find the correct command name even if a global input option is present before it * * e.g. "composer -d foo bar" should detect bar as the command name, and not foo */ private function getCommandNameBeforeBinding(InputInterface $input) : ?string { $input = clone $input; try { // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. $input->bind($this->getDefinition()); } catch (ExceptionInterface $e) { // Errors must be ignored, full binding/validation happens later when the command is known. } return $input->getFirstArgument(); } public function getLongVersion() : string { $branchAliasString = ''; if (Composer::BRANCH_ALIAS_VERSION && Composer::BRANCH_ALIAS_VERSION !== '@package_branch_alias_version' . '@') { $branchAliasString = \sprintf(' (%s)', Composer::BRANCH_ALIAS_VERSION); } return \sprintf('%s version %s%s %s', $this->getName(), $this->getVersion(), $branchAliasString, Composer::RELEASE_DATE); } protected function getDefaultInputDefinition() : InputDefinition { $definition = parent::getDefaultInputDefinition(); $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information')); $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.')); $definition->addOption(new InputOption('--no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.')); $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.')); $definition->addOption(new InputOption('--no-cache', null, InputOption::VALUE_NONE, 'Prevent use of the cache')); return $definition; } /** * @return Command\BaseCommand[] */ private function getPluginCommands() : array { $commands = []; $composer = $this->getComposer(\false, \false); if (null === $composer) { $composer = Factory::createGlobal($this->io, $this->disablePluginsByDefault, $this->disableScriptsByDefault); } if (null !== $composer) { $pm = $composer->getPluginManager(); foreach ($pm->getPluginCapabilities('Composer\\Plugin\\Capability\\CommandProvider', ['composer' => $composer, 'io' => $this->io]) as $capability) { $newCommands = $capability->getCommands(); if (!\is_array($newCommands)) { throw new \UnexpectedValueException('Plugin capability ' . \get_class($capability) . ' failed to return an array from getCommands'); } foreach ($newCommands as $command) { if (!$command instanceof Command\BaseCommand) { throw new \UnexpectedValueException('Plugin capability ' . \get_class($capability) . ' returned an invalid value, we expected an array of Composer\\Command\\BaseCommand objects'); } } $commands = \array_merge($commands, $newCommands); } } return $commands; } /** * Get the working directory at startup time * * @return string|false */ public function getInitialWorkingDirectory() { return $this->initialWorkingDirectory; } public function getDisablePluginsByDefault() : bool { return $this->disablePluginsByDefault; } public function getDisableScriptsByDefault() : bool { return $this->disableScriptsByDefault; } /** * @return 'prompt'|bool */ private function getUseParentDirConfigValue() { $config = Factory::createConfig($this->io); return $config->get('use-parent-dir'); } private function isRunningAsRoot() : bool { return \function_exists('posix_getuid') && \posix_getuid() === 0; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Console; use Composer\IO\IOInterface; use Composer\Util\Platform; final class GithubActionError { /** * @var IOInterface */ protected $io; public function __construct(IOInterface $io) { $this->io = $io; } public function emit(string $message, ?string $file = null, ?int $line = null) : void { if (Platform::getEnv('GITHUB_ACTIONS') && !Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING')) { $message = $this->escapeData($message); if ($file && $line) { $file = $this->escapeProperty($file); $this->io->write("::error file=" . $file . ",line=" . $line . "::" . $message); } elseif ($file) { $file = $this->escapeProperty($file); $this->io->write("::error file=" . $file . "::" . $message); } else { $this->io->write("::error ::" . $message); } } } private function escapeData(string $data) : string { // see https://github.com/actions/toolkit/blob/4f7fb6513a355689f69f0849edeb369a4dc81729/packages/core/src/command.ts#L80-L85 $data = \str_replace("%", '%25', $data); $data = \str_replace("\r", '%0D', $data); $data = \str_replace("\n", '%0A', $data); return $data; } private function escapeProperty(string $property) : string { // see https://github.com/actions/toolkit/blob/4f7fb6513a355689f69f0849edeb369a4dc81729/packages/core/src/command.ts#L87-L94 $property = \str_replace("%", '%25', $property); $property = \str_replace("\r", '%0D', $property); $property = \str_replace("\n", '%0A', $property); $property = \str_replace(":", '%3A', $property); $property = \str_replace(",", '%2C', $property); return $property; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Console\Input; use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput; use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions; use _ContaoManager\Symfony\Component\Console\Completion\Suggestion; use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException; use _ContaoManager\Symfony\Component\Console\Exception\LogicException; use _ContaoManager\Symfony\Component\Console\Input\InputArgument as BaseInputArgument; /** * Backport suggested values definition from symfony/console 6.1+ * * @author Jérôme Tamarelle * * @internal * * TODO symfony/console:6.1 drop when PHP 8.1 / symfony 6.1+ can be required */ class InputArgument extends BaseInputArgument { /** * @var list|\Closure(CompletionInput,CompletionSuggestions):list */ private $suggestedValues; /** * @param string $name The argument name * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text * @param string|bool|int|float|string[]|null $default The default value (for self::OPTIONAL mode only) * @param list|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion * * @throws InvalidArgumentException When argument mode is not valid */ public function __construct(string $name, ?int $mode = null, string $description = '', $default = null, $suggestedValues = []) { parent::__construct($name, $mode, $description, $default); $this->suggestedValues = $suggestedValues; } /** * Adds suggestions to $suggestions for the current completion input. * * @see Command::complete() */ public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void { $values = $this->suggestedValues; if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore function.impossibleType throw new LogicException(\sprintf('Closure for option "%s" must return an array. Got "%s".', $this->getName(), \get_debug_type($values))); } if ([] !== $values) { $suggestions->suggestValues($values); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Console\Input; use _ContaoManager\Symfony\Component\Console\Completion\CompletionInput; use _ContaoManager\Symfony\Component\Console\Completion\CompletionSuggestions; use _ContaoManager\Symfony\Component\Console\Completion\Suggestion; use _ContaoManager\Symfony\Component\Console\Exception\InvalidArgumentException; use _ContaoManager\Symfony\Component\Console\Exception\LogicException; use _ContaoManager\Symfony\Component\Console\Input\InputOption as BaseInputOption; /** * Backport suggested values definition from symfony/console 6.1+ * * @author Jérôme Tamarelle * * @internal * * TODO symfony/console:6.1 drop when PHP 8.1 / symfony 6.1+ can be required */ class InputOption extends BaseInputOption { /** * @var list|\Closure(CompletionInput,CompletionSuggestions):list */ private $suggestedValues; /** * @param string|string[]|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param int|null $mode The option mode: One of the VALUE_* constants * @param string|bool|int|float|string[]|null $default The default value (must be null for self::VALUE_NONE) * @param list|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completionnull for self::VALUE_NONE) * * @throws InvalidArgumentException If option mode is invalid or incompatible */ public function __construct(string $name, $shortcut = null, ?int $mode = null, string $description = '', $default = null, $suggestedValues = []) { parent::__construct($name, $shortcut, $mode, $description, $default); $this->suggestedValues = $suggestedValues; if ([] !== $suggestedValues && !$this->acceptValue()) { throw new LogicException('Cannot set suggested values if the option does not accept a value.'); } } /** * Adds suggestions to $suggestions for the current completion input. * * @see Command::complete() */ public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void { $values = $this->suggestedValues; if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore function.impossibleType throw new LogicException(\sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->getName(), \get_debug_type($values))); } if ([] !== $values) { $suggestions->suggestValues($values); } } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Console; use Closure; use Composer\Pcre\Preg; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatter; use _ContaoManager\Symfony\Component\Console\Formatter\OutputFormatterStyle; /** * @author Jordi Boggiano */ class HtmlOutputFormatter extends OutputFormatter { /** @var array */ private static $availableForegroundColors = [30 => 'black', 31 => 'red', 32 => 'green', 33 => 'yellow', 34 => 'blue', 35 => 'magenta', 36 => 'cyan', 37 => 'white']; /** @var array */ private static $availableBackgroundColors = [40 => 'black', 41 => 'red', 42 => 'green', 43 => 'yellow', 44 => 'blue', 45 => 'magenta', 46 => 'cyan', 47 => 'white']; /** @var array */ private static $availableOptions = [1 => 'bold', 4 => 'underscore']; /** * @param array $styles Array of "name => FormatterStyle" instances */ public function __construct(array $styles = []) { parent::__construct(\true, $styles); } public function format(?string $message) : ?string { $formatted = parent::format($message); if ($formatted === null) { return null; } $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)'; return Preg::replaceCallback("{\x1b\\[([0-9;]+)m(.*?)\x1b\\[(?:" . $clearEscapeCodes . ";)*?" . $clearEscapeCodes . "m}s", Closure::fromCallable([$this, 'formatHtml']), $formatted); } /** * @param array $matches */ private function formatHtml(array $matches) : string { \assert(\is_string($matches[1])); $out = '' . $matches[2] . ''; } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Composer\Autoload\ClassLoader; function includeIfExists(string $file) : ?ClassLoader { return \file_exists($file) ? include $file : null; } if (!($loader = includeIfExists(__DIR__ . '/../vendor/autoload.php')) && !($loader = includeIfExists(__DIR__ . '/../../../autoload.php'))) { echo 'You must set up the project dependencies using `composer install`' . \PHP_EOL . 'See https://getcomposer.org/download/ for instructions on installing Composer' . \PHP_EOL; exit(1); } return $loader; ## ## Bundle of CA Root Certificates ## ## Certificate data from Mozilla as of: Tue Dec 31 04:12:05 2024 GMT ## ## Find updated versions here: https://curl.se/docs/caextract.html ## ## 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: c99d6d3f8d3d4e47719ba2b648992f5b58b150128d3aca3c05c566d8dc98e116 ## GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- Entrust.net Premium 2048 Secure Server CA ========================================= -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= -----END CERTIFICATE----- Baltimore CyberTrust Root ========================= -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- Entrust Root Certification Authority ==================================== -----BEGIN CERTIFICATE----- MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- Comodo AAA Services root ======================== -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- QuoVadis Root CA 2 ================== -----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- QuoVadis Root CA 3 ================== -----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- Go Daddy Class 2 CA =================== -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b vZ8= -----END CERTIFICATE----- Starfield Class 2 CA ==================== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- DigiCert Assured ID Root CA =========================== -----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- DigiCert Global Root CA ======================= -----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- DigiCert High Assurance EV Root CA ================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K -----END CERTIFICATE----- SwissSign Gold CA - G2 ====================== -----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- SwissSign Silver CA - G2 ======================== -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- SecureTrust CA ============== -----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- Secure Global CA ================ -----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- COMODO Certification Authority ============================== -----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== -----END CERTIFICATE----- COMODO ECC Certification Authority ================================== -----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- Certigna ======== -----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- ePKI Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- certSIGN ROOT CA ================ -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD -----END CERTIFICATE----- NetLock Arany (Class Gold) Főtanúsítvány ======================================== -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- Microsec e-Szigno Root CA 2009 ============================== -----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi LXpUq3DDfSJlgnCW -----END CERTIFICATE----- GlobalSign Root CA - R3 ======================= -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r kpeDMdmztcpHWD9f -----END CERTIFICATE----- Izenpe.com ========== -----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- Go Daddy Root Certificate Authority - G2 ======================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 -----END CERTIFICATE----- Starfield Root Certificate Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- Starfield Services Root Certificate Authority - G2 ================================================== -----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 -----END CERTIFICATE----- AffirmTrust Commercial ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -----END CERTIFICATE----- AffirmTrust Networking ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- AffirmTrust Premium =================== -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== -----END CERTIFICATE----- AffirmTrust Premium ECC ======================= -----BEGIN CERTIFICATE----- MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM eQ== -----END CERTIFICATE----- Certum Trusted Network CA ========================= -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- Security Communication RootCA2 ============================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- Actalis Authentication Root CA ============================== -----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- Buypass Class 2 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN rJgWVqA= -----END CERTIFICATE----- Buypass Class 3 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi Cp/HuZc= -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 3 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 2009 ============================== -----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 EV 2009 ================================= -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv w9y4AyHqnxbxLFS1 -----END CERTIFICATE----- CA Disig Root R2 ================ -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV 7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- ACCVRAIZ1 ========= -----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p EfbRD0tVNEYqi4Y7 -----END CERTIFICATE----- TWCA Global Root CA =================== -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= -----END CERTIFICATE----- TeliaSonera Root CA v1 ====================== -----BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 2 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== -----END CERTIFICATE----- Atos TrustedRoot 2011 ===================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- QuoVadis Root CA 1 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV hMJKzRwuJIczYOXD -----END CERTIFICATE----- QuoVadis Root CA 2 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr O3jtZsSOeWmD3n+M -----END CERTIFICATE----- QuoVadis Root CA 3 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 PpxxVJkES/1Y+Zj0 -----END CERTIFICATE----- DigiCert Assured ID Root G2 =========================== -----BEGIN CERTIFICATE----- MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo IhNzbM8m9Yop5w== -----END CERTIFICATE----- DigiCert Assured ID Root G3 =========================== -----BEGIN CERTIFICATE----- MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy 1vUhZscv6pZjamVFkpUBtA== -----END CERTIFICATE----- DigiCert Global Root G2 ======================= -----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl MrY= -----END CERTIFICATE----- DigiCert Global Root G3 ======================= -----BEGIN CERTIFICATE----- MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 VOKa5Vt8sycX -----END CERTIFICATE----- DigiCert Trusted Root G4 ======================== -----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP 82Z+ -----END CERTIFICATE----- COMODO RSA Certification Authority ================================== -----BEGIN CERTIFICATE----- MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I LaZRfyHBNVOFBkpdn627G190 -----END CERTIFICATE----- USERTrust RSA Certification Authority ===================================== -----BEGIN CERTIFICATE----- MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- USERTrust ECC Certification Authority ===================================== -----BEGIN CERTIFICATE----- MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= -----END CERTIFICATE----- GlobalSign ECC Root CA - R5 =========================== -----BEGIN CERTIFICATE----- MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- IdenTrust Commercial Root CA 1 ============================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R cGzM7vRX+Bi6hG6H -----END CERTIFICATE----- IdenTrust Public Sector Root CA 1 ================================= -----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ 3Wl9af0AVqW3rLatt8o+Ae+c -----END CERTIFICATE----- Entrust Root Certification Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO e4pIb4tF9g== -----END CERTIFICATE----- Entrust Root Certification Authority - EC1 ========================================== -----BEGIN CERTIFICATE----- MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G -----END CERTIFICATE----- CFCA EV ROOT ============ -----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- OISTE WISeKey Global Root GB CA =============================== -----BEGIN CERTIFICATE----- MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= -----END CERTIFICATE----- SZAFIR ROOT CA2 =============== -----BEGIN CERTIFICATE----- MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== -----END CERTIFICATE----- Certum Trusted Network CA 2 =========================== -----BEGIN CERTIFICATE----- MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 zAYspsbiDrW5viSP -----END CERTIFICATE----- Hellenic Academic and Research Institutions RootCA 2015 ======================================================= -----BEGIN CERTIFICATE----- MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q p/UsQu0yrbYhnr68 -----END CERTIFICATE----- Hellenic Academic and Research Institutions ECC RootCA 2015 =========================================================== -----BEGIN CERTIFICATE----- MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -----END CERTIFICATE----- ISRG Root X1 ============ -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ m+kXQ99b21/+jh5Xos1AnX5iItreGCc= -----END CERTIFICATE----- AC RAIZ FNMT-RCM ================ -----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= -----END CERTIFICATE----- Amazon Root CA 1 ================ -----BEGIN CERTIFICATE----- MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 -----END CERTIFICATE----- Amazon Root CA 2 ================ -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= -----END CERTIFICATE----- Amazon Root CA 3 ================ -----BEGIN CERTIFICATE----- MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== -----END CERTIFICATE----- Amazon Root CA 4 ================ -----BEGIN CERTIFICATE----- MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== -----END CERTIFICATE----- TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 ============================================= -----BEGIN CERTIFICATE----- MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= -----END CERTIFICATE----- GDCA TrustAUTH R5 ROOT ====================== -----BEGIN CERTIFICATE----- MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ 9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx 9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd +PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ 8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv /EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== -----END CERTIFICATE----- SSL.com Root Certification Authority RSA ======================================== -----BEGIN CERTIFICATE----- MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= -----END CERTIFICATE----- SSL.com Root Certification Authority ECC ======================================== -----BEGIN CERTIFICATE----- MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ 8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z 5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl -----END CERTIFICATE----- SSL.com EV Root Certification Authority RSA R2 ============================================== -----BEGIN CERTIFICATE----- MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim 9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 +qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 ++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX 9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== -----END CERTIFICATE----- SSL.com EV Root Certification Authority ECC =========================================== -----BEGIN CERTIFICATE----- MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy 3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe 5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== -----END CERTIFICATE----- GlobalSign Root CA - R6 ======================= -----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE 3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP 0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr 3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= -----END CERTIFICATE----- OISTE WISeKey Global Root GC CA =============================== -----BEGIN CERTIFICATE----- MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 -----END CERTIFICATE----- UCA Global G2 Root ================== -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV 8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa 4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo 5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== -----END CERTIFICATE----- UCA Extended Validation Root ============================ -----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR 59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH 0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS 3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb +7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr dhh2n1ax -----END CERTIFICATE----- Certigna Root CA ================ -----BEGIN CERTIFICATE----- MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq 4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ /TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of 1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq 7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd 8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS 6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= -----END CERTIFICATE----- emSign Root CA - G1 =================== -----BEGIN CERTIFICATE----- MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ 6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q +Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx iN66zB+Afko= -----END CERTIFICATE----- emSign ECC Root CA - G3 ======================= -----BEGIN CERTIFICATE----- MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc 58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj -----END CERTIFICATE----- emSign Root CA - C1 =================== -----BEGIN CERTIFICATE----- MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp /6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= -----END CERTIFICATE----- emSign ECC Root CA - C3 ======================= -----BEGIN CERTIFICATE----- MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd 6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== -----END CERTIFICATE----- Hongkong Post Root CA 3 ======================= -----BEGIN CERTIFICATE----- MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim 5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj 0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h +bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov +BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw 9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB 60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq dBb9HxEGmpv0 -----END CERTIFICATE----- Microsoft ECC Root Certificate Authority 2017 ============================================= -----BEGIN CERTIFICATE----- MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM +Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= -----END CERTIFICATE----- Microsoft RSA Root Certificate Authority 2017 ============================================= -----BEGIN CERTIFICATE----- MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml 7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ 0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og 6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk +ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex /2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE 7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D 5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E -----END CERTIFICATE----- e-Szigno Root CA 2017 ===================== -----BEGIN CERTIFICATE----- MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO svxyqltZ+efcMQ== -----END CERTIFICATE----- certSIGN Root CA G2 =================== -----BEGIN CERTIFICATE----- MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf 95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB /AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N 0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= -----END CERTIFICATE----- Trustwave Global Certification Authority ======================================== -----BEGIN CERTIFICATE----- MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29 zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+ OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40 Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm +9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla 4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O 856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu 3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP 29FpHOTKyeC2nOnOcXHebD8WpHk= -----END CERTIFICATE----- Trustwave Global ECC P256 Certification Authority ================================================= -----BEGIN CERTIFICATE----- MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj 43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt 0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 -----END CERTIFICATE----- Trustwave Global ECC P384 Certification Authority ================================================= -----BEGIN CERTIFICATE----- MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr /TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== -----END CERTIFICATE----- NAVER Global Root Certification Authority ========================================= -----BEGIN CERTIFICATE----- MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW +j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK 21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg kpzNNIaRkPpkUZ3+/uul9XXeifdy -----END CERTIFICATE----- AC RAIZ FNMT-RCM SERVIDORES SEGUROS =================================== -----BEGIN CERTIFICATE----- MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= -----END CERTIFICATE----- GlobalSign Root R46 =================== -----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje 2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 QEUxeCp6 -----END CERTIFICATE----- GlobalSign Root E46 =================== -----BEGIN CERTIFICATE----- MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ CAezNIm8BZ/3Hobui3A= -----END CERTIFICATE----- GLOBALTRUST 2020 ================ -----BEGIN CERTIFICATE----- MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw 4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS 8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== -----END CERTIFICATE----- ANF Secure Server Root CA ========================= -----BEGIN CERTIFICATE----- MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4 NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j 7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe 8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM 5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb 5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54 EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3 r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= -----END CERTIFICATE----- Certum EC-384 CA ================ -----BEGIN CERTIFICATE----- MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2 MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0 QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= -----END CERTIFICATE----- Certum Trusted Root CA ====================== -----BEGIN CERTIFICATE----- MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52 HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2 fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4 NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8 CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA 4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj 6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb -----END CERTIFICATE----- TunTrust Root CA ================ -----BEGIN CERTIFICATE----- MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz 2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7 NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI 04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl 0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= -----END CERTIFICATE----- HARICA TLS RSA Root CA 2021 =========================== -----BEGIN CERTIFICATE----- MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K 5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR 0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5 vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0 qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6 Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/ PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn kf3/W9b3raYvAwtt41dU63ZTGI0RmLo= -----END CERTIFICATE----- HARICA TLS ECC Root CA 2021 =========================== -----BEGIN CERTIFICATE----- MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW 0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps -----END CERTIFICATE----- Autoridad de Certificacion Firmaprofesional CIF A62634068 ========================================================= -----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL 4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH 9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE ZycPvEJdvSRUDewdcAZfpLz6IHxV -----END CERTIFICATE----- vTrus ECC Root CA ================= -----BEGIN CERTIFICATE----- MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL YgmRWAD5Tfs0aNoJrSEGGJTO -----END CERTIFICATE----- vTrus Root CA ============= -----BEGIN CERTIFICATE----- MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70 kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2 AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu /9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu 1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO 9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4 8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4 sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H l3s= -----END CERTIFICATE----- ISRG Root X2 ============ -----BEGIN CERTIFICATE----- MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5 U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn -----END CERTIFICATE----- HiPKI Root CA - G1 ================== -----BEGIN CERTIFICATE----- MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0 o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj 1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4 9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/ Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF 8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi 7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv 5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/ yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== -----END CERTIFICATE----- GlobalSign ECC Root CA - R4 =========================== -----BEGIN CERTIFICATE----- MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm -----END CERTIFICATE----- GTS Root R1 =========== -----BEGIN CERTIFICATE----- MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0 xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk 9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+ 7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3 FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3 gm3c -----END CERTIFICATE----- GTS Root R2 =========== -----BEGIN CERTIFICATE----- MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS +LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel /FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5 9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M 7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8 0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW HYbL -----END CERTIFICATE----- GTS Root R3 =========== -----BEGIN CERTIFICATE----- MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout 736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV 11RZt+cRLInUue4X -----END CERTIFICATE----- GTS Root R4 =========== -----BEGIN CERTIFICATE----- MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1 PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh 4rsUecrNIdSUtUlD -----END CERTIFICATE----- Telia Root CA v2 ================ -----BEGIN CERTIFICATE----- MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2 MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7 6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q 9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW 5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4 M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ 8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5 tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15 h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70 sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9 xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc= -----END CERTIFICATE----- D-TRUST BR Root CA 1 2020 ========================= -----BEGIN CERTIFICATE----- MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7 dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87 -----END CERTIFICATE----- D-TRUST EV Root CA 1 2020 ========================= -----BEGIN CERTIFICATE----- MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8 ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW -----END CERTIFICATE----- DigiCert TLS ECC P384 Root G5 ============================= -----BEGIN CERTIFICATE----- MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4 NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB /wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA== -----END CERTIFICATE----- DigiCert TLS RSA4096 Root G5 ============================ -----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0 MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2 IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8 7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/ MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/ u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh 47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP bEtoL8pU9ozaMv7Da4M/OMZ+ -----END CERTIFICATE----- Certainly Root R1 ================= -----BEGIN CERTIFICATE----- MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O 5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl 8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1 VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d 8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+ gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7 fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8= -----END CERTIFICATE----- Certainly Root E1 ================= -----BEGIN CERTIFICATE----- MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0 MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4 fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9 YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8 rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR -----END CERTIFICATE----- Security Communication ECC RootCA1 ================================== -----BEGIN CERTIFICATE----- MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo 5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e N9k= -----END CERTIFICATE----- BJCA Global Root CA1 ==================== -----BEGIN CERTIFICATE----- MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8 60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW 4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx 4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps 3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI= -----END CERTIFICATE----- BJCA Global Root CA2 ==================== -----BEGIN CERTIFICATE----- MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK /eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI 1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8 W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== -----END CERTIFICATE----- Sectigo Public Server Authentication Root E46 ============================================= -----BEGIN CERTIFICATE----- MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJH QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2 ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5 WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0 aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUr gQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0 NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1Ud DgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB /zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RH lAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21U SAGKcw== -----END CERTIFICATE----- Sectigo Public Server Authentication Root R46 ============================================= -----BEGIN CERTIFICATE----- MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQG EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1 OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3 DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k 1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+Kxwf GExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMP FF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vu ZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5Qaz Yw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/A wSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYF plhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZ EoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW 6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWI IUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYp E0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4 exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M 0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI 84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9m pFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5Hrwd Vw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/b E/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmm J1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL -----END CERTIFICATE----- SSL.com TLS RSA Root CA 2022 ============================ -----BEGIN CERTIFICATE----- MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQG EwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0Eg Um9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMC VVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJv b3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u 9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y 7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7Qcac oOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5M R7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDG D6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEW TO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk 8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSq g+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk 7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1Ud EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsu N+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTN j8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5by iB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjU o3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqo ENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7Egkaib MOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICi vRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7 P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB0 9+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= -----END CERTIFICATE----- SSL.com TLS ECC Root CA 2022 ============================ -----BEGIN CERTIFICATE----- MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV UzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9v dCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMx GDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3Qg Q0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWy JGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v1 5wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR7 81a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGG MAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w 7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5 Zn6g6g== -----END CERTIFICATE----- Atos TrustedRoot Root CA ECC TLS 2021 ===================================== -----BEGIN CERTIFICATE----- MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVB dG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYD VQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3Mg VHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYT AkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6K DP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQS b+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPX NtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+ uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGY a3cpetskz2VAv9LcjBHo9H1/IISpQuQo -----END CERTIFICATE----- Atos TrustedRoot Root CA RSA TLS 2021 ===================================== -----BEGIN CERTIFICATE----- MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQD DCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQsw CQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0 b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNV BAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BB l01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBG vevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdK ZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt 0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVK PNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMY sluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBY Br3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+ rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xa fJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0G CSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS 4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCpl Q3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWX AdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9G slA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2Vkt afcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9q TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj 1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/l PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W HYMfRsCbvUOZ58SWLs5fyQ== -----END CERTIFICATE----- TrustAsia Global Root CA G3 =========================== -----BEGIN CERTIFICATE----- MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEMBQAwWjELMAkG A1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMM G1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAeFw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEw MTlaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMu MSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNST1QY4Sxz lZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqKAtCWHwDNBSHvBm3dIZwZ Q0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/V P68czH5GX6zfZBCK70bwkPAPLfSIC7Epqq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1Ag dB4SQXMeJNnKziyhWTXAyB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm 9WAPzJMshH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gXzhqc D0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAvkV34PmVACxmZySYg WmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msTf9FkPz2ccEblooV7WIQn3MSAPmea mseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jAuPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCF TIcQcf+eQxuulXUtgQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj 7zjKsK5Xf/IhMBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4wM8zAQLpw6o1 D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2XFNFV1pF1AWZLy4jVe5jaN/T G3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNj duMNhXJEIlU/HHzp/LgV6FL6qj6jITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstl cHboCoWASzY9M/eVVHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys +TIxxHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1onAX1daBli 2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d7XB4tmBZrOFdRWOPyN9y aFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2NtjjgKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsAS ZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFR JQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH -----END CERTIFICATE----- TrustAsia Global Root CA G4 =========================== -----BEGIN CERTIFICATE----- MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UE BhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1Ry dXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJa MFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQw IgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi AATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8 m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQF MAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/ pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AA bbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xk dUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== -----END CERTIFICATE----- CommScope Public Trust ECC Root-01 ================================== -----BEGIN CERTIFICATE----- MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMwTjELMAkGA1UE BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz dCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNaFw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYT AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg RUNDIFJvb3QtMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLx eP0CflfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJEhRGnSjot 6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G A1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggqhkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2 Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liW pDVfG2XqYZpwI7UNo5uSUm9poIyNStDuiw7LR47QjRE= -----END CERTIFICATE----- CommScope Public Trust ECC Root-02 ================================== -----BEGIN CERTIFICATE----- MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMwTjELMAkGA1UE BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz dCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRaFw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYT AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg RUNDIFJvb3QtMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/M MDALj2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmUv4RDsNuE SgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G A1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggqhkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9 Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/nich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs7 3u1Z/GtMMH9ZzkXpc2AVmkzw5l4lIhVtwodZ0LKOag== -----END CERTIFICATE----- CommScope Public Trust RSA Root-01 ================================== -----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQELBQAwTjELMAkG A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU cnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNV BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1 c3QgUlNBIFJvb3QtMDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45Ft nYSkYZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslhsuitQDy6 uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0alDrJLpA6lfO741GIDuZNq ihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3OjWiE260f6GBfZumbCk6SP/F2krfxQapWs vCQz0b2If4b19bJzKo98rwjyGpg/qYFlP8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/c Zip8UlF1y5mO6D1cv547KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTif BSeolz7pUcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/kQO9 lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JOHg9O5j9ZpSPcPYeo KFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkBEa801M/XrmLTBQe0MXXgDW1XT2mH +VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6UCBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm4 5P3luG0wDQYJKoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6 NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQnmhUQo8mUuJM 3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+QgvfKNmwrZggvkN80V4aCRck jXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2vtrV0KnahP/t1MJ+UXjulYPPLXAziDslg+Mkf Foom3ecnf+slpoq9uC02EJqxWE2aaE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/W NyVntHKLr4W96ioDj8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+ o/E4Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0wlREQKC6/ oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHnYfkUyq+Dj7+vsQpZXdxc 1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVocicCMb3SgazNNtQEo/a2tiRc7ppqEvOuM 6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw -----END CERTIFICATE----- CommScope Public Trust RSA Root-02 ================================== -----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQELBQAwTjELMAkG A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU cnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNV BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1 c3QgUlNBIFJvb3QtMDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3V rCLENQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0kyI9p+Kx 7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1CrWDaSWqVcN3SAOLMV2MC e5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxzhkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2W Wy09X6GDRl224yW4fKcZgBzqZUPckXk2LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rp M9kzXzehxfCrPfp4sOcsn/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIf hs1w/tkuFT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5kQMr eyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3wNemKfrb3vOTlycE VS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6vwQcQeKwRoi9C8DfF8rhW3Q5iLc4t Vn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7Gx cJXvYXowDQYJKoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3+VGXu6TwYofF 1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbymeAPnCKfWxkxlSaRosTKCL4BWa MS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3NyqpgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xd gSGn2rtO/+YHqP65DSdsu3BaVXoT6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2O HG1QAk8mGEPej1WFsQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+Nm YWvtPjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2dlklyALKr dVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQ iRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzN lM47ni3niAIi9G7oyOzWPPO5std3eqx7 -----END CERTIFICATE----- Telekom Security TLS ECC Root 2020 ================================== -----BEGIN CERTIFICATE----- MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJE RTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxl a29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIz NTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkg R21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqG SM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M1 2kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NC MEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P AQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZ Mo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdU ga/sf+Rn27iQ7t0l -----END CERTIFICATE----- Telekom Security TLS RSA Root 2023 ================================== -----BEGIN CERTIFICATE----- MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQG EwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJU ZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAyMDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMy NzIzNTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJp dHkgR21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9cUD/h3VC KSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHVcp6R+SPWcHu79ZvB7JPP GeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMAU6DksquDOFczJZSfvkgdmOGjup5czQRx UX11eKvzWarE4GC+j4NSuHUaQTXtvPM6Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWo l8hHD/BeEIvnHRz+sTugBTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9 FIS3R/qy8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73Jco4v zLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg8qKrBC7m8kwOFjQg rIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8rFEz0ciD0cmfHdRHNCk+y7AO+oML KFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7S WWO/gLCMk3PLNaaZlSJhZQNg+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNV HQ4EFgQUtqeXgj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQpGv7qHBFfLp+ sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm9S3ul0A8Yute1hTWjOKWi0Fp kzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErwM807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy /SKE8YXJN3nptT+/XOR0so8RYgDdGGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4 mZqTuXNnQkYRIer+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtz aL1txKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+w6jv/naa oqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aKL4x35bcF7DvB7L6Gs4a8 wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeE HVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0 o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A= -----END CERTIFICATE----- FIRMAPROFESIONAL CA ROOT-A WEB ============================== -----BEGIN CERTIFICATE----- MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQswCQYDVQQGEwJF UzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4 MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2 WhcNNDcwMzMxMDkwMTM2WjBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25h bCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFM IENBIFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zfe9MEkVz6 iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6CcyvHZpsKjECcfIr28jlg st7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FD Y1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB /wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgL cFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQ pYXFuXqUPoeovQA= -----END CERTIFICATE----- TWCA CYBER Root CA ================== -----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYDVQQG EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB IENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQG EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB IENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1s Ts6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxFavcokPFh V8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/34bKS1PE2Y2yHer43CdT o0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684iJkXXYJndzk834H/nY62wuFm40AZoNWDT Nq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK /c/WMw+f+5eesRycnupfXtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkH IuNZW0CP2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TM fAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF 2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzR wyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83 QOGt4A1WNzAdBgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olN c79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/x X9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDR IG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq /p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0R FxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz8ppy6rBe Pm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4NxKfKjLji7gh7MMrZQzv It6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrruoBa3lwtcHb4yOWHh8qgnaHl IhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X -----END CERTIFICATE----- SecureSign Root CA12 ==================== -----BEGIN CERTIFICATE----- MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkG A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT ZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJ BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU U2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3 emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwcc J/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZl fO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBF EaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1Uef NzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P AQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOC AQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQi LUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpce mik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPS vWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhga aaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== -----END CERTIFICATE----- SecureSign Root CA14 ==================== -----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTELMAkG A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT ZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJ BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU U2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh 1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOgvlIfX8xn bacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy6pJxaeQp8E+BgQQ8sqVb 1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa /d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOE kJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSx jVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18iz ju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0 dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsY AFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQAB o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeq YR3r6/wtbyPk86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoA ymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/Ds Hzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPG FrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6q nsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/ OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6dB7h7sxa OgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtlLor6CZpO2oYofaphNdgO pygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6UeTo3cKXhZ+PmhIIynJkBugnLN eLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S -----END CERTIFICATE----- SecureSign Root CA15 ==================== -----BEGIN CERTIFICATE----- MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UE BhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1 cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNV BAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2Vj dXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5G dCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB 2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD AgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6J fl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJ SwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= -----END CERTIFICATE----- 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. 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. { "name": "composer\/ca-bundle", "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", "type": "library", "license": "MIT", "keywords": [ "cabundle", "cacert", "certificate", "ssl", "tls" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http:\/\/seld.be" } ], "support": { "irc": "irc:\/\/irc.freenode.org\/composer", "issues": "https:\/\/github.com\/composer\/ca-bundle\/issues" }, "require": { "ext-openssl": "*", "ext-pcre": "*", "php": "^7.2 || ^8.0" }, "require-dev": { "phpunit\/phpunit": "^8 || ^9", "phpstan\/phpstan": "^1.10", "psr\/log": "^1.0 || ^2.0 || ^3.0", "symfony\/process": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "autoload": { "psr-4": { "Composer\\CaBundle\\": "src" } }, "autoload-dev": { "psr-4": { "Composer\\CaBundle\\": "tests" } }, "extra": { "branch-alias": { "dev-main": "1.x-dev" } }, "scripts": { "test": "@php phpunit", "phpstan": "@php phpstan analyse" } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\CaBundle; use _ContaoManager\Psr\Log\LoggerInterface; use _ContaoManager\Symfony\Component\Process\PhpProcess; /** * @author Chris Smith * @author Jordi Boggiano */ class CaBundle { /** @var string|null */ private static $caPath; /** @var array */ private static $caFileValidity = array(); /** * Returns the system CA bundle path, or a path to the bundled one * * This method was adapted from Sslurp. * https://github.com/EvanDotPro/Sslurp * * (c) Evan Coury * * For the full copyright and license information, please see below: * * Copyright (c) 2013, Evan Coury * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @param LoggerInterface $logger optional logger for information about which CA files were loaded * @return string path to a CA bundle file or directory */ public static function getSystemCaRootBundlePath(?LoggerInterface $logger = null) { if (self::$caPath !== null) { return self::$caPath; } $caBundlePaths = array(); // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that. // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE'); // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that. // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR'); $caBundlePaths[] = \ini_get('openssl.cafile'); $caBundlePaths[] = \ini_get('openssl.capath'); $otherLocations = array( '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package) '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package) '/usr/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/openssl/cert.pem', // OS X homebrew, openssl package '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package '/opt/homebrew/etc/openssl@3/cert.pem', // macOS silicon homebrew, openssl@3 package '/opt/homebrew/etc/openssl@1.1/cert.pem', // macOS silicon homebrew, openssl@1.1 package '/etc/pki/tls/certs', '/etc/ssl/certs', ); $caBundlePaths = \array_merge($caBundlePaths, $otherLocations); foreach ($caBundlePaths as $caBundle) { if ($caBundle && self::caFileUsable($caBundle, $logger)) { return self::$caPath = $caBundle; } if ($caBundle && self::caDirUsable($caBundle, $logger)) { return self::$caPath = $caBundle; } } return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort } /** * Returns the path to the bundled CA file * * In case you don't want to trust the user or the system, you can use this directly * * @return string path to a CA bundle file */ public static function getBundledCaBundlePath() { $caBundleFile = __DIR__ . '/../res/cacert.pem'; // cURL does not understand 'phar://' paths // see https://github.com/composer/ca-bundle/issues/10 if (0 === \strpos($caBundleFile, 'phar://')) { $tempCaBundleFile = \tempnam(\sys_get_temp_dir(), 'openssl-ca-bundle-'); if (\false === $tempCaBundleFile) { throw new \RuntimeException('Could not create a temporary file to store the bundled CA file'); } \file_put_contents($tempCaBundleFile, \file_get_contents($caBundleFile)); \register_shutdown_function(function () use($tempCaBundleFile) { @\unlink($tempCaBundleFile); }); $caBundleFile = $tempCaBundleFile; } return $caBundleFile; } /** * Validates a CA file using opensl_x509_parse only if it is safe to use * * @param string $filename * @param LoggerInterface $logger optional logger for information about which CA files were loaded * * @return bool */ public static function validateCaFile($filename, ?LoggerInterface $logger = null) { static $warned = \false; if (isset(self::$caFileValidity[$filename])) { return self::$caFileValidity[$filename]; } $contents = \file_get_contents($filename); if (\is_string($contents) && \strlen($contents) > 0) { $contents = \preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents); if (null === $contents) { // regex extraction failed $isValid = \false; } else { $isValid = (bool) \openssl_x509_parse($contents); } } else { $isValid = \false; } if ($logger) { $logger->debug('Checked CA file ' . \realpath($filename) . ': ' . ($isValid ? 'valid' : 'invalid')); } return self::$caFileValidity[$filename] = $isValid; } /** * Test if it is safe to use the PHP function openssl_x509_parse(). * * This checks if OpenSSL extensions is vulnerable to remote code execution * via the exploit documented as CVE-2013-6420. * * @return bool */ public static function isOpensslParseSafe() { return \true; } /** * Resets the static caches * @return void */ public static function reset() { self::$caFileValidity = array(); self::$caPath = null; } /** * @param string $name * @return string|false */ private static function getEnvVariable($name) { if (isset($_SERVER[$name])) { return (string) $_SERVER[$name]; } if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== \false && $value !== null) { return (string) $value; } return \false; } /** * @param string|false $certFile * @param LoggerInterface|null $logger * @return bool */ private static function caFileUsable($certFile, ?LoggerInterface $logger = null) { return $certFile && self::isFile($certFile, $logger) && self::isReadable($certFile, $logger) && self::validateCaFile($certFile, $logger); } /** * @param string|false $certDir * @param LoggerInterface|null $logger * @return bool */ private static function caDirUsable($certDir, ?LoggerInterface $logger = null) { return $certDir && self::isDir($certDir, $logger) && self::isReadable($certDir, $logger) && self::glob($certDir . '/*', $logger); } /** * @param string $certFile * @param LoggerInterface|null $logger * @return bool */ private static function isFile($certFile, ?LoggerInterface $logger = null) { $isFile = @\is_file($certFile); if (!$isFile && $logger) { $logger->debug(\sprintf('Checked CA file %s does not exist or it is not a file.', $certFile)); } return $isFile; } /** * @param string $certDir * @param LoggerInterface|null $logger * @return bool */ private static function isDir($certDir, ?LoggerInterface $logger = null) { $isDir = @\is_dir($certDir); if (!$isDir && $logger) { $logger->debug(\sprintf('Checked directory %s does not exist or it is not a directory.', $certDir)); } return $isDir; } /** * @param string $certFileOrDir * @param LoggerInterface|null $logger * @return bool */ private static function isReadable($certFileOrDir, ?LoggerInterface $logger = null) { $isReadable = @\is_readable($certFileOrDir); if (!$isReadable && $logger) { $logger->debug(\sprintf('Checked file or directory %s is not readable.', $certFileOrDir)); } return $isReadable; } /** * @param string $pattern * @param LoggerInterface|null $logger * @return bool */ private static function glob($pattern, ?LoggerInterface $logger = null) { $certs = \glob($pattern); if ($certs === \false) { if ($logger) { $logger->debug(\sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern)); } return \false; } if (\count($certs) === 0) { if ($logger) { $logger->debug(\sprintf("No CA files found for pattern: %s", $pattern)); } return \false; } return \true; } } array($vendorDir . '/studio24/rotate/src'), '_ContaoManager\\phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), '_ContaoManager\\Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), '_ContaoManager\\Webauthn\\' => array($vendorDir . '/web-auth/webauthn-lib/src'), '_ContaoManager\\Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), '_ContaoManager\\Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'), '_ContaoManager\\Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), '_ContaoManager\\Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), '_ContaoManager\\Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), '_ContaoManager\\Symfony\\Component\\Uid\\' => array($vendorDir . '/symfony/uid'), '_ContaoManager\\Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), '_ContaoManager\\Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'), '_ContaoManager\\Symfony\\Component\\Security\\Http\\' => array($vendorDir . '/symfony/security-http'), '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\' => array($vendorDir . '/symfony/security-csrf'), '_ContaoManager\\Symfony\\Component\\Security\\Core\\' => array($vendorDir . '/symfony/security-core'), '_ContaoManager\\Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), '_ContaoManager\\Symfony\\Component\\PropertyInfo\\' => array($vendorDir . '/symfony/property-info'), '_ContaoManager\\Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'), '_ContaoManager\\Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), '_ContaoManager\\Symfony\\Component\\PasswordHasher\\' => array($vendorDir . '/symfony/password-hasher'), '_ContaoManager\\Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'), '_ContaoManager\\Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), '_ContaoManager\\Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), '_ContaoManager\\Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'), '_ContaoManager\\Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), '_ContaoManager\\Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'), '_ContaoManager\\Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'), '_ContaoManager\\Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), '_ContaoManager\\Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'), '_ContaoManager\\Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'), '_ContaoManager\\Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'), '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\' => array($vendorDir . '/symfony/security-bundle'), '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\' => array($vendorDir . '/symfony/monolog-bundle'), '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), '_ContaoManager\\Symfony\\Bridge\\Monolog\\' => array($vendorDir . '/symfony/monolog-bridge'), '_ContaoManager\\SpomkyLabs\\Pki\\' => array($vendorDir . '/spomky-labs/pki-framework/src'), '_ContaoManager\\Seld\\Signal\\' => array($vendorDir . '/seld/signal-handler/src'), '_ContaoManager\\Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'), '_ContaoManager\\Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'), '_ContaoManager\\Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'), '_ContaoManager\\Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'), '_ContaoManager\\Psr\\Log\\' => array($vendorDir . '/psr/log/src'), '_ContaoManager\\Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), '_ContaoManager\\Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), '_ContaoManager\\Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), '_ContaoManager\\Psr\\Container\\' => array($vendorDir . '/psr/container/src'), '_ContaoManager\\Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'), '_ContaoManager\\Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), '_ContaoManager\\ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'), '_ContaoManager\\PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'), '_ContaoManager\\OTPHP\\' => array($vendorDir . '/spomky-labs/otphp/src'), '_ContaoManager\\Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), '_ContaoManager\\Lcobucci\\Clock\\' => array($vendorDir . '/lcobucci/clock/src'), '_ContaoManager\\JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'), '_ContaoManager\\Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'), '_ContaoManager\\Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'), '_ContaoManager\\Crell\\ApiProblem\\' => array($vendorDir . '/crell/api-problem/src'), '_ContaoManager\\Cose\\' => array($vendorDir . '/web-auth/cose-lib/src'), '_ContaoManager\\Contao\\ManagerApi\\' => array($baseDir . '/api'), '_ContaoManager\\CBOR\\' => array($vendorDir . '/spomky-labs/cbor-php/src'), '_ContaoManager\\Brick\\Math\\' => array($vendorDir . '/brick/math/src'), 'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'), 'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'), 'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'), 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), 'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'), 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), 'React\\Promise\\' => array($vendorDir . '/react/promise/src'), 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'), 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'), 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), 'Composer\\Pcre\\' => array($vendorDir . '/composer/pcre/src'), 'Composer\\MetadataMinifier\\' => array($vendorDir . '/composer/metadata-minifier/src'), 'Composer\\ClassMapGenerator\\' => array($vendorDir . '/composer/class-map-generator/src'), 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'), 'Composer\\' => array($vendorDir . '/composer/composer/src/Composer'), ); $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'CURLStringFile' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\Advisory\\Auditor' => $vendorDir . '/composer/composer/src/Composer/Advisory/Auditor.php', 'Composer\\Advisory\\IgnoredSecurityAdvisory' => $vendorDir . '/composer/composer/src/Composer/Advisory/IgnoredSecurityAdvisory.php', 'Composer\\Advisory\\PartialSecurityAdvisory' => $vendorDir . '/composer/composer/src/Composer/Advisory/PartialSecurityAdvisory.php', 'Composer\\Advisory\\SecurityAdvisory' => $vendorDir . '/composer/composer/src/Composer/Advisory/SecurityAdvisory.php', 'Composer\\Autoload\\AutoloadGenerator' => $vendorDir . '/composer/composer/src/Composer/Autoload/AutoloadGenerator.php', 'Composer\\Autoload\\ClassLoader' => $vendorDir . '/composer/composer/src/Composer/Autoload/ClassLoader.php', 'Composer\\Autoload\\ClassMapGenerator' => $vendorDir . '/composer/composer/src/Composer/Autoload/ClassMapGenerator.php', 'Composer\\CaBundle\\CaBundle' => $vendorDir . '/composer/ca-bundle/src/CaBundle.php', 'Composer\\Cache' => $vendorDir . '/composer/composer/src/Composer/Cache.php', 'Composer\\ClassMapGenerator\\ClassMap' => $vendorDir . '/composer/class-map-generator/src/ClassMap.php', 'Composer\\ClassMapGenerator\\ClassMapGenerator' => $vendorDir . '/composer/class-map-generator/src/ClassMapGenerator.php', 'Composer\\ClassMapGenerator\\FileList' => $vendorDir . '/composer/class-map-generator/src/FileList.php', 'Composer\\ClassMapGenerator\\PhpFileCleaner' => $vendorDir . '/composer/class-map-generator/src/PhpFileCleaner.php', 'Composer\\ClassMapGenerator\\PhpFileParser' => $vendorDir . '/composer/class-map-generator/src/PhpFileParser.php', 'Composer\\Command\\AboutCommand' => $vendorDir . '/composer/composer/src/Composer/Command/AboutCommand.php', 'Composer\\Command\\ArchiveCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ArchiveCommand.php', 'Composer\\Command\\AuditCommand' => $vendorDir . '/composer/composer/src/Composer/Command/AuditCommand.php', 'Composer\\Command\\BaseCommand' => $vendorDir . '/composer/composer/src/Composer/Command/BaseCommand.php', 'Composer\\Command\\BaseDependencyCommand' => $vendorDir . '/composer/composer/src/Composer/Command/BaseDependencyCommand.php', 'Composer\\Command\\BumpCommand' => $vendorDir . '/composer/composer/src/Composer/Command/BumpCommand.php', 'Composer\\Command\\CheckPlatformReqsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php', 'Composer\\Command\\ClearCacheCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ClearCacheCommand.php', 'Composer\\Command\\CompletionTrait' => $vendorDir . '/composer/composer/src/Composer/Command/CompletionTrait.php', 'Composer\\Command\\ConfigCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ConfigCommand.php', 'Composer\\Command\\CreateProjectCommand' => $vendorDir . '/composer/composer/src/Composer/Command/CreateProjectCommand.php', 'Composer\\Command\\DependsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/DependsCommand.php', 'Composer\\Command\\DiagnoseCommand' => $vendorDir . '/composer/composer/src/Composer/Command/DiagnoseCommand.php', 'Composer\\Command\\DumpAutoloadCommand' => $vendorDir . '/composer/composer/src/Composer/Command/DumpAutoloadCommand.php', 'Composer\\Command\\ExecCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ExecCommand.php', 'Composer\\Command\\FundCommand' => $vendorDir . '/composer/composer/src/Composer/Command/FundCommand.php', 'Composer\\Command\\GlobalCommand' => $vendorDir . '/composer/composer/src/Composer/Command/GlobalCommand.php', 'Composer\\Command\\HomeCommand' => $vendorDir . '/composer/composer/src/Composer/Command/HomeCommand.php', 'Composer\\Command\\InitCommand' => $vendorDir . '/composer/composer/src/Composer/Command/InitCommand.php', 'Composer\\Command\\InstallCommand' => $vendorDir . '/composer/composer/src/Composer/Command/InstallCommand.php', 'Composer\\Command\\LicensesCommand' => $vendorDir . '/composer/composer/src/Composer/Command/LicensesCommand.php', 'Composer\\Command\\OutdatedCommand' => $vendorDir . '/composer/composer/src/Composer/Command/OutdatedCommand.php', 'Composer\\Command\\PackageDiscoveryTrait' => $vendorDir . '/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php', 'Composer\\Command\\ProhibitsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ProhibitsCommand.php', 'Composer\\Command\\ReinstallCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ReinstallCommand.php', 'Composer\\Command\\RemoveCommand' => $vendorDir . '/composer/composer/src/Composer/Command/RemoveCommand.php', 'Composer\\Command\\RequireCommand' => $vendorDir . '/composer/composer/src/Composer/Command/RequireCommand.php', 'Composer\\Command\\RunScriptCommand' => $vendorDir . '/composer/composer/src/Composer/Command/RunScriptCommand.php', 'Composer\\Command\\ScriptAliasCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ScriptAliasCommand.php', 'Composer\\Command\\SearchCommand' => $vendorDir . '/composer/composer/src/Composer/Command/SearchCommand.php', 'Composer\\Command\\SelfUpdateCommand' => $vendorDir . '/composer/composer/src/Composer/Command/SelfUpdateCommand.php', 'Composer\\Command\\ShowCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ShowCommand.php', 'Composer\\Command\\StatusCommand' => $vendorDir . '/composer/composer/src/Composer/Command/StatusCommand.php', 'Composer\\Command\\SuggestsCommand' => $vendorDir . '/composer/composer/src/Composer/Command/SuggestsCommand.php', 'Composer\\Command\\UpdateCommand' => $vendorDir . '/composer/composer/src/Composer/Command/UpdateCommand.php', 'Composer\\Command\\ValidateCommand' => $vendorDir . '/composer/composer/src/Composer/Command/ValidateCommand.php', 'Composer\\Compiler' => $vendorDir . '/composer/composer/src/Composer/Compiler.php', 'Composer\\Composer' => $vendorDir . '/composer/composer/src/Composer/Composer.php', 'Composer\\Config' => $vendorDir . '/composer/composer/src/Composer/Config.php', 'Composer\\Config\\ConfigSourceInterface' => $vendorDir . '/composer/composer/src/Composer/Config/ConfigSourceInterface.php', 'Composer\\Config\\JsonConfigSource' => $vendorDir . '/composer/composer/src/Composer/Config/JsonConfigSource.php', 'Composer\\Console\\Application' => $vendorDir . '/composer/composer/src/Composer/Console/Application.php', 'Composer\\Console\\GithubActionError' => $vendorDir . '/composer/composer/src/Composer/Console/GithubActionError.php', 'Composer\\Console\\HtmlOutputFormatter' => $vendorDir . '/composer/composer/src/Composer/Console/HtmlOutputFormatter.php', 'Composer\\Console\\Input\\InputArgument' => $vendorDir . '/composer/composer/src/Composer/Console/Input/InputArgument.php', 'Composer\\Console\\Input\\InputOption' => $vendorDir . '/composer/composer/src/Composer/Console/Input/InputOption.php', 'Composer\\DependencyResolver\\Decisions' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Decisions.php', 'Composer\\DependencyResolver\\DefaultPolicy' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php', 'Composer\\DependencyResolver\\GenericRule' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/GenericRule.php', 'Composer\\DependencyResolver\\LocalRepoTransaction' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php', 'Composer\\DependencyResolver\\LockTransaction' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/LockTransaction.php', 'Composer\\DependencyResolver\\MultiConflictRule' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php', 'Composer\\DependencyResolver\\Operation\\InstallOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php', 'Composer\\DependencyResolver\\Operation\\MarkAliasInstalledOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php', 'Composer\\DependencyResolver\\Operation\\MarkAliasUninstalledOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php', 'Composer\\DependencyResolver\\Operation\\OperationInterface' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php', 'Composer\\DependencyResolver\\Operation\\SolverOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php', 'Composer\\DependencyResolver\\Operation\\UninstallOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php', 'Composer\\DependencyResolver\\Operation\\UpdateOperation' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php', 'Composer\\DependencyResolver\\PolicyInterface' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php', 'Composer\\DependencyResolver\\Pool' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Pool.php', 'Composer\\DependencyResolver\\PoolBuilder' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php', 'Composer\\DependencyResolver\\PoolOptimizer' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php', 'Composer\\DependencyResolver\\Problem' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Problem.php', 'Composer\\DependencyResolver\\Request' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Request.php', 'Composer\\DependencyResolver\\Rule' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Rule.php', 'Composer\\DependencyResolver\\Rule2Literals' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php', 'Composer\\DependencyResolver\\RuleSet' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleSet.php', 'Composer\\DependencyResolver\\RuleSetGenerator' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php', 'Composer\\DependencyResolver\\RuleSetIterator' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php', 'Composer\\DependencyResolver\\RuleWatchChain' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php', 'Composer\\DependencyResolver\\RuleWatchGraph' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php', 'Composer\\DependencyResolver\\RuleWatchNode' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php', 'Composer\\DependencyResolver\\Solver' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Solver.php', 'Composer\\DependencyResolver\\SolverBugException' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/SolverBugException.php', 'Composer\\DependencyResolver\\SolverProblemsException' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php', 'Composer\\DependencyResolver\\Transaction' => $vendorDir . '/composer/composer/src/Composer/DependencyResolver/Transaction.php', 'Composer\\Downloader\\ArchiveDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/ArchiveDownloader.php', 'Composer\\Downloader\\ChangeReportInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/ChangeReportInterface.php', 'Composer\\Downloader\\DownloadManager' => $vendorDir . '/composer/composer/src/Composer/Downloader/DownloadManager.php', 'Composer\\Downloader\\DownloaderInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/DownloaderInterface.php', 'Composer\\Downloader\\DvcsDownloaderInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/DvcsDownloaderInterface.php', 'Composer\\Downloader\\FileDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/FileDownloader.php', 'Composer\\Downloader\\FilesystemException' => $vendorDir . '/composer/composer/src/Composer/Downloader/FilesystemException.php', 'Composer\\Downloader\\FossilDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/FossilDownloader.php', 'Composer\\Downloader\\GitDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/GitDownloader.php', 'Composer\\Downloader\\GzipDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/GzipDownloader.php', 'Composer\\Downloader\\HgDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/HgDownloader.php', 'Composer\\Downloader\\MaxFileSizeExceededException' => $vendorDir . '/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php', 'Composer\\Downloader\\PathDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/PathDownloader.php', 'Composer\\Downloader\\PerforceDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/PerforceDownloader.php', 'Composer\\Downloader\\PharDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/PharDownloader.php', 'Composer\\Downloader\\RarDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/RarDownloader.php', 'Composer\\Downloader\\SvnDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/SvnDownloader.php', 'Composer\\Downloader\\TarDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/TarDownloader.php', 'Composer\\Downloader\\TransportException' => $vendorDir . '/composer/composer/src/Composer/Downloader/TransportException.php', 'Composer\\Downloader\\VcsCapableDownloaderInterface' => $vendorDir . '/composer/composer/src/Composer/Downloader/VcsCapableDownloaderInterface.php', 'Composer\\Downloader\\VcsDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/VcsDownloader.php', 'Composer\\Downloader\\XzDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/XzDownloader.php', 'Composer\\Downloader\\ZipDownloader' => $vendorDir . '/composer/composer/src/Composer/Downloader/ZipDownloader.php', 'Composer\\EventDispatcher\\Event' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/Event.php', 'Composer\\EventDispatcher\\EventDispatcher' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php', 'Composer\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/EventSubscriberInterface.php', 'Composer\\EventDispatcher\\ScriptExecutionException' => $vendorDir . '/composer/composer/src/Composer/EventDispatcher/ScriptExecutionException.php', 'Composer\\Exception\\IrrecoverableDownloadException' => $vendorDir . '/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php', 'Composer\\Exception\\NoSslException' => $vendorDir . '/composer/composer/src/Composer/Exception/NoSslException.php', 'Composer\\Factory' => $vendorDir . '/composer/composer/src/Composer/Factory.php', 'Composer\\Filter\\PlatformRequirementFilter\\IgnoreAllPlatformRequirementFilter' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreAllPlatformRequirementFilter.php', 'Composer\\Filter\\PlatformRequirementFilter\\IgnoreListPlatformRequirementFilter' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php', 'Composer\\Filter\\PlatformRequirementFilter\\IgnoreNothingPlatformRequirementFilter' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreNothingPlatformRequirementFilter.php', 'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterFactory' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterFactory.php', 'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterInterface' => $vendorDir . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterInterface.php', 'Composer\\IO\\BaseIO' => $vendorDir . '/composer/composer/src/Composer/IO/BaseIO.php', 'Composer\\IO\\BufferIO' => $vendorDir . '/composer/composer/src/Composer/IO/BufferIO.php', 'Composer\\IO\\ConsoleIO' => $vendorDir . '/composer/composer/src/Composer/IO/ConsoleIO.php', 'Composer\\IO\\IOInterface' => $vendorDir . '/composer/composer/src/Composer/IO/IOInterface.php', 'Composer\\IO\\NullIO' => $vendorDir . '/composer/composer/src/Composer/IO/NullIO.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'Composer\\Installer' => $vendorDir . '/composer/composer/src/Composer/Installer.php', 'Composer\\Installer\\BinaryInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/BinaryInstaller.php', 'Composer\\Installer\\BinaryPresenceInterface' => $vendorDir . '/composer/composer/src/Composer/Installer/BinaryPresenceInterface.php', 'Composer\\Installer\\InstallationManager' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallationManager.php', 'Composer\\Installer\\InstallerEvent' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallerEvent.php', 'Composer\\Installer\\InstallerEvents' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallerEvents.php', 'Composer\\Installer\\InstallerInterface' => $vendorDir . '/composer/composer/src/Composer/Installer/InstallerInterface.php', 'Composer\\Installer\\LibraryInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/LibraryInstaller.php', 'Composer\\Installer\\MetapackageInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/MetapackageInstaller.php', 'Composer\\Installer\\NoopInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/NoopInstaller.php', 'Composer\\Installer\\PackageEvent' => $vendorDir . '/composer/composer/src/Composer/Installer/PackageEvent.php', 'Composer\\Installer\\PackageEvents' => $vendorDir . '/composer/composer/src/Composer/Installer/PackageEvents.php', 'Composer\\Installer\\PluginInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/PluginInstaller.php', 'Composer\\Installer\\ProjectInstaller' => $vendorDir . '/composer/composer/src/Composer/Installer/ProjectInstaller.php', 'Composer\\Installer\\SuggestedPackagesReporter' => $vendorDir . '/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php', 'Composer\\Json\\JsonFile' => $vendorDir . '/composer/composer/src/Composer/Json/JsonFile.php', 'Composer\\Json\\JsonFormatter' => $vendorDir . '/composer/composer/src/Composer/Json/JsonFormatter.php', 'Composer\\Json\\JsonManipulator' => $vendorDir . '/composer/composer/src/Composer/Json/JsonManipulator.php', 'Composer\\Json\\JsonValidationException' => $vendorDir . '/composer/composer/src/Composer/Json/JsonValidationException.php', 'Composer\\MetadataMinifier\\MetadataMinifier' => $vendorDir . '/composer/metadata-minifier/src/MetadataMinifier.php', 'Composer\\PHPStan\\ConfigReturnTypeExtension' => $vendorDir . '/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php', 'Composer\\PHPStan\\RuleReasonDataReturnTypeExtension' => $vendorDir . '/composer/composer/src/Composer/PHPStan/RuleReasonDataReturnTypeExtension.php', 'Composer\\Package\\AliasPackage' => $vendorDir . '/composer/composer/src/Composer/Package/AliasPackage.php', 'Composer\\Package\\Archiver\\ArchivableFilesFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFilter.php', 'Composer\\Package\\Archiver\\ArchivableFilesFinder' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php', 'Composer\\Package\\Archiver\\ArchiveManager' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php', 'Composer\\Package\\Archiver\\ArchiverInterface' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ArchiverInterface.php', 'Composer\\Package\\Archiver\\BaseExcludeFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/BaseExcludeFilter.php', 'Composer\\Package\\Archiver\\ComposerExcludeFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ComposerExcludeFilter.php', 'Composer\\Package\\Archiver\\GitExcludeFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/GitExcludeFilter.php', 'Composer\\Package\\Archiver\\PharArchiver' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/PharArchiver.php', 'Composer\\Package\\Archiver\\ZipArchiver' => $vendorDir . '/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php', 'Composer\\Package\\BasePackage' => $vendorDir . '/composer/composer/src/Composer/Package/BasePackage.php', 'Composer\\Package\\Comparer\\Comparer' => $vendorDir . '/composer/composer/src/Composer/Package/Comparer/Comparer.php', 'Composer\\Package\\CompleteAliasPackage' => $vendorDir . '/composer/composer/src/Composer/Package/CompleteAliasPackage.php', 'Composer\\Package\\CompletePackage' => $vendorDir . '/composer/composer/src/Composer/Package/CompletePackage.php', 'Composer\\Package\\CompletePackageInterface' => $vendorDir . '/composer/composer/src/Composer/Package/CompletePackageInterface.php', 'Composer\\Package\\Dumper\\ArrayDumper' => $vendorDir . '/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php', 'Composer\\Package\\Link' => $vendorDir . '/composer/composer/src/Composer/Package/Link.php', 'Composer\\Package\\Loader\\ArrayLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/ArrayLoader.php', 'Composer\\Package\\Loader\\InvalidPackageException' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/InvalidPackageException.php', 'Composer\\Package\\Loader\\JsonLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/JsonLoader.php', 'Composer\\Package\\Loader\\LoaderInterface' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/LoaderInterface.php', 'Composer\\Package\\Loader\\RootPackageLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php', 'Composer\\Package\\Loader\\ValidatingArrayLoader' => $vendorDir . '/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php', 'Composer\\Package\\Locker' => $vendorDir . '/composer/composer/src/Composer/Package/Locker.php', 'Composer\\Package\\Package' => $vendorDir . '/composer/composer/src/Composer/Package/Package.php', 'Composer\\Package\\PackageInterface' => $vendorDir . '/composer/composer/src/Composer/Package/PackageInterface.php', 'Composer\\Package\\RootAliasPackage' => $vendorDir . '/composer/composer/src/Composer/Package/RootAliasPackage.php', 'Composer\\Package\\RootPackage' => $vendorDir . '/composer/composer/src/Composer/Package/RootPackage.php', 'Composer\\Package\\RootPackageInterface' => $vendorDir . '/composer/composer/src/Composer/Package/RootPackageInterface.php', 'Composer\\Package\\Version\\StabilityFilter' => $vendorDir . '/composer/composer/src/Composer/Package/Version/StabilityFilter.php', 'Composer\\Package\\Version\\VersionBumper' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionBumper.php', 'Composer\\Package\\Version\\VersionGuesser' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionGuesser.php', 'Composer\\Package\\Version\\VersionParser' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionParser.php', 'Composer\\Package\\Version\\VersionSelector' => $vendorDir . '/composer/composer/src/Composer/Package/Version/VersionSelector.php', 'Composer\\PartialComposer' => $vendorDir . '/composer/composer/src/Composer/PartialComposer.php', 'Composer\\Pcre\\MatchAllResult' => $vendorDir . '/composer/pcre/src/MatchAllResult.php', 'Composer\\Pcre\\MatchAllStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchAllStrictGroupsResult.php', 'Composer\\Pcre\\MatchAllWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchAllWithOffsetsResult.php', 'Composer\\Pcre\\MatchResult' => $vendorDir . '/composer/pcre/src/MatchResult.php', 'Composer\\Pcre\\MatchStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchStrictGroupsResult.php', 'Composer\\Pcre\\MatchWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchWithOffsetsResult.php', 'Composer\\Pcre\\PHPStan\\InvalidRegexPatternRule' => $vendorDir . '/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php', 'Composer\\Pcre\\PHPStan\\PregMatchFlags' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchFlags.php', 'Composer\\Pcre\\PHPStan\\PregMatchParameterOutTypeExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php', 'Composer\\Pcre\\PHPStan\\PregMatchTypeSpecifyingExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php', 'Composer\\Pcre\\PHPStan\\PregReplaceCallbackClosureTypeExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.php', 'Composer\\Pcre\\PHPStan\\UnsafeStrictGroupsCallRule' => $vendorDir . '/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php', 'Composer\\Pcre\\PcreException' => $vendorDir . '/composer/pcre/src/PcreException.php', 'Composer\\Pcre\\Preg' => $vendorDir . '/composer/pcre/src/Preg.php', 'Composer\\Pcre\\Regex' => $vendorDir . '/composer/pcre/src/Regex.php', 'Composer\\Pcre\\ReplaceResult' => $vendorDir . '/composer/pcre/src/ReplaceResult.php', 'Composer\\Pcre\\UnexpectedNullMatchException' => $vendorDir . '/composer/pcre/src/UnexpectedNullMatchException.php', 'Composer\\Platform\\HhvmDetector' => $vendorDir . '/composer/composer/src/Composer/Platform/HhvmDetector.php', 'Composer\\Platform\\Runtime' => $vendorDir . '/composer/composer/src/Composer/Platform/Runtime.php', 'Composer\\Platform\\Version' => $vendorDir . '/composer/composer/src/Composer/Platform/Version.php', 'Composer\\Plugin\\Capability\\Capability' => $vendorDir . '/composer/composer/src/Composer/Plugin/Capability/Capability.php', 'Composer\\Plugin\\Capability\\CommandProvider' => $vendorDir . '/composer/composer/src/Composer/Plugin/Capability/CommandProvider.php', 'Composer\\Plugin\\Capable' => $vendorDir . '/composer/composer/src/Composer/Plugin/Capable.php', 'Composer\\Plugin\\CommandEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/CommandEvent.php', 'Composer\\Plugin\\PluginBlockedException' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginBlockedException.php', 'Composer\\Plugin\\PluginEvents' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginEvents.php', 'Composer\\Plugin\\PluginInterface' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginInterface.php', 'Composer\\Plugin\\PluginManager' => $vendorDir . '/composer/composer/src/Composer/Plugin/PluginManager.php', 'Composer\\Plugin\\PostFileDownloadEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php', 'Composer\\Plugin\\PreCommandRunEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PreCommandRunEvent.php', 'Composer\\Plugin\\PreFileDownloadEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PreFileDownloadEvent.php', 'Composer\\Plugin\\PrePoolCreateEvent' => $vendorDir . '/composer/composer/src/Composer/Plugin/PrePoolCreateEvent.php', 'Composer\\Question\\StrictConfirmationQuestion' => $vendorDir . '/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php', 'Composer\\Repository\\AdvisoryProviderInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/AdvisoryProviderInterface.php', 'Composer\\Repository\\ArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/ArrayRepository.php', 'Composer\\Repository\\ArtifactRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/ArtifactRepository.php', 'Composer\\Repository\\CanonicalPackagesTrait' => $vendorDir . '/composer/composer/src/Composer/Repository/CanonicalPackagesTrait.php', 'Composer\\Repository\\ComposerRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/ComposerRepository.php', 'Composer\\Repository\\CompositeRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/CompositeRepository.php', 'Composer\\Repository\\ConfigurableRepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/ConfigurableRepositoryInterface.php', 'Composer\\Repository\\FilesystemRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/FilesystemRepository.php', 'Composer\\Repository\\FilterRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/FilterRepository.php', 'Composer\\Repository\\InstalledArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledArrayRepository.php', 'Composer\\Repository\\InstalledFilesystemRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledFilesystemRepository.php', 'Composer\\Repository\\InstalledRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledRepository.php', 'Composer\\Repository\\InstalledRepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/InstalledRepositoryInterface.php', 'Composer\\Repository\\InvalidRepositoryException' => $vendorDir . '/composer/composer/src/Composer/Repository/InvalidRepositoryException.php', 'Composer\\Repository\\LockArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/LockArrayRepository.php', 'Composer\\Repository\\PackageRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PackageRepository.php', 'Composer\\Repository\\PathRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PathRepository.php', 'Composer\\Repository\\PearRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PearRepository.php', 'Composer\\Repository\\PlatformRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/PlatformRepository.php', 'Composer\\Repository\\RepositoryFactory' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryFactory.php', 'Composer\\Repository\\RepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryInterface.php', 'Composer\\Repository\\RepositoryManager' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryManager.php', 'Composer\\Repository\\RepositorySecurityException' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositorySecurityException.php', 'Composer\\Repository\\RepositorySet' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositorySet.php', 'Composer\\Repository\\RepositoryUtils' => $vendorDir . '/composer/composer/src/Composer/Repository/RepositoryUtils.php', 'Composer\\Repository\\RootPackageRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/RootPackageRepository.php', 'Composer\\Repository\\VcsRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/VcsRepository.php', 'Composer\\Repository\\Vcs\\FossilDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/FossilDriver.php', 'Composer\\Repository\\Vcs\\GitBitbucketDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitBitbucketDriver.php', 'Composer\\Repository\\Vcs\\GitDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitDriver.php', 'Composer\\Repository\\Vcs\\GitHubDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitHubDriver.php', 'Composer\\Repository\\Vcs\\GitLabDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/GitLabDriver.php', 'Composer\\Repository\\Vcs\\HgDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/HgDriver.php', 'Composer\\Repository\\Vcs\\PerforceDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/PerforceDriver.php', 'Composer\\Repository\\Vcs\\SvnDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/SvnDriver.php', 'Composer\\Repository\\Vcs\\VcsDriver' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/VcsDriver.php', 'Composer\\Repository\\Vcs\\VcsDriverInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/Vcs/VcsDriverInterface.php', 'Composer\\Repository\\VersionCacheInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/VersionCacheInterface.php', 'Composer\\Repository\\WritableArrayRepository' => $vendorDir . '/composer/composer/src/Composer/Repository/WritableArrayRepository.php', 'Composer\\Repository\\WritableRepositoryInterface' => $vendorDir . '/composer/composer/src/Composer/Repository/WritableRepositoryInterface.php', 'Composer\\Script\\Event' => $vendorDir . '/composer/composer/src/Composer/Script/Event.php', 'Composer\\Script\\ScriptEvents' => $vendorDir . '/composer/composer/src/Composer/Script/ScriptEvents.php', 'Composer\\SelfUpdate\\Keys' => $vendorDir . '/composer/composer/src/Composer/SelfUpdate/Keys.php', 'Composer\\SelfUpdate\\Versions' => $vendorDir . '/composer/composer/src/Composer/SelfUpdate/Versions.php', 'Composer\\Semver\\Comparator' => $vendorDir . '/composer/semver/src/Comparator.php', 'Composer\\Semver\\CompilingMatcher' => $vendorDir . '/composer/semver/src/CompilingMatcher.php', 'Composer\\Semver\\Constraint\\Bound' => $vendorDir . '/composer/semver/src/Constraint/Bound.php', 'Composer\\Semver\\Constraint\\Constraint' => $vendorDir . '/composer/semver/src/Constraint/Constraint.php', 'Composer\\Semver\\Constraint\\ConstraintInterface' => $vendorDir . '/composer/semver/src/Constraint/ConstraintInterface.php', 'Composer\\Semver\\Constraint\\MatchAllConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchAllConstraint.php', 'Composer\\Semver\\Constraint\\MatchNoneConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchNoneConstraint.php', 'Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir . '/composer/semver/src/Constraint/MultiConstraint.php', 'Composer\\Semver\\Interval' => $vendorDir . '/composer/semver/src/Interval.php', 'Composer\\Semver\\Intervals' => $vendorDir . '/composer/semver/src/Intervals.php', 'Composer\\Semver\\Semver' => $vendorDir . '/composer/semver/src/Semver.php', 'Composer\\Semver\\VersionParser' => $vendorDir . '/composer/semver/src/VersionParser.php', 'Composer\\Spdx\\SpdxLicenses' => $vendorDir . '/composer/spdx-licenses/src/SpdxLicenses.php', 'Composer\\Util\\AuthHelper' => $vendorDir . '/composer/composer/src/Composer/Util/AuthHelper.php', 'Composer\\Util\\Bitbucket' => $vendorDir . '/composer/composer/src/Composer/Util/Bitbucket.php', 'Composer\\Util\\ComposerMirror' => $vendorDir . '/composer/composer/src/Composer/Util/ComposerMirror.php', 'Composer\\Util\\ConfigValidator' => $vendorDir . '/composer/composer/src/Composer/Util/ConfigValidator.php', 'Composer\\Util\\ErrorHandler' => $vendorDir . '/composer/composer/src/Composer/Util/ErrorHandler.php', 'Composer\\Util\\Filesystem' => $vendorDir . '/composer/composer/src/Composer/Util/Filesystem.php', 'Composer\\Util\\Git' => $vendorDir . '/composer/composer/src/Composer/Util/Git.php', 'Composer\\Util\\GitHub' => $vendorDir . '/composer/composer/src/Composer/Util/GitHub.php', 'Composer\\Util\\GitLab' => $vendorDir . '/composer/composer/src/Composer/Util/GitLab.php', 'Composer\\Util\\Hg' => $vendorDir . '/composer/composer/src/Composer/Util/Hg.php', 'Composer\\Util\\HttpDownloader' => $vendorDir . '/composer/composer/src/Composer/Util/HttpDownloader.php', 'Composer\\Util\\Http\\CurlDownloader' => $vendorDir . '/composer/composer/src/Composer/Util/Http/CurlDownloader.php', 'Composer\\Util\\Http\\CurlResponse' => $vendorDir . '/composer/composer/src/Composer/Util/Http/CurlResponse.php', 'Composer\\Util\\Http\\ProxyItem' => $vendorDir . '/composer/composer/src/Composer/Util/Http/ProxyItem.php', 'Composer\\Util\\Http\\ProxyManager' => $vendorDir . '/composer/composer/src/Composer/Util/Http/ProxyManager.php', 'Composer\\Util\\Http\\RequestProxy' => $vendorDir . '/composer/composer/src/Composer/Util/Http/RequestProxy.php', 'Composer\\Util\\Http\\Response' => $vendorDir . '/composer/composer/src/Composer/Util/Http/Response.php', 'Composer\\Util\\IniHelper' => $vendorDir . '/composer/composer/src/Composer/Util/IniHelper.php', 'Composer\\Util\\Loop' => $vendorDir . '/composer/composer/src/Composer/Util/Loop.php', 'Composer\\Util\\MetadataMinifier' => $vendorDir . '/composer/composer/src/Composer/Util/MetadataMinifier.php', 'Composer\\Util\\NoProxyPattern' => $vendorDir . '/composer/composer/src/Composer/Util/NoProxyPattern.php', 'Composer\\Util\\PackageInfo' => $vendorDir . '/composer/composer/src/Composer/Util/PackageInfo.php', 'Composer\\Util\\PackageSorter' => $vendorDir . '/composer/composer/src/Composer/Util/PackageSorter.php', 'Composer\\Util\\Perforce' => $vendorDir . '/composer/composer/src/Composer/Util/Perforce.php', 'Composer\\Util\\Platform' => $vendorDir . '/composer/composer/src/Composer/Util/Platform.php', 'Composer\\Util\\ProcessExecutor' => $vendorDir . '/composer/composer/src/Composer/Util/ProcessExecutor.php', 'Composer\\Util\\RemoteFilesystem' => $vendorDir . '/composer/composer/src/Composer/Util/RemoteFilesystem.php', 'Composer\\Util\\Silencer' => $vendorDir . '/composer/composer/src/Composer/Util/Silencer.php', 'Composer\\Util\\StreamContextFactory' => $vendorDir . '/composer/composer/src/Composer/Util/StreamContextFactory.php', 'Composer\\Util\\Svn' => $vendorDir . '/composer/composer/src/Composer/Util/Svn.php', 'Composer\\Util\\SyncHelper' => $vendorDir . '/composer/composer/src/Composer/Util/SyncHelper.php', 'Composer\\Util\\Tar' => $vendorDir . '/composer/composer/src/Composer/Util/Tar.php', 'Composer\\Util\\TlsHelper' => $vendorDir . '/composer/composer/src/Composer/Util/TlsHelper.php', 'Composer\\Util\\Url' => $vendorDir . '/composer/composer/src/Composer/Util/Url.php', 'Composer\\Util\\Zip' => $vendorDir . '/composer/composer/src/Composer/Util/Zip.php', 'Composer\\XdebugHandler\\PhpConfig' => $vendorDir . '/composer/xdebug-handler/src/PhpConfig.php', 'Composer\\XdebugHandler\\Process' => $vendorDir . '/composer/xdebug-handler/src/Process.php', 'Composer\\XdebugHandler\\Status' => $vendorDir . '/composer/xdebug-handler/src/Status.php', 'Composer\\XdebugHandler\\XdebugHandler' => $vendorDir . '/composer/xdebug-handler/src/XdebugHandler.php', 'DateError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateError.php', 'DateException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateException.php', 'DateInvalidOperationException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php', 'DateInvalidTimeZoneException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php', 'DateMalformedIntervalStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php', 'DateMalformedPeriodStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php', 'DateMalformedStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php', 'DateObjectError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php', 'DateRangeError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php', 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'Override' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/Override.php', 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'React\\Promise\\Deferred' => $vendorDir . '/react/promise/src/Deferred.php', 'React\\Promise\\Exception\\CompositeException' => $vendorDir . '/react/promise/src/Exception/CompositeException.php', 'React\\Promise\\Exception\\LengthException' => $vendorDir . '/react/promise/src/Exception/LengthException.php', 'React\\Promise\\Internal\\CancellationQueue' => $vendorDir . '/react/promise/src/Internal/CancellationQueue.php', 'React\\Promise\\Internal\\FulfilledPromise' => $vendorDir . '/react/promise/src/Internal/FulfilledPromise.php', 'React\\Promise\\Internal\\RejectedPromise' => $vendorDir . '/react/promise/src/Internal/RejectedPromise.php', 'React\\Promise\\Promise' => $vendorDir . '/react/promise/src/Promise.php', 'React\\Promise\\PromiseInterface' => $vendorDir . '/react/promise/src/PromiseInterface.php', 'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php', 'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => $vendorDir . '/symfony/polyfill-intl-grapheme/Grapheme.php', 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php73\\Php73' => $vendorDir . '/symfony/polyfill-php73/Php73.php', 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', 'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php81\\Php81' => $vendorDir . '/symfony/polyfill-php81/Php81.php', 'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php', 'Symfony\\Polyfill\\Uuid\\Uuid' => $vendorDir . '/symfony/polyfill-uuid/Uuid.php', 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', '_ContaoManager\\Brick\\Math\\BigDecimal' => $vendorDir . '/brick/math/src/BigDecimal.php', '_ContaoManager\\Brick\\Math\\BigInteger' => $vendorDir . '/brick/math/src/BigInteger.php', '_ContaoManager\\Brick\\Math\\BigNumber' => $vendorDir . '/brick/math/src/BigNumber.php', '_ContaoManager\\Brick\\Math\\BigRational' => $vendorDir . '/brick/math/src/BigRational.php', '_ContaoManager\\Brick\\Math\\Exception\\DivisionByZeroException' => $vendorDir . '/brick/math/src/Exception/DivisionByZeroException.php', '_ContaoManager\\Brick\\Math\\Exception\\IntegerOverflowException' => $vendorDir . '/brick/math/src/Exception/IntegerOverflowException.php', '_ContaoManager\\Brick\\Math\\Exception\\MathException' => $vendorDir . '/brick/math/src/Exception/MathException.php', '_ContaoManager\\Brick\\Math\\Exception\\NegativeNumberException' => $vendorDir . '/brick/math/src/Exception/NegativeNumberException.php', '_ContaoManager\\Brick\\Math\\Exception\\NumberFormatException' => $vendorDir . '/brick/math/src/Exception/NumberFormatException.php', '_ContaoManager\\Brick\\Math\\Exception\\RoundingNecessaryException' => $vendorDir . '/brick/math/src/Exception/RoundingNecessaryException.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator' => $vendorDir . '/brick/math/src/Internal/Calculator.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/BcMathCalculator.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\GmpCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/GmpCalculator.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\NativeCalculator' => $vendorDir . '/brick/math/src/Internal/Calculator/NativeCalculator.php', '_ContaoManager\\Brick\\Math\\RoundingMode' => $vendorDir . '/brick/math/src/RoundingMode.php', '_ContaoManager\\CBOR\\AbstractCBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/AbstractCBORObject.php', '_ContaoManager\\CBOR\\ByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/ByteStringObject.php', '_ContaoManager\\CBOR\\CBORObject' => $vendorDir . '/spomky-labs/cbor-php/src/CBORObject.php', '_ContaoManager\\CBOR\\Decoder' => $vendorDir . '/spomky-labs/cbor-php/src/Decoder.php', '_ContaoManager\\CBOR\\DecoderInterface' => $vendorDir . '/spomky-labs/cbor-php/src/DecoderInterface.php', '_ContaoManager\\CBOR\\IndefiniteLengthByteStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php', '_ContaoManager\\CBOR\\IndefiniteLengthListObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php', '_ContaoManager\\CBOR\\IndefiniteLengthMapObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php', '_ContaoManager\\CBOR\\IndefiniteLengthTextStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php', '_ContaoManager\\CBOR\\LengthCalculator' => $vendorDir . '/spomky-labs/cbor-php/src/LengthCalculator.php', '_ContaoManager\\CBOR\\ListObject' => $vendorDir . '/spomky-labs/cbor-php/src/ListObject.php', '_ContaoManager\\CBOR\\MapItem' => $vendorDir . '/spomky-labs/cbor-php/src/MapItem.php', '_ContaoManager\\CBOR\\MapObject' => $vendorDir . '/spomky-labs/cbor-php/src/MapObject.php', '_ContaoManager\\CBOR\\NegativeIntegerObject' => $vendorDir . '/spomky-labs/cbor-php/src/NegativeIntegerObject.php', '_ContaoManager\\CBOR\\Normalizable' => $vendorDir . '/spomky-labs/cbor-php/src/Normalizable.php', '_ContaoManager\\CBOR\\OtherObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject.php', '_ContaoManager\\CBOR\\OtherObject\\BreakObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/BreakObject.php', '_ContaoManager\\CBOR\\OtherObject\\DoublePrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php', '_ContaoManager\\CBOR\\OtherObject\\FalseObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/FalseObject.php', '_ContaoManager\\CBOR\\OtherObject\\GenericObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/GenericObject.php', '_ContaoManager\\CBOR\\OtherObject\\HalfPrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php', '_ContaoManager\\CBOR\\OtherObject\\NullObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/NullObject.php', '_ContaoManager\\CBOR\\OtherObject\\OtherObjectInterface' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectInterface.php', '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManager' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php', '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManagerInterface' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php', '_ContaoManager\\CBOR\\OtherObject\\SimpleObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php', '_ContaoManager\\CBOR\\OtherObject\\SinglePrecisionFloatObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php', '_ContaoManager\\CBOR\\OtherObject\\TrueObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/TrueObject.php', '_ContaoManager\\CBOR\\OtherObject\\UndefinedObject' => $vendorDir . '/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php', '_ContaoManager\\CBOR\\Stream' => $vendorDir . '/spomky-labs/cbor-php/src/Stream.php', '_ContaoManager\\CBOR\\StringStream' => $vendorDir . '/spomky-labs/cbor-php/src/StringStream.php', '_ContaoManager\\CBOR\\Tag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag.php', '_ContaoManager\\CBOR\\Tag\\Base16EncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php', '_ContaoManager\\CBOR\\Tag\\Base64EncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php', '_ContaoManager\\CBOR\\Tag\\Base64Tag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64Tag.php', '_ContaoManager\\CBOR\\Tag\\Base64UrlEncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php', '_ContaoManager\\CBOR\\Tag\\Base64UrlTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php', '_ContaoManager\\CBOR\\Tag\\BigFloatTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/BigFloatTag.php', '_ContaoManager\\CBOR\\Tag\\CBOREncodingTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php', '_ContaoManager\\CBOR\\Tag\\CBORTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/CBORTag.php', '_ContaoManager\\CBOR\\Tag\\DatetimeTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/DatetimeTag.php', '_ContaoManager\\CBOR\\Tag\\DecimalFractionTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php', '_ContaoManager\\CBOR\\Tag\\GenericTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/GenericTag.php', '_ContaoManager\\CBOR\\Tag\\MimeTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/MimeTag.php', '_ContaoManager\\CBOR\\Tag\\NegativeBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php', '_ContaoManager\\CBOR\\Tag\\TagInterface' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagInterface.php', '_ContaoManager\\CBOR\\Tag\\TagManager' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManager.php', '_ContaoManager\\CBOR\\Tag\\TagManagerInterface' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php', '_ContaoManager\\CBOR\\Tag\\TimestampTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/TimestampTag.php', '_ContaoManager\\CBOR\\Tag\\UnsignedBigIntegerTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php', '_ContaoManager\\CBOR\\Tag\\UriTag' => $vendorDir . '/spomky-labs/cbor-php/src/Tag/UriTag.php', '_ContaoManager\\CBOR\\TextStringObject' => $vendorDir . '/spomky-labs/cbor-php/src/TextStringObject.php', '_ContaoManager\\CBOR\\UnsignedIntegerObject' => $vendorDir . '/spomky-labs/cbor-php/src/UnsignedIntegerObject.php', '_ContaoManager\\CBOR\\Utils' => $vendorDir . '/spomky-labs/cbor-php/src/Utils.php', '_ContaoManager\\Contao\\ManagerApi\\ApiApplication' => $baseDir . '/api/ApiApplication.php', '_ContaoManager\\Contao\\ManagerApi\\ApiKernel' => $baseDir . '/api/ApiKernel.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand' => $baseDir . '/api/Command/AboutCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => $baseDir . '/api/Command/IntegrityCheckCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => $baseDir . '/api/Command/ProcessRunnerCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand' => $baseDir . '/api/Command/TaskAbortCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand' => $baseDir . '/api/Command/TaskDeleteCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand' => $baseDir . '/api/Command/TaskUpdateCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand' => $baseDir . '/api/Command/UpdateCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudChanges' => $baseDir . '/api/Composer/CloudChanges.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudException' => $baseDir . '/api/Composer/CloudException.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudJob' => $baseDir . '/api/Composer/CloudJob.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver' => $baseDir . '/api/Composer/CloudResolver.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment' => $baseDir . '/api/Composer/Environment.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\AbstractConfig' => $baseDir . '/api/Config/AbstractConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\AuthConfig' => $baseDir . '/api/Config/AuthConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig' => $baseDir . '/api/Config/ComposerConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig' => $baseDir . '/api/Config/ManagerConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\PartialConfig' => $baseDir . '/api/Config/PartialConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig' => $baseDir . '/api/Config/UploadsConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig' => $baseDir . '/api/Config/UserConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AbstractConfigController' => $baseDir . '/api/Controller/Config/AbstractConfigController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController' => $baseDir . '/api/Controller/Config/AuthController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController' => $baseDir . '/api/Controller/Config/ComposerController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController' => $baseDir . '/api/Controller/Config/ManagerController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController' => $baseDir . '/api/Controller/ConstraintController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController' => $baseDir . '/api/Controller/Contao/AccessKeyController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController' => $baseDir . '/api/Controller/Contao/BackupController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController' => $baseDir . '/api/Controller/Contao/DatabaseMigrationController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController' => $baseDir . '/api/Controller/Contao/InstallToolLockController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController' => $baseDir . '/api/Controller/Contao/JwtCookieController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController' => $baseDir . '/api/Controller/Contao/MaintenanceModeController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController' => $baseDir . '/api/Controller/FileController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController' => $baseDir . '/api/Controller/LogController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController' => $baseDir . '/api/Controller/Packages/CloudController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController' => $baseDir . '/api/Controller/Packages/LocalPackagesController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController' => $baseDir . '/api/Controller/Packages/MissingPackagesController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController' => $baseDir . '/api/Controller/Packages/RootPackageController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController' => $baseDir . '/api/Controller/Packages/UploadPackagesController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => $baseDir . '/api/Controller/Server/AdminUserController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => $baseDir . '/api/Controller/Server/ComposerController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController' => $baseDir . '/api/Controller/Server/ConfigController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController' => $baseDir . '/api/Controller/Server/ContaoController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController' => $baseDir . '/api/Controller/Server/DatabaseController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController' => $baseDir . '/api/Controller/Server/OpcacheController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => $baseDir . '/api/Controller/Server/PhpCliController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => $baseDir . '/api/Controller/Server/PhpWebController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController' => $baseDir . '/api/Controller/Server/PhpinfoController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => $baseDir . '/api/Controller/Server/SelfUpdateController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController' => $baseDir . '/api/Controller/SessionController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController' => $baseDir . '/api/Controller/TaskController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController' => $baseDir . '/api/Controller/UserController.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener' => $baseDir . '/api/EventListener/CheckTotpListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener' => $baseDir . '/api/EventListener/ExceptionListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener' => $baseDir . '/api/EventListener/JsonRequestListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener' => $baseDir . '/api/EventListener/LocaleListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener' => $baseDir . '/api/EventListener/SecurityListener.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\ApiProblemException' => $baseDir . '/api/Exception/ApiProblemException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidJsonException' => $baseDir . '/api/Exception/InvalidJsonException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidTotpException' => $baseDir . '/api/Exception/InvalidTotpException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\ProcessOutputException' => $baseDir . '/api/Exception/ProcessOutputException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\RequestException' => $baseDir . '/api/Exception/RequestException.php', '_ContaoManager\\Contao\\ManagerApi\\HttpKernel\\ApiProblemResponse' => $baseDir . '/api/HttpKernel/ApiProblemResponse.php', '_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator' => $baseDir . '/api/I18n/Translator.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AbstractIntegrityCheck' => $baseDir . '/api/IntegrityCheck/AbstractIntegrityCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck' => $baseDir . '/api/IntegrityCheck/AllowUrlFopenCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck' => $baseDir . '/api/IntegrityCheck/GraphicsLibCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => $baseDir . '/api/IntegrityCheck/IntegrityCheckFactory.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckInterface' => $baseDir . '/api/IntegrityCheck/IntegrityCheckInterface.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck' => $baseDir . '/api/IntegrityCheck/MemoryLimitCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck' => $baseDir . '/api/IntegrityCheck/PhpExtensionsCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck' => $baseDir . '/api/IntegrityCheck/ProcessCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck' => $baseDir . '/api/IntegrityCheck/SessionCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck' => $baseDir . '/api/IntegrityCheck/SymlinkCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck' => $baseDir . '/api/IntegrityCheck/SysTempDirCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ZipCheck' => $baseDir . '/api/IntegrityCheck/ZipCheck.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\AbstractProcess' => $baseDir . '/api/Process/AbstractProcess.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => $baseDir . '/api/Process/ConsoleProcessFactory.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi' => $baseDir . '/api/Process/ContaoApi.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole' => $baseDir . '/api/Process/ContaoConsole.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\AbstractForker' => $baseDir . '/api/Process/Forker/AbstractForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\DisownForker' => $baseDir . '/api/Process/Forker/DisownForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\ForkerInterface' => $baseDir . '/api/Process/Forker/ForkerInterface.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\InlineForker' => $baseDir . '/api/Process/Forker/InlineForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\NohupForker' => $baseDir . '/api/Process/Forker/NohupForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\WindowsStartForker' => $baseDir . '/api/Process/Forker/WindowsStartForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\PhpExecutableFinder' => $baseDir . '/api/Process/PhpExecutableFinder.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessController' => $baseDir . '/api/Process/ProcessController.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessRunner' => $baseDir . '/api/Process/ProcessRunner.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Utf8Process' => $baseDir . '/api/Process/Utf8Process.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\AbstractBrowserAuthenticator' => $baseDir . '/api/Security/AbstractBrowserAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator' => $baseDir . '/api/Security/JwtAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager' => $baseDir . '/api/Security/JwtManager.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator' => $baseDir . '/api/Security/LoginAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator' => $baseDir . '/api/Security/PasswordlessAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator' => $baseDir . '/api/Security/TokenAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\TotpBadge' => $baseDir . '/api/Security/TotpBadge.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\User' => $baseDir . '/api/Security/User.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider' => $baseDir . '/api/Security/UserProvider.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => $baseDir . '/api/Security/WebauthnAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\System\\Request' => $baseDir . '/api/System/Request.php', '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate' => $baseDir . '/api/System/SelfUpdate.php', '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo' => $baseDir . '/api/System/ServerInfo.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractInlineOperation' => $baseDir . '/api/TaskOperation/AbstractInlineOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractProcessOperation' => $baseDir . '/api/TaskOperation/AbstractProcessOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\ClearCacheOperation' => $baseDir . '/api/TaskOperation/Composer/ClearCacheOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CloudOperation' => $baseDir . '/api/TaskOperation/Composer/CloudOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CreateProjectOperation' => $baseDir . '/api/TaskOperation/Composer/CreateProjectOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\DumpAutoloadOperation' => $baseDir . '/api/TaskOperation/Composer/DumpAutoloadOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\InstallOperation' => $baseDir . '/api/TaskOperation/Composer/InstallOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RemoveOperation' => $baseDir . '/api/TaskOperation/Composer/RemoveOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RequireOperation' => $baseDir . '/api/TaskOperation/Composer/RequireOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\UpdateOperation' => $baseDir . '/api/TaskOperation/Composer/UpdateOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\ConsoleOutput' => $baseDir . '/api/TaskOperation/ConsoleOutput.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupCreateOperation' => $baseDir . '/api/TaskOperation/Contao/BackupCreateOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupRestoreOperation' => $baseDir . '/api/TaskOperation/Contao/BackupRestoreOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheClearOperation' => $baseDir . '/api/TaskOperation/Contao/CacheClearOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheWarmupOperation' => $baseDir . '/api/TaskOperation/Contao/CacheWarmupOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CreateContaoOperation' => $baseDir . '/api/TaskOperation/Contao/CreateContaoOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\MaintenanceModeOperation' => $baseDir . '/api/TaskOperation/Contao/MaintenanceModeOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\InstallUploadsOperation' => $baseDir . '/api/TaskOperation/Filesystem/InstallUploadsOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveCacheOperation' => $baseDir . '/api/TaskOperation/Filesystem/RemoveCacheOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveUploadsOperation' => $baseDir . '/api/TaskOperation/Filesystem/RemoveUploadsOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveVendorOperation' => $baseDir . '/api/TaskOperation/Filesystem/RemoveVendorOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Manager\\SelfUpdateOperation' => $baseDir . '/api/TaskOperation/Manager/SelfUpdateOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\SponsoredOperationInterface' => $baseDir . '/api/TaskOperation/SponsoredOperationInterface.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\TaskOperationInterface' => $baseDir . '/api/TaskOperation/TaskOperationInterface.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\AbstractTask' => $baseDir . '/api/Task/AbstractTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => $baseDir . '/api/Task/Composer/ClearCacheTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => $baseDir . '/api/Task/Composer/DumpAutoloadTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => $baseDir . '/api/Task/Contao/BackupCreateTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => $baseDir . '/api/Task/Contao/BackupRestoreTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => $baseDir . '/api/Task/Contao/RebuildCacheTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => $baseDir . '/api/Task/Manager/SelfUpdateTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\AbstractPackagesTask' => $baseDir . '/api/Task/Packages/AbstractPackagesTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask' => $baseDir . '/api/Task/Packages/InstallTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask' => $baseDir . '/api/Task/Packages/SetupTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => $baseDir . '/api/Task/Packages/UpdateTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskConfig' => $baseDir . '/api/Task/TaskConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskInterface' => $baseDir . '/api/Task/TaskInterface.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager' => $baseDir . '/api/Task/TaskManager.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskStatus' => $baseDir . '/api/Task/TaskStatus.php', '_ContaoManager\\Contao\\ManagerApi\\Tests\\Composer\\CloudJobTest' => $baseDir . '/api/Tests/Composer/CloudJobTest.php', '_ContaoManager\\Contao\\ManagerApi\\Tests\\Controller\\LogPatternTest' => $baseDir . '/api/Tests/Controller/LogPatternTest.php', '_ContaoManager\\Cose\\Algorithm\\Algorithm' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Algorithm.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS256.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256Truncated64' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS384.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/HS512.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\Hmac' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\Mac' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Mac/Mac.php', '_ContaoManager\\Cose\\Algorithm\\Manager' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Manager.php', '_ContaoManager\\Cose\\Algorithm\\ManagerFactory' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/ManagerFactory.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECDSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECSignature' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256K' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed25519' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\EdDSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PSSRSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS1' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS256' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS384' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS512' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RSA' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\Signature' => $vendorDir . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php', '_ContaoManager\\Cose\\Algorithms' => $vendorDir . '/web-auth/cose-lib/src/Algorithms.php', '_ContaoManager\\Cose\\BigInteger' => $vendorDir . '/web-auth/cose-lib/src/BigInteger.php', '_ContaoManager\\Cose\\Hash' => $vendorDir . '/web-auth/cose-lib/src/Hash.php', '_ContaoManager\\Cose\\Key\\Ec2Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Ec2Key.php', '_ContaoManager\\Cose\\Key\\Key' => $vendorDir . '/web-auth/cose-lib/src/Key/Key.php', '_ContaoManager\\Cose\\Key\\OkpKey' => $vendorDir . '/web-auth/cose-lib/src/Key/OkpKey.php', '_ContaoManager\\Cose\\Key\\RsaKey' => $vendorDir . '/web-auth/cose-lib/src/Key/RsaKey.php', '_ContaoManager\\Cose\\Key\\SymmetricKey' => $vendorDir . '/web-auth/cose-lib/src/Key/SymmetricKey.php', '_ContaoManager\\Crell\\ApiProblem\\ApiProblem' => $vendorDir . '/crell/api-problem/src/ApiProblem.php', '_ContaoManager\\Crell\\ApiProblem\\HttpConverter' => $vendorDir . '/crell/api-problem/src/HttpConverter.php', '_ContaoManager\\Crell\\ApiProblem\\JsonEncodeException' => $vendorDir . '/crell/api-problem/src/JsonEncodeException.php', '_ContaoManager\\Crell\\ApiProblem\\JsonException' => $vendorDir . '/crell/api-problem/src/JsonException.php', '_ContaoManager\\Crell\\ApiProblem\\JsonParseException' => $vendorDir . '/crell/api-problem/src/JsonParseException.php', '_ContaoManager\\Doctrine\\Deprecations\\Deprecation' => $vendorDir . '/doctrine/deprecations/src/Deprecation.php', '_ContaoManager\\Doctrine\\Deprecations\\PHPUnit\\VerifyDeprecations' => $vendorDir . '/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php', '_ContaoManager\\Firebase\\JWT\\BeforeValidException' => $vendorDir . '/firebase/php-jwt/src/BeforeValidException.php', '_ContaoManager\\Firebase\\JWT\\CachedKeySet' => $vendorDir . '/firebase/php-jwt/src/CachedKeySet.php', '_ContaoManager\\Firebase\\JWT\\ExpiredException' => $vendorDir . '/firebase/php-jwt/src/ExpiredException.php', '_ContaoManager\\Firebase\\JWT\\JWK' => $vendorDir . '/firebase/php-jwt/src/JWK.php', '_ContaoManager\\Firebase\\JWT\\JWT' => $vendorDir . '/firebase/php-jwt/src/JWT.php', '_ContaoManager\\Firebase\\JWT\\JWTExceptionWithPayloadInterface' => $vendorDir . '/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php', '_ContaoManager\\Firebase\\JWT\\Key' => $vendorDir . '/firebase/php-jwt/src/Key.php', '_ContaoManager\\Firebase\\JWT\\SignatureInvalidException' => $vendorDir . '/firebase/php-jwt/src/SignatureInvalidException.php', '_ContaoManager\\JsonSchema\\Constraints\\BaseConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\CollectionConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\Constraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php', '_ContaoManager\\JsonSchema\\Constraints\\ConstraintInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php', '_ContaoManager\\JsonSchema\\Constraints\\EnumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\Factory' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php', '_ContaoManager\\JsonSchema\\Constraints\\FormatConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\NumberConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\ObjectConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\SchemaConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\StringConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\LooseTypeCheck' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\StrictTypeCheck' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\TypeCheckInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\UndefinedConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php', '_ContaoManager\\JsonSchema\\Entity\\JsonPointer' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php', '_ContaoManager\\JsonSchema\\Exception\\ExceptionInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidArgumentException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidConfigException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaMediaTypeException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidSourceUriException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php', '_ContaoManager\\JsonSchema\\Exception\\JsonDecodingException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php', '_ContaoManager\\JsonSchema\\Exception\\ResourceNotFoundException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php', '_ContaoManager\\JsonSchema\\Exception\\RuntimeException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php', '_ContaoManager\\JsonSchema\\Exception\\UnresolvableJsonPointerException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php', '_ContaoManager\\JsonSchema\\Exception\\UriResolverException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php', '_ContaoManager\\JsonSchema\\Exception\\ValidationException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.php', '_ContaoManager\\JsonSchema\\Iterator\\ObjectIterator' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php', '_ContaoManager\\JsonSchema\\Rfc3339' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php', '_ContaoManager\\JsonSchema\\SchemaStorage' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php', '_ContaoManager\\JsonSchema\\SchemaStorageInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php', '_ContaoManager\\JsonSchema\\UriResolverInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php', '_ContaoManager\\JsonSchema\\UriRetrieverInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\AbstractRetriever' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\Curl' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\FileGetContents' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\PredefinedArray' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\UriRetrieverInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php', '_ContaoManager\\JsonSchema\\Uri\\UriResolver' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php', '_ContaoManager\\JsonSchema\\Uri\\UriRetriever' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php', '_ContaoManager\\JsonSchema\\Validator' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Validator.php', '_ContaoManager\\Lcobucci\\Clock\\Clock' => $vendorDir . '/lcobucci/clock/src/Clock.php', '_ContaoManager\\Lcobucci\\Clock\\FrozenClock' => $vendorDir . '/lcobucci/clock/src/FrozenClock.php', '_ContaoManager\\Lcobucci\\Clock\\SystemClock' => $vendorDir . '/lcobucci/clock/src/SystemClock.php', '_ContaoManager\\Monolog\\Attribute\\AsMonologProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php', '_ContaoManager\\Monolog\\Attribute\\WithMonologChannel' => $vendorDir . '/monolog/monolog/src/Monolog/Attribute/WithMonologChannel.php', '_ContaoManager\\Monolog\\DateTimeImmutable' => $vendorDir . '/monolog/monolog/src/Monolog/DateTimeImmutable.php', '_ContaoManager\\Monolog\\ErrorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/ErrorHandler.php', '_ContaoManager\\Monolog\\Formatter\\ChromePHPFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php', '_ContaoManager\\Monolog\\Formatter\\ElasticaFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php', '_ContaoManager\\Monolog\\Formatter\\ElasticsearchFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php', '_ContaoManager\\Monolog\\Formatter\\FlowdockFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php', '_ContaoManager\\Monolog\\Formatter\\FluentdFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php', '_ContaoManager\\Monolog\\Formatter\\FormatterInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php', '_ContaoManager\\Monolog\\Formatter\\GelfMessageFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php', '_ContaoManager\\Monolog\\Formatter\\GoogleCloudLoggingFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php', '_ContaoManager\\Monolog\\Formatter\\HtmlFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php', '_ContaoManager\\Monolog\\Formatter\\JsonFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LineFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LogglyFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LogmaticFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LogstashFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php', '_ContaoManager\\Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php', '_ContaoManager\\Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php', '_ContaoManager\\Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php', '_ContaoManager\\Monolog\\Formatter\\SyslogFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php', '_ContaoManager\\Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php', '_ContaoManager\\Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php', '_ContaoManager\\Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php', '_ContaoManager\\Monolog\\Handler\\AbstractSyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php', '_ContaoManager\\Monolog\\Handler\\AmqpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php', '_ContaoManager\\Monolog\\Handler\\BrowserConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php', '_ContaoManager\\Monolog\\Handler\\BufferHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php', '_ContaoManager\\Monolog\\Handler\\ChromePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php', '_ContaoManager\\Monolog\\Handler\\CouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php', '_ContaoManager\\Monolog\\Handler\\CubeHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php', '_ContaoManager\\Monolog\\Handler\\Curl\\Util' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php', '_ContaoManager\\Monolog\\Handler\\DeduplicationHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php', '_ContaoManager\\Monolog\\Handler\\DoctrineCouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php', '_ContaoManager\\Monolog\\Handler\\DynamoDbHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php', '_ContaoManager\\Monolog\\Handler\\ElasticaHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php', '_ContaoManager\\Monolog\\Handler\\ElasticsearchHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php', '_ContaoManager\\Monolog\\Handler\\ErrorLogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php', '_ContaoManager\\Monolog\\Handler\\FallbackGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php', '_ContaoManager\\Monolog\\Handler\\FilterHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossedHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php', '_ContaoManager\\Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php', '_ContaoManager\\Monolog\\Handler\\FleepHookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php', '_ContaoManager\\Monolog\\Handler\\FlowdockHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php', '_ContaoManager\\Monolog\\Handler\\FormattableHandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php', '_ContaoManager\\Monolog\\Handler\\FormattableHandlerTrait' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php', '_ContaoManager\\Monolog\\Handler\\GelfHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php', '_ContaoManager\\Monolog\\Handler\\GroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php', '_ContaoManager\\Monolog\\Handler\\Handler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Handler.php', '_ContaoManager\\Monolog\\Handler\\HandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php', '_ContaoManager\\Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php', '_ContaoManager\\Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php', '_ContaoManager\\Monolog\\Handler\\InsightOpsHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php', '_ContaoManager\\Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php', '_ContaoManager\\Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php', '_ContaoManager\\Monolog\\Handler\\LogmaticHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php', '_ContaoManager\\Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php', '_ContaoManager\\Monolog\\Handler\\MandrillHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php', '_ContaoManager\\Monolog\\Handler\\MissingExtensionException' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php', '_ContaoManager\\Monolog\\Handler\\MongoDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php', '_ContaoManager\\Monolog\\Handler\\NativeMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php', '_ContaoManager\\Monolog\\Handler\\NewRelicHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php', '_ContaoManager\\Monolog\\Handler\\NoopHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NoopHandler.php', '_ContaoManager\\Monolog\\Handler\\NullHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NullHandler.php', '_ContaoManager\\Monolog\\Handler\\OverflowHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/OverflowHandler.php', '_ContaoManager\\Monolog\\Handler\\PHPConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php', '_ContaoManager\\Monolog\\Handler\\ProcessHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ProcessHandler.php', '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php', '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerTrait' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php', '_ContaoManager\\Monolog\\Handler\\PsrHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php', '_ContaoManager\\Monolog\\Handler\\PushoverHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php', '_ContaoManager\\Monolog\\Handler\\RedisHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php', '_ContaoManager\\Monolog\\Handler\\RedisPubSubHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php', '_ContaoManager\\Monolog\\Handler\\RollbarHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php', '_ContaoManager\\Monolog\\Handler\\RotatingFileHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php', '_ContaoManager\\Monolog\\Handler\\SamplingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php', '_ContaoManager\\Monolog\\Handler\\SendGridHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SendGridHandler.php', '_ContaoManager\\Monolog\\Handler\\SlackHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php', '_ContaoManager\\Monolog\\Handler\\SlackWebhookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php', '_ContaoManager\\Monolog\\Handler\\Slack\\SlackRecord' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php', '_ContaoManager\\Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php', '_ContaoManager\\Monolog\\Handler\\SqsHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php', '_ContaoManager\\Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php', '_ContaoManager\\Monolog\\Handler\\SymfonyMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php', '_ContaoManager\\Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php', '_ContaoManager\\Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php', '_ContaoManager\\Monolog\\Handler\\SyslogUdp\\UdpSocket' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php', '_ContaoManager\\Monolog\\Handler\\TelegramBotHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php', '_ContaoManager\\Monolog\\Handler\\TestHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/TestHandler.php', '_ContaoManager\\Monolog\\Handler\\WebRequestRecognizerTrait' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php', '_ContaoManager\\Monolog\\Handler\\WhatFailureGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php', '_ContaoManager\\Monolog\\Handler\\ZendMonitorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php', '_ContaoManager\\Monolog\\JsonSerializableDateTimeImmutable' => $vendorDir . '/monolog/monolog/src/Monolog/JsonSerializableDateTimeImmutable.php', '_ContaoManager\\Monolog\\Level' => $vendorDir . '/monolog/monolog/src/Monolog/Level.php', '_ContaoManager\\Monolog\\LogRecord' => $vendorDir . '/monolog/monolog/src/Monolog/LogRecord.php', '_ContaoManager\\Monolog\\Logger' => $vendorDir . '/monolog/monolog/src/Monolog/Logger.php', '_ContaoManager\\Monolog\\Processor\\ClosureContextProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ClosureContextProcessor.php', '_ContaoManager\\Monolog\\Processor\\GitProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php', '_ContaoManager\\Monolog\\Processor\\HostnameProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php', '_ContaoManager\\Monolog\\Processor\\IntrospectionProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php', '_ContaoManager\\Monolog\\Processor\\LoadAverageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/LoadAverageProcessor.php', '_ContaoManager\\Monolog\\Processor\\MemoryPeakUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php', '_ContaoManager\\Monolog\\Processor\\MemoryProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php', '_ContaoManager\\Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php', '_ContaoManager\\Monolog\\Processor\\MercurialProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php', '_ContaoManager\\Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php', '_ContaoManager\\Monolog\\Processor\\ProcessorInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php', '_ContaoManager\\Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php', '_ContaoManager\\Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php', '_ContaoManager\\Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php', '_ContaoManager\\Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php', '_ContaoManager\\Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php', '_ContaoManager\\Monolog\\ResettableInterface' => $vendorDir . '/monolog/monolog/src/Monolog/ResettableInterface.php', '_ContaoManager\\Monolog\\SignalHandler' => $vendorDir . '/monolog/monolog/src/Monolog/SignalHandler.php', '_ContaoManager\\Monolog\\Test\\TestCase' => $vendorDir . '/monolog/monolog/src/Monolog/Test/TestCase.php', '_ContaoManager\\Monolog\\Utils' => $vendorDir . '/monolog/monolog/src/Monolog/Utils.php', '_ContaoManager\\OTPHP\\Factory' => $vendorDir . '/spomky-labs/otphp/src/Factory.php', '_ContaoManager\\OTPHP\\FactoryInterface' => $vendorDir . '/spomky-labs/otphp/src/FactoryInterface.php', '_ContaoManager\\OTPHP\\HOTP' => $vendorDir . '/spomky-labs/otphp/src/HOTP.php', '_ContaoManager\\OTPHP\\HOTPInterface' => $vendorDir . '/spomky-labs/otphp/src/HOTPInterface.php', '_ContaoManager\\OTPHP\\InternalClock' => $vendorDir . '/spomky-labs/otphp/src/InternalClock.php', '_ContaoManager\\OTPHP\\OTP' => $vendorDir . '/spomky-labs/otphp/src/OTP.php', '_ContaoManager\\OTPHP\\OTPInterface' => $vendorDir . '/spomky-labs/otphp/src/OTPInterface.php', '_ContaoManager\\OTPHP\\ParameterTrait' => $vendorDir . '/spomky-labs/otphp/src/ParameterTrait.php', '_ContaoManager\\OTPHP\\TOTP' => $vendorDir . '/spomky-labs/otphp/src/TOTP.php', '_ContaoManager\\OTPHP\\TOTPInterface' => $vendorDir . '/spomky-labs/otphp/src/TOTPInterface.php', '_ContaoManager\\OTPHP\\Url' => $vendorDir . '/spomky-labs/otphp/src/Url.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Attribute' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Attribute.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Comment' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Comment.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Node' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Node.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Lexer\\Lexer' => $vendorDir . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php', '_ContaoManager\\PHPStan\\PhpDocParser\\ParserConfig' => $vendorDir . '/phpstan/phpdoc-parser/src/ParserConfig.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ParserException' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ParserException.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TokenIterator' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TypeParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\DiffElem' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Differ' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Differ.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Printer' => $vendorDir . '/phpstan/phpdoc-parser/src/Printer/Printer.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base32' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base32Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Base32Hex.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlash' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlash.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64UrlSafe' => $vendorDir . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Binary' => $vendorDir . '/paragonie/constant_time_encoding/src/Binary.php', '_ContaoManager\\ParagonIE\\ConstantTime\\EncoderInterface' => $vendorDir . '/paragonie/constant_time_encoding/src/EncoderInterface.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Encoding' => $vendorDir . '/paragonie/constant_time_encoding/src/Encoding.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Hex' => $vendorDir . '/paragonie/constant_time_encoding/src/Hex.php', '_ContaoManager\\ParagonIE\\ConstantTime\\RFC4648' => $vendorDir . '/paragonie/constant_time_encoding/src/RFC4648.php', '_ContaoManager\\Psr\\Cache\\CacheException' => $vendorDir . '/psr/cache/src/CacheException.php', '_ContaoManager\\Psr\\Cache\\CacheItemInterface' => $vendorDir . '/psr/cache/src/CacheItemInterface.php', '_ContaoManager\\Psr\\Cache\\CacheItemPoolInterface' => $vendorDir . '/psr/cache/src/CacheItemPoolInterface.php', '_ContaoManager\\Psr\\Cache\\InvalidArgumentException' => $vendorDir . '/psr/cache/src/InvalidArgumentException.php', '_ContaoManager\\Psr\\Clock\\ClockInterface' => $vendorDir . '/psr/clock/src/ClockInterface.php', '_ContaoManager\\Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php', '_ContaoManager\\Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php', '_ContaoManager\\Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php', '_ContaoManager\\Psr\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/psr/event-dispatcher/src/EventDispatcherInterface.php', '_ContaoManager\\Psr\\EventDispatcher\\ListenerProviderInterface' => $vendorDir . '/psr/event-dispatcher/src/ListenerProviderInterface.php', '_ContaoManager\\Psr\\EventDispatcher\\StoppableEventInterface' => $vendorDir . '/psr/event-dispatcher/src/StoppableEventInterface.php', '_ContaoManager\\Psr\\Http\\Client\\ClientExceptionInterface' => $vendorDir . '/psr/http-client/src/ClientExceptionInterface.php', '_ContaoManager\\Psr\\Http\\Client\\ClientInterface' => $vendorDir . '/psr/http-client/src/ClientInterface.php', '_ContaoManager\\Psr\\Http\\Client\\NetworkExceptionInterface' => $vendorDir . '/psr/http-client/src/NetworkExceptionInterface.php', '_ContaoManager\\Psr\\Http\\Client\\RequestExceptionInterface' => $vendorDir . '/psr/http-client/src/RequestExceptionInterface.php', '_ContaoManager\\Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php', '_ContaoManager\\Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/RequestFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/psr/http-factory/src/ResponseFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/ServerRequestFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php', '_ContaoManager\\Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/psr/http-factory/src/StreamFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/psr/http-factory/src/UploadedFileFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/psr/http-factory/src/UriFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php', '_ContaoManager\\Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/src/AbstractLogger.php', '_ContaoManager\\Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/src/InvalidArgumentException.php', '_ContaoManager\\Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/src/LogLevel.php', '_ContaoManager\\Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/src/LoggerAwareInterface.php', '_ContaoManager\\Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/src/LoggerAwareTrait.php', '_ContaoManager\\Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/src/LoggerInterface.php', '_ContaoManager\\Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/src/LoggerTrait.php', '_ContaoManager\\Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/src/NullLogger.php', '_ContaoManager\\Ramsey\\Collection\\AbstractArray' => $vendorDir . '/ramsey/collection/src/AbstractArray.php', '_ContaoManager\\Ramsey\\Collection\\AbstractCollection' => $vendorDir . '/ramsey/collection/src/AbstractCollection.php', '_ContaoManager\\Ramsey\\Collection\\AbstractSet' => $vendorDir . '/ramsey/collection/src/AbstractSet.php', '_ContaoManager\\Ramsey\\Collection\\ArrayInterface' => $vendorDir . '/ramsey/collection/src/ArrayInterface.php', '_ContaoManager\\Ramsey\\Collection\\Collection' => $vendorDir . '/ramsey/collection/src/Collection.php', '_ContaoManager\\Ramsey\\Collection\\CollectionInterface' => $vendorDir . '/ramsey/collection/src/CollectionInterface.php', '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueue' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueue.php', '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueueInterface' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueueInterface.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionException' => $vendorDir . '/ramsey/collection/src/Exception/CollectionException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionMismatchException' => $vendorDir . '/ramsey/collection/src/Exception/CollectionMismatchException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidArgumentException' => $vendorDir . '/ramsey/collection/src/Exception/InvalidArgumentException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidPropertyOrMethod' => $vendorDir . '/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\NoSuchElementException' => $vendorDir . '/ramsey/collection/src/Exception/NoSuchElementException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\OutOfBoundsException' => $vendorDir . '/ramsey/collection/src/Exception/OutOfBoundsException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\UnsupportedOperationException' => $vendorDir . '/ramsey/collection/src/Exception/UnsupportedOperationException.php', '_ContaoManager\\Ramsey\\Collection\\GenericArray' => $vendorDir . '/ramsey/collection/src/GenericArray.php', '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractMap' => $vendorDir . '/ramsey/collection/src/Map/AbstractMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractTypedMap' => $vendorDir . '/ramsey/collection/src/Map/AbstractTypedMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\AssociativeArrayMap' => $vendorDir . '/ramsey/collection/src/Map/AssociativeArrayMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\MapInterface' => $vendorDir . '/ramsey/collection/src/Map/MapInterface.php', '_ContaoManager\\Ramsey\\Collection\\Map\\NamedParameterMap' => $vendorDir . '/ramsey/collection/src/Map/NamedParameterMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMap' => $vendorDir . '/ramsey/collection/src/Map/TypedMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMapInterface' => $vendorDir . '/ramsey/collection/src/Map/TypedMapInterface.php', '_ContaoManager\\Ramsey\\Collection\\Queue' => $vendorDir . '/ramsey/collection/src/Queue.php', '_ContaoManager\\Ramsey\\Collection\\QueueInterface' => $vendorDir . '/ramsey/collection/src/QueueInterface.php', '_ContaoManager\\Ramsey\\Collection\\Set' => $vendorDir . '/ramsey/collection/src/Set.php', '_ContaoManager\\Ramsey\\Collection\\Sort' => $vendorDir . '/ramsey/collection/src/Sort.php', '_ContaoManager\\Ramsey\\Collection\\Tool\\TypeTrait' => $vendorDir . '/ramsey/collection/src/Tool/TypeTrait.php', '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueExtractorTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueExtractorTrait.php', '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueToStringTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueToStringTrait.php', '_ContaoManager\\Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\BuilderCollection' => $vendorDir . '/ramsey/uuid/src/Builder/BuilderCollection.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\FallbackBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/FallbackBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\UuidBuilderInterface' => $vendorDir . '/ramsey/uuid/src/Builder/UuidBuilderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\CodecInterface' => $vendorDir . '/ramsey/uuid/src/Codec/CodecInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\GuidStringCodec' => $vendorDir . '/ramsey/uuid/src/Codec/GuidStringCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\OrderedTimeCodec' => $vendorDir . '/ramsey/uuid/src/Codec/OrderedTimeCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\StringCodec' => $vendorDir . '/ramsey/uuid/src/Codec/StringCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampFirstCombCodec' => $vendorDir . '/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampLastCombCodec' => $vendorDir . '/ramsey/uuid/src/Codec/TimestampLastCombCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\NumberConverterInterface' => $vendorDir . '/ramsey/uuid/src/Converter/NumberConverterInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\BigNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/BigNumberConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\DegradedNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\GenericNumberConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\TimeConverterInterface' => $vendorDir . '/ramsey/uuid/src/Converter/TimeConverterInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\BigNumberTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\DegradedTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\GenericTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\PhpTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\UnixTimeConverter' => $vendorDir . '/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\DegradedUuid' => $vendorDir . '/ramsey/uuid/src/DegradedUuid.php', '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidInterface' => $vendorDir . '/ramsey/uuid/src/DeprecatedUuidInterface.php', '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidMethodsTrait' => $vendorDir . '/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\BuilderNotFoundException' => $vendorDir . '/ramsey/uuid/src/Exception/BuilderNotFoundException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\DateTimeException' => $vendorDir . '/ramsey/uuid/src/Exception/DateTimeException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\DceSecurityException' => $vendorDir . '/ramsey/uuid/src/Exception/DceSecurityException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidArgumentException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidArgumentException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidBytesException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidBytesException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidUuidStringException' => $vendorDir . '/ramsey/uuid/src/Exception/InvalidUuidStringException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\NameException' => $vendorDir . '/ramsey/uuid/src/Exception/NameException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\NodeException' => $vendorDir . '/ramsey/uuid/src/Exception/NodeException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\RandomSourceException' => $vendorDir . '/ramsey/uuid/src/Exception/RandomSourceException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\TimeSourceException' => $vendorDir . '/ramsey/uuid/src/Exception/TimeSourceException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnableToBuildUuidException' => $vendorDir . '/ramsey/uuid/src/Exception/UnableToBuildUuidException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnsupportedOperationException' => $vendorDir . '/ramsey/uuid/src/Exception/UnsupportedOperationException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\UuidExceptionInterface' => $vendorDir . '/ramsey/uuid/src/Exception/UuidExceptionInterface.php', '_ContaoManager\\Ramsey\\Uuid\\FeatureSet' => $vendorDir . '/ramsey/uuid/src/FeatureSet.php', '_ContaoManager\\Ramsey\\Uuid\\Fields\\FieldsInterface' => $vendorDir . '/ramsey/uuid/src/Fields/FieldsInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Fields\\SerializableFieldsTrait' => $vendorDir . '/ramsey/uuid/src/Fields/SerializableFieldsTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\CombGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/CombGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DceSecurityGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultNameGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DefaultNameGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/DefaultTimeGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/NameGeneratorFactory.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/NameGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidNameGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidRandomGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomBytesGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/RandomBytesGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/RandomGeneratorFactory.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/RandomGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomLibAdapter' => $vendorDir . '/ramsey/uuid/src/Generator/RandomLibAdapter.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorFactory' => $vendorDir . '/ramsey/uuid/src/Generator/TimeGeneratorFactory.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorInterface' => $vendorDir . '/ramsey/uuid/src/Generator/TimeGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\UnixTimeGenerator' => $vendorDir . '/ramsey/uuid/src/Generator/UnixTimeGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Guid\\Fields' => $vendorDir . '/ramsey/uuid/src/Guid/Fields.php', '_ContaoManager\\Ramsey\\Uuid\\Guid\\Guid' => $vendorDir . '/ramsey/uuid/src/Guid/Guid.php', '_ContaoManager\\Ramsey\\Uuid\\Guid\\GuidBuilder' => $vendorDir . '/ramsey/uuid/src/Guid/GuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Lazy\\LazyUuidFromString' => $vendorDir . '/ramsey/uuid/src/Lazy/LazyUuidFromString.php', '_ContaoManager\\Ramsey\\Uuid\\Math\\BrickMathCalculator' => $vendorDir . '/ramsey/uuid/src/Math/BrickMathCalculator.php', '_ContaoManager\\Ramsey\\Uuid\\Math\\CalculatorInterface' => $vendorDir . '/ramsey/uuid/src/Math/CalculatorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Math\\RoundingMode' => $vendorDir . '/ramsey/uuid/src/Math/RoundingMode.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Fields' => $vendorDir . '/ramsey/uuid/src/Nonstandard/Fields.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Uuid' => $vendorDir . '/ramsey/uuid/src/Nonstandard/Uuid.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidBuilder' => $vendorDir . '/ramsey/uuid/src/Nonstandard/UuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidV6' => $vendorDir . '/ramsey/uuid/src/Nonstandard/UuidV6.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\DceSecurityProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Dce\\SystemDceSecurityProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\NodeProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/NodeProviderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\FallbackNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\NodeProviderCollection' => $vendorDir . '/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\RandomNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\StaticNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\SystemNodeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\TimeProviderInterface' => $vendorDir . '/ramsey/uuid/src/Provider/TimeProviderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\FixedTimeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\SystemTimeProvider' => $vendorDir . '/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Fields' => $vendorDir . '/ramsey/uuid/src/Rfc4122/Fields.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\FieldsInterface' => $vendorDir . '/ramsey/uuid/src/Rfc4122/FieldsInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/MaxTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxUuid' => $vendorDir . '/ramsey/uuid/src/Rfc4122/MaxUuid.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/NilTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilUuid' => $vendorDir . '/ramsey/uuid/src/Rfc4122/NilUuid.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\TimeTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/TimeTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidBuilder' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidInterface' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV1' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV1.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV2' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV2.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV3' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV3.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV4' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV4.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV5' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV5.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV6' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV6.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV7' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV7.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV8' => $vendorDir . '/ramsey/uuid/src/Rfc4122/UuidV8.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Validator' => $vendorDir . '/ramsey/uuid/src/Rfc4122/Validator.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VariantTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/VariantTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VersionTrait' => $vendorDir . '/ramsey/uuid/src/Rfc4122/VersionTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Decimal' => $vendorDir . '/ramsey/uuid/src/Type/Decimal.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Hexadecimal' => $vendorDir . '/ramsey/uuid/src/Type/Hexadecimal.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Integer' => $vendorDir . '/ramsey/uuid/src/Type/Integer.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\NumberInterface' => $vendorDir . '/ramsey/uuid/src/Type/NumberInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Time' => $vendorDir . '/ramsey/uuid/src/Type/Time.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\TypeInterface' => $vendorDir . '/ramsey/uuid/src/Type/TypeInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Uuid' => $vendorDir . '/ramsey/uuid/src/Uuid.php', '_ContaoManager\\Ramsey\\Uuid\\UuidFactory' => $vendorDir . '/ramsey/uuid/src/UuidFactory.php', '_ContaoManager\\Ramsey\\Uuid\\UuidFactoryInterface' => $vendorDir . '/ramsey/uuid/src/UuidFactoryInterface.php', '_ContaoManager\\Ramsey\\Uuid\\UuidInterface' => $vendorDir . '/ramsey/uuid/src/UuidInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Validator\\GenericValidator' => $vendorDir . '/ramsey/uuid/src/Validator/GenericValidator.php', '_ContaoManager\\Ramsey\\Uuid\\Validator\\ValidatorInterface' => $vendorDir . '/ramsey/uuid/src/Validator/ValidatorInterface.php', '_ContaoManager\\Seld\\JsonLint\\DuplicateKeyException' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php', '_ContaoManager\\Seld\\JsonLint\\JsonParser' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/JsonParser.php', '_ContaoManager\\Seld\\JsonLint\\Lexer' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/Lexer.php', '_ContaoManager\\Seld\\JsonLint\\ParsingException' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/ParsingException.php', '_ContaoManager\\Seld\\JsonLint\\Undefined' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/Undefined.php', '_ContaoManager\\Seld\\PharUtils\\Linter' => $vendorDir . '/seld/phar-utils/src/Linter.php', '_ContaoManager\\Seld\\PharUtils\\Timestamps' => $vendorDir . '/seld/phar-utils/src/Timestamps.php', '_ContaoManager\\Seld\\Signal\\SignalHandler' => $vendorDir . '/seld/signal-handler/src/SignalHandler.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Identifier' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Component/Identifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Length' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Component/Length.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\DERData' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/DERData.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Element' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Element.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Exception\\DecodeException' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Exception/DecodeException.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\ElementBase' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Feature/ElementBase.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Encodable' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Feature/Encodable.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Stringable' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Feature/Stringable.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/BaseString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseTime' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/BaseTime.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\ConstructedString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/ConstructedString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Sequence' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Sequence.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Set' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Set.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BMPString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BMPString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BitString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BitString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Boolean' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Boolean.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\CharacterString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/CharacterString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\EOC' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/EOC.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Enumerated' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Enumerated.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralizedTime' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralizedTime.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GraphicString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GraphicString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\IA5String' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/IA5String.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Integer' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Integer.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NullType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NullType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Number' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Number.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NumericString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NumericString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectDescriptor' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectDescriptor.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\OctetString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/OctetString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\PrintableString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/PrintableString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Real' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Real.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\RelativeOID' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/RelativeOID.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\T61String' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/T61String.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTCTime' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTCTime.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTF8String' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTF8String.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UniversalString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UniversalString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VideotexString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VideotexString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VisibleString' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VisibleString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\StringType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/StringType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Structure' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Structure.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/TaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ApplicationType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ApplicationType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ContextSpecificType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ContextSpecificType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\DERTaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/DERTaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitTagging' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitTagging.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitlyTaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitlyTaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitTagging' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitTagging.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitlyTaggedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitlyTaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\PrivateType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/PrivateType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\TaggedTypeWrap' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/TaggedTypeWrap.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TimeType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/TimeType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UniversalClass' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/UniversalClass.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UnspecifiedType' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Type/UnspecifiedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\BigInt' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Util/BigInt.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\Flags' => $vendorDir . '/spomky-labs/pki-framework/src/ASN1/Util/Flags.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto\\OpenSSLCrypto' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto/OpenSSLCrypto.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEM' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoEncoding/PEM.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEMBundle' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoEncoding/PEMBundle.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierFactory' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierFactory.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierProvider' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierProvider.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\ECPublicKeyAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/ECPublicKeyAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed25519AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed25519AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed448AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed448AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410EdAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410EdAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410XAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410XAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAPSSSSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAPSSSSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X25519AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X25519AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X448AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X448AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES128CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES128CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES192CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES192CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES256CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES256CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AESCBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AESCBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\BlockCipherAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/BlockCipherAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\CipherAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/CipherAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESCBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESCBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESEDE3CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESEDE3CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\RC2CBCAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/RC2CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AlgorithmIdentifierType' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AlgorithmIdentifierType.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AsymmetricCryptoAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AsymmetricCryptoAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\EncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/EncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\HashAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/HashAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\PRFAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/PRFAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\SignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/SignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\GenericAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/GenericAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA1AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA1AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA224AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA224AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA256AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA256AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA384AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA384AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA512AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA512AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\MD5AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/MD5AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\RFC4231HMACAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/RFC4231HMACAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA1AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA1AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA224AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA224AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA256AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA256AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA2AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA2AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA384AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA384AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA512AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA512AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA1AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA1AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA224AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA224AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA256AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA256AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA384AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA384AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA512AlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA512AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECSignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECSignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD2WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD2WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD4WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD4WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD5WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD5WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC3279RSASignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC3279RSASignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC4055RSASignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC4055RSASignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RSASignatureAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RSASignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA1WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA1WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA224WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA224WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA256WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA256WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA384WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA384WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA512WithRSAEncryptionAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA512WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\SpecificAlgorithmIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/SpecificAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\Attribute\\OneAsymmetricKeyAttributes' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/Attribute/OneAsymmetricKeyAttributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECConversion' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECConversion.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\OneAsymmetricKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/OneAsymmetricKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKeyInfo' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKeyInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKeyInfo' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKeyInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPublicKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSASSAPSSPrivateKey' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSASSAPSSPrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\ECSignature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/ECSignature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed25519Signature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed25519Signature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed448Signature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed448Signature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\GenericSignature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/GenericSignature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\RSASignature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/RSASignature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Signature' => $vendorDir . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Signature.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Attribute' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Attribute.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeType' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeType.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeTypeAndValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeTypeAndValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\AttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/AttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CommonNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CommonNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CountryNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CountryNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\DescriptionValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/DescriptionValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\DirectoryString' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/DirectoryString.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\PrintableStringValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/PrintableStringValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\GivenNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/GivenNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\LocalityNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/LocalityNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\NameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/NameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationalUnitNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationalUnitNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\PseudonymValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/PseudonymValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SerialNumberValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SerialNumberValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\StateOrProvinceNameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/StateOrProvinceNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SurnameValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SurnameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\TitleValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/TitleValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\UnknownAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/UnknownAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\AttributeCollection' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/AttributeCollection.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SequenceOfAttributes' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SequenceOfAttributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SetOfAttributes' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SetOfAttributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Name' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/Name.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\RDN' => $vendorDir . '/spomky-labs/pki-framework/src/X501/ASN1/RDN.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\DN\\DNParser' => $vendorDir . '/spomky-labs/pki-framework/src/X501/DN/DNParser.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\BinaryMatch' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/BinaryMatch.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseExactMatch' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseExactMatch.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseIgnoreMatch' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseIgnoreMatch.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\MatchingRule' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/MatchingRule.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\StringPrepMatchingRule' => $vendorDir . '/spomky-labs/pki-framework/src/X501/MatchingRule/StringPrepMatchingRule.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\CheckBidiStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/CheckBidiStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\InsignificantNonSubstringSpaceStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/InsignificantNonSubstringSpaceStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\MapStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/MapStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\NormalizeStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/NormalizeStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\PrepareStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/PrepareStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\ProhibitStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/ProhibitStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\StringPreparer' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/StringPreparer.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\TranscodeStep' => $vendorDir . '/spomky-labs/pki-framework/src/X501/StringPrep/TranscodeStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertIssuer' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertIssuer.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertValidityPeriod' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertValidityPeriod.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificate' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificate.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificateInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificateInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AccessIdentityAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AccessIdentityAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AuthenticationInfoAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AuthenticationInfoAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\ChargingIdentityAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/ChargingIdentityAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\GroupAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/GroupAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrSyntax' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrSyntax.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\RoleAttributeValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/RoleAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\SvceAuthInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/SvceAuthInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attributes' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Holder' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Holder.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\IssuerSerial' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/IssuerSerial.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\ObjectDigestInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/ObjectDigestInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\V2Form' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/V2Form.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidationConfig' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidationConfig.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidator' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidator.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\Exception\\ACValidationException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/Exception/ACValidationException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Certificate' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Certificate.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateBundle' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateBundle.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateChain' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateChain.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AAControlsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AAControlsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AccessDescription' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AccessDescription.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AuthorityAccessDescription' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AuthorityAccessDescription.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\SubjectAccessDescription' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/SubjectAccessDescription.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityInformationAccessExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityInformationAccessExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityKeyIdentifierExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityKeyIdentifierExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\BasicConstraintsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/BasicConstraintsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CRLDistributionPointsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CRLDistributionPointsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePoliciesExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePoliciesExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\CPSQualifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/CPSQualifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\DisplayText' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/DisplayText.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\NoticeReference' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/NoticeReference.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyInformation' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyInformation.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyQualifierInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyQualifierInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\UserNoticeQualifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/UserNoticeQualifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPoint' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPoint.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPointName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPointName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\FullName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/FullName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\ReasonFlags' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/ReasonFlags.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\RelativeName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/RelativeName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\ExtendedKeyUsageExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/ExtendedKeyUsageExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Extension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Extension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\FreshestCRLExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/FreshestCRLExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\InhibitAnyPolicyExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/InhibitAnyPolicyExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\IssuerAlternativeNameExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/IssuerAlternativeNameExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\KeyUsageExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/KeyUsageExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraintsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraintsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtree' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtree.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtrees' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtrees.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NoRevocationAvailableExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NoRevocationAvailableExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyConstraintsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyConstraintsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappingsExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappingsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappings\\PolicyMapping' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappings/PolicyMapping.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectAlternativeNameExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectAlternativeNameExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectDirectoryAttributesExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectDirectoryAttributesExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectInformationAccessExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectInformationAccessExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectKeyIdentifierExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectKeyIdentifierExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\TargetInformationExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/TargetInformationExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Target' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Target.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetGroup' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetGroup.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Targets' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Targets.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\UnknownExtension' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/UnknownExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extensions' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Extensions.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\TBSCertificate' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/TBSCertificate.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Time' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Time.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\UniqueIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/UniqueIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Validity' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Certificate/Validity.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\CertificationPath' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/CertificationPath.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathBuildingException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathBuildingException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathValidationException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathValidationException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathBuilding\\CertificationPathBuilder' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathBuilding/CertificationPathBuilder.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationConfig' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationConfig.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationResult' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationResult.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidator' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidator.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\ValidatorState' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/ValidatorState.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyNode' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyNode.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyTree' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyTree.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attribute\\ExtensionRequestValue' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attribute/ExtensionRequestValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attributes' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequest' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequest.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequestInfo' => $vendorDir . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequestInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Exception\\X509ValidationException' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Exception/X509ValidationException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Feature\\DateTimeHelper' => $vendorDir . '/spomky-labs/pki-framework/src/X509/Feature/DateTimeHelper.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DNSName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/DNSName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DirectoryName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/DirectoryName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\EDIPartyName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/EDIPartyName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralNames' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralNames.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPAddress' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/IPAddress.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv4Address' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv4Address.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv6Address' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv6Address.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\OtherName' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/OtherName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RFC822Name' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/RFC822Name.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RegisteredID' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/RegisteredID.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\UniformResourceIdentifier' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/UniformResourceIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\X400Address' => $vendorDir . '/spomky-labs/pki-framework/src/X509/GeneralName/X400Address.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Command\\ServerLogCommand' => $vendorDir . '/symfony/monolog-bridge/Command/ServerLogCommand.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\CompatibilityFormatter' => $vendorDir . '/symfony/monolog-bridge/Formatter/CompatibilityFormatter.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\ConsoleFormatter' => $vendorDir . '/symfony/monolog-bridge/Formatter/ConsoleFormatter.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\VarDumperFormatter' => $vendorDir . '/symfony/monolog-bridge/Formatter/VarDumperFormatter.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ChromePhpHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ChromePhpHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/CompatibilityHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityProcessingHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/CompatibilityProcessingHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ConsoleHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ElasticsearchLogstashHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ElasticsearchLogstashHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\HttpCodeActivationStrategy' => $vendorDir . '/symfony/monolog-bridge/Handler/FingersCrossed/HttpCodeActivationStrategy.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\NotFoundActivationStrategy' => $vendorDir . '/symfony/monolog-bridge/Handler/FingersCrossed/NotFoundActivationStrategy.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/FirePHPHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\MailerHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/MailerHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\NotifierHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/NotifierHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ServerLogHandler' => $vendorDir . '/symfony/monolog-bridge/Handler/ServerLogHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Logger' => $vendorDir . '/symfony/monolog-bridge/Logger.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\AbstractTokenProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/AbstractTokenProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\CompatibilityProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/CompatibilityProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\ConsoleCommandProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/ConsoleCommandProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\DebugProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/DebugProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\RouteProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/RouteProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\SwitchUserTokenProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/SwitchUserTokenProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\TokenProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/TokenProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\WebProcessor' => $vendorDir . '/symfony/monolog-bridge/Processor/WebProcessor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ConfigBuilderCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\RouterCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\SerializerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\TranslationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ValidatorCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AboutCommand' => $vendorDir . '/symfony/framework-bundle/Command/AboutCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AbstractConfigCommand' => $vendorDir . '/symfony/framework-bundle/Command/AbstractConfigCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AssetsInstallCommand' => $vendorDir . '/symfony/framework-bundle/Command/AssetsInstallCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\BuildDebugContainerTrait' => $vendorDir . '/symfony/framework-bundle/Command/BuildDebugContainerTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheClearCommand' => $vendorDir . '/symfony/framework-bundle/Command/CacheClearCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolClearCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolClearCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolDeleteCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolDeleteCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolInvalidateTagsCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolInvalidateTagsCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolListCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolListCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolPruneCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolPruneCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheWarmupCommand' => $vendorDir . '/symfony/framework-bundle/Command/CacheWarmupCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/ConfigDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDumpReferenceCommand' => $vendorDir . '/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/ContainerDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/ContainerLintCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\DebugAutowiringCommand' => $vendorDir . '/symfony/framework-bundle/Command/DebugAutowiringCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\EventDispatcherDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/RouterDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterMatchCommand' => $vendorDir . '/symfony/framework-bundle/Command/RouterMatchCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsDecryptToLocalCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsEncryptFromLocalCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsGenerateKeysCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsListCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsListCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsRemoveCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsRemoveCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsSetCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsSetCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/TranslationDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationUpdateCommand' => $vendorDir . '/symfony/framework-bundle/Command/TranslationUpdateCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\WorkflowDumpCommand' => $vendorDir . '/symfony/framework-bundle/Command/WorkflowDumpCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\XliffLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/XliffLintCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\YamlLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/YamlLintCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Application' => $vendorDir . '/symfony/framework-bundle/Console/Application.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/Descriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/framework-bundle/Console/Helper/DescriptorHelper.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController' => $vendorDir . '/symfony/framework-bundle/Controller/AbstractController.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver' => $vendorDir . '/symfony/framework-bundle/Controller/ControllerResolver.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController' => $vendorDir . '/symfony/framework-bundle/Controller/RedirectController.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController' => $vendorDir . '/symfony/framework-bundle/Controller/TemplateController.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\AbstractDataCollector' => $vendorDir . '/symfony/framework-bundle/DataCollector/AbstractDataCollector.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\RouterDataCollector' => $vendorDir . '/symfony/framework-bundle/DataCollector/RouterDataCollector.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\TemplateAwareDataCollectorInterface' => $vendorDir . '/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddAnnotationsCachedReaderPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddDebugLogProcessorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AssetsContextPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ContainerBuilderDebugDumpPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\DataCollectorTranslatorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\EnableLoggerDebugModePass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/EnableLoggerDebugModePass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ErrorLoggerCompilerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ErrorLoggerCompilerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\LoggingTranslatorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ProfilerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TranslationUpdateCommandPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Configuration.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\FrameworkExtension' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\VirtualRequestStackPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/VirtualRequestStackPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\ConsoleProfilerListener' => $vendorDir . '/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\SuggestMissingPackageSubscriber' => $vendorDir . '/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle' => $vendorDir . '/symfony/framework-bundle/FrameworkBundle.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache' => $vendorDir . '/symfony/framework-bundle/HttpCache/HttpCache.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\KernelBrowser' => $vendorDir . '/symfony/framework-bundle/KernelBrowser.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Kernel\\MicroKernelTrait' => $vendorDir . '/symfony/framework-bundle/Kernel/MicroKernelTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AnnotatedRouteControllerLoader' => $vendorDir . '/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AttributeRouteControllerLoader' => $vendorDir . '/symfony/framework-bundle/Routing/AttributeRouteControllerLoader.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Attribute\\AsRoutingConditionService' => $vendorDir . '/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader' => $vendorDir . '/symfony/framework-bundle/Routing/DelegatingLoader.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher' => $vendorDir . '/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RouteLoaderInterface' => $vendorDir . '/symfony/framework-bundle/Routing/RouteLoaderInterface.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Router' => $vendorDir . '/symfony/framework-bundle/Routing/Router.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\AbstractVault' => $vendorDir . '/symfony/framework-bundle/Secrets/AbstractVault.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\DotenvVault' => $vendorDir . '/symfony/framework-bundle/Secrets/DotenvVault.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\SodiumVault' => $vendorDir . '/symfony/framework-bundle/Secrets/SodiumVault.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\BrowserKitAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\DomCrawlerAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\HttpClientAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => $vendorDir . '/symfony/framework-bundle/Test/KernelTestCase.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\MailerAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/MailerAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\NotificationAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/NotificationAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestBrowserToken' => $vendorDir . '/symfony/framework-bundle/Test/TestBrowserToken.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestContainer' => $vendorDir . '/symfony/framework-bundle/Test/TestContainer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestAssertionsTrait' => $vendorDir . '/symfony/framework-bundle/Test/WebTestAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => $vendorDir . '/symfony/framework-bundle/Test/WebTestCase.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Translation\\Translator' => $vendorDir . '/symfony/framework-bundle/Translation/Translator.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddProcessorsPass' => $vendorDir . '/symfony/monolog-bundle/DependencyInjection/Compiler/AddProcessorsPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddSwiftMailerTransportPass' => $vendorDir . '/symfony/monolog-bundle/DependencyInjection/Compiler/AddSwiftMailerTransportPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\DebugHandlerPass' => $vendorDir . '/symfony/monolog-bundle/DependencyInjection/Compiler/DebugHandlerPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\FixEmptyLoggerPass' => $vendorDir . '/symfony/monolog-bundle/DependencyInjection/Compiler/FixEmptyLoggerPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\LoggerChannelPass' => $vendorDir . '/symfony/monolog-bundle/DependencyInjection/Compiler/LoggerChannelPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/monolog-bundle/DependencyInjection/Configuration.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\MonologExtension' => $vendorDir . '/symfony/monolog-bundle/DependencyInjection/MonologExtension.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\MonologBundle' => $vendorDir . '/symfony/monolog-bundle/MonologBundle.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\SwiftMailer\\MessageFactory' => $vendorDir . '/symfony/monolog-bundle/SwiftMailer/MessageFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\CacheWarmer\\ExpressionCacheWarmer' => $vendorDir . '/symfony/security-bundle/CacheWarmer/ExpressionCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Command\\DebugFirewallCommand' => $vendorDir . '/symfony/security-bundle/Command/DebugFirewallCommand.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DataCollector\\SecurityDataCollector' => $vendorDir . '/symfony/security-bundle/DataCollector/SecurityDataCollector.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableFirewallListener' => $vendorDir . '/symfony/security-bundle/Debug/TraceableFirewallListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableListenerTrait' => $vendorDir . '/symfony/security-bundle/Debug/TraceableListenerTrait.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedLazyListener' => $vendorDir . '/symfony/security-bundle/Debug/WrappedLazyListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedListener' => $vendorDir . '/symfony/security-bundle/Debug/WrappedListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSecurityVotersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSessionDomainConstraintPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\CleanRememberMeVerifierPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/CleanRememberMeVerifierPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\MakeFirewallsEventDispatcherTraceablePass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/MakeFirewallsEventDispatcherTraceablePass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterCsrfFeaturesPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterEntryPointPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterEntryPointPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterGlobalSecurityEventListenersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterLdapLocatorPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterLdapLocatorPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterTokenUsageTrackingPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\ReplaceDecoratedRememberMeHandlerPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/ReplaceDecoratedRememberMeHandlerPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\SortFirewallListenersPass' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Compiler/SortFirewallListenersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\MainConfiguration' => $vendorDir . '/symfony/security-bundle/DependencyInjection/MainConfiguration.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\SecurityExtension' => $vendorDir . '/symfony/security-bundle/DependencyInjection/SecurityExtension.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcTokenHandlerFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcUserInfoTokenHandlerFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcUserInfoTokenHandlerFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\ServiceTokenHandlerFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/ServiceTokenHandlerFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\TokenHandlerFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/TokenHandlerFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AbstractFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/AbstractFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AccessTokenFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/AccessTokenFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AuthenticatorFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/AuthenticatorFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\CustomAuthenticatorFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/CustomAuthenticatorFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FirewallListenerFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/FirewallListenerFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginLdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicLdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginLdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginLdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LdapFactoryTrait' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginLinkFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginLinkFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginThrottlingFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RememberMeFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/RememberMeFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RemoteUserFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/RemoteUserFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\SignatureAlgorithmFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/SignatureAlgorithmFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\StatelessAuthenticatorFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/StatelessAuthenticatorFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\X509Factory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/Factory/X509Factory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\InMemoryFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\LdapFactory' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/LdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\UserProviderFactoryInterface' => $vendorDir . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/UserProviderFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener' => $vendorDir . '/symfony/security-bundle/EventListener/FirewallListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\VoteListener' => $vendorDir . '/symfony/security-bundle/EventListener/VoteListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\LoginLink\\FirewallAwareLoginLinkHandler' => $vendorDir . '/symfony/security-bundle/LoginLink/FirewallAwareLoginLinkHandler.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\DecoratedRememberMeHandler' => $vendorDir . '/symfony/security-bundle/RememberMe/DecoratedRememberMeHandler.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\FirewallAwareRememberMeHandler' => $vendorDir . '/symfony/security-bundle/RememberMe/FirewallAwareRememberMeHandler.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Routing\\LogoutRouteLoader' => $vendorDir . '/symfony/security-bundle/Routing/LogoutRouteLoader.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security' => $vendorDir . '/symfony/security-bundle/Security.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\SecurityBundle' => $vendorDir . '/symfony/security-bundle/SecurityBundle.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallAwareTrait' => $vendorDir . '/symfony/security-bundle/Security/FirewallAwareTrait.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallConfig' => $vendorDir . '/symfony/security-bundle/Security/FirewallConfig.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext' => $vendorDir . '/symfony/security-bundle/Security/FirewallContext.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap' => $vendorDir . '/symfony/security-bundle/Security/FirewallMap.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\LazyFirewallContext' => $vendorDir . '/symfony/security-bundle/Security/LazyFirewallContext.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\UserAuthenticator' => $vendorDir . '/symfony/security-bundle/Security/UserAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => $vendorDir . '/symfony/cache/Adapter/AdapterInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => $vendorDir . '/symfony/cache/Adapter/ApcuAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/ArrayAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => $vendorDir . '/symfony/cache/Adapter/ChainAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseBucketAdapter' => $vendorDir . '/symfony/cache/Adapter/CouchbaseBucketAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseCollectionAdapter' => $vendorDir . '/symfony/cache/Adapter/CouchbaseCollectionAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\DoctrineDbalAdapter' => $vendorDir . '/symfony/cache/Adapter/DoctrineDbalAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => $vendorDir . '/symfony/cache/Adapter/MemcachedAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\NullAdapter' => $vendorDir . '/symfony/cache/Adapter/NullAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ParameterNormalizer' => $vendorDir . '/symfony/cache/Adapter/ParameterNormalizer.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => $vendorDir . '/symfony/cache/Adapter/PdoAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpArrayAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpFilesAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => $vendorDir . '/symfony/cache/Adapter/ProxyAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => $vendorDir . '/symfony/cache/Adapter/Psr16Adapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\CacheItem' => $vendorDir . '/symfony/cache/CacheItem.php', '_ContaoManager\\Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => $vendorDir . '/symfony/cache/DataCollector/CacheDataCollector.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => $vendorDir . '/symfony/cache/DependencyInjection/CacheCollectorPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\CacheException' => $vendorDir . '/symfony/cache/Exception/CacheException.php', '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/cache/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\LogicException' => $vendorDir . '/symfony/cache/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Cache\\LockRegistry' => $vendorDir . '/symfony/cache/LockRegistry.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DefaultMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DeflateMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => $vendorDir . '/symfony/cache/Marshaller/MarshallerInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\SodiumMarshaller' => $vendorDir . '/symfony/cache/Marshaller/SodiumMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => $vendorDir . '/symfony/cache/Marshaller/TagAwareMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationDispatcher' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationDispatcher.php', '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationHandler' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationHandler.php', '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationMessage' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationMessage.php', '_ContaoManager\\Symfony\\Component\\Cache\\PruneableInterface' => $vendorDir . '/symfony/cache/PruneableInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Psr16Cache' => $vendorDir . '/symfony/cache/Psr16Cache.php', '_ContaoManager\\Symfony\\Component\\Cache\\ResettableInterface' => $vendorDir . '/symfony/cache/ResettableInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => $vendorDir . '/symfony/cache/Traits/AbstractAdapterTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ContractsTrait' => $vendorDir . '/symfony/cache/Traits/ContractsTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ProxyTrait' => $vendorDir . '/symfony/cache/Traits/ProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => $vendorDir . '/symfony/cache/Traits/Redis5Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => $vendorDir . '/symfony/cache/Traits/Redis6Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis6ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis6ProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster5Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster6Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster6ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster6ProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterNodeProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisProxy' => $vendorDir . '/symfony/cache/Traits/RedisProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisTrait' => $vendorDir . '/symfony/cache/Traits/RedisTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxy' => $vendorDir . '/symfony/cache/Traits/RelayProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => $vendorDir . '/symfony/cache/Traits/RelayProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => $vendorDir . '/symfony/cache/Traits/Relay/CopyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GeosearchTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GetrangeTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => $vendorDir . '/symfony/cache/Traits/Relay/HsetTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => $vendorDir . '/symfony/cache/Traits/Relay/MoveTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => $vendorDir . '/symfony/cache/Traits/Relay/NullableReturnTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => $vendorDir . '/symfony/cache/Traits/Relay/PfcountTrait.php', '_ContaoManager\\Symfony\\Component\\Clock\\Clock' => $vendorDir . '/symfony/clock/Clock.php', '_ContaoManager\\Symfony\\Component\\Clock\\ClockAwareTrait' => $vendorDir . '/symfony/clock/ClockAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Clock\\ClockInterface' => $vendorDir . '/symfony/clock/ClockInterface.php', '_ContaoManager\\Symfony\\Component\\Clock\\DatePoint' => $vendorDir . '/symfony/clock/DatePoint.php', '_ContaoManager\\Symfony\\Component\\Clock\\MockClock' => $vendorDir . '/symfony/clock/MockClock.php', '_ContaoManager\\Symfony\\Component\\Clock\\MonotonicClock' => $vendorDir . '/symfony/clock/MonotonicClock.php', '_ContaoManager\\Symfony\\Component\\Clock\\NativeClock' => $vendorDir . '/symfony/clock/NativeClock.php', '_ContaoManager\\Symfony\\Component\\Clock\\Test\\ClockSensitiveTrait' => $vendorDir . '/symfony/clock/Test/ClockSensitiveTrait.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ClassBuilder' => $vendorDir . '/symfony/config/Builder/ClassBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGenerator.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Method' => $vendorDir . '/symfony/config/Builder/Method.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Property' => $vendorDir . '/symfony/config/Builder/Property.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCache' => $vendorDir . '/symfony/config/ConfigCache.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactory' => $vendorDir . '/symfony/config/ConfigCacheFactory.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactoryInterface' => $vendorDir . '/symfony/config/ConfigCacheFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheInterface' => $vendorDir . '/symfony/config/ConfigCacheInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ArrayNode' => $vendorDir . '/symfony/config/Definition/ArrayNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BaseNode' => $vendorDir . '/symfony/config/Definition/BaseNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BooleanNode' => $vendorDir . '/symfony/config/Definition/BooleanNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/ArrayNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BooleanNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/BooleanNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BuilderAwareInterface' => $vendorDir . '/symfony/config/Definition/Builder/BuilderAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\EnumNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/EnumNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ExprBuilder' => $vendorDir . '/symfony/config/Definition/Builder/ExprBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\FloatNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/FloatNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/IntegerNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\MergeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/MergeBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/NodeBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/NodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface' => $vendorDir . '/symfony/config/Definition/Builder/NodeParentInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NormalizationBuilder' => $vendorDir . '/symfony/config/Definition/Builder/NormalizationBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NumericNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/NumericNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ParentNodeDefinitionInterface' => $vendorDir . '/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ScalarNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/ScalarNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/TreeBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ValidationBuilder' => $vendorDir . '/symfony/config/Definition/Builder/ValidationBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\VariableNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/VariableNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurableInterface' => $vendorDir . '/symfony/config/Definition/ConfigurableInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configuration' => $vendorDir . '/symfony/config/Definition/Configuration.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurationInterface' => $vendorDir . '/symfony/config/Definition/ConfigurationInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configurator\\DefinitionConfigurator' => $vendorDir . '/symfony/config/Definition/Configurator/DefinitionConfigurator.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\XmlReferenceDumper' => $vendorDir . '/symfony/config/Definition/Dumper/XmlReferenceDumper.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\YamlReferenceDumper' => $vendorDir . '/symfony/config/Definition/Dumper/YamlReferenceDumper.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\EnumNode' => $vendorDir . '/symfony/config/Definition/EnumNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\DuplicateKeyException' => $vendorDir . '/symfony/config/Definition/Exception/DuplicateKeyException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\Exception' => $vendorDir . '/symfony/config/Definition/Exception/Exception.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\ForbiddenOverwriteException' => $vendorDir . '/symfony/config/Definition/Exception/ForbiddenOverwriteException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidConfigurationException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidConfigurationException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidDefinitionException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidDefinitionException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidTypeException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidTypeException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\UnsetKeyException' => $vendorDir . '/symfony/config/Definition/Exception/UnsetKeyException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\FloatNode' => $vendorDir . '/symfony/config/Definition/FloatNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\IntegerNode' => $vendorDir . '/symfony/config/Definition/IntegerNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Loader\\DefinitionFileLoader' => $vendorDir . '/symfony/config/Definition/Loader/DefinitionFileLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NodeInterface' => $vendorDir . '/symfony/config/Definition/NodeInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NumericNode' => $vendorDir . '/symfony/config/Definition/NumericNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Processor' => $vendorDir . '/symfony/config/Definition/Processor.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypeNodeInterface' => $vendorDir . '/symfony/config/Definition/PrototypeNodeInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypedArrayNode' => $vendorDir . '/symfony/config/Definition/PrototypedArrayNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ScalarNode' => $vendorDir . '/symfony/config/Definition/ScalarNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\VariableNode' => $vendorDir . '/symfony/config/Definition/VariableNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => $vendorDir . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => $vendorDir . '/symfony/config/Exception/FileLocatorFileNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Config\\Exception\\LoaderLoadException' => $vendorDir . '/symfony/config/Exception/LoaderLoadException.php', '_ContaoManager\\Symfony\\Component\\Config\\FileLocator' => $vendorDir . '/symfony/config/FileLocator.php', '_ContaoManager\\Symfony\\Component\\Config\\FileLocatorInterface' => $vendorDir . '/symfony/config/FileLocatorInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DelegatingLoader' => $vendorDir . '/symfony/config/Loader/DelegatingLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DirectoryAwareLoaderInterface' => $vendorDir . '/symfony/config/Loader/DirectoryAwareLoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\FileLoader' => $vendorDir . '/symfony/config/Loader/FileLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/config/Loader/GlobFileLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\Loader' => $vendorDir . '/symfony/config/Loader/Loader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderInterface' => $vendorDir . '/symfony/config/Loader/LoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolver' => $vendorDir . '/symfony/config/Loader/LoaderResolver.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolverInterface' => $vendorDir . '/symfony/config/Loader/LoaderResolverInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\ParamConfigurator' => $vendorDir . '/symfony/config/Loader/ParamConfigurator.php', '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCache' => $vendorDir . '/symfony/config/ResourceCheckerConfigCache.php', '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCacheFactory' => $vendorDir . '/symfony/config/ResourceCheckerConfigCacheFactory.php', '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerInterface' => $vendorDir . '/symfony/config/ResourceCheckerInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ClassExistenceResource' => $vendorDir . '/symfony/config/Resource/ClassExistenceResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ComposerResource' => $vendorDir . '/symfony/config/Resource/ComposerResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\DirectoryResource' => $vendorDir . '/symfony/config/Resource/DirectoryResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileExistenceResource' => $vendorDir . '/symfony/config/Resource/FileExistenceResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileResource' => $vendorDir . '/symfony/config/Resource/FileResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\GlobResource' => $vendorDir . '/symfony/config/Resource/GlobResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ReflectionClassResource' => $vendorDir . '/symfony/config/Resource/ReflectionClassResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ResourceInterface' => $vendorDir . '/symfony/config/Resource/ResourceInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceChecker' => $vendorDir . '/symfony/config/Resource/SelfCheckingResourceChecker.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceInterface' => $vendorDir . '/symfony/config/Resource/SelfCheckingResourceInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\InvalidXmlException' => $vendorDir . '/symfony/config/Util/Exception/InvalidXmlException.php', '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\XmlParsingException' => $vendorDir . '/symfony/config/Util/Exception/XmlParsingException.php', '_ContaoManager\\Symfony\\Component\\Config\\Util\\XmlUtils' => $vendorDir . '/symfony/config/Util/XmlUtils.php', '_ContaoManager\\Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php', '_ContaoManager\\Symfony\\Component\\Console\\Attribute\\AsCommand' => $vendorDir . '/symfony/console/Attribute/AsCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => $vendorDir . '/symfony/console/CI/GithubActionReporter.php', '_ContaoManager\\Symfony\\Component\\Console\\Color' => $vendorDir . '/symfony/console/Color.php', '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php', '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\CompleteCommand' => $vendorDir . '/symfony/console/Command/CompleteCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => $vendorDir . '/symfony/console/Command/DumpCompletionCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\LazyCommand' => $vendorDir . '/symfony/console/Command/LazyCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => $vendorDir . '/symfony/console/Command/SignalableCommandInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\TraceableCommand' => $vendorDir . '/symfony/console/Command/TraceableCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionInput' => $vendorDir . '/symfony/console/Completion/CompletionInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => $vendorDir . '/symfony/console/Completion/CompletionSuggestions.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/BashCompletionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => $vendorDir . '/symfony/console/Completion/Output/CompletionOutputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\FishCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/FishCompletionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\ZshCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/ZshCompletionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Suggestion' => $vendorDir . '/symfony/console/Completion/Suggestion.php', '_ContaoManager\\Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php', '_ContaoManager\\Symfony\\Component\\Console\\Cursor' => $vendorDir . '/symfony/console/Cursor.php', '_ContaoManager\\Symfony\\Component\\Console\\DataCollector\\CommandDataCollector' => $vendorDir . '/symfony/console/DataCollector/CommandDataCollector.php', '_ContaoManager\\Symfony\\Component\\Console\\Debug\\CliRequest' => $vendorDir . '/symfony/console/Debug/CliRequest.php', '_ContaoManager\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ReStructuredTextDescriptor' => $vendorDir . '/symfony/console/Descriptor/ReStructuredTextDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => $vendorDir . '/symfony/console/Event/ConsoleSignalEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/symfony/console/Exception/MissingInputException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/symfony/console/Exception/NamespaceNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RunCommandFailedException' => $vendorDir . '/symfony/console/Exception/RunCommandFailedException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatter.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatterStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/symfony/console/Helper/Dumper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\OutputWrapper' => $vendorDir . '/symfony/console/Helper/OutputWrapper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => $vendorDir . '/symfony/console/Helper/TableCellStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php', '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandContext' => $vendorDir . '/symfony/console/Messenger/RunCommandContext.php', '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessage' => $vendorDir . '/symfony/console/Messenger/RunCommandMessage.php', '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessageHandler' => $vendorDir . '/symfony/console/Messenger/RunCommandMessageHandler.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\AnsiColorMode' => $vendorDir . '/symfony/console/Output/AnsiColorMode.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => $vendorDir . '/symfony/console/Output/ConsoleSectionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => $vendorDir . '/symfony/console/Output/TrimmedBufferOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php', '_ContaoManager\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php', '_ContaoManager\\Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php', '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalMap' => $vendorDir . '/symfony/console/SignalRegistry/SignalMap.php', '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => $vendorDir . '/symfony/console/SignalRegistry/SignalRegistry.php', '_ContaoManager\\Symfony\\Component\\Console\\SingleCommandApplication' => $vendorDir . '/symfony/console/SingleCommandApplication.php', '_ContaoManager\\Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => $vendorDir . '/symfony/console/Tester/CommandCompletionTester.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => $vendorDir . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/symfony/console/Tester/TesterTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Alias' => $vendorDir . '/symfony/dependency-injection/Alias.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\AbstractArgument' => $vendorDir . '/symfony/dependency-injection/Argument/AbstractArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ArgumentInterface' => $vendorDir . '/symfony/dependency-injection/Argument/ArgumentInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\BoundArgument' => $vendorDir . '/symfony/dependency-injection/Argument/BoundArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\IteratorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/IteratorArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\LazyClosure' => $vendorDir . '/symfony/dependency-injection/Argument/LazyClosure.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ReferenceSetArgumentTrait' => $vendorDir . '/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => $vendorDir . '/symfony/dependency-injection/Argument/RewindableGenerator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceClosureArgument' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceClosureArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocator' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocatorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceLocatorArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\TaggedIteratorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/TaggedIteratorArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsAlias' => $vendorDir . '/symfony/dependency-injection/Attribute/AsAlias.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsDecorator' => $vendorDir . '/symfony/dependency-injection/Attribute/AsDecorator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsTaggedItem' => $vendorDir . '/symfony/dependency-injection/Attribute/AsTaggedItem.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autoconfigure' => $vendorDir . '/symfony/dependency-injection/Attribute/Autoconfigure.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutoconfigureTag' => $vendorDir . '/symfony/dependency-injection/Attribute/AutoconfigureTag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autowire' => $vendorDir . '/symfony/dependency-injection/Attribute/Autowire.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireCallable' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireCallable.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireDecorated' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireDecorated.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireIterator' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireIterator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireServiceClosure' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireServiceClosure.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Exclude' => $vendorDir . '/symfony/dependency-injection/Attribute/Exclude.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated' => $vendorDir . '/symfony/dependency-injection/Attribute/MapDecorated.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedIterator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Target' => $vendorDir . '/symfony/dependency-injection/Attribute/Target.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\When' => $vendorDir . '/symfony/dependency-injection/Attribute/When.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ChildDefinition' => $vendorDir . '/symfony/dependency-injection/ChildDefinition.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AbstractRecursivePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AliasDeprecatedPublicServicesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AnalyzeServiceReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AttributeAutoconfigurationPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutoAliasServicePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutoAliasServicePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireAsDecoratorPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireAsDecoratorPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowirePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckReferenceValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckTypeDeclarationsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\Compiler' => $vendorDir . '/symfony/dependency-injection/Compiler/Compiler.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface' => $vendorDir . '/symfony/dependency-injection/Compiler/CompilerPassInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DecoratorServicePass' => $vendorDir . '/symfony/dependency-injection/Compiler/DecoratorServicePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DefinitionErrorExceptionPass' => $vendorDir . '/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ExtensionCompilerPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\InlineServiceDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\MergeExtensionConfigurationPass' => $vendorDir . '/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PassConfig' => $vendorDir . '/symfony/dependency-injection/Compiler/PassConfig.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PriorityTaggedServiceTrait' => $vendorDir . '/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterAutoconfigureAttributesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterEnvVarProcessorsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterReverseContainerPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterServiceSubscribersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveAbstractDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveBuildParametersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveBuildParametersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveClassPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveDecoratorStackPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveEnvPlaceholdersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveFactoryClassPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveHotPathPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveHotPathPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInstanceofConditionalsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInvalidReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNamedArgumentsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNoPreloadPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveReferencesToAliasesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveServiceSubscribersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveTaggedIteratorArgumentPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceLocatorTagPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraph' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphEdge' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphNode' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ValidateEnvPlaceholdersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResource' => $vendorDir . '/symfony/dependency-injection/Config/ContainerParametersResource.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResourceChecker' => $vendorDir . '/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Container' => $vendorDir . '/symfony/dependency-injection/Container.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareInterface' => $vendorDir . '/symfony/dependency-injection/ContainerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareTrait' => $vendorDir . '/symfony/dependency-injection/ContainerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerBuilder' => $vendorDir . '/symfony/dependency-injection/ContainerBuilder.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => $vendorDir . '/symfony/dependency-injection/ContainerInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Definition' => $vendorDir . '/symfony/dependency-injection/Definition.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Dumper' => $vendorDir . '/symfony/dependency-injection/Dumper/Dumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/Dumper/DumperInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\GraphvizDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/GraphvizDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\PhpDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/PhpDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Preloader' => $vendorDir . '/symfony/dependency-injection/Dumper/Preloader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\XmlDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/XmlDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\YamlDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/YamlDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarLoaderInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessor.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessorInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => $vendorDir . '/symfony/dependency-injection/Exception/AutowiringFailedException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/dependency-injection/Exception/BadMethodCallException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/EnvNotFoundException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvParameterException' => $vendorDir . '/symfony/dependency-injection/Exception/EnvParameterException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/dependency-injection/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/dependency-injection/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidParameterTypeException' => $vendorDir . '/symfony/dependency-injection/Exception/InvalidParameterTypeException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => $vendorDir . '/symfony/dependency-injection/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/dependency-injection/Exception/OutOfBoundsException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/ParameterNotFoundException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => $vendorDir . '/symfony/dependency-injection/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/ServiceNotFoundException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguage' => $vendorDir . '/symfony/dependency-injection/ExpressionLanguage.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguageProvider' => $vendorDir . '/symfony/dependency-injection/ExpressionLanguageProvider.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\AbstractExtension' => $vendorDir . '/symfony/dependency-injection/Extension/AbstractExtension.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurableExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ConfigurableExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurationExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\Extension' => $vendorDir . '/symfony/dependency-injection/Extension/Extension.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionTrait' => $vendorDir . '/symfony/dependency-injection/Extension/ExtensionTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/PrependExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\InstantiatorInterface' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\LazyServiceInstantiator' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/LazyServiceInstantiator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\RealServiceInstantiator' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\LazyServiceDumper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\NullDumper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\ProxyHelper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/ProxyHelper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\ClosureLoader' => $vendorDir . '/symfony/dependency-injection/Loader/ClosureLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AliasConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ClosureReferenceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ContainerConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\DefaultsConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\EnvConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\FromCallableConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/FromCallableConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InlineServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InstanceofConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ParametersConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\PrototypeConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ReferenceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServicesConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AbstractTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ArgumentTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutoconfigureTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutowireTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\BindTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\CallTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ClassTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConfiguratorTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConstructorTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ConstructorTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DecorateTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DeprecateTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FactoryTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FileTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FromCallableTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FromCallableTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\LazyTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ParentTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PropertyTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PublicTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ShareTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\SyntheticTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\TagTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\DirectoryLoader' => $vendorDir . '/symfony/dependency-injection/Loader/DirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\FileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/FileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/GlobFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/IniFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/PhpFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/XmlFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/YamlFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Parameter' => $vendorDir . '/symfony/dependency-injection/Parameter.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ContainerBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBagInterface' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ParameterBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Reference' => $vendorDir . '/symfony/dependency-injection/Reference.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ReverseContainer' => $vendorDir . '/symfony/dependency-injection/ReverseContainer.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ServiceLocator' => $vendorDir . '/symfony/dependency-injection/ServiceLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => $vendorDir . '/symfony/dependency-injection/TaggedContainerInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TypedReference' => $vendorDir . '/symfony/dependency-injection/TypedReference.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Variable' => $vendorDir . '/symfony/dependency-injection/Variable.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\BufferingLogger' => $vendorDir . '/symfony/error-handler/BufferingLogger.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Debug' => $vendorDir . '/symfony/error-handler/Debug.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\DebugClassLoader' => $vendorDir . '/symfony/error-handler/DebugClassLoader.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ClassNotFoundErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ErrorEnhancerInterface' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedFunctionErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedMethodErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorHandler' => $vendorDir . '/symfony/error-handler/ErrorHandler.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\CliErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface' => $vendorDir . '/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter' => $vendorDir . '/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\HtmlErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\SerializerErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\ClassNotFoundError' => $vendorDir . '/symfony/error-handler/Error/ClassNotFoundError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\FatalError' => $vendorDir . '/symfony/error-handler/Error/FatalError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\OutOfMemoryError' => $vendorDir . '/symfony/error-handler/Error/OutOfMemoryError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedFunctionError' => $vendorDir . '/symfony/error-handler/Error/UndefinedFunctionError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedMethodError' => $vendorDir . '/symfony/error-handler/Error/UndefinedMethodError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\FlattenException' => $vendorDir . '/symfony/error-handler/Exception/FlattenException.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => $vendorDir . '/symfony/error-handler/Exception/SilencedErrorContext.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Internal\\TentativeTypes' => $vendorDir . '/symfony/error-handler/Internal/TentativeTypes.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ThrowableUtils' => $vendorDir . '/symfony/error-handler/ThrowableUtils.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Attribute\\AsEventListener' => $vendorDir . '/symfony/event-dispatcher/Attribute/AsEventListener.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Debug/WrappedListener.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/EventDispatcher.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/EventDispatcherInterface.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/symfony/event-dispatcher/EventSubscriberInterface.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\GenericEvent' => $vendorDir . '/symfony/event-dispatcher/GenericEvent.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ImmutableEventDispatcher.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/filesystem/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\FileNotFoundException' => $vendorDir . '/symfony/filesystem/Exception/FileNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOException' => $vendorDir . '/symfony/filesystem/Exception/IOException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface' => $vendorDir . '/symfony/filesystem/Exception/IOExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/filesystem/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\RuntimeException' => $vendorDir . '/symfony/filesystem/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Filesystem' => $vendorDir . '/symfony/filesystem/Filesystem.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Path' => $vendorDir . '/symfony/filesystem/Path.php', '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php', '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => $vendorDir . '/symfony/finder/Exception/DirectoryNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php', '_ContaoManager\\Symfony\\Component\\Finder\\Gitignore' => $vendorDir . '/symfony/finder/Gitignore.php', '_ContaoManager\\Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\LazyIterator' => $vendorDir . '/symfony/finder/Iterator/LazyIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => $vendorDir . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeader' => $vendorDir . '/symfony/http-foundation/AcceptHeader.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeaderItem' => $vendorDir . '/symfony/http-foundation/AcceptHeaderItem.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\BinaryFileResponse' => $vendorDir . '/symfony/http-foundation/BinaryFileResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ChainRequestMatcher' => $vendorDir . '/symfony/http-foundation/ChainRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Cookie' => $vendorDir . '/symfony/http-foundation/Cookie.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException' => $vendorDir . '/symfony/http-foundation/Exception/BadRequestException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\ConflictingHeadersException' => $vendorDir . '/symfony/http-foundation/Exception/ConflictingHeadersException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\JsonException' => $vendorDir . '/symfony/http-foundation/Exception/JsonException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\RequestExceptionInterface' => $vendorDir . '/symfony/http-foundation/Exception/RequestExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SessionNotFoundException' => $vendorDir . '/symfony/http-foundation/Exception/SessionNotFoundException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SuspiciousOperationException' => $vendorDir . '/symfony/http-foundation/Exception/SuspiciousOperationException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\UnexpectedValueException' => $vendorDir . '/symfony/http-foundation/Exception/UnexpectedValueException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ExpressionRequestMatcher' => $vendorDir . '/symfony/http-foundation/ExpressionRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\FileBag' => $vendorDir . '/symfony/http-foundation/FileBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/http-foundation/File/Exception/AccessDeniedException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\CannotWriteFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/CannotWriteFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\ExtensionFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/ExtensionFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileException' => $vendorDir . '/symfony/http-foundation/File/Exception/FileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException' => $vendorDir . '/symfony/http-foundation/File/Exception/FileNotFoundException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FormSizeFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/FormSizeFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\IniSizeFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/IniSizeFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/NoFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoTmpDirFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/NoTmpDirFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\PartialFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/PartialFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/http-foundation/File/Exception/UnexpectedTypeException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UploadException' => $vendorDir . '/symfony/http-foundation/File/Exception/UploadException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\File' => $vendorDir . '/symfony/http-foundation/File/File.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Stream' => $vendorDir . '/symfony/http-foundation/File/Stream.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile' => $vendorDir . '/symfony/http-foundation/File/UploadedFile.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderBag' => $vendorDir . '/symfony/http-foundation/HeaderBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderUtils' => $vendorDir . '/symfony/http-foundation/HeaderUtils.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\InputBag' => $vendorDir . '/symfony/http-foundation/InputBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\IpUtils' => $vendorDir . '/symfony/http-foundation/IpUtils.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\JsonResponse' => $vendorDir . '/symfony/http-foundation/JsonResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ParameterBag' => $vendorDir . '/symfony/http-foundation/ParameterBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\AbstractRequestRateLimiter' => $vendorDir . '/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\PeekableRequestRateLimiterInterface' => $vendorDir . '/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\RequestRateLimiterInterface' => $vendorDir . '/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RedirectResponse' => $vendorDir . '/symfony/http-foundation/RedirectResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Request' => $vendorDir . '/symfony/http-foundation/Request.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcherInterface' => $vendorDir . '/symfony/http-foundation/RequestMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\AttributesRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\ExpressionRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\HostRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IpsRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IsJsonRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\MethodRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PathRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PortRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\SchemeRequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestStack' => $vendorDir . '/symfony/http-foundation/RequestStack.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Response' => $vendorDir . '/symfony/http-foundation/Response.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ResponseHeaderBag' => $vendorDir . '/symfony/http-foundation/ResponseHeaderBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ServerBag' => $vendorDir . '/symfony/http-foundation/ServerBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBag' => $vendorDir . '/symfony/http-foundation/Session/Attribute/AttributeBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface' => $vendorDir . '/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\FlashBagAwareSessionInterface' => $vendorDir . '/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\AutoExpireFlashBag' => $vendorDir . '/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBag' => $vendorDir . '/symfony/http-foundation/Session/Flash/FlashBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface' => $vendorDir . '/symfony/http-foundation/Session/Flash/FlashBagInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Session' => $vendorDir . '/symfony/http-foundation/Session/Session.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionBagInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagProxy' => $vendorDir . '/symfony/http-foundation/Session/SessionBagProxy.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactory' => $vendorDir . '/symfony/http-foundation/Session/SessionFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactoryInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionUtils' => $vendorDir . '/symfony/http-foundation/Session/SessionUtils.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\AbstractSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\IdentityMarshaller' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MarshallingSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcachedSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MigratingSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MongoDbSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NullSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\RedisSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\SessionHandlerFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\StrictSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MetadataBag' => $vendorDir . '/symfony/http-foundation/Session/Storage/MetadataBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/NativeSessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy' => $vendorDir . '/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy' => $vendorDir . '/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageFactoryInterface' => $vendorDir . '/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface' => $vendorDir . '/symfony/http-foundation/Session/Storage/SessionStorageInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedJsonResponse' => $vendorDir . '/symfony/http-foundation/StreamedJsonResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedResponse' => $vendorDir . '/symfony/http-foundation/StreamedResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\RequestAttributeValueSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseCookieValueSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseFormatSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasCookie' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasHeader' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderLocationSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsRedirected' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsSuccessful' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsUnprocessable' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseStatusCodeSame' => $vendorDir . '/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UriSigner' => $vendorDir . '/symfony/http-foundation/UriSigner.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UrlHelper' => $vendorDir . '/symfony/http-foundation/UrlHelper.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsController' => $vendorDir . '/symfony/http-kernel/Attribute/AsController.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsTargetedValueResolver' => $vendorDir . '/symfony/http-kernel/Attribute/AsTargetedValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\Cache' => $vendorDir . '/symfony/http-kernel/Attribute/Cache.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapDateTime' => $vendorDir . '/symfony/http-kernel/Attribute/MapDateTime.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryParameter' => $vendorDir . '/symfony/http-kernel/Attribute/MapQueryParameter.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryString' => $vendorDir . '/symfony/http-kernel/Attribute/MapQueryString.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapRequestPayload' => $vendorDir . '/symfony/http-kernel/Attribute/MapRequestPayload.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\ValueResolver' => $vendorDir . '/symfony/http-kernel/Attribute/ValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithHttpStatus' => $vendorDir . '/symfony/http-kernel/Attribute/WithHttpStatus.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithLogLevel' => $vendorDir . '/symfony/http-kernel/Attribute/WithLogLevel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle' => $vendorDir . '/symfony/http-kernel/Bundle/AbstractBundle.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\Bundle' => $vendorDir . '/symfony/http-kernel/Bundle/Bundle.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleExtension' => $vendorDir . '/symfony/http-kernel/Bundle/BundleExtension.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface' => $vendorDir . '/symfony/http-kernel/Bundle/BundleInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\CacheClearerInterface' => $vendorDir . '/symfony/http-kernel/CacheClearer/CacheClearerInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\ChainCacheClearer' => $vendorDir . '/symfony/http-kernel/CacheClearer/ChainCacheClearer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\Psr6CacheClearer' => $vendorDir . '/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmer' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerAggregate' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerInterface' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\WarmableInterface' => $vendorDir . '/symfony/http-kernel/CacheWarmer/WarmableInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Config\\FileLocator' => $vendorDir . '/symfony/http-kernel/Config/FileLocator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactoryInterface' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/ContainerControllerResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerReference' => $vendorDir . '/symfony/http-kernel/Controller/ControllerReference.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/ControllerResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ControllerResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ErrorController' => $vendorDir . '/symfony/http-kernel/Controller/ErrorController.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver' => $vendorDir . '/symfony/http-kernel/Controller/TraceableArgumentResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/TraceableControllerResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ValueResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ValueResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\AjaxDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/AjaxDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ConfigDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/ConfigDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/DataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface' => $vendorDir . '/symfony/http-kernel/DataCollector/DataCollectorInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DumpDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/DumpDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\EventDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/EventDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ExceptionDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/ExceptionDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LateDataCollectorInterface' => $vendorDir . '/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LoggerDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/LoggerDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\MemoryDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/MemoryDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RequestDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/RequestDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RouterDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/RouterDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\TimeDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/TimeDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\ErrorHandlerConfigurator' => $vendorDir . '/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter' => $vendorDir . '/symfony/http-kernel/Debug/FileLinkFormatter.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/http-kernel/Debug/TraceableEventDispatcher.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\VirtualRequestStack' => $vendorDir . '/symfony/http-kernel/Debug/VirtualRequestStack.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\AddAnnotatedClassesToCachePass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ConfigurableExtension' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ControllerArgumentValueResolverPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\Extension' => $vendorDir . '/symfony/http-kernel/DependencyInjection/Extension.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\FragmentRendererPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LazyLoadingFragmentHandler' => $vendorDir . '/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LoggerPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/LoggerPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\MergeExtensionConfigurationPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterControllerArgumentLocatorsPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterLocaleAwareServicesPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RemoveEmptyControllerArgumentLocatorsPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ResettableServicePass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ResettableServicePass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ServicesResetter.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/AbstractSessionListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AddRequestFormatsListener' => $vendorDir . '/symfony/http-kernel/EventListener/AddRequestFormatsListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\CacheAttributeListener' => $vendorDir . '/symfony/http-kernel/EventListener/CacheAttributeListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener' => $vendorDir . '/symfony/http-kernel/EventListener/DebugHandlersListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DisallowRobotsIndexingListener' => $vendorDir . '/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DumpListener' => $vendorDir . '/symfony/http-kernel/EventListener/DumpListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener' => $vendorDir . '/symfony/http-kernel/EventListener/ErrorListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\FragmentListener' => $vendorDir . '/symfony/http-kernel/EventListener/FragmentListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleAwareListener' => $vendorDir . '/symfony/http-kernel/EventListener/LocaleAwareListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleListener' => $vendorDir . '/symfony/http-kernel/EventListener/LocaleListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ProfilerListener' => $vendorDir . '/symfony/http-kernel/EventListener/ProfilerListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener' => $vendorDir . '/symfony/http-kernel/EventListener/ResponseListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener' => $vendorDir . '/symfony/http-kernel/EventListener/RouterListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/SessionListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\StreamedResponseListener' => $vendorDir . '/symfony/http-kernel/EventListener/StreamedResponseListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SurrogateListener' => $vendorDir . '/symfony/http-kernel/EventListener/SurrogateListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener' => $vendorDir . '/symfony/http-kernel/EventListener/ValidateRequestListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerArgumentsEvent' => $vendorDir . '/symfony/http-kernel/Event/ControllerArgumentsEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerEvent' => $vendorDir . '/symfony/http-kernel/Event/ControllerEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ExceptionEvent' => $vendorDir . '/symfony/http-kernel/Event/ExceptionEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent' => $vendorDir . '/symfony/http-kernel/Event/FinishRequestEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\KernelEvent' => $vendorDir . '/symfony/http-kernel/Event/KernelEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\RequestEvent' => $vendorDir . '/symfony/http-kernel/Event/RequestEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ResponseEvent' => $vendorDir . '/symfony/http-kernel/Event/ResponseEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\TerminateEvent' => $vendorDir . '/symfony/http-kernel/Event/TerminateEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ViewEvent' => $vendorDir . '/symfony/http-kernel/Event/ViewEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/AccessDeniedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException' => $vendorDir . '/symfony/http-kernel/Exception/BadRequestHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException' => $vendorDir . '/symfony/http-kernel/Exception/ConflictHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ControllerDoesNotReturnResponseException' => $vendorDir . '/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException' => $vendorDir . '/symfony/http-kernel/Exception/GoneHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpException' => $vendorDir . '/symfony/http-kernel/Exception/HttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface' => $vendorDir . '/symfony/http-kernel/Exception/HttpExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\InvalidMetadataException' => $vendorDir . '/symfony/http-kernel/Exception/InvalidMetadataException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException' => $vendorDir . '/symfony/http-kernel/Exception/LengthRequiredHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LockedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/LockedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException' => $vendorDir . '/symfony/http-kernel/Exception/NotAcceptableHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException' => $vendorDir . '/symfony/http-kernel/Exception/NotFoundHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/PreconditionFailedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException' => $vendorDir . '/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ResolverNotFoundException' => $vendorDir . '/symfony/http-kernel/Exception/ResolverNotFoundException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException' => $vendorDir . '/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException' => $vendorDir . '/symfony/http-kernel/Exception/TooManyRequestsHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnauthorizedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnexpectedSessionUsageException' => $vendorDir . '/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\AbstractSurrogateFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\EsiFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/EsiFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentHandler' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentHandler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentRendererInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGenerator' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentUriGenerator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGeneratorInterface' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\HIncludeFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\InlineFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/InlineFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => $vendorDir . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => $vendorDir . '/symfony/http-kernel/HttpCache/Esi.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => $vendorDir . '/symfony/http-kernel/HttpCache/HttpCache.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => $vendorDir . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategyInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Ssi' => $vendorDir . '/symfony/http-kernel/HttpCache/Ssi.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Store' => $vendorDir . '/symfony/http-kernel/HttpCache/Store.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/StoreInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SubRequestHandler' => $vendorDir . '/symfony/http-kernel/HttpCache/SubRequestHandler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SurrogateInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/SurrogateInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpClientKernel' => $vendorDir . '/symfony/http-kernel/HttpClientKernel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernel' => $vendorDir . '/symfony/http-kernel/HttpKernel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelBrowser' => $vendorDir . '/symfony/http-kernel/HttpKernelBrowser.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelInterface' => $vendorDir . '/symfony/http-kernel/HttpKernelInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Kernel' => $vendorDir . '/symfony/http-kernel/Kernel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelEvents' => $vendorDir . '/symfony/http-kernel/KernelEvents.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelInterface' => $vendorDir . '/symfony/http-kernel/KernelInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerConfigurator' => $vendorDir . '/symfony/http-kernel/Log/DebugLoggerConfigurator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerInterface' => $vendorDir . '/symfony/http-kernel/Log/DebugLoggerInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\Logger' => $vendorDir . '/symfony/http-kernel/Log/Logger.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\FileProfilerStorage' => $vendorDir . '/symfony/http-kernel/Profiler/FileProfilerStorage.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profile' => $vendorDir . '/symfony/http-kernel/Profiler/Profile.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profiler' => $vendorDir . '/symfony/http-kernel/Profiler/Profiler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface' => $vendorDir . '/symfony/http-kernel/Profiler/ProfilerStorageInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\RebootableInterface' => $vendorDir . '/symfony/http-kernel/RebootableInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\TerminableInterface' => $vendorDir . '/symfony/http-kernel/TerminableInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\UriSigner' => $vendorDir . '/symfony/http-kernel/UriSigner.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Command\\UserPasswordHashCommand' => $vendorDir . '/symfony/password-hasher/Command/UserPasswordHashCommand.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/password-hasher/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\InvalidPasswordException' => $vendorDir . '/symfony/password-hasher/Exception/InvalidPasswordException.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\LogicException' => $vendorDir . '/symfony/password-hasher/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\CheckPasswordLengthTrait' => $vendorDir . '/symfony/password-hasher/Hasher/CheckPasswordLengthTrait.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MessageDigestPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/MessageDigestPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MigratingPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/MigratingPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\NativePasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/NativePasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherAwareInterface' => $vendorDir . '/symfony/password-hasher/Hasher/PasswordHasherAwareInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactory' => $vendorDir . '/symfony/password-hasher/Hasher/PasswordHasherFactory.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactoryInterface' => $vendorDir . '/symfony/password-hasher/Hasher/PasswordHasherFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\Pbkdf2PasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/Pbkdf2PasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PlaintextPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/PlaintextPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\SodiumPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/SodiumPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasher' => $vendorDir . '/symfony/password-hasher/Hasher/UserPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasherInterface' => $vendorDir . '/symfony/password-hasher/Hasher/UserPasswordHasherInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\LegacyPasswordHasherInterface' => $vendorDir . '/symfony/password-hasher/LegacyPasswordHasherInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\PasswordHasherInterface' => $vendorDir . '/symfony/password-hasher/PasswordHasherInterface.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/process/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/process/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/symfony/process/Exception/ProcessSignaledException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => $vendorDir . '/symfony/process/Exception/RunProcessFailedException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/symfony/process/ExecutableFinder.php', '_ContaoManager\\Symfony\\Component\\Process\\InputStream' => $vendorDir . '/symfony/process/InputStream.php', '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessContext' => $vendorDir . '/symfony/process/Messenger/RunProcessContext.php', '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessage' => $vendorDir . '/symfony/process/Messenger/RunProcessMessage.php', '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessageHandler' => $vendorDir . '/symfony/process/Messenger/RunProcessMessageHandler.php', '_ContaoManager\\Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/symfony/process/PhpExecutableFinder.php', '_ContaoManager\\Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/symfony/process/PhpProcess.php', '_ContaoManager\\Symfony\\Component\\Process\\PhpSubprocess' => $vendorDir . '/symfony/process/PhpSubprocess.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/symfony/process/Pipes/AbstractPipes.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/symfony/process/Pipes/PipesInterface.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/symfony/process/Pipes/UnixPipes.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Pipes/WindowsPipes.php', '_ContaoManager\\Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Process.php', '_ContaoManager\\Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/ProcessUtils.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => $vendorDir . '/symfony/property-access/Exception/AccessException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/property-access/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/property-access/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => $vendorDir . '/symfony/property-access/Exception/InvalidPropertyPathException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => $vendorDir . '/symfony/property-access/Exception/NoSuchIndexException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => $vendorDir . '/symfony/property-access/Exception/NoSuchPropertyException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/property-access/Exception/OutOfBoundsException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => $vendorDir . '/symfony/property-access/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/property-access/Exception/UnexpectedTypeException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => $vendorDir . '/symfony/property-access/Exception/UninitializedPropertyException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccess' => $vendorDir . '/symfony/property-access/PropertyAccess.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessor' => $vendorDir . '/symfony/property-access/PropertyAccessor.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => $vendorDir . '/symfony/property-access/PropertyAccessorBuilder.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => $vendorDir . '/symfony/property-access/PropertyAccessorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPath' => $vendorDir . '/symfony/property-access/PropertyPath.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => $vendorDir . '/symfony/property-access/PropertyPathBuilder.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => $vendorDir . '/symfony/property-access/PropertyPathInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => $vendorDir . '/symfony/property-access/PropertyPathIterator.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => $vendorDir . '/symfony/property-access/PropertyPathIteratorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => $vendorDir . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => $vendorDir . '/symfony/property-info/Extractor/ConstructorExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpDocExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpStanExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => $vendorDir . '/symfony/property-info/Extractor/ReflectionExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => $vendorDir . '/symfony/property-info/Extractor/SerializerExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScope' => $vendorDir . '/symfony/property-info/PhpStan/NameScope.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScopeFactory' => $vendorDir . '/symfony/property-info/PhpStan/NameScopeFactory.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyAccessExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyDescriptionExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoCacheExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInfoExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInitializableExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyListExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => $vendorDir . '/symfony/property-info/PropertyReadInfo.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyReadInfoExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyTypeExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => $vendorDir . '/symfony/property-info/PropertyWriteInfo.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Type' => $vendorDir . '/symfony/property-info/Type.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpDocTypeHelper.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpStanTypeHelper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Alias' => $vendorDir . '/symfony/routing/Alias.php', '_ContaoManager\\Symfony\\Component\\Routing\\Annotation\\Route' => $vendorDir . '/symfony/routing/Annotation/Route.php', '_ContaoManager\\Symfony\\Component\\Routing\\Attribute\\Route' => $vendorDir . '/symfony/routing/Attribute/Route.php', '_ContaoManager\\Symfony\\Component\\Routing\\CompiledRoute' => $vendorDir . '/symfony/routing/CompiledRoute.php', '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\AddExpressionLanguageProvidersPass' => $vendorDir . '/symfony/routing/DependencyInjection/AddExpressionLanguageProvidersPass.php', '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\RoutingResolverPass' => $vendorDir . '/symfony/routing/DependencyInjection/RoutingResolverPass.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/routing/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/routing/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => $vendorDir . '/symfony/routing/Exception/InvalidParameterException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => $vendorDir . '/symfony/routing/Exception/MethodNotAllowedException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => $vendorDir . '/symfony/routing/Exception/MissingMandatoryParametersException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => $vendorDir . '/symfony/routing/Exception/NoConfigurationException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException' => $vendorDir . '/symfony/routing/Exception/ResourceNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteCircularReferenceException' => $vendorDir . '/symfony/routing/Exception/RouteCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteNotFoundException' => $vendorDir . '/symfony/routing/Exception/RouteNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RuntimeException' => $vendorDir . '/symfony/routing/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator' => $vendorDir . '/symfony/routing/Generator/CompiledUrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\ConfigurableRequirementsInterface' => $vendorDir . '/symfony/routing/Generator/ConfigurableRequirementsInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper' => $vendorDir . '/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumper' => $vendorDir . '/symfony/routing/Generator/Dumper/GeneratorDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumperInterface' => $vendorDir . '/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGenerator' => $vendorDir . '/symfony/routing/Generator/UrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface' => $vendorDir . '/symfony/routing/Generator/UrlGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationClassLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationClassLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationDirectoryLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationDirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationFileLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeClassLoader' => $vendorDir . '/symfony/routing/Loader/AttributeClassLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeDirectoryLoader' => $vendorDir . '/symfony/routing/Loader/AttributeDirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeFileLoader' => $vendorDir . '/symfony/routing/Loader/AttributeFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ClosureLoader' => $vendorDir . '/symfony/routing/Loader/ClosureLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\AliasConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/AliasConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\CollectionConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/CollectionConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/ImportConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RouteConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/RouteConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/RoutingConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\AddTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/AddTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\HostTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/HostTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\LocalizedRouteTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\PrefixTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\RouteTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/RouteTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ContainerLoader' => $vendorDir . '/symfony/routing/Loader/ContainerLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\DirectoryLoader' => $vendorDir . '/symfony/routing/Loader/DirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/routing/Loader/GlobFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ObjectLoader' => $vendorDir . '/symfony/routing/Loader/ObjectLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/routing/Loader/PhpFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Psr4DirectoryLoader' => $vendorDir . '/symfony/routing/Loader/Psr4DirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/routing/Loader/XmlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/routing/Loader/YamlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\CompiledUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/CompiledUrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper' => $vendorDir . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherTrait' => $vendorDir . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumper' => $vendorDir . '/symfony/routing/Matcher/Dumper/MatcherDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumperInterface' => $vendorDir . '/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\StaticPrefixCollection' => $vendorDir . '/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\ExpressionLanguageProvider' => $vendorDir . '/symfony/routing/Matcher/ExpressionLanguageProvider.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/RedirectableUrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RequestMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/RequestMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\TraceableUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/TraceableUrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcher' => $vendorDir . '/symfony/routing/Matcher/UrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/UrlMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\RequestContext' => $vendorDir . '/symfony/routing/RequestContext.php', '_ContaoManager\\Symfony\\Component\\Routing\\RequestContextAwareInterface' => $vendorDir . '/symfony/routing/RequestContextAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\EnumRequirement' => $vendorDir . '/symfony/routing/Requirement/EnumRequirement.php', '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\Requirement' => $vendorDir . '/symfony/routing/Requirement/Requirement.php', '_ContaoManager\\Symfony\\Component\\Routing\\Route' => $vendorDir . '/symfony/routing/Route.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouteCollection' => $vendorDir . '/symfony/routing/RouteCollection.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompiler' => $vendorDir . '/symfony/routing/RouteCompiler.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompilerInterface' => $vendorDir . '/symfony/routing/RouteCompilerInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Router' => $vendorDir . '/symfony/routing/Router.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouterInterface' => $vendorDir . '/symfony/routing/RouterInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\AuthenticationEvents' => $vendorDir . '/symfony/security-core/AuthenticationEvents.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolver' => $vendorDir . '/symfony/security-core/Authentication/AuthenticationTrustResolver.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface' => $vendorDir . '/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\CacheTokenVerifier' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/CacheTokenVerifier.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\InMemoryTokenProvider' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/InMemoryTokenProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentToken' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/PersistentToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentTokenInterface' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/PersistentTokenInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenProviderInterface' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/TokenProviderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenVerifierInterface' => $vendorDir . '/symfony/security-core/Authentication/RememberMe/TokenVerifierInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\AbstractToken' => $vendorDir . '/symfony/security-core/Authentication/Token/AbstractToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\NullToken' => $vendorDir . '/symfony/security-core/Authentication/Token/NullToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\PreAuthenticatedToken' => $vendorDir . '/symfony/security-core/Authentication/Token/PreAuthenticatedToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken' => $vendorDir . '/symfony/security-core/Authentication/Token/RememberMeToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorage' => $vendorDir . '/symfony/security-core/Authentication/Token/Storage/TokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface' => $vendorDir . '/symfony/security-core/Authentication/Token/Storage/TokenStorageInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\UsageTrackingTokenStorage' => $vendorDir . '/symfony/security-core/Authentication/Token/Storage/UsageTrackingTokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\SwitchUserToken' => $vendorDir . '/symfony/security-core/Authentication/Token/SwitchUserToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface' => $vendorDir . '/symfony/security-core/Authentication/Token/TokenInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken' => $vendorDir . '/symfony/security-core/Authentication/Token/UsernamePasswordToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager' => $vendorDir . '/symfony/security-core/Authorization/AccessDecisionManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface' => $vendorDir . '/symfony/security-core/Authorization/AccessDecisionManagerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker' => $vendorDir . '/symfony/security-core/Authorization/AuthorizationChecker.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationCheckerInterface' => $vendorDir . '/symfony/security-core/Authorization/AuthorizationCheckerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguage' => $vendorDir . '/symfony/security-core/Authorization/ExpressionLanguage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguageProvider' => $vendorDir . '/symfony/security-core/Authorization/ExpressionLanguageProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AccessDecisionStrategyInterface' => $vendorDir . '/symfony/security-core/Authorization/Strategy/AccessDecisionStrategyInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AffirmativeStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/AffirmativeStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\ConsensusStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/ConsensusStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\PriorityStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/PriorityStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\UnanimousStrategy' => $vendorDir . '/symfony/security-core/Authorization/Strategy/UnanimousStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\TraceableAccessDecisionManager' => $vendorDir . '/symfony/security-core/Authorization/TraceableAccessDecisionManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AuthenticatedVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/AuthenticatedVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface' => $vendorDir . '/symfony/security-core/Authorization/Voter/CacheableVoterInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\ExpressionVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/ExpressionVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleHierarchyVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/RoleHierarchyVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/RoleVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\TraceableVoter' => $vendorDir . '/symfony/security-core/Authorization/Voter/TraceableVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\Voter' => $vendorDir . '/symfony/security-core/Authorization/Voter/Voter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface' => $vendorDir . '/symfony/security-core/Authorization/Voter/VoterInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationEvent' => $vendorDir . '/symfony/security-core/Event/AuthenticationEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationSuccessEvent' => $vendorDir . '/symfony/security-core/Event/AuthenticationSuccessEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\VoteEvent' => $vendorDir . '/symfony/security-core/Event/VoteEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/security-core/Exception/AccessDeniedException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountExpiredException' => $vendorDir . '/symfony/security-core/Exception/AccountExpiredException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountStatusException' => $vendorDir . '/symfony/security-core/Exception/AccountStatusException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationCredentialsNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationExpiredException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationServiceException' => $vendorDir . '/symfony/security-core/Exception/AuthenticationServiceException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException' => $vendorDir . '/symfony/security-core/Exception/BadCredentialsException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CookieTheftException' => $vendorDir . '/symfony/security-core/Exception/CookieTheftException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CredentialsExpiredException' => $vendorDir . '/symfony/security-core/Exception/CredentialsExpiredException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAccountStatusException' => $vendorDir . '/symfony/security-core/Exception/CustomUserMessageAccountStatusException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAuthenticationException' => $vendorDir . '/symfony/security-core/Exception/CustomUserMessageAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\DisabledException' => $vendorDir . '/symfony/security-core/Exception/DisabledException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/security-core/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InsufficientAuthenticationException' => $vendorDir . '/symfony/security-core/Exception/InsufficientAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/security-core/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidCsrfTokenException' => $vendorDir . '/symfony/security-core/Exception/InvalidCsrfTokenException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LazyResponseException' => $vendorDir . '/symfony/security-core/Exception/LazyResponseException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LockedException' => $vendorDir . '/symfony/security-core/Exception/LockedException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogicException' => $vendorDir . '/symfony/security-core/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogoutException' => $vendorDir . '/symfony/security-core/Exception/LogoutException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ProviderNotFoundException' => $vendorDir . '/symfony/security-core/Exception/ProviderNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\RuntimeException' => $vendorDir . '/symfony/security-core/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\SessionUnavailableException' => $vendorDir . '/symfony/security-core/Exception/SessionUnavailableException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TokenNotFoundException' => $vendorDir . '/symfony/security-core/Exception/TokenNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TooManyLoginAttemptsAuthenticationException' => $vendorDir . '/symfony/security-core/Exception/TooManyLoginAttemptsAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UnsupportedUserException' => $vendorDir . '/symfony/security-core/Exception/UnsupportedUserException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UserNotFoundException' => $vendorDir . '/symfony/security-core/Exception/UserNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\Role' => $vendorDir . '/symfony/security-core/Role/Role.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchy' => $vendorDir . '/symfony/security-core/Role/RoleHierarchy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchyInterface' => $vendorDir . '/symfony/security-core/Role/RoleHierarchyInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\SwitchUserRole' => $vendorDir . '/symfony/security-core/Role/SwitchUserRole.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Security' => $vendorDir . '/symfony/security-core/Security.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\ExpiredSignatureException' => $vendorDir . '/symfony/security-core/Signature/Exception/ExpiredSignatureException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\InvalidSignatureException' => $vendorDir . '/symfony/security-core/Signature/Exception/InvalidSignatureException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\ExpiredSignatureStorage' => $vendorDir . '/symfony/security-core/Signature/ExpiredSignatureStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\SignatureHasher' => $vendorDir . '/symfony/security-core/Signature/SignatureHasher.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Test\\AccessDecisionStrategyTestCase' => $vendorDir . '/symfony/security-core/Test/AccessDecisionStrategyTestCase.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\AttributesBasedUserProviderInterface' => $vendorDir . '/symfony/security-core/User/AttributesBasedUserProviderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserChecker' => $vendorDir . '/symfony/security-core/User/ChainUserChecker.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserProvider' => $vendorDir . '/symfony/security-core/User/ChainUserProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\EquatableInterface' => $vendorDir . '/symfony/security-core/User/EquatableInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUser' => $vendorDir . '/symfony/security-core/User/InMemoryUser.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserChecker' => $vendorDir . '/symfony/security-core/User/InMemoryUserChecker.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserProvider' => $vendorDir . '/symfony/security-core/User/InMemoryUserProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\LegacyPasswordAuthenticatedUserInterface' => $vendorDir . '/symfony/security-core/User/LegacyPasswordAuthenticatedUserInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\MissingUserProvider' => $vendorDir . '/symfony/security-core/User/MissingUserProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\OidcUser' => $vendorDir . '/symfony/security-core/User/OidcUser.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordAuthenticatedUserInterface' => $vendorDir . '/symfony/security-core/User/PasswordAuthenticatedUserInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordUpgraderInterface' => $vendorDir . '/symfony/security-core/User/PasswordUpgraderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface' => $vendorDir . '/symfony/security-core/User/UserCheckerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserInterface' => $vendorDir . '/symfony/security-core/User/UserInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserProviderInterface' => $vendorDir . '/symfony/security-core/User/UserProviderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPassword' => $vendorDir . '/symfony/security-core/Validator/Constraints/UserPassword.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPasswordValidator' => $vendorDir . '/symfony/security-core/Validator/Constraints/UserPasswordValidator.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfToken' => $vendorDir . '/symfony/security-csrf/CsrfToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManager' => $vendorDir . '/symfony/security-csrf/CsrfTokenManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManagerInterface' => $vendorDir . '/symfony/security-csrf/CsrfTokenManagerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\Exception\\TokenNotFoundException' => $vendorDir . '/symfony/security-csrf/Exception/TokenNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\TokenGeneratorInterface' => $vendorDir . '/symfony/security-csrf/TokenGenerator/TokenGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\UriSafeTokenGenerator' => $vendorDir . '/symfony/security-csrf/TokenGenerator/UriSafeTokenGenerator.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\ClearableTokenStorageInterface' => $vendorDir . '/symfony/security-csrf/TokenStorage/ClearableTokenStorageInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\NativeSessionTokenStorage' => $vendorDir . '/symfony/security-csrf/TokenStorage/NativeSessionTokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\SessionTokenStorage' => $vendorDir . '/symfony/security-csrf/TokenStorage/SessionTokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\TokenStorageInterface' => $vendorDir . '/symfony/security-csrf/TokenStorage/TokenStorageInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMap' => $vendorDir . '/symfony/security-http/AccessMap.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMapInterface' => $vendorDir . '/symfony/security-http/AccessMapInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenExtractorInterface' => $vendorDir . '/symfony/security-http/AccessToken/AccessTokenExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenHandlerInterface' => $vendorDir . '/symfony/security-http/AccessToken/AccessTokenHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\ChainAccessTokenExtractor' => $vendorDir . '/symfony/security-http/AccessToken/ChainAccessTokenExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\FormEncodedBodyExtractor' => $vendorDir . '/symfony/security-http/AccessToken/FormEncodedBodyExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\HeaderAccessTokenExtractor' => $vendorDir . '/symfony/security-http/AccessToken/HeaderAccessTokenExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\InvalidSignatureException' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/Exception/InvalidSignatureException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\MissingClaimException' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/Exception/MissingClaimException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTokenHandler' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/OidcTokenHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTrait' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/OidcTrait.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcUserInfoTokenHandler' => $vendorDir . '/symfony/security-http/AccessToken/Oidc/OidcUserInfoTokenHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\QueryAccessTokenExtractor' => $vendorDir . '/symfony/security-http/AccessToken/QueryAccessTokenExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\CurrentUser' => $vendorDir . '/symfony/security-http/Attribute/CurrentUser.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\IsGranted' => $vendorDir . '/symfony/security-http/Attribute/IsGranted.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface' => $vendorDir . '/symfony/security-http/Authentication/AuthenticationFailureHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationSuccessHandlerInterface' => $vendorDir . '/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationUtils' => $vendorDir . '/symfony/security-http/Authentication/AuthenticationUtils.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManager' => $vendorDir . '/symfony/security-http/Authentication/AuthenticatorManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManagerInterface' => $vendorDir . '/symfony/security-http/Authentication/AuthenticatorManagerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationFailureHandler' => $vendorDir . '/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationSuccessHandler' => $vendorDir . '/symfony/security-http/Authentication/CustomAuthenticationSuccessHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationFailureHandler' => $vendorDir . '/symfony/security-http/Authentication/DefaultAuthenticationFailureHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationSuccessHandler' => $vendorDir . '/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\UserAuthenticatorInterface' => $vendorDir . '/symfony/security-http/Authentication/UserAuthenticatorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AbstractAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractLoginFormAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractPreAuthenticatedAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AccessTokenAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/AccessTokenAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AuthenticatorInterface' => $vendorDir . '/symfony/security-http/Authenticator/AuthenticatorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticatorManagerListener' => $vendorDir . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FallbackUserLoader' => $vendorDir . '/symfony/security-http/Authenticator/FallbackUserLoader.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/FormLoginAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\HttpBasicAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/HttpBasicAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\InteractiveAuthenticatorInterface' => $vendorDir . '/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\JsonLoginAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/JsonLoginAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\LoginLinkAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/LoginLinkAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\BadgeInterface' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\CsrfTokenBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PasswordUpgradeBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PreAuthenticatedUserBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\RememberMeBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\UserBadge' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CredentialsInterface' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CustomCredentials' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\PasswordCredentials' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Passport' => $vendorDir . '/symfony/security-http/Authenticator/Passport/Passport.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\SelfValidatingPassport' => $vendorDir . '/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RememberMeAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/RememberMeAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RemoteUserAuthenticator' => $vendorDir . '/symfony/security-http/Authenticator/RemoteUserAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Token\\PostAuthenticationToken' => $vendorDir . '/symfony/security-http/Authenticator/Token/PostAuthenticationToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\X509Authenticator' => $vendorDir . '/symfony/security-http/Authenticator/X509Authenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authorization\\AccessDeniedHandlerInterface' => $vendorDir . '/symfony/security-http/Authorization/AccessDeniedHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver' => $vendorDir . '/symfony/security-http/Controller/SecurityTokenValueResolver.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver' => $vendorDir . '/symfony/security-http/Controller/UserValueResolver.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface' => $vendorDir . '/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\Exception\\NotAnEntryPointException' => $vendorDir . '/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckCredentialsListener' => $vendorDir . '/symfony/security-http/EventListener/CheckCredentialsListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckRememberMeConditionsListener' => $vendorDir . '/symfony/security-http/EventListener/CheckRememberMeConditionsListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\ClearSiteDataLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/ClearSiteDataLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CookieClearingLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/CookieClearingLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfProtectionListener' => $vendorDir . '/symfony/security-http/EventListener/CsrfProtectionListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfTokenClearingLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/CsrfTokenClearingLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\DefaultLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/DefaultLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\IsGrantedAttributeListener' => $vendorDir . '/symfony/security-http/EventListener/IsGrantedAttributeListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\LoginThrottlingListener' => $vendorDir . '/symfony/security-http/EventListener/LoginThrottlingListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener' => $vendorDir . '/symfony/security-http/EventListener/PasswordMigratingListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\RememberMeListener' => $vendorDir . '/symfony/security-http/EventListener/RememberMeListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionLogoutListener' => $vendorDir . '/symfony/security-http/EventListener/SessionLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionStrategyListener' => $vendorDir . '/symfony/security-http/EventListener/SessionStrategyListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserCheckerListener' => $vendorDir . '/symfony/security-http/EventListener/UserCheckerListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener' => $vendorDir . '/symfony/security-http/EventListener/UserProviderListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\AuthenticationTokenCreatedEvent' => $vendorDir . '/symfony/security-http/Event/AuthenticationTokenCreatedEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent' => $vendorDir . '/symfony/security-http/Event/CheckPassportEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\InteractiveLoginEvent' => $vendorDir . '/symfony/security-http/Event/InteractiveLoginEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LazyResponseEvent' => $vendorDir . '/symfony/security-http/Event/LazyResponseEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginFailureEvent' => $vendorDir . '/symfony/security-http/Event/LoginFailureEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent' => $vendorDir . '/symfony/security-http/Event/LoginSuccessEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LogoutEvent' => $vendorDir . '/symfony/security-http/Event/LogoutEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\SwitchUserEvent' => $vendorDir . '/symfony/security-http/Event/SwitchUserEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\TokenDeauthenticatedEvent' => $vendorDir . '/symfony/security-http/Event/TokenDeauthenticatedEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall' => $vendorDir . '/symfony/security-http/Firewall.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMap' => $vendorDir . '/symfony/security-http/FirewallMap.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMapInterface' => $vendorDir . '/symfony/security-http/FirewallMapInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AbstractListener' => $vendorDir . '/symfony/security-http/Firewall/AbstractListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AccessListener' => $vendorDir . '/symfony/security-http/Firewall/AccessListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AuthenticatorManagerListener' => $vendorDir . '/symfony/security-http/Firewall/AuthenticatorManagerListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ChannelListener' => $vendorDir . '/symfony/security-http/Firewall/ChannelListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ContextListener' => $vendorDir . '/symfony/security-http/Firewall/ContextListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ExceptionListener' => $vendorDir . '/symfony/security-http/Firewall/ExceptionListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\FirewallListenerInterface' => $vendorDir . '/symfony/security-http/Firewall/FirewallListenerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\LogoutListener' => $vendorDir . '/symfony/security-http/Firewall/LogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\SwitchUserListener' => $vendorDir . '/symfony/security-http/Firewall/SwitchUserListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\HttpUtils' => $vendorDir . '/symfony/security-http/HttpUtils.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Impersonate\\ImpersonateUrlGenerator' => $vendorDir . '/symfony/security-http/Impersonate/ImpersonateUrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\ExpiredLoginLinkException' => $vendorDir . '/symfony/security-http/LoginLink/Exception/ExpiredLoginLinkException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkAuthenticationException' => $vendorDir . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkException' => $vendorDir . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkExceptionInterface' => $vendorDir . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkDetails' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkDetails.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandler' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandlerInterface' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkNotification' => $vendorDir . '/symfony/security-http/LoginLink/LoginLinkNotification.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Logout\\LogoutUrlGenerator' => $vendorDir . '/symfony/security-http/Logout/LogoutUrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\ParameterBagUtils' => $vendorDir . '/symfony/security-http/ParameterBagUtils.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RateLimiter\\DefaultLoginRateLimiter' => $vendorDir . '/symfony/security-http/RateLimiter/DefaultLoginRateLimiter.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\AbstractRememberMeHandler' => $vendorDir . '/symfony/security-http/RememberMe/AbstractRememberMeHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\PersistentRememberMeHandler' => $vendorDir . '/symfony/security-http/RememberMe/PersistentRememberMeHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeDetails' => $vendorDir . '/symfony/security-http/RememberMe/RememberMeDetails.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeHandlerInterface' => $vendorDir . '/symfony/security-http/RememberMe/RememberMeHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\ResponseListener' => $vendorDir . '/symfony/security-http/RememberMe/ResponseListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\SignatureRememberMeHandler' => $vendorDir . '/symfony/security-http/RememberMe/SignatureRememberMeHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityEvents' => $vendorDir . '/symfony/security-http/SecurityEvents.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityRequestAttributes' => $vendorDir . '/symfony/security-http/SecurityRequestAttributes.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategy' => $vendorDir . '/symfony/security-http/Session/SessionAuthenticationStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategyInterface' => $vendorDir . '/symfony/security-http/Session/SessionAuthenticationStrategyInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Util\\TargetPathTrait' => $vendorDir . '/symfony/security-http/Util/TargetPathTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Context' => $vendorDir . '/symfony/serializer/Annotation/Context.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\DiscriminatorMap' => $vendorDir . '/symfony/serializer/Annotation/DiscriminatorMap.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Groups' => $vendorDir . '/symfony/serializer/Annotation/Groups.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Ignore' => $vendorDir . '/symfony/serializer/Annotation/Ignore.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\MaxDepth' => $vendorDir . '/symfony/serializer/Annotation/MaxDepth.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedName' => $vendorDir . '/symfony/serializer/Annotation/SerializedName.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedPath' => $vendorDir . '/symfony/serializer/Annotation/SerializedPath.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Context' => $vendorDir . '/symfony/serializer/Attribute/Context.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\DiscriminatorMap' => $vendorDir . '/symfony/serializer/Attribute/DiscriminatorMap.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Groups' => $vendorDir . '/symfony/serializer/Attribute/Groups.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Ignore' => $vendorDir . '/symfony/serializer/Attribute/Ignore.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\MaxDepth' => $vendorDir . '/symfony/serializer/Attribute/MaxDepth.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedName' => $vendorDir . '/symfony/serializer/Attribute/SerializedName.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedPath' => $vendorDir . '/symfony/serializer/Attribute/SerializedPath.php', '_ContaoManager\\Symfony\\Component\\Serializer\\CacheWarmer\\CompiledClassMetadataCacheWarmer' => $vendorDir . '/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Command\\DebugCommand' => $vendorDir . '/symfony/serializer/Command/DebugCommand.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderInterface' => $vendorDir . '/symfony/serializer/Context/ContextBuilderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderTrait' => $vendorDir . '/symfony/serializer/Context/ContextBuilderTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\CsvEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\JsonEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\XmlEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\YamlEncoderContextBuilder' => $vendorDir . '/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractObjectNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\BackedEnumNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ConstraintViolationListNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateIntervalNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateTimeNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\FormErrorNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\GetSetMethodNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\JsonSerializableNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ObjectNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ProblemNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\PropertyNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UidNormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UnwrappingDenormalizerContextBuilder' => $vendorDir . '/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\SerializerContextBuilder' => $vendorDir . '/symfony/serializer/Context/SerializerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\DataCollector\\SerializerDataCollector' => $vendorDir . '/symfony/serializer/DataCollector/SerializerDataCollector.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableEncoder' => $vendorDir . '/symfony/serializer/Debug/TraceableEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableNormalizer' => $vendorDir . '/symfony/serializer/Debug/TraceableNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableSerializer' => $vendorDir . '/symfony/serializer/Debug/TraceableSerializer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\DependencyInjection\\SerializerPass' => $vendorDir . '/symfony/serializer/DependencyInjection/SerializerPass.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainDecoder' => $vendorDir . '/symfony/serializer/Encoder/ChainDecoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainEncoder' => $vendorDir . '/symfony/serializer/Encoder/ChainEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareDecoderInterface' => $vendorDir . '/symfony/serializer/Encoder/ContextAwareDecoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareEncoderInterface' => $vendorDir . '/symfony/serializer/Encoder/ContextAwareEncoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\CsvEncoder' => $vendorDir . '/symfony/serializer/Encoder/CsvEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\DecoderInterface' => $vendorDir . '/symfony/serializer/Encoder/DecoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\EncoderInterface' => $vendorDir . '/symfony/serializer/Encoder/EncoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonDecode' => $vendorDir . '/symfony/serializer/Encoder/JsonDecode.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncode' => $vendorDir . '/symfony/serializer/Encoder/JsonEncode.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncoder' => $vendorDir . '/symfony/serializer/Encoder/JsonEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\NormalizationAwareInterface' => $vendorDir . '/symfony/serializer/Encoder/NormalizationAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\XmlEncoder' => $vendorDir . '/symfony/serializer/Encoder/XmlEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\YamlEncoder' => $vendorDir . '/symfony/serializer/Encoder/YamlEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/serializer/Exception/BadMethodCallException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\CircularReferenceException' => $vendorDir . '/symfony/serializer/Exception/CircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/serializer/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExtraAttributesException' => $vendorDir . '/symfony/serializer/Exception/ExtraAttributesException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/serializer/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\LogicException' => $vendorDir . '/symfony/serializer/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MappingException' => $vendorDir . '/symfony/serializer/Exception/MappingException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MissingConstructorArgumentsException' => $vendorDir . '/symfony/serializer/Exception/MissingConstructorArgumentsException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotEncodableValueException' => $vendorDir . '/symfony/serializer/Exception/NotEncodableValueException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotNormalizableValueException' => $vendorDir . '/symfony/serializer/Exception/NotNormalizableValueException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\PartialDenormalizationException' => $vendorDir . '/symfony/serializer/Exception/PartialDenormalizationException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\RuntimeException' => $vendorDir . '/symfony/serializer/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnexpectedValueException' => $vendorDir . '/symfony/serializer/Exception/UnexpectedValueException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedException' => $vendorDir . '/symfony/serializer/Exception/UnsupportedException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedFormatException' => $vendorDir . '/symfony/serializer/Exception/UnsupportedFormatException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractor' => $vendorDir . '/symfony/serializer/Extractor/ObjectPropertyListExtractor.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractorInterface' => $vendorDir . '/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadata' => $vendorDir . '/symfony/serializer/Mapping/AttributeMetadata.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadataInterface' => $vendorDir . '/symfony/serializer/Mapping/AttributeMetadataInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorFromClassMetadata' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorMapping' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorMapping.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorResolverInterface' => $vendorDir . '/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadata' => $vendorDir . '/symfony/serializer/Mapping/ClassMetadata.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadataInterface' => $vendorDir . '/symfony/serializer/Mapping/ClassMetadataInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CacheClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryCompiler' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryInterface' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassResolverTrait' => $vendorDir . '/symfony/serializer/Mapping/Factory/ClassResolverTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CompiledClassMetadataFactory' => $vendorDir . '/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AnnotationLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/AnnotationLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AttributeLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/AttributeLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\FileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/FileLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderChain' => $vendorDir . '/symfony/serializer/Mapping/Loader/LoaderChain.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderInterface' => $vendorDir . '/symfony/serializer/Mapping/Loader/LoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/XmlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/serializer/Mapping/Loader/YamlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\AdvancedNameConverterInterface' => $vendorDir . '/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\CamelCaseToSnakeCaseNameConverter' => $vendorDir . '/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter' => $vendorDir . '/symfony/serializer/NameConverter/MetadataAwareNameConverter.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface' => $vendorDir . '/symfony/serializer/NameConverter/NameConverterInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/AbstractNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/AbstractObjectNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ArrayDenormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\BackedEnumNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/BackedEnumNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CacheableSupportsMethodInterface' => $vendorDir . '/symfony/serializer/Normalizer/CacheableSupportsMethodInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ConstraintViolationListNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareDenormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/ContextAwareDenormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareNormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/ContextAwareNormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CustomNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/CustomNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DataUriNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DataUriNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateIntervalNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateIntervalNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateTimeNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeZoneNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizableInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizableInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareTrait' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/DenormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\FormErrorNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/FormErrorNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/GetSetMethodNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\JsonSerializableNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/JsonSerializableNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\MimeMessageNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/MimeMessageNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizableInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizableInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareTrait' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface' => $vendorDir . '/symfony/serializer/Normalizer/NormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ObjectNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectToPopulateTrait' => $vendorDir . '/symfony/serializer/Normalizer/ObjectToPopulateTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ProblemNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/ProblemNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/PropertyNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\TranslatableNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/TranslatableNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UidNormalizer' => $vendorDir . '/symfony/serializer/Normalizer/UidNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UnwrappingDenormalizer' => $vendorDir . '/symfony/serializer/Normalizer/UnwrappingDenormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Serializer' => $vendorDir . '/symfony/serializer/Serializer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareInterface' => $vendorDir . '/symfony/serializer/SerializerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareTrait' => $vendorDir . '/symfony/serializer/SerializerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerInterface' => $vendorDir . '/symfony/serializer/SerializerInterface.php', '_ContaoManager\\Symfony\\Component\\String\\AbstractString' => $vendorDir . '/symfony/string/AbstractString.php', '_ContaoManager\\Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/symfony/string/AbstractUnicodeString.php', '_ContaoManager\\Symfony\\Component\\String\\ByteString' => $vendorDir . '/symfony/string/ByteString.php', '_ContaoManager\\Symfony\\Component\\String\\CodePointString' => $vendorDir . '/symfony/string/CodePointString.php', '_ContaoManager\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/string/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/string/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\String\\Exception\\RuntimeException' => $vendorDir . '/symfony/string/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => $vendorDir . '/symfony/string/Inflector/EnglishInflector.php', '_ContaoManager\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => $vendorDir . '/symfony/string/Inflector/FrenchInflector.php', '_ContaoManager\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => $vendorDir . '/symfony/string/Inflector/InflectorInterface.php', '_ContaoManager\\Symfony\\Component\\String\\LazyString' => $vendorDir . '/symfony/string/LazyString.php', '_ContaoManager\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => $vendorDir . '/symfony/string/Slugger/AsciiSlugger.php', '_ContaoManager\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => $vendorDir . '/symfony/string/Slugger/SluggerInterface.php', '_ContaoManager\\Symfony\\Component\\String\\UnicodeString' => $vendorDir . '/symfony/string/UnicodeString.php', '_ContaoManager\\Symfony\\Component\\Uid\\AbstractUid' => $vendorDir . '/symfony/uid/AbstractUid.php', '_ContaoManager\\Symfony\\Component\\Uid\\BinaryUtil' => $vendorDir . '/symfony/uid/BinaryUtil.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUlidCommand' => $vendorDir . '/symfony/uid/Command/GenerateUlidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUuidCommand' => $vendorDir . '/symfony/uid/Command/GenerateUuidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUlidCommand' => $vendorDir . '/symfony/uid/Command/InspectUlidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUuidCommand' => $vendorDir . '/symfony/uid/Command/InspectUuidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\NameBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/NameBasedUuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\RandomBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/RandomBasedUuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\TimeBasedUuidFactory' => $vendorDir . '/symfony/uid/Factory/TimeBasedUuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UlidFactory' => $vendorDir . '/symfony/uid/Factory/UlidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UuidFactory' => $vendorDir . '/symfony/uid/Factory/UuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\MaxUlid' => $vendorDir . '/symfony/uid/MaxUlid.php', '_ContaoManager\\Symfony\\Component\\Uid\\MaxUuid' => $vendorDir . '/symfony/uid/MaxUuid.php', '_ContaoManager\\Symfony\\Component\\Uid\\NilUlid' => $vendorDir . '/symfony/uid/NilUlid.php', '_ContaoManager\\Symfony\\Component\\Uid\\NilUuid' => $vendorDir . '/symfony/uid/NilUuid.php', '_ContaoManager\\Symfony\\Component\\Uid\\TimeBasedUidInterface' => $vendorDir . '/symfony/uid/TimeBasedUidInterface.php', '_ContaoManager\\Symfony\\Component\\Uid\\Ulid' => $vendorDir . '/symfony/uid/Ulid.php', '_ContaoManager\\Symfony\\Component\\Uid\\Uuid' => $vendorDir . '/symfony/uid/Uuid.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV1' => $vendorDir . '/symfony/uid/UuidV1.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV3' => $vendorDir . '/symfony/uid/UuidV3.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV4' => $vendorDir . '/symfony/uid/UuidV4.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV5' => $vendorDir . '/symfony/uid/UuidV5.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV6' => $vendorDir . '/symfony/uid/UuidV6.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV7' => $vendorDir . '/symfony/uid/UuidV7.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV8' => $vendorDir . '/symfony/uid/UuidV8.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\AmqpCaster' => $vendorDir . '/symfony/var-dumper/Caster/AmqpCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ArgsStub' => $vendorDir . '/symfony/var-dumper/Caster/ArgsStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\Caster' => $vendorDir . '/symfony/var-dumper/Caster/Caster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ClassStub' => $vendorDir . '/symfony/var-dumper/Caster/ClassStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ConstStub' => $vendorDir . '/symfony/var-dumper/Caster/ConstStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => $vendorDir . '/symfony/var-dumper/Caster/CutArrayStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutStub' => $vendorDir . '/symfony/var-dumper/Caster/CutStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DOMCaster' => $vendorDir . '/symfony/var-dumper/Caster/DOMCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DateCaster' => $vendorDir . '/symfony/var-dumper/Caster/DateCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster' => $vendorDir . '/symfony/var-dumper/Caster/DoctrineCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsCaster' => $vendorDir . '/symfony/var-dumper/Caster/DsCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => $vendorDir . '/symfony/var-dumper/Caster/DsPairStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\EnumStub' => $vendorDir . '/symfony/var-dumper/Caster/EnumStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster' => $vendorDir . '/symfony/var-dumper/Caster/ExceptionCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FFICaster' => $vendorDir . '/symfony/var-dumper/Caster/FFICaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FiberCaster' => $vendorDir . '/symfony/var-dumper/Caster/FiberCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FrameStub' => $vendorDir . '/symfony/var-dumper/Caster/FrameStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\GmpCaster' => $vendorDir . '/symfony/var-dumper/Caster/GmpCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImagineCaster' => $vendorDir . '/symfony/var-dumper/Caster/ImagineCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImgStub' => $vendorDir . '/symfony/var-dumper/Caster/ImgStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\IntlCaster' => $vendorDir . '/symfony/var-dumper/Caster/IntlCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\LinkStub' => $vendorDir . '/symfony/var-dumper/Caster/LinkStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster' => $vendorDir . '/symfony/var-dumper/Caster/MemcachedCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MysqliCaster' => $vendorDir . '/symfony/var-dumper/Caster/MysqliCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PdoCaster' => $vendorDir . '/symfony/var-dumper/Caster/PdoCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster' => $vendorDir . '/symfony/var-dumper/Caster/PgSqlCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster' => $vendorDir . '/symfony/var-dumper/Caster/ProxyManagerCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster' => $vendorDir . '/symfony/var-dumper/Caster/RdKafkaCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RedisCaster' => $vendorDir . '/symfony/var-dumper/Caster/RedisCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster' => $vendorDir . '/symfony/var-dumper/Caster/ReflectionCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ResourceCaster' => $vendorDir . '/symfony/var-dumper/Caster/ResourceCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ScalarStub' => $vendorDir . '/symfony/var-dumper/Caster/ScalarStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SplCaster' => $vendorDir . '/symfony/var-dumper/Caster/SplCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\StubCaster' => $vendorDir . '/symfony/var-dumper/Caster/StubCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster' => $vendorDir . '/symfony/var-dumper/Caster/SymfonyCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\TraceStub' => $vendorDir . '/symfony/var-dumper/Caster/TraceStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UninitializedStub' => $vendorDir . '/symfony/var-dumper/Caster/UninitializedStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UuidCaster' => $vendorDir . '/symfony/var-dumper/Caster/UuidCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster' => $vendorDir . '/symfony/var-dumper/Caster/XmlReaderCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster' => $vendorDir . '/symfony/var-dumper/Caster/XmlResourceCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => $vendorDir . '/symfony/var-dumper/Cloner/AbstractCloner.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\ClonerInterface' => $vendorDir . '/symfony/var-dumper/Cloner/ClonerInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Cursor' => $vendorDir . '/symfony/var-dumper/Cloner/Cursor.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Data' => $vendorDir . '/symfony/var-dumper/Cloner/Data.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => $vendorDir . '/symfony/var-dumper/Cloner/DumperInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => $vendorDir . '/symfony/var-dumper/Cloner/Internal/NoDefault.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Stub' => $vendorDir . '/symfony/var-dumper/Cloner/Stub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => $vendorDir . '/symfony/var-dumper/Cloner/VarCloner.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand' => $vendorDir . '/symfony/var-dumper/Command/ServerDumpCommand.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper' => $vendorDir . '/symfony/var-dumper/Dumper/AbstractDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\CliDumper' => $vendorDir . '/symfony/var-dumper/Dumper/CliDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper' => $vendorDir . '/symfony/var-dumper/Dumper/ContextualizedDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => $vendorDir . '/symfony/var-dumper/Dumper/DataDumperInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => $vendorDir . '/symfony/var-dumper/Dumper/HtmlDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ServerDumper' => $vendorDir . '/symfony/var-dumper/Dumper/ServerDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => $vendorDir . '/symfony/var-dumper/Exception/ThrowingCasterException.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\Connection' => $vendorDir . '/symfony/var-dumper/Server/Connection.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\DumpServer' => $vendorDir . '/symfony/var-dumper/Server/DumpServer.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => $vendorDir . '/symfony/var-dumper/Test/VarDumperTestTrait.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\VarDumper' => $vendorDir . '/symfony/var-dumper/VarDumper.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => $vendorDir . '/symfony/var-exporter/Exception/ClassNotFoundException.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/var-exporter/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\LogicException' => $vendorDir . '/symfony/var-exporter/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => $vendorDir . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Hydrator' => $vendorDir . '/symfony/var-exporter/Hydrator.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Instantiator' => $vendorDir . '/symfony/var-exporter/Instantiator.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Exporter' => $vendorDir . '/symfony/var-exporter/Internal/Exporter.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Hydrator' => $vendorDir . '/symfony/var-exporter/Internal/Hydrator.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectRegistry' => $vendorDir . '/symfony/var-exporter/Internal/LazyObjectRegistry.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectState' => $vendorDir . '/symfony/var-exporter/Internal/LazyObjectState.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectTrait' => $vendorDir . '/symfony/var-exporter/Internal/LazyObjectTrait.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Reference' => $vendorDir . '/symfony/var-exporter/Internal/Reference.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Registry' => $vendorDir . '/symfony/var-exporter/Internal/Registry.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Values' => $vendorDir . '/symfony/var-exporter/Internal/Values.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyGhostTrait' => $vendorDir . '/symfony/var-exporter/LazyGhostTrait.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyObjectInterface' => $vendorDir . '/symfony/var-exporter/LazyObjectInterface.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyProxyTrait' => $vendorDir . '/symfony/var-exporter/LazyProxyTrait.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\ProxyHelper' => $vendorDir . '/symfony/var-exporter/ProxyHelper.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\VarExporter' => $vendorDir . '/symfony/var-exporter/VarExporter.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Command\\LintCommand' => $vendorDir . '/symfony/yaml/Command/LintCommand.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Dumper.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Escaper' => $vendorDir . '/symfony/yaml/Escaper.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\DumpException' => $vendorDir . '/symfony/yaml/Exception/DumpException.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/yaml/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ParseException' => $vendorDir . '/symfony/yaml/Exception/ParseException.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\RuntimeException' => $vendorDir . '/symfony/yaml/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Inline' => $vendorDir . '/symfony/yaml/Inline.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Parser' => $vendorDir . '/symfony/yaml/Parser.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Tag\\TaggedValue' => $vendorDir . '/symfony/yaml/Tag/TaggedValue.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Unescaper' => $vendorDir . '/symfony/yaml/Unescaper.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Yaml' => $vendorDir . '/symfony/yaml/Yaml.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheInterface' => $vendorDir . '/symfony/cache-contracts/CacheInterface.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheTrait' => $vendorDir . '/symfony/cache-contracts/CacheTrait.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\CallbackInterface' => $vendorDir . '/symfony/cache-contracts/CallbackInterface.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\ItemInterface' => $vendorDir . '/symfony/cache-contracts/ItemInterface.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => $vendorDir . '/symfony/cache-contracts/TagAwareCacheInterface.php', '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher-contracts/Event.php', '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceCollectionInterface' => $vendorDir . '/symfony/service-contracts/ServiceCollectionInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObject' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObjectLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatement' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php', '_ContaoManager\\Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => $vendorDir . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestedCredentialData' => $vendorDir . '/web-auth/webauthn-lib/src/AttestedCredentialData.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensions' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php', '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php', '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponseValidator' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php', '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php', '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponseValidator' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php', '_ContaoManager\\Webauthn\\AuthenticatorData' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorData.php', '_ContaoManager\\Webauthn\\AuthenticatorDataLoader' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorDataLoader.php', '_ContaoManager\\Webauthn\\AuthenticatorResponse' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorResponse.php', '_ContaoManager\\Webauthn\\AuthenticatorSelectionCriteria' => $vendorDir . '/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStep' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStep.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManager' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManager.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManagerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAlgorithm' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAlgorithm.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAllowedCredentialList' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedCredentialList.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAttestationFormatIsKnownAndValid' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAttestationFormatIsKnownAndValid.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckBackupBitsAreConsistent' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckBackupBitsAreConsistent.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckChallenge' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckChallenge.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckClientDataCollectorType' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckClientDataCollectorType.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCounter' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCounter.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCredentialId' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCredentialId.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckExtensions' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckExtensions.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckHasAttestedCredentialData' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckHasAttestedCredentialData.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckMetadataStatement' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckMetadataStatement.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckOrigin' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckOrigin.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckRelyingPartyIdIdHash' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckRelyingPartyIdIdHash.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckSignature' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckSignature.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckTopOrigin' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckTopOrigin.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserHandle' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserHandle.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserVerification' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserVerification.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserWasPresent' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserWasPresent.php', '_ContaoManager\\Webauthn\\CeremonyStep\\HostTopOriginValidator' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/HostTopOriginValidator.php', '_ContaoManager\\Webauthn\\CeremonyStep\\TopOriginValidator' => $vendorDir . '/web-auth/webauthn-lib/src/CeremonyStep/TopOriginValidator.php', '_ContaoManager\\Webauthn\\CertificateChainChecker\\CertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php', '_ContaoManager\\Webauthn\\CertificateChainChecker\\PhpCertificateChainChecker' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php', '_ContaoManager\\Webauthn\\CertificateToolbox' => $vendorDir . '/web-auth/webauthn-lib/src/CertificateToolbox.php', '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollector' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.php', '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollectorManager' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php', '_ContaoManager\\Webauthn\\ClientDataCollector\\WebauthnAuthenticationCollector' => $vendorDir . '/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php', '_ContaoManager\\Webauthn\\CollectedClientData' => $vendorDir . '/web-auth/webauthn-lib/src/CollectedClientData.php', '_ContaoManager\\Webauthn\\Counter\\CounterChecker' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php', '_ContaoManager\\Webauthn\\Counter\\ThrowExceptionIfInvalid' => $vendorDir . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php', '_ContaoManager\\Webauthn\\Credential' => $vendorDir . '/web-auth/webauthn-lib/src/Credential.php', '_ContaoManager\\Webauthn\\Denormalizer\\AttestationObjectDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestationObjectDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AttestationStatementDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestationStatementDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AttestedCredentialDataNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AttestedCredentialDataNormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionNormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionsDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAssertionResponseDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAttestationResponseDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAttestationResponseDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorDataDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorDataDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorResponseDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorResponseDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\CollectedClientDataDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/CollectedClientDataDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\ExtensionDescriptorDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/ExtensionDescriptorDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDescriptorNormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialOptionsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialOptionsDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialParametersDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialParametersDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialSourceDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialUserEntityDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialUserEntityDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\TrustPathDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/TrustPathDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\VerificationMethodANDCombinationsDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/VerificationMethodANDCombinationsDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\WebauthnSerializerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/Denormalizer/WebauthnSerializerFactory.php', '_ContaoManager\\Webauthn\\Event\\AttestationObjectLoaded' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php', '_ContaoManager\\Webauthn\\Event\\AttestationStatementLoaded' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AttestationStatementLoaded.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationFailedEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationFailedEvent.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationSucceededEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationFailedEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationSucceededEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php', '_ContaoManager\\Webauthn\\Event\\BeforeCertificateChainValidation' => $vendorDir . '/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.php', '_ContaoManager\\Webauthn\\Event\\CanDispatchEvents' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php', '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationFailed' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.php', '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationSucceeded' => $vendorDir . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationSucceeded.php', '_ContaoManager\\Webauthn\\Event\\MetadataStatementFound' => $vendorDir . '/web-auth/webauthn-lib/src/Event/MetadataStatementFound.php', '_ContaoManager\\Webauthn\\Event\\NullEventDispatcher' => $vendorDir . '/web-auth/webauthn-lib/src/Event/NullEventDispatcher.php', '_ContaoManager\\Webauthn\\Event\\WebauthnEvent' => $vendorDir . '/web-auth/webauthn-lib/src/Event/WebauthnEvent.php', '_ContaoManager\\Webauthn\\Exception\\AttestationStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AttestationStatementException.php', '_ContaoManager\\Webauthn\\Exception\\AttestationStatementLoadingException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AttestationStatementLoadingException.php', '_ContaoManager\\Webauthn\\Exception\\AttestationStatementVerificationException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AttestationStatementVerificationException.php', '_ContaoManager\\Webauthn\\Exception\\AuthenticationExtensionException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AuthenticationExtensionException.php', '_ContaoManager\\Webauthn\\Exception\\AuthenticatorResponseVerificationException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/AuthenticatorResponseVerificationException.php', '_ContaoManager\\Webauthn\\Exception\\CertificateChainException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CertificateChainException.php', '_ContaoManager\\Webauthn\\Exception\\CertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CertificateException.php', '_ContaoManager\\Webauthn\\Exception\\CertificateRevocationListException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CertificateRevocationListException.php', '_ContaoManager\\Webauthn\\Exception\\CounterException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/CounterException.php', '_ContaoManager\\Webauthn\\Exception\\ExpiredCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/ExpiredCertificateException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidAttestationStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidAttestationStatementException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidCertificateException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidDataException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidDataException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidTrustPathException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidTrustPathException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidUserHandleException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/InvalidUserHandleException.php', '_ContaoManager\\Webauthn\\Exception\\MetadataServiceException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MetadataServiceException.php', '_ContaoManager\\Webauthn\\Exception\\MetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MetadataStatementException.php', '_ContaoManager\\Webauthn\\Exception\\MetadataStatementLoadingException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MetadataStatementLoadingException.php', '_ContaoManager\\Webauthn\\Exception\\MissingMetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/MissingMetadataStatementException.php', '_ContaoManager\\Webauthn\\Exception\\RevokedCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/RevokedCertificateException.php', '_ContaoManager\\Webauthn\\Exception\\UnsupportedFeatureException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/UnsupportedFeatureException.php', '_ContaoManager\\Webauthn\\Exception\\WebauthnException' => $vendorDir . '/web-auth/webauthn-lib/src/Exception/WebauthnException.php', '_ContaoManager\\Webauthn\\FakeCredentialGenerator' => $vendorDir . '/web-auth/webauthn-lib/src/FakeCredentialGenerator.php', '_ContaoManager\\Webauthn\\MetadataService\\CanLogData' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CanLogData.php', '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateChainValidator' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateChainValidator.php', '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateToolbox' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateToolbox.php', '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\PhpCertificateChainValidator' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/PhpCertificateChainValidator.php', '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\ExtensionDescriptorDenormalizer' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php', '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\MetadataStatementSerializerFactory' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\BeforeCertificateChainValidation' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\CanDispatchEvents' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationFailed' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationFailed.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationSucceeded' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationSucceeded.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\MetadataStatementFound' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/MetadataStatementFound.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\NullEventDispatcher' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/NullEventDispatcher.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\WebauthnEvent' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateChainException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateRevocationListException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\ExpiredCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\InvalidCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataServiceException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementLoadingException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MissingMetadataStatementException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\RevokedCertificateException' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\MetadataStatementRepository' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/MetadataStatementRepository.php', '_ContaoManager\\Webauthn\\MetadataService\\Psr18HttpClient' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Psr18HttpClient.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\ChainedMetadataServices' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\DistantResourceMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/DistantResourceMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\FidoAllianceCompliantMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/FidoAllianceCompliantMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\FolderResourceMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/FolderResourceMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\InMemoryMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/InMemoryMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\JsonMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/JsonMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\LocalResourceMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/LocalResourceMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayload' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayloadEntry' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\StringMetadataService' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AbstractDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AlternativeDescriptions' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorGetInfo' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorGetInfo.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorStatus' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorStatus.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricAccuracyDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricStatusReport' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricStatusReport.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\CodeAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/CodeAccuracyDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\DisplayPNGCharacteristicsDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\EcdaaTrustAnchor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\ExtensionDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/ExtensionDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\MetadataStatement' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/MetadataStatement.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\PatternAccuracyDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/PatternAccuracyDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RgbPaletteEntry' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/RgbPaletteEntry.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RogueListEntry' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/RogueListEntry.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\StatusReport' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/StatusReport.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodANDCombinations' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodANDCombinations.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\Version' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/Statement/Version.php', '_ContaoManager\\Webauthn\\MetadataService\\StatusReportRepository' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/StatusReportRepository.php', '_ContaoManager\\Webauthn\\MetadataService\\ValueFilter' => $vendorDir . '/web-auth/webauthn-lib/src/MetadataService/ValueFilter.php', '_ContaoManager\\Webauthn\\PublicKeyCredential' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredential.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialCreationOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptor' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptorCollection' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialLoader' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialParameters' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialRequestOptions' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialRpEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialSource' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialSourceRepository' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialUserEntity' => $vendorDir . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php', '_ContaoManager\\Webauthn\\SimpleFakeCredentialGenerator' => $vendorDir . '/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php', '_ContaoManager\\Webauthn\\StringStream' => $vendorDir . '/web-auth/webauthn-lib/src/StringStream.php', '_ContaoManager\\Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php', '_ContaoManager\\Webauthn\\TokenBinding\\SecTokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php', '_ContaoManager\\Webauthn\\TokenBinding\\TokenBinding' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php', '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php', '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => $vendorDir . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php', '_ContaoManager\\Webauthn\\TrustPath\\CertificateTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\EmptyTrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\TrustPath' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\TrustPathLoader' => $vendorDir . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php', '_ContaoManager\\Webauthn\\U2FPublicKey' => $vendorDir . '/web-auth/webauthn-lib/src/U2FPublicKey.php', '_ContaoManager\\Webauthn\\Util\\Base64' => $vendorDir . '/web-auth/webauthn-lib/src/Util/Base64.php', '_ContaoManager\\Webauthn\\Util\\CoseSignatureFixer' => $vendorDir . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php', '_ContaoManager\\Webmozart\\Assert\\Assert' => $vendorDir . '/webmozart/assert/src/Assert.php', '_ContaoManager\\Webmozart\\Assert\\InvalidArgumentException' => $vendorDir . '/webmozart/assert/src/InvalidArgumentException.php', '_ContaoManager\\Webmozart\\Assert\\Mixin' => $vendorDir . '/webmozart/assert/src/Mixin.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactoryInterface' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Description' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Serializer' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\TagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Extends_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\AbstractPHPStanFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ExtendsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\Factory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ImplementsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ImplementsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodParameterFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PHPStanFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ParamFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ParamFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyReadFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyWriteFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ReturnFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\StaticMethod' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateExtendsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateExtendsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateImplementsFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\VarFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Implements_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\MethodParameter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Mixin' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Template' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateCovariant' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateExtends' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateImplements' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php', '_ContaoManager\\phpDocumentor\\Reflection\\Element' => $vendorDir . '/phpdocumentor/reflection-common/src/Element.php', '_ContaoManager\\phpDocumentor\\Reflection\\Exception\\PcreException' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php', '_ContaoManager\\phpDocumentor\\Reflection\\File' => $vendorDir . '/phpdocumentor/reflection-common/src/File.php', '_ContaoManager\\phpDocumentor\\Reflection\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-common/src/Fqsen.php', '_ContaoManager\\phpDocumentor\\Reflection\\FqsenResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/FqsenResolver.php', '_ContaoManager\\phpDocumentor\\Reflection\\Location' => $vendorDir . '/phpdocumentor/reflection-common/src/Location.php', '_ContaoManager\\phpDocumentor\\Reflection\\Project' => $vendorDir . '/phpdocumentor/reflection-common/src/Project.php', '_ContaoManager\\phpDocumentor\\Reflection\\ProjectFactory' => $vendorDir . '/phpdocumentor/reflection-common/src/ProjectFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoType' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoType.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\CallableString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ConstExpression' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\False_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\FloatValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\HtmlEscapedString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerRange' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\List_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/List_.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LiteralString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LowercaseString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NegativeInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyArray' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyList' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyLowercaseString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NumericString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\Numeric_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShape' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\PositiveInteger' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ShapeItem' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\StringValue' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\TraitString' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\True_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Type' => $vendorDir . '/phpdocumentor/type-resolver/src/Type.php', '_ContaoManager\\phpDocumentor\\Reflection\\TypeResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/TypeResolver.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AbstractList' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AbstractList.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AggregatedType' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ArrayKey' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ArrayKey.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Array_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Array_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Boolean' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Boolean.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\CallableParameter' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/CallableParameter.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Callable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Callable_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ClassString' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ClassString.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Collection' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Collection.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Compound' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Compound.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Context' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Context.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ContextFactory' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Expression' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Expression.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Float_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Float_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Integer' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Integer.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\InterfaceString' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/InterfaceString.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Intersection' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Intersection.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Iterable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Iterable_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Mixed_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Mixed_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Never_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Never_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Null_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Null_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Nullable' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Nullable.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Object_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Object_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Parent_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Parent_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Resource_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Resource_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Scalar' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Scalar.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Self_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Self_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Static_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Static_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\String_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/String_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\This' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/This.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Void_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Void_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Utils' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Utils.php', '_ContaoManager\\studio24\\Rotate\\Delete' => $vendorDir . '/studio24/rotate/src/Delete.php', '_ContaoManager\\studio24\\Rotate\\DirectoryIterator' => $vendorDir . '/studio24/rotate/src/DirectoryIterator.php', '_ContaoManager\\studio24\\Rotate\\FilenameFormat' => $vendorDir . '/studio24/rotate/src/FilenameFormat.php', '_ContaoManager\\studio24\\Rotate\\FilenameFormatException' => $vendorDir . '/studio24/rotate/src/FilenameFormatException.php', '_ContaoManager\\studio24\\Rotate\\Rotate' => $vendorDir . '/studio24/rotate/src/Rotate.php', '_ContaoManager\\studio24\\Rotate\\RotateAbstract' => $vendorDir . '/studio24/rotate/src/RotateAbstract.php', '_ContaoManager\\studio24\\Rotate\\RotateException' => $vendorDir . '/studio24/rotate/src/RotateException.php', '_ContaoManager\\' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php', ); = 80100)) { $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.'; } if ($issues) { if (!headers_sent()) { header('HTTP/1.1 500 Internal Server Error'); } if (!ini_get('display_errors')) { if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); } elseif (!headers_sent()) { echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; } } trigger_error( 'Composer detected issues in your platform: ' . implode(' ', $issues), E_USER_ERROR ); } __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '09f6b20656683369174dd6fa83b7e5fb' => __DIR__ . '/..' . '/symfony/polyfill-uuid/bootstrap.php', 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', '2203a247e6fda86070a5e4e07aed533a' => __DIR__ . '/..' . '/symfony/clock/Resources/now.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', 'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php', ); public static $prefixLengthsPsr4 = array ( '_' => array ( '_ContaoManager\\studio24\\Rotate\\' => 31, '_ContaoManager\\phpDocumentor\\Reflection\\' => 40, '_ContaoManager\\Webmozart\\Assert\\' => 32, '_ContaoManager\\Webauthn\\' => 24, '_ContaoManager\\Symfony\\Contracts\\Service\\' => 41, '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\' => 49, '_ContaoManager\\Symfony\\Contracts\\Cache\\' => 39, '_ContaoManager\\Symfony\\Component\\Yaml\\' => 38, '_ContaoManager\\Symfony\\Component\\VarExporter\\' => 45, '_ContaoManager\\Symfony\\Component\\VarDumper\\' => 43, '_ContaoManager\\Symfony\\Component\\Uid\\' => 37, '_ContaoManager\\Symfony\\Component\\String\\' => 40, '_ContaoManager\\Symfony\\Component\\Serializer\\' => 44, '_ContaoManager\\Symfony\\Component\\Security\\Http\\' => 47, '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\' => 47, '_ContaoManager\\Symfony\\Component\\Security\\Core\\' => 47, '_ContaoManager\\Symfony\\Component\\Routing\\' => 41, '_ContaoManager\\Symfony\\Component\\PropertyInfo\\' => 46, '_ContaoManager\\Symfony\\Component\\PropertyAccess\\' => 48, '_ContaoManager\\Symfony\\Component\\Process\\' => 41, '_ContaoManager\\Symfony\\Component\\PasswordHasher\\' => 48, '_ContaoManager\\Symfony\\Component\\HttpKernel\\' => 44, '_ContaoManager\\Symfony\\Component\\HttpFoundation\\' => 48, '_ContaoManager\\Symfony\\Component\\Finder\\' => 40, '_ContaoManager\\Symfony\\Component\\Filesystem\\' => 44, '_ContaoManager\\Symfony\\Component\\EventDispatcher\\' => 49, '_ContaoManager\\Symfony\\Component\\ErrorHandler\\' => 46, '_ContaoManager\\Symfony\\Component\\DependencyInjection\\' => 53, '_ContaoManager\\Symfony\\Component\\Console\\' => 41, '_ContaoManager\\Symfony\\Component\\Config\\' => 40, '_ContaoManager\\Symfony\\Component\\Clock\\' => 39, '_ContaoManager\\Symfony\\Component\\Cache\\' => 39, '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\' => 45, '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\' => 44, '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\' => 46, '_ContaoManager\\Symfony\\Bridge\\Monolog\\' => 38, '_ContaoManager\\SpomkyLabs\\Pki\\' => 30, '_ContaoManager\\Seld\\Signal\\' => 27, '_ContaoManager\\Seld\\PharUtils\\' => 30, '_ContaoManager\\Seld\\JsonLint\\' => 29, '_ContaoManager\\Ramsey\\Uuid\\' => 27, '_ContaoManager\\Ramsey\\Collection\\' => 33, '_ContaoManager\\Psr\\Log\\' => 23, '_ContaoManager\\Psr\\Http\\Message\\' => 32, '_ContaoManager\\Psr\\Http\\Client\\' => 31, '_ContaoManager\\Psr\\EventDispatcher\\' => 35, '_ContaoManager\\Psr\\Container\\' => 29, '_ContaoManager\\Psr\\Clock\\' => 25, '_ContaoManager\\Psr\\Cache\\' => 25, '_ContaoManager\\ParagonIE\\ConstantTime\\' => 38, '_ContaoManager\\PHPStan\\PhpDocParser\\' => 36, '_ContaoManager\\OTPHP\\' => 21, '_ContaoManager\\Monolog\\' => 23, '_ContaoManager\\Lcobucci\\Clock\\' => 30, '_ContaoManager\\JsonSchema\\' => 26, '_ContaoManager\\Firebase\\JWT\\' => 28, '_ContaoManager\\Doctrine\\Deprecations\\' => 37, '_ContaoManager\\Crell\\ApiProblem\\' => 32, '_ContaoManager\\Cose\\' => 20, '_ContaoManager\\Contao\\ManagerApi\\' => 33, '_ContaoManager\\CBOR\\' => 20, '_ContaoManager\\Brick\\Math\\' => 26, ), 'S' => array ( 'Symfony\\Polyfill\\Uuid\\' => 22, 'Symfony\\Polyfill\\Php83\\' => 23, 'Symfony\\Polyfill\\Php81\\' => 23, 'Symfony\\Polyfill\\Php80\\' => 23, 'Symfony\\Polyfill\\Php73\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, 'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31, 'Symfony\\Polyfill\\Ctype\\' => 23, ), 'R' => array ( 'React\\Promise\\' => 14, ), 'C' => array ( 'Composer\\XdebugHandler\\' => 23, 'Composer\\Spdx\\' => 14, 'Composer\\Semver\\' => 16, 'Composer\\Pcre\\' => 14, 'Composer\\MetadataMinifier\\' => 26, 'Composer\\ClassMapGenerator\\' => 27, 'Composer\\CaBundle\\' => 18, 'Composer\\' => 9, ), ); public static $prefixDirsPsr4 = array ( '_ContaoManager\\studio24\\Rotate\\' => array ( 0 => __DIR__ . '/..' . '/studio24/rotate/src', ), '_ContaoManager\\phpDocumentor\\Reflection\\' => array ( 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', 1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', 2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', ), '_ContaoManager\\Webmozart\\Assert\\' => array ( 0 => __DIR__ . '/..' . '/webmozart/assert/src', ), '_ContaoManager\\Webauthn\\' => array ( 0 => __DIR__ . '/..' . '/web-auth/webauthn-lib/src', ), '_ContaoManager\\Symfony\\Contracts\\Service\\' => array ( 0 => __DIR__ . '/..' . '/symfony/service-contracts', ), '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\' => array ( 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', ), '_ContaoManager\\Symfony\\Contracts\\Cache\\' => array ( 0 => __DIR__ . '/..' . '/symfony/cache-contracts', ), '_ContaoManager\\Symfony\\Component\\Yaml\\' => array ( 0 => __DIR__ . '/..' . '/symfony/yaml', ), '_ContaoManager\\Symfony\\Component\\VarExporter\\' => array ( 0 => __DIR__ . '/..' . '/symfony/var-exporter', ), '_ContaoManager\\Symfony\\Component\\VarDumper\\' => array ( 0 => __DIR__ . '/..' . '/symfony/var-dumper', ), '_ContaoManager\\Symfony\\Component\\Uid\\' => array ( 0 => __DIR__ . '/..' . '/symfony/uid', ), '_ContaoManager\\Symfony\\Component\\String\\' => array ( 0 => __DIR__ . '/..' . '/symfony/string', ), '_ContaoManager\\Symfony\\Component\\Serializer\\' => array ( 0 => __DIR__ . '/..' . '/symfony/serializer', ), '_ContaoManager\\Symfony\\Component\\Security\\Http\\' => array ( 0 => __DIR__ . '/..' . '/symfony/security-http', ), '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\' => array ( 0 => __DIR__ . '/..' . '/symfony/security-csrf', ), '_ContaoManager\\Symfony\\Component\\Security\\Core\\' => array ( 0 => __DIR__ . '/..' . '/symfony/security-core', ), '_ContaoManager\\Symfony\\Component\\Routing\\' => array ( 0 => __DIR__ . '/..' . '/symfony/routing', ), '_ContaoManager\\Symfony\\Component\\PropertyInfo\\' => array ( 0 => __DIR__ . '/..' . '/symfony/property-info', ), '_ContaoManager\\Symfony\\Component\\PropertyAccess\\' => array ( 0 => __DIR__ . '/..' . '/symfony/property-access', ), '_ContaoManager\\Symfony\\Component\\Process\\' => array ( 0 => __DIR__ . '/..' . '/symfony/process', ), '_ContaoManager\\Symfony\\Component\\PasswordHasher\\' => array ( 0 => __DIR__ . '/..' . '/symfony/password-hasher', ), '_ContaoManager\\Symfony\\Component\\HttpKernel\\' => array ( 0 => __DIR__ . '/..' . '/symfony/http-kernel', ), '_ContaoManager\\Symfony\\Component\\HttpFoundation\\' => array ( 0 => __DIR__ . '/..' . '/symfony/http-foundation', ), '_ContaoManager\\Symfony\\Component\\Finder\\' => array ( 0 => __DIR__ . '/..' . '/symfony/finder', ), '_ContaoManager\\Symfony\\Component\\Filesystem\\' => array ( 0 => __DIR__ . '/..' . '/symfony/filesystem', ), '_ContaoManager\\Symfony\\Component\\EventDispatcher\\' => array ( 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', ), '_ContaoManager\\Symfony\\Component\\ErrorHandler\\' => array ( 0 => __DIR__ . '/..' . '/symfony/error-handler', ), '_ContaoManager\\Symfony\\Component\\DependencyInjection\\' => array ( 0 => __DIR__ . '/..' . '/symfony/dependency-injection', ), '_ContaoManager\\Symfony\\Component\\Console\\' => array ( 0 => __DIR__ . '/..' . '/symfony/console', ), '_ContaoManager\\Symfony\\Component\\Config\\' => array ( 0 => __DIR__ . '/..' . '/symfony/config', ), '_ContaoManager\\Symfony\\Component\\Clock\\' => array ( 0 => __DIR__ . '/..' . '/symfony/clock', ), '_ContaoManager\\Symfony\\Component\\Cache\\' => array ( 0 => __DIR__ . '/..' . '/symfony/cache', ), '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\' => array ( 0 => __DIR__ . '/..' . '/symfony/security-bundle', ), '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\' => array ( 0 => __DIR__ . '/..' . '/symfony/monolog-bundle', ), '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\' => array ( 0 => __DIR__ . '/..' . '/symfony/framework-bundle', ), '_ContaoManager\\Symfony\\Bridge\\Monolog\\' => array ( 0 => __DIR__ . '/..' . '/symfony/monolog-bridge', ), '_ContaoManager\\SpomkyLabs\\Pki\\' => array ( 0 => __DIR__ . '/..' . '/spomky-labs/pki-framework/src', ), '_ContaoManager\\Seld\\Signal\\' => array ( 0 => __DIR__ . '/..' . '/seld/signal-handler/src', ), '_ContaoManager\\Seld\\PharUtils\\' => array ( 0 => __DIR__ . '/..' . '/seld/phar-utils/src', ), '_ContaoManager\\Seld\\JsonLint\\' => array ( 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint', ), '_ContaoManager\\Ramsey\\Uuid\\' => array ( 0 => __DIR__ . '/..' . '/ramsey/uuid/src', ), '_ContaoManager\\Ramsey\\Collection\\' => array ( 0 => __DIR__ . '/..' . '/ramsey/collection/src', ), '_ContaoManager\\Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/src', ), '_ContaoManager\\Psr\\Http\\Message\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-factory/src', 1 => __DIR__ . '/..' . '/psr/http-message/src', ), '_ContaoManager\\Psr\\Http\\Client\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-client/src', ), '_ContaoManager\\Psr\\EventDispatcher\\' => array ( 0 => __DIR__ . '/..' . '/psr/event-dispatcher/src', ), '_ContaoManager\\Psr\\Container\\' => array ( 0 => __DIR__ . '/..' . '/psr/container/src', ), '_ContaoManager\\Psr\\Clock\\' => array ( 0 => __DIR__ . '/..' . '/psr/clock/src', ), '_ContaoManager\\Psr\\Cache\\' => array ( 0 => __DIR__ . '/..' . '/psr/cache/src', ), '_ContaoManager\\ParagonIE\\ConstantTime\\' => array ( 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src', ), '_ContaoManager\\PHPStan\\PhpDocParser\\' => array ( 0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src', ), '_ContaoManager\\OTPHP\\' => array ( 0 => __DIR__ . '/..' . '/spomky-labs/otphp/src', ), '_ContaoManager\\Monolog\\' => array ( 0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog', ), '_ContaoManager\\Lcobucci\\Clock\\' => array ( 0 => __DIR__ . '/..' . '/lcobucci/clock/src', ), '_ContaoManager\\JsonSchema\\' => array ( 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema', ), '_ContaoManager\\Firebase\\JWT\\' => array ( 0 => __DIR__ . '/..' . '/firebase/php-jwt/src', ), '_ContaoManager\\Doctrine\\Deprecations\\' => array ( 0 => __DIR__ . '/..' . '/doctrine/deprecations/src', ), '_ContaoManager\\Crell\\ApiProblem\\' => array ( 0 => __DIR__ . '/..' . '/crell/api-problem/src', ), '_ContaoManager\\Cose\\' => array ( 0 => __DIR__ . '/..' . '/web-auth/cose-lib/src', ), '_ContaoManager\\Contao\\ManagerApi\\' => array ( 0 => __DIR__ . '/../..' . '/api', ), '_ContaoManager\\CBOR\\' => array ( 0 => __DIR__ . '/..' . '/spomky-labs/cbor-php/src', ), '_ContaoManager\\Brick\\Math\\' => array ( 0 => __DIR__ . '/..' . '/brick/math/src', ), 'Symfony\\Polyfill\\Uuid\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-uuid', ), 'Symfony\\Polyfill\\Php83\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php83', ), 'Symfony\\Polyfill\\Php81\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php81', ), 'Symfony\\Polyfill\\Php80\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', ), 'Symfony\\Polyfill\\Php73\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', ), 'Symfony\\Polyfill\\Mbstring\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', ), 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer', ), 'Symfony\\Polyfill\\Intl\\Grapheme\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme', ), 'Symfony\\Polyfill\\Ctype\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', ), 'React\\Promise\\' => array ( 0 => __DIR__ . '/..' . '/react/promise/src', ), 'Composer\\XdebugHandler\\' => array ( 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src', ), 'Composer\\Spdx\\' => array ( 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src', ), 'Composer\\Semver\\' => array ( 0 => __DIR__ . '/..' . '/composer/semver/src', ), 'Composer\\Pcre\\' => array ( 0 => __DIR__ . '/..' . '/composer/pcre/src', ), 'Composer\\MetadataMinifier\\' => array ( 0 => __DIR__ . '/..' . '/composer/metadata-minifier/src', ), 'Composer\\ClassMapGenerator\\' => array ( 0 => __DIR__ . '/..' . '/composer/class-map-generator/src', ), 'Composer\\CaBundle\\' => array ( 0 => __DIR__ . '/..' . '/composer/ca-bundle/src', ), 'Composer\\' => array ( 0 => __DIR__ . '/..' . '/composer/composer/src/Composer', ), ); public static $classMap = array ( 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'CURLStringFile' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\Advisory\\Auditor' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/Auditor.php', 'Composer\\Advisory\\IgnoredSecurityAdvisory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/IgnoredSecurityAdvisory.php', 'Composer\\Advisory\\PartialSecurityAdvisory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/PartialSecurityAdvisory.php', 'Composer\\Advisory\\SecurityAdvisory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Advisory/SecurityAdvisory.php', 'Composer\\Autoload\\AutoloadGenerator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Autoload/AutoloadGenerator.php', 'Composer\\Autoload\\ClassLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Autoload/ClassLoader.php', 'Composer\\Autoload\\ClassMapGenerator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Autoload/ClassMapGenerator.php', 'Composer\\CaBundle\\CaBundle' => __DIR__ . '/..' . '/composer/ca-bundle/src/CaBundle.php', 'Composer\\Cache' => __DIR__ . '/..' . '/composer/composer/src/Composer/Cache.php', 'Composer\\ClassMapGenerator\\ClassMap' => __DIR__ . '/..' . '/composer/class-map-generator/src/ClassMap.php', 'Composer\\ClassMapGenerator\\ClassMapGenerator' => __DIR__ . '/..' . '/composer/class-map-generator/src/ClassMapGenerator.php', 'Composer\\ClassMapGenerator\\FileList' => __DIR__ . '/..' . '/composer/class-map-generator/src/FileList.php', 'Composer\\ClassMapGenerator\\PhpFileCleaner' => __DIR__ . '/..' . '/composer/class-map-generator/src/PhpFileCleaner.php', 'Composer\\ClassMapGenerator\\PhpFileParser' => __DIR__ . '/..' . '/composer/class-map-generator/src/PhpFileParser.php', 'Composer\\Command\\AboutCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/AboutCommand.php', 'Composer\\Command\\ArchiveCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ArchiveCommand.php', 'Composer\\Command\\AuditCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/AuditCommand.php', 'Composer\\Command\\BaseCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/BaseCommand.php', 'Composer\\Command\\BaseDependencyCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/BaseDependencyCommand.php', 'Composer\\Command\\BumpCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/BumpCommand.php', 'Composer\\Command\\CheckPlatformReqsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php', 'Composer\\Command\\ClearCacheCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ClearCacheCommand.php', 'Composer\\Command\\CompletionTrait' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/CompletionTrait.php', 'Composer\\Command\\ConfigCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ConfigCommand.php', 'Composer\\Command\\CreateProjectCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/CreateProjectCommand.php', 'Composer\\Command\\DependsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/DependsCommand.php', 'Composer\\Command\\DiagnoseCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/DiagnoseCommand.php', 'Composer\\Command\\DumpAutoloadCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/DumpAutoloadCommand.php', 'Composer\\Command\\ExecCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ExecCommand.php', 'Composer\\Command\\FundCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/FundCommand.php', 'Composer\\Command\\GlobalCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/GlobalCommand.php', 'Composer\\Command\\HomeCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/HomeCommand.php', 'Composer\\Command\\InitCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/InitCommand.php', 'Composer\\Command\\InstallCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/InstallCommand.php', 'Composer\\Command\\LicensesCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/LicensesCommand.php', 'Composer\\Command\\OutdatedCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/OutdatedCommand.php', 'Composer\\Command\\PackageDiscoveryTrait' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/PackageDiscoveryTrait.php', 'Composer\\Command\\ProhibitsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ProhibitsCommand.php', 'Composer\\Command\\ReinstallCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ReinstallCommand.php', 'Composer\\Command\\RemoveCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/RemoveCommand.php', 'Composer\\Command\\RequireCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/RequireCommand.php', 'Composer\\Command\\RunScriptCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/RunScriptCommand.php', 'Composer\\Command\\ScriptAliasCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ScriptAliasCommand.php', 'Composer\\Command\\SearchCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/SearchCommand.php', 'Composer\\Command\\SelfUpdateCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/SelfUpdateCommand.php', 'Composer\\Command\\ShowCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ShowCommand.php', 'Composer\\Command\\StatusCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/StatusCommand.php', 'Composer\\Command\\SuggestsCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/SuggestsCommand.php', 'Composer\\Command\\UpdateCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/UpdateCommand.php', 'Composer\\Command\\ValidateCommand' => __DIR__ . '/..' . '/composer/composer/src/Composer/Command/ValidateCommand.php', 'Composer\\Compiler' => __DIR__ . '/..' . '/composer/composer/src/Composer/Compiler.php', 'Composer\\Composer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Composer.php', 'Composer\\Config' => __DIR__ . '/..' . '/composer/composer/src/Composer/Config.php', 'Composer\\Config\\ConfigSourceInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Config/ConfigSourceInterface.php', 'Composer\\Config\\JsonConfigSource' => __DIR__ . '/..' . '/composer/composer/src/Composer/Config/JsonConfigSource.php', 'Composer\\Console\\Application' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/Application.php', 'Composer\\Console\\GithubActionError' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/GithubActionError.php', 'Composer\\Console\\HtmlOutputFormatter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/HtmlOutputFormatter.php', 'Composer\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/Input/InputArgument.php', 'Composer\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/composer/composer/src/Composer/Console/Input/InputOption.php', 'Composer\\DependencyResolver\\Decisions' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Decisions.php', 'Composer\\DependencyResolver\\DefaultPolicy' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/DefaultPolicy.php', 'Composer\\DependencyResolver\\GenericRule' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/GenericRule.php', 'Composer\\DependencyResolver\\LocalRepoTransaction' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/LocalRepoTransaction.php', 'Composer\\DependencyResolver\\LockTransaction' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/LockTransaction.php', 'Composer\\DependencyResolver\\MultiConflictRule' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/MultiConflictRule.php', 'Composer\\DependencyResolver\\Operation\\InstallOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/InstallOperation.php', 'Composer\\DependencyResolver\\Operation\\MarkAliasInstalledOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php', 'Composer\\DependencyResolver\\Operation\\MarkAliasUninstalledOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.php', 'Composer\\DependencyResolver\\Operation\\OperationInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/OperationInterface.php', 'Composer\\DependencyResolver\\Operation\\SolverOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/SolverOperation.php', 'Composer\\DependencyResolver\\Operation\\UninstallOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/UninstallOperation.php', 'Composer\\DependencyResolver\\Operation\\UpdateOperation' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Operation/UpdateOperation.php', 'Composer\\DependencyResolver\\PolicyInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/PolicyInterface.php', 'Composer\\DependencyResolver\\Pool' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Pool.php', 'Composer\\DependencyResolver\\PoolBuilder' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/PoolBuilder.php', 'Composer\\DependencyResolver\\PoolOptimizer' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php', 'Composer\\DependencyResolver\\Problem' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Problem.php', 'Composer\\DependencyResolver\\Request' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Request.php', 'Composer\\DependencyResolver\\Rule' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Rule.php', 'Composer\\DependencyResolver\\Rule2Literals' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Rule2Literals.php', 'Composer\\DependencyResolver\\RuleSet' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleSet.php', 'Composer\\DependencyResolver\\RuleSetGenerator' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php', 'Composer\\DependencyResolver\\RuleSetIterator' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleSetIterator.php', 'Composer\\DependencyResolver\\RuleWatchChain' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleWatchChain.php', 'Composer\\DependencyResolver\\RuleWatchGraph' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleWatchGraph.php', 'Composer\\DependencyResolver\\RuleWatchNode' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/RuleWatchNode.php', 'Composer\\DependencyResolver\\Solver' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Solver.php', 'Composer\\DependencyResolver\\SolverBugException' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/SolverBugException.php', 'Composer\\DependencyResolver\\SolverProblemsException' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/SolverProblemsException.php', 'Composer\\DependencyResolver\\Transaction' => __DIR__ . '/..' . '/composer/composer/src/Composer/DependencyResolver/Transaction.php', 'Composer\\Downloader\\ArchiveDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/ArchiveDownloader.php', 'Composer\\Downloader\\ChangeReportInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/ChangeReportInterface.php', 'Composer\\Downloader\\DownloadManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/DownloadManager.php', 'Composer\\Downloader\\DownloaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/DownloaderInterface.php', 'Composer\\Downloader\\DvcsDownloaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/DvcsDownloaderInterface.php', 'Composer\\Downloader\\FileDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/FileDownloader.php', 'Composer\\Downloader\\FilesystemException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/FilesystemException.php', 'Composer\\Downloader\\FossilDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/FossilDownloader.php', 'Composer\\Downloader\\GitDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/GitDownloader.php', 'Composer\\Downloader\\GzipDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/GzipDownloader.php', 'Composer\\Downloader\\HgDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/HgDownloader.php', 'Composer\\Downloader\\MaxFileSizeExceededException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/MaxFileSizeExceededException.php', 'Composer\\Downloader\\PathDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/PathDownloader.php', 'Composer\\Downloader\\PerforceDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/PerforceDownloader.php', 'Composer\\Downloader\\PharDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/PharDownloader.php', 'Composer\\Downloader\\RarDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/RarDownloader.php', 'Composer\\Downloader\\SvnDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/SvnDownloader.php', 'Composer\\Downloader\\TarDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/TarDownloader.php', 'Composer\\Downloader\\TransportException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/TransportException.php', 'Composer\\Downloader\\VcsCapableDownloaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/VcsCapableDownloaderInterface.php', 'Composer\\Downloader\\VcsDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/VcsDownloader.php', 'Composer\\Downloader\\XzDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/XzDownloader.php', 'Composer\\Downloader\\ZipDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Downloader/ZipDownloader.php', 'Composer\\EventDispatcher\\Event' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/Event.php', 'Composer\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/EventDispatcher.php', 'Composer\\EventDispatcher\\EventSubscriberInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/EventSubscriberInterface.php', 'Composer\\EventDispatcher\\ScriptExecutionException' => __DIR__ . '/..' . '/composer/composer/src/Composer/EventDispatcher/ScriptExecutionException.php', 'Composer\\Exception\\IrrecoverableDownloadException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Exception/IrrecoverableDownloadException.php', 'Composer\\Exception\\NoSslException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Exception/NoSslException.php', 'Composer\\Factory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Factory.php', 'Composer\\Filter\\PlatformRequirementFilter\\IgnoreAllPlatformRequirementFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreAllPlatformRequirementFilter.php', 'Composer\\Filter\\PlatformRequirementFilter\\IgnoreListPlatformRequirementFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php', 'Composer\\Filter\\PlatformRequirementFilter\\IgnoreNothingPlatformRequirementFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/IgnoreNothingPlatformRequirementFilter.php', 'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterFactory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterFactory.php', 'Composer\\Filter\\PlatformRequirementFilter\\PlatformRequirementFilterInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Filter/PlatformRequirementFilter/PlatformRequirementFilterInterface.php', 'Composer\\IO\\BaseIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/BaseIO.php', 'Composer\\IO\\BufferIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/BufferIO.php', 'Composer\\IO\\ConsoleIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/ConsoleIO.php', 'Composer\\IO\\IOInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/IOInterface.php', 'Composer\\IO\\NullIO' => __DIR__ . '/..' . '/composer/composer/src/Composer/IO/NullIO.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'Composer\\Installer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer.php', 'Composer\\Installer\\BinaryInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/BinaryInstaller.php', 'Composer\\Installer\\BinaryPresenceInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/BinaryPresenceInterface.php', 'Composer\\Installer\\InstallationManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallationManager.php', 'Composer\\Installer\\InstallerEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallerEvent.php', 'Composer\\Installer\\InstallerEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallerEvents.php', 'Composer\\Installer\\InstallerInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/InstallerInterface.php', 'Composer\\Installer\\LibraryInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/LibraryInstaller.php', 'Composer\\Installer\\MetapackageInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/MetapackageInstaller.php', 'Composer\\Installer\\NoopInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/NoopInstaller.php', 'Composer\\Installer\\PackageEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/PackageEvent.php', 'Composer\\Installer\\PackageEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/PackageEvents.php', 'Composer\\Installer\\PluginInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/PluginInstaller.php', 'Composer\\Installer\\ProjectInstaller' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/ProjectInstaller.php', 'Composer\\Installer\\SuggestedPackagesReporter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Installer/SuggestedPackagesReporter.php', 'Composer\\Json\\JsonFile' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonFile.php', 'Composer\\Json\\JsonFormatter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonFormatter.php', 'Composer\\Json\\JsonManipulator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonManipulator.php', 'Composer\\Json\\JsonValidationException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Json/JsonValidationException.php', 'Composer\\MetadataMinifier\\MetadataMinifier' => __DIR__ . '/..' . '/composer/metadata-minifier/src/MetadataMinifier.php', 'Composer\\PHPStan\\ConfigReturnTypeExtension' => __DIR__ . '/..' . '/composer/composer/src/Composer/PHPStan/ConfigReturnTypeExtension.php', 'Composer\\PHPStan\\RuleReasonDataReturnTypeExtension' => __DIR__ . '/..' . '/composer/composer/src/Composer/PHPStan/RuleReasonDataReturnTypeExtension.php', 'Composer\\Package\\AliasPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/AliasPackage.php', 'Composer\\Package\\Archiver\\ArchivableFilesFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFilter.php', 'Composer\\Package\\Archiver\\ArchivableFilesFinder' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchivableFilesFinder.php', 'Composer\\Package\\Archiver\\ArchiveManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchiveManager.php', 'Composer\\Package\\Archiver\\ArchiverInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ArchiverInterface.php', 'Composer\\Package\\Archiver\\BaseExcludeFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/BaseExcludeFilter.php', 'Composer\\Package\\Archiver\\ComposerExcludeFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ComposerExcludeFilter.php', 'Composer\\Package\\Archiver\\GitExcludeFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/GitExcludeFilter.php', 'Composer\\Package\\Archiver\\PharArchiver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/PharArchiver.php', 'Composer\\Package\\Archiver\\ZipArchiver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Archiver/ZipArchiver.php', 'Composer\\Package\\BasePackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/BasePackage.php', 'Composer\\Package\\Comparer\\Comparer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Comparer/Comparer.php', 'Composer\\Package\\CompleteAliasPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/CompleteAliasPackage.php', 'Composer\\Package\\CompletePackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/CompletePackage.php', 'Composer\\Package\\CompletePackageInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/CompletePackageInterface.php', 'Composer\\Package\\Dumper\\ArrayDumper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Dumper/ArrayDumper.php', 'Composer\\Package\\Link' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Link.php', 'Composer\\Package\\Loader\\ArrayLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/ArrayLoader.php', 'Composer\\Package\\Loader\\InvalidPackageException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/InvalidPackageException.php', 'Composer\\Package\\Loader\\JsonLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/JsonLoader.php', 'Composer\\Package\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/LoaderInterface.php', 'Composer\\Package\\Loader\\RootPackageLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/RootPackageLoader.php', 'Composer\\Package\\Loader\\ValidatingArrayLoader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Loader/ValidatingArrayLoader.php', 'Composer\\Package\\Locker' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Locker.php', 'Composer\\Package\\Package' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Package.php', 'Composer\\Package\\PackageInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/PackageInterface.php', 'Composer\\Package\\RootAliasPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/RootAliasPackage.php', 'Composer\\Package\\RootPackage' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/RootPackage.php', 'Composer\\Package\\RootPackageInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/RootPackageInterface.php', 'Composer\\Package\\Version\\StabilityFilter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/StabilityFilter.php', 'Composer\\Package\\Version\\VersionBumper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionBumper.php', 'Composer\\Package\\Version\\VersionGuesser' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionGuesser.php', 'Composer\\Package\\Version\\VersionParser' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionParser.php', 'Composer\\Package\\Version\\VersionSelector' => __DIR__ . '/..' . '/composer/composer/src/Composer/Package/Version/VersionSelector.php', 'Composer\\PartialComposer' => __DIR__ . '/..' . '/composer/composer/src/Composer/PartialComposer.php', 'Composer\\Pcre\\MatchAllResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllResult.php', 'Composer\\Pcre\\MatchAllStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllStrictGroupsResult.php', 'Composer\\Pcre\\MatchAllWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchAllWithOffsetsResult.php', 'Composer\\Pcre\\MatchResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchResult.php', 'Composer\\Pcre\\MatchStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchStrictGroupsResult.php', 'Composer\\Pcre\\MatchWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchWithOffsetsResult.php', 'Composer\\Pcre\\PHPStan\\InvalidRegexPatternRule' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php', 'Composer\\Pcre\\PHPStan\\PregMatchFlags' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchFlags.php', 'Composer\\Pcre\\PHPStan\\PregMatchParameterOutTypeExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php', 'Composer\\Pcre\\PHPStan\\PregMatchTypeSpecifyingExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php', 'Composer\\Pcre\\PHPStan\\PregReplaceCallbackClosureTypeExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.php', 'Composer\\Pcre\\PHPStan\\UnsafeStrictGroupsCallRule' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php', 'Composer\\Pcre\\PcreException' => __DIR__ . '/..' . '/composer/pcre/src/PcreException.php', 'Composer\\Pcre\\Preg' => __DIR__ . '/..' . '/composer/pcre/src/Preg.php', 'Composer\\Pcre\\Regex' => __DIR__ . '/..' . '/composer/pcre/src/Regex.php', 'Composer\\Pcre\\ReplaceResult' => __DIR__ . '/..' . '/composer/pcre/src/ReplaceResult.php', 'Composer\\Pcre\\UnexpectedNullMatchException' => __DIR__ . '/..' . '/composer/pcre/src/UnexpectedNullMatchException.php', 'Composer\\Platform\\HhvmDetector' => __DIR__ . '/..' . '/composer/composer/src/Composer/Platform/HhvmDetector.php', 'Composer\\Platform\\Runtime' => __DIR__ . '/..' . '/composer/composer/src/Composer/Platform/Runtime.php', 'Composer\\Platform\\Version' => __DIR__ . '/..' . '/composer/composer/src/Composer/Platform/Version.php', 'Composer\\Plugin\\Capability\\Capability' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/Capability/Capability.php', 'Composer\\Plugin\\Capability\\CommandProvider' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/Capability/CommandProvider.php', 'Composer\\Plugin\\Capable' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/Capable.php', 'Composer\\Plugin\\CommandEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/CommandEvent.php', 'Composer\\Plugin\\PluginBlockedException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginBlockedException.php', 'Composer\\Plugin\\PluginEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginEvents.php', 'Composer\\Plugin\\PluginInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginInterface.php', 'Composer\\Plugin\\PluginManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PluginManager.php', 'Composer\\Plugin\\PostFileDownloadEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PostFileDownloadEvent.php', 'Composer\\Plugin\\PreCommandRunEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PreCommandRunEvent.php', 'Composer\\Plugin\\PreFileDownloadEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PreFileDownloadEvent.php', 'Composer\\Plugin\\PrePoolCreateEvent' => __DIR__ . '/..' . '/composer/composer/src/Composer/Plugin/PrePoolCreateEvent.php', 'Composer\\Question\\StrictConfirmationQuestion' => __DIR__ . '/..' . '/composer/composer/src/Composer/Question/StrictConfirmationQuestion.php', 'Composer\\Repository\\AdvisoryProviderInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/AdvisoryProviderInterface.php', 'Composer\\Repository\\ArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ArrayRepository.php', 'Composer\\Repository\\ArtifactRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ArtifactRepository.php', 'Composer\\Repository\\CanonicalPackagesTrait' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/CanonicalPackagesTrait.php', 'Composer\\Repository\\ComposerRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ComposerRepository.php', 'Composer\\Repository\\CompositeRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/CompositeRepository.php', 'Composer\\Repository\\ConfigurableRepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/ConfigurableRepositoryInterface.php', 'Composer\\Repository\\FilesystemRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/FilesystemRepository.php', 'Composer\\Repository\\FilterRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/FilterRepository.php', 'Composer\\Repository\\InstalledArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledArrayRepository.php', 'Composer\\Repository\\InstalledFilesystemRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledFilesystemRepository.php', 'Composer\\Repository\\InstalledRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledRepository.php', 'Composer\\Repository\\InstalledRepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InstalledRepositoryInterface.php', 'Composer\\Repository\\InvalidRepositoryException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/InvalidRepositoryException.php', 'Composer\\Repository\\LockArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/LockArrayRepository.php', 'Composer\\Repository\\PackageRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PackageRepository.php', 'Composer\\Repository\\PathRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PathRepository.php', 'Composer\\Repository\\PearRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PearRepository.php', 'Composer\\Repository\\PlatformRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/PlatformRepository.php', 'Composer\\Repository\\RepositoryFactory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryFactory.php', 'Composer\\Repository\\RepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryInterface.php', 'Composer\\Repository\\RepositoryManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryManager.php', 'Composer\\Repository\\RepositorySecurityException' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositorySecurityException.php', 'Composer\\Repository\\RepositorySet' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositorySet.php', 'Composer\\Repository\\RepositoryUtils' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RepositoryUtils.php', 'Composer\\Repository\\RootPackageRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/RootPackageRepository.php', 'Composer\\Repository\\VcsRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/VcsRepository.php', 'Composer\\Repository\\Vcs\\FossilDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/FossilDriver.php', 'Composer\\Repository\\Vcs\\GitBitbucketDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitBitbucketDriver.php', 'Composer\\Repository\\Vcs\\GitDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitDriver.php', 'Composer\\Repository\\Vcs\\GitHubDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitHubDriver.php', 'Composer\\Repository\\Vcs\\GitLabDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/GitLabDriver.php', 'Composer\\Repository\\Vcs\\HgDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/HgDriver.php', 'Composer\\Repository\\Vcs\\PerforceDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/PerforceDriver.php', 'Composer\\Repository\\Vcs\\SvnDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/SvnDriver.php', 'Composer\\Repository\\Vcs\\VcsDriver' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/VcsDriver.php', 'Composer\\Repository\\Vcs\\VcsDriverInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/Vcs/VcsDriverInterface.php', 'Composer\\Repository\\VersionCacheInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/VersionCacheInterface.php', 'Composer\\Repository\\WritableArrayRepository' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/WritableArrayRepository.php', 'Composer\\Repository\\WritableRepositoryInterface' => __DIR__ . '/..' . '/composer/composer/src/Composer/Repository/WritableRepositoryInterface.php', 'Composer\\Script\\Event' => __DIR__ . '/..' . '/composer/composer/src/Composer/Script/Event.php', 'Composer\\Script\\ScriptEvents' => __DIR__ . '/..' . '/composer/composer/src/Composer/Script/ScriptEvents.php', 'Composer\\SelfUpdate\\Keys' => __DIR__ . '/..' . '/composer/composer/src/Composer/SelfUpdate/Keys.php', 'Composer\\SelfUpdate\\Versions' => __DIR__ . '/..' . '/composer/composer/src/Composer/SelfUpdate/Versions.php', 'Composer\\Semver\\Comparator' => __DIR__ . '/..' . '/composer/semver/src/Comparator.php', 'Composer\\Semver\\CompilingMatcher' => __DIR__ . '/..' . '/composer/semver/src/CompilingMatcher.php', 'Composer\\Semver\\Constraint\\Bound' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Bound.php', 'Composer\\Semver\\Constraint\\Constraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Constraint.php', 'Composer\\Semver\\Constraint\\ConstraintInterface' => __DIR__ . '/..' . '/composer/semver/src/Constraint/ConstraintInterface.php', 'Composer\\Semver\\Constraint\\MatchAllConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchAllConstraint.php', 'Composer\\Semver\\Constraint\\MatchNoneConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchNoneConstraint.php', 'Composer\\Semver\\Constraint\\MultiConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MultiConstraint.php', 'Composer\\Semver\\Interval' => __DIR__ . '/..' . '/composer/semver/src/Interval.php', 'Composer\\Semver\\Intervals' => __DIR__ . '/..' . '/composer/semver/src/Intervals.php', 'Composer\\Semver\\Semver' => __DIR__ . '/..' . '/composer/semver/src/Semver.php', 'Composer\\Semver\\VersionParser' => __DIR__ . '/..' . '/composer/semver/src/VersionParser.php', 'Composer\\Spdx\\SpdxLicenses' => __DIR__ . '/..' . '/composer/spdx-licenses/src/SpdxLicenses.php', 'Composer\\Util\\AuthHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/AuthHelper.php', 'Composer\\Util\\Bitbucket' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Bitbucket.php', 'Composer\\Util\\ComposerMirror' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ComposerMirror.php', 'Composer\\Util\\ConfigValidator' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ConfigValidator.php', 'Composer\\Util\\ErrorHandler' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ErrorHandler.php', 'Composer\\Util\\Filesystem' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Filesystem.php', 'Composer\\Util\\Git' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Git.php', 'Composer\\Util\\GitHub' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/GitHub.php', 'Composer\\Util\\GitLab' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/GitLab.php', 'Composer\\Util\\Hg' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Hg.php', 'Composer\\Util\\HttpDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/HttpDownloader.php', 'Composer\\Util\\Http\\CurlDownloader' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/CurlDownloader.php', 'Composer\\Util\\Http\\CurlResponse' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/CurlResponse.php', 'Composer\\Util\\Http\\ProxyItem' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/ProxyItem.php', 'Composer\\Util\\Http\\ProxyManager' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/ProxyManager.php', 'Composer\\Util\\Http\\RequestProxy' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/RequestProxy.php', 'Composer\\Util\\Http\\Response' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Http/Response.php', 'Composer\\Util\\IniHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/IniHelper.php', 'Composer\\Util\\Loop' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Loop.php', 'Composer\\Util\\MetadataMinifier' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/MetadataMinifier.php', 'Composer\\Util\\NoProxyPattern' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/NoProxyPattern.php', 'Composer\\Util\\PackageInfo' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/PackageInfo.php', 'Composer\\Util\\PackageSorter' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/PackageSorter.php', 'Composer\\Util\\Perforce' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Perforce.php', 'Composer\\Util\\Platform' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Platform.php', 'Composer\\Util\\ProcessExecutor' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/ProcessExecutor.php', 'Composer\\Util\\RemoteFilesystem' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/RemoteFilesystem.php', 'Composer\\Util\\Silencer' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Silencer.php', 'Composer\\Util\\StreamContextFactory' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/StreamContextFactory.php', 'Composer\\Util\\Svn' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Svn.php', 'Composer\\Util\\SyncHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/SyncHelper.php', 'Composer\\Util\\Tar' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Tar.php', 'Composer\\Util\\TlsHelper' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/TlsHelper.php', 'Composer\\Util\\Url' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Url.php', 'Composer\\Util\\Zip' => __DIR__ . '/..' . '/composer/composer/src/Composer/Util/Zip.php', 'Composer\\XdebugHandler\\PhpConfig' => __DIR__ . '/..' . '/composer/xdebug-handler/src/PhpConfig.php', 'Composer\\XdebugHandler\\Process' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Process.php', 'Composer\\XdebugHandler\\Status' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Status.php', 'Composer\\XdebugHandler\\XdebugHandler' => __DIR__ . '/..' . '/composer/xdebug-handler/src/XdebugHandler.php', 'DateError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateError.php', 'DateException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateException.php', 'DateInvalidOperationException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php', 'DateInvalidTimeZoneException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php', 'DateMalformedIntervalStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php', 'DateMalformedPeriodStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php', 'DateMalformedStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php', 'DateObjectError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php', 'DateRangeError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php', 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'Override' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/Override.php', 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'React\\Promise\\Deferred' => __DIR__ . '/..' . '/react/promise/src/Deferred.php', 'React\\Promise\\Exception\\CompositeException' => __DIR__ . '/..' . '/react/promise/src/Exception/CompositeException.php', 'React\\Promise\\Exception\\LengthException' => __DIR__ . '/..' . '/react/promise/src/Exception/LengthException.php', 'React\\Promise\\Internal\\CancellationQueue' => __DIR__ . '/..' . '/react/promise/src/Internal/CancellationQueue.php', 'React\\Promise\\Internal\\FulfilledPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/FulfilledPromise.php', 'React\\Promise\\Internal\\RejectedPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/RejectedPromise.php', 'React\\Promise\\Promise' => __DIR__ . '/..' . '/react/promise/src/Promise.php', 'React\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/react/promise/src/PromiseInterface.php', 'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php', 'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/Grapheme.php', 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php73\\Php73' => __DIR__ . '/..' . '/symfony/polyfill-php73/Php73.php', 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', 'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php81\\Php81' => __DIR__ . '/..' . '/symfony/polyfill-php81/Php81.php', 'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php', 'Symfony\\Polyfill\\Uuid\\Uuid' => __DIR__ . '/..' . '/symfony/polyfill-uuid/Uuid.php', 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', '_ContaoManager\\Brick\\Math\\BigDecimal' => __DIR__ . '/..' . '/brick/math/src/BigDecimal.php', '_ContaoManager\\Brick\\Math\\BigInteger' => __DIR__ . '/..' . '/brick/math/src/BigInteger.php', '_ContaoManager\\Brick\\Math\\BigNumber' => __DIR__ . '/..' . '/brick/math/src/BigNumber.php', '_ContaoManager\\Brick\\Math\\BigRational' => __DIR__ . '/..' . '/brick/math/src/BigRational.php', '_ContaoManager\\Brick\\Math\\Exception\\DivisionByZeroException' => __DIR__ . '/..' . '/brick/math/src/Exception/DivisionByZeroException.php', '_ContaoManager\\Brick\\Math\\Exception\\IntegerOverflowException' => __DIR__ . '/..' . '/brick/math/src/Exception/IntegerOverflowException.php', '_ContaoManager\\Brick\\Math\\Exception\\MathException' => __DIR__ . '/..' . '/brick/math/src/Exception/MathException.php', '_ContaoManager\\Brick\\Math\\Exception\\NegativeNumberException' => __DIR__ . '/..' . '/brick/math/src/Exception/NegativeNumberException.php', '_ContaoManager\\Brick\\Math\\Exception\\NumberFormatException' => __DIR__ . '/..' . '/brick/math/src/Exception/NumberFormatException.php', '_ContaoManager\\Brick\\Math\\Exception\\RoundingNecessaryException' => __DIR__ . '/..' . '/brick/math/src/Exception/RoundingNecessaryException.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\BcMathCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/BcMathCalculator.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\GmpCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/GmpCalculator.php', '_ContaoManager\\Brick\\Math\\Internal\\Calculator\\NativeCalculator' => __DIR__ . '/..' . '/brick/math/src/Internal/Calculator/NativeCalculator.php', '_ContaoManager\\Brick\\Math\\RoundingMode' => __DIR__ . '/..' . '/brick/math/src/RoundingMode.php', '_ContaoManager\\CBOR\\AbstractCBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/AbstractCBORObject.php', '_ContaoManager\\CBOR\\ByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ByteStringObject.php', '_ContaoManager\\CBOR\\CBORObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/CBORObject.php', '_ContaoManager\\CBOR\\Decoder' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Decoder.php', '_ContaoManager\\CBOR\\DecoderInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/DecoderInterface.php', '_ContaoManager\\CBOR\\IndefiniteLengthByteStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthByteStringObject.php', '_ContaoManager\\CBOR\\IndefiniteLengthListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthListObject.php', '_ContaoManager\\CBOR\\IndefiniteLengthMapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthMapObject.php', '_ContaoManager\\CBOR\\IndefiniteLengthTextStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/IndefiniteLengthTextStringObject.php', '_ContaoManager\\CBOR\\LengthCalculator' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/LengthCalculator.php', '_ContaoManager\\CBOR\\ListObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/ListObject.php', '_ContaoManager\\CBOR\\MapItem' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/MapItem.php', '_ContaoManager\\CBOR\\MapObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/MapObject.php', '_ContaoManager\\CBOR\\NegativeIntegerObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/NegativeIntegerObject.php', '_ContaoManager\\CBOR\\Normalizable' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Normalizable.php', '_ContaoManager\\CBOR\\OtherObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject.php', '_ContaoManager\\CBOR\\OtherObject\\BreakObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/BreakObject.php', '_ContaoManager\\CBOR\\OtherObject\\DoublePrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/DoublePrecisionFloatObject.php', '_ContaoManager\\CBOR\\OtherObject\\FalseObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/FalseObject.php', '_ContaoManager\\CBOR\\OtherObject\\GenericObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/GenericObject.php', '_ContaoManager\\CBOR\\OtherObject\\HalfPrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/HalfPrecisionFloatObject.php', '_ContaoManager\\CBOR\\OtherObject\\NullObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/NullObject.php', '_ContaoManager\\CBOR\\OtherObject\\OtherObjectInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectInterface.php', '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManager.php', '_ContaoManager\\CBOR\\OtherObject\\OtherObjectManagerInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/OtherObjectManagerInterface.php', '_ContaoManager\\CBOR\\OtherObject\\SimpleObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/SimpleObject.php', '_ContaoManager\\CBOR\\OtherObject\\SinglePrecisionFloatObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/SinglePrecisionFloatObject.php', '_ContaoManager\\CBOR\\OtherObject\\TrueObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/TrueObject.php', '_ContaoManager\\CBOR\\OtherObject\\UndefinedObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/OtherObject/UndefinedObject.php', '_ContaoManager\\CBOR\\Stream' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Stream.php', '_ContaoManager\\CBOR\\StringStream' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/StringStream.php', '_ContaoManager\\CBOR\\Tag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag.php', '_ContaoManager\\CBOR\\Tag\\Base16EncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base16EncodingTag.php', '_ContaoManager\\CBOR\\Tag\\Base64EncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64EncodingTag.php', '_ContaoManager\\CBOR\\Tag\\Base64Tag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64Tag.php', '_ContaoManager\\CBOR\\Tag\\Base64UrlEncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64UrlEncodingTag.php', '_ContaoManager\\CBOR\\Tag\\Base64UrlTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/Base64UrlTag.php', '_ContaoManager\\CBOR\\Tag\\BigFloatTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/BigFloatTag.php', '_ContaoManager\\CBOR\\Tag\\CBOREncodingTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/CBOREncodingTag.php', '_ContaoManager\\CBOR\\Tag\\CBORTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/CBORTag.php', '_ContaoManager\\CBOR\\Tag\\DatetimeTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/DatetimeTag.php', '_ContaoManager\\CBOR\\Tag\\DecimalFractionTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/DecimalFractionTag.php', '_ContaoManager\\CBOR\\Tag\\GenericTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/GenericTag.php', '_ContaoManager\\CBOR\\Tag\\MimeTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/MimeTag.php', '_ContaoManager\\CBOR\\Tag\\NegativeBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/NegativeBigIntegerTag.php', '_ContaoManager\\CBOR\\Tag\\TagInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagInterface.php', '_ContaoManager\\CBOR\\Tag\\TagManager' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManager.php', '_ContaoManager\\CBOR\\Tag\\TagManagerInterface' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TagManagerInterface.php', '_ContaoManager\\CBOR\\Tag\\TimestampTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/TimestampTag.php', '_ContaoManager\\CBOR\\Tag\\UnsignedBigIntegerTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/UnsignedBigIntegerTag.php', '_ContaoManager\\CBOR\\Tag\\UriTag' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Tag/UriTag.php', '_ContaoManager\\CBOR\\TextStringObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/TextStringObject.php', '_ContaoManager\\CBOR\\UnsignedIntegerObject' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/UnsignedIntegerObject.php', '_ContaoManager\\CBOR\\Utils' => __DIR__ . '/..' . '/spomky-labs/cbor-php/src/Utils.php', '_ContaoManager\\Contao\\ManagerApi\\ApiApplication' => __DIR__ . '/../..' . '/api/ApiApplication.php', '_ContaoManager\\Contao\\ManagerApi\\ApiKernel' => __DIR__ . '/../..' . '/api/ApiKernel.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\AboutCommand' => __DIR__ . '/../..' . '/api/Command/AboutCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\IntegrityCheckCommand' => __DIR__ . '/../..' . '/api/Command/IntegrityCheckCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\ProcessRunnerCommand' => __DIR__ . '/../..' . '/api/Command/ProcessRunnerCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskAbortCommand' => __DIR__ . '/../..' . '/api/Command/TaskAbortCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskDeleteCommand' => __DIR__ . '/../..' . '/api/Command/TaskDeleteCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\TaskUpdateCommand' => __DIR__ . '/../..' . '/api/Command/TaskUpdateCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Command\\UpdateCommand' => __DIR__ . '/../..' . '/api/Command/UpdateCommand.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudChanges' => __DIR__ . '/../..' . '/api/Composer/CloudChanges.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudException' => __DIR__ . '/../..' . '/api/Composer/CloudException.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudJob' => __DIR__ . '/../..' . '/api/Composer/CloudJob.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\CloudResolver' => __DIR__ . '/../..' . '/api/Composer/CloudResolver.php', '_ContaoManager\\Contao\\ManagerApi\\Composer\\Environment' => __DIR__ . '/../..' . '/api/Composer/Environment.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\AbstractConfig' => __DIR__ . '/../..' . '/api/Config/AbstractConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\AuthConfig' => __DIR__ . '/../..' . '/api/Config/AuthConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\ComposerConfig' => __DIR__ . '/../..' . '/api/Config/ComposerConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\ManagerConfig' => __DIR__ . '/../..' . '/api/Config/ManagerConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\PartialConfig' => __DIR__ . '/../..' . '/api/Config/PartialConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\UploadsConfig' => __DIR__ . '/../..' . '/api/Config/UploadsConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Config\\UserConfig' => __DIR__ . '/../..' . '/api/Config/UserConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AbstractConfigController' => __DIR__ . '/../..' . '/api/Controller/Config/AbstractConfigController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\AuthController' => __DIR__ . '/../..' . '/api/Controller/Config/AuthController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ComposerController' => __DIR__ . '/../..' . '/api/Controller/Config/ComposerController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Config\\ManagerController' => __DIR__ . '/../..' . '/api/Controller/Config/ManagerController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\ConstraintController' => __DIR__ . '/../..' . '/api/Controller/ConstraintController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\AccessKeyController' => __DIR__ . '/../..' . '/api/Controller/Contao/AccessKeyController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\BackupController' => __DIR__ . '/../..' . '/api/Controller/Contao/BackupController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\DatabaseMigrationController' => __DIR__ . '/../..' . '/api/Controller/Contao/DatabaseMigrationController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\InstallToolLockController' => __DIR__ . '/../..' . '/api/Controller/Contao/InstallToolLockController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\JwtCookieController' => __DIR__ . '/../..' . '/api/Controller/Contao/JwtCookieController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Contao\\MaintenanceModeController' => __DIR__ . '/../..' . '/api/Controller/Contao/MaintenanceModeController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\FileController' => __DIR__ . '/../..' . '/api/Controller/FileController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\LogController' => __DIR__ . '/../..' . '/api/Controller/LogController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\CloudController' => __DIR__ . '/../..' . '/api/Controller/Packages/CloudController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\LocalPackagesController' => __DIR__ . '/../..' . '/api/Controller/Packages/LocalPackagesController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\MissingPackagesController' => __DIR__ . '/../..' . '/api/Controller/Packages/MissingPackagesController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\RootPackageController' => __DIR__ . '/../..' . '/api/Controller/Packages/RootPackageController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Packages\\UploadPackagesController' => __DIR__ . '/../..' . '/api/Controller/Packages/UploadPackagesController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\AdminUserController' => __DIR__ . '/../..' . '/api/Controller/Server/AdminUserController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ComposerController' => __DIR__ . '/../..' . '/api/Controller/Server/ComposerController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ConfigController' => __DIR__ . '/../..' . '/api/Controller/Server/ConfigController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\ContaoController' => __DIR__ . '/../..' . '/api/Controller/Server/ContaoController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\DatabaseController' => __DIR__ . '/../..' . '/api/Controller/Server/DatabaseController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\OpcacheController' => __DIR__ . '/../..' . '/api/Controller/Server/OpcacheController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpCliController' => __DIR__ . '/../..' . '/api/Controller/Server/PhpCliController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpWebController' => __DIR__ . '/../..' . '/api/Controller/Server/PhpWebController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\PhpinfoController' => __DIR__ . '/../..' . '/api/Controller/Server/PhpinfoController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\Server\\SelfUpdateController' => __DIR__ . '/../..' . '/api/Controller/Server/SelfUpdateController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\SessionController' => __DIR__ . '/../..' . '/api/Controller/SessionController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\TaskController' => __DIR__ . '/../..' . '/api/Controller/TaskController.php', '_ContaoManager\\Contao\\ManagerApi\\Controller\\UserController' => __DIR__ . '/../..' . '/api/Controller/UserController.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\CheckTotpListener' => __DIR__ . '/../..' . '/api/EventListener/CheckTotpListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\ExceptionListener' => __DIR__ . '/../..' . '/api/EventListener/ExceptionListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\JsonRequestListener' => __DIR__ . '/../..' . '/api/EventListener/JsonRequestListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\LocaleListener' => __DIR__ . '/../..' . '/api/EventListener/LocaleListener.php', '_ContaoManager\\Contao\\ManagerApi\\EventListener\\SecurityListener' => __DIR__ . '/../..' . '/api/EventListener/SecurityListener.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\ApiProblemException' => __DIR__ . '/../..' . '/api/Exception/ApiProblemException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidJsonException' => __DIR__ . '/../..' . '/api/Exception/InvalidJsonException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\InvalidTotpException' => __DIR__ . '/../..' . '/api/Exception/InvalidTotpException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\ProcessOutputException' => __DIR__ . '/../..' . '/api/Exception/ProcessOutputException.php', '_ContaoManager\\Contao\\ManagerApi\\Exception\\RequestException' => __DIR__ . '/../..' . '/api/Exception/RequestException.php', '_ContaoManager\\Contao\\ManagerApi\\HttpKernel\\ApiProblemResponse' => __DIR__ . '/../..' . '/api/HttpKernel/ApiProblemResponse.php', '_ContaoManager\\Contao\\ManagerApi\\I18n\\Translator' => __DIR__ . '/../..' . '/api/I18n/Translator.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AbstractIntegrityCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/AbstractIntegrityCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\AllowUrlFopenCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/AllowUrlFopenCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\GraphicsLibCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/GraphicsLibCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckFactory' => __DIR__ . '/../..' . '/api/IntegrityCheck/IntegrityCheckFactory.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\IntegrityCheckInterface' => __DIR__ . '/../..' . '/api/IntegrityCheck/IntegrityCheckInterface.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\MemoryLimitCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/MemoryLimitCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\PhpExtensionsCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/PhpExtensionsCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ProcessCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/ProcessCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SessionCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/SessionCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SymlinkCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/SymlinkCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\SysTempDirCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/SysTempDirCheck.php', '_ContaoManager\\Contao\\ManagerApi\\IntegrityCheck\\ZipCheck' => __DIR__ . '/../..' . '/api/IntegrityCheck/ZipCheck.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\AbstractProcess' => __DIR__ . '/../..' . '/api/Process/AbstractProcess.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ConsoleProcessFactory' => __DIR__ . '/../..' . '/api/Process/ConsoleProcessFactory.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoApi' => __DIR__ . '/../..' . '/api/Process/ContaoApi.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ContaoConsole' => __DIR__ . '/../..' . '/api/Process/ContaoConsole.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\AbstractForker' => __DIR__ . '/../..' . '/api/Process/Forker/AbstractForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\DisownForker' => __DIR__ . '/../..' . '/api/Process/Forker/DisownForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\ForkerInterface' => __DIR__ . '/../..' . '/api/Process/Forker/ForkerInterface.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\InlineForker' => __DIR__ . '/../..' . '/api/Process/Forker/InlineForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\NohupForker' => __DIR__ . '/../..' . '/api/Process/Forker/NohupForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Forker\\WindowsStartForker' => __DIR__ . '/../..' . '/api/Process/Forker/WindowsStartForker.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\PhpExecutableFinder' => __DIR__ . '/../..' . '/api/Process/PhpExecutableFinder.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessController' => __DIR__ . '/../..' . '/api/Process/ProcessController.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\ProcessRunner' => __DIR__ . '/../..' . '/api/Process/ProcessRunner.php', '_ContaoManager\\Contao\\ManagerApi\\Process\\Utf8Process' => __DIR__ . '/../..' . '/api/Process/Utf8Process.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\AbstractBrowserAuthenticator' => __DIR__ . '/../..' . '/api/Security/AbstractBrowserAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtAuthenticator' => __DIR__ . '/../..' . '/api/Security/JwtAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\JwtManager' => __DIR__ . '/../..' . '/api/Security/JwtManager.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\LoginAuthenticator' => __DIR__ . '/../..' . '/api/Security/LoginAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\PasswordlessAuthenticator' => __DIR__ . '/../..' . '/api/Security/PasswordlessAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\TokenAuthenticator' => __DIR__ . '/../..' . '/api/Security/TokenAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\TotpBadge' => __DIR__ . '/../..' . '/api/Security/TotpBadge.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\User' => __DIR__ . '/../..' . '/api/Security/User.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\UserProvider' => __DIR__ . '/../..' . '/api/Security/UserProvider.php', '_ContaoManager\\Contao\\ManagerApi\\Security\\WebauthnAuthenticator' => __DIR__ . '/../..' . '/api/Security/WebauthnAuthenticator.php', '_ContaoManager\\Contao\\ManagerApi\\System\\Request' => __DIR__ . '/../..' . '/api/System/Request.php', '_ContaoManager\\Contao\\ManagerApi\\System\\SelfUpdate' => __DIR__ . '/../..' . '/api/System/SelfUpdate.php', '_ContaoManager\\Contao\\ManagerApi\\System\\ServerInfo' => __DIR__ . '/../..' . '/api/System/ServerInfo.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractInlineOperation' => __DIR__ . '/../..' . '/api/TaskOperation/AbstractInlineOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\AbstractProcessOperation' => __DIR__ . '/../..' . '/api/TaskOperation/AbstractProcessOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\ClearCacheOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/ClearCacheOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CloudOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/CloudOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\CreateProjectOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/CreateProjectOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\DumpAutoloadOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/DumpAutoloadOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\InstallOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/InstallOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RemoveOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/RemoveOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\RequireOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/RequireOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Composer\\UpdateOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Composer/UpdateOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\ConsoleOutput' => __DIR__ . '/../..' . '/api/TaskOperation/ConsoleOutput.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupCreateOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/BackupCreateOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\BackupRestoreOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/BackupRestoreOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheClearOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/CacheClearOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CacheWarmupOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/CacheWarmupOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\CreateContaoOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/CreateContaoOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Contao\\MaintenanceModeOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Contao/MaintenanceModeOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\InstallUploadsOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/InstallUploadsOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveCacheOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/RemoveCacheOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveUploadsOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/RemoveUploadsOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Filesystem\\RemoveVendorOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Filesystem/RemoveVendorOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\Manager\\SelfUpdateOperation' => __DIR__ . '/../..' . '/api/TaskOperation/Manager/SelfUpdateOperation.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\SponsoredOperationInterface' => __DIR__ . '/../..' . '/api/TaskOperation/SponsoredOperationInterface.php', '_ContaoManager\\Contao\\ManagerApi\\TaskOperation\\TaskOperationInterface' => __DIR__ . '/../..' . '/api/TaskOperation/TaskOperationInterface.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\AbstractTask' => __DIR__ . '/../..' . '/api/Task/AbstractTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\ClearCacheTask' => __DIR__ . '/../..' . '/api/Task/Composer/ClearCacheTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Composer\\DumpAutoloadTask' => __DIR__ . '/../..' . '/api/Task/Composer/DumpAutoloadTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupCreateTask' => __DIR__ . '/../..' . '/api/Task/Contao/BackupCreateTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\BackupRestoreTask' => __DIR__ . '/../..' . '/api/Task/Contao/BackupRestoreTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Contao\\RebuildCacheTask' => __DIR__ . '/../..' . '/api/Task/Contao/RebuildCacheTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Manager\\SelfUpdateTask' => __DIR__ . '/../..' . '/api/Task/Manager/SelfUpdateTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\AbstractPackagesTask' => __DIR__ . '/../..' . '/api/Task/Packages/AbstractPackagesTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\InstallTask' => __DIR__ . '/../..' . '/api/Task/Packages/InstallTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\SetupTask' => __DIR__ . '/../..' . '/api/Task/Packages/SetupTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\Packages\\UpdateTask' => __DIR__ . '/../..' . '/api/Task/Packages/UpdateTask.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskConfig' => __DIR__ . '/../..' . '/api/Task/TaskConfig.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskInterface' => __DIR__ . '/../..' . '/api/Task/TaskInterface.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskManager' => __DIR__ . '/../..' . '/api/Task/TaskManager.php', '_ContaoManager\\Contao\\ManagerApi\\Task\\TaskStatus' => __DIR__ . '/../..' . '/api/Task/TaskStatus.php', '_ContaoManager\\Contao\\ManagerApi\\Tests\\Composer\\CloudJobTest' => __DIR__ . '/../..' . '/api/Tests/Composer/CloudJobTest.php', '_ContaoManager\\Contao\\ManagerApi\\Tests\\Controller\\LogPatternTest' => __DIR__ . '/../..' . '/api/Tests/Controller/LogPatternTest.php', '_ContaoManager\\Cose\\Algorithm\\Algorithm' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Algorithm.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS256.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS256Truncated64' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS256Truncated64.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS384.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\HS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/HS512.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\Hmac' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/Hmac.php', '_ContaoManager\\Cose\\Algorithm\\Mac\\Mac' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Mac/Mac.php', '_ContaoManager\\Cose\\Algorithm\\Manager' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Manager.php', '_ContaoManager\\Cose\\Algorithm\\ManagerFactory' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/ManagerFactory.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECDSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECDSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ECSignature' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ECSignature.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES256K' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES256K.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES384.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\ECDSA\\ES512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/ECDSA/ES512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed25519' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed25519.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\Ed512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\EdDSA\\EdDSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/EdDSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS384.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PS512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\PSSRSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/PSSRSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS1' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS1.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS256' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS256.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS384' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS384.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RS512' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RS512.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\RSA\\RSA' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/RSA/RSA.php', '_ContaoManager\\Cose\\Algorithm\\Signature\\Signature' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithm/Signature/Signature.php', '_ContaoManager\\Cose\\Algorithms' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Algorithms.php', '_ContaoManager\\Cose\\BigInteger' => __DIR__ . '/..' . '/web-auth/cose-lib/src/BigInteger.php', '_ContaoManager\\Cose\\Hash' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Hash.php', '_ContaoManager\\Cose\\Key\\Ec2Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Ec2Key.php', '_ContaoManager\\Cose\\Key\\Key' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/Key.php', '_ContaoManager\\Cose\\Key\\OkpKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/OkpKey.php', '_ContaoManager\\Cose\\Key\\RsaKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/RsaKey.php', '_ContaoManager\\Cose\\Key\\SymmetricKey' => __DIR__ . '/..' . '/web-auth/cose-lib/src/Key/SymmetricKey.php', '_ContaoManager\\Crell\\ApiProblem\\ApiProblem' => __DIR__ . '/..' . '/crell/api-problem/src/ApiProblem.php', '_ContaoManager\\Crell\\ApiProblem\\HttpConverter' => __DIR__ . '/..' . '/crell/api-problem/src/HttpConverter.php', '_ContaoManager\\Crell\\ApiProblem\\JsonEncodeException' => __DIR__ . '/..' . '/crell/api-problem/src/JsonEncodeException.php', '_ContaoManager\\Crell\\ApiProblem\\JsonException' => __DIR__ . '/..' . '/crell/api-problem/src/JsonException.php', '_ContaoManager\\Crell\\ApiProblem\\JsonParseException' => __DIR__ . '/..' . '/crell/api-problem/src/JsonParseException.php', '_ContaoManager\\Doctrine\\Deprecations\\Deprecation' => __DIR__ . '/..' . '/doctrine/deprecations/src/Deprecation.php', '_ContaoManager\\Doctrine\\Deprecations\\PHPUnit\\VerifyDeprecations' => __DIR__ . '/..' . '/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php', '_ContaoManager\\Firebase\\JWT\\BeforeValidException' => __DIR__ . '/..' . '/firebase/php-jwt/src/BeforeValidException.php', '_ContaoManager\\Firebase\\JWT\\CachedKeySet' => __DIR__ . '/..' . '/firebase/php-jwt/src/CachedKeySet.php', '_ContaoManager\\Firebase\\JWT\\ExpiredException' => __DIR__ . '/..' . '/firebase/php-jwt/src/ExpiredException.php', '_ContaoManager\\Firebase\\JWT\\JWK' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWK.php', '_ContaoManager\\Firebase\\JWT\\JWT' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWT.php', '_ContaoManager\\Firebase\\JWT\\JWTExceptionWithPayloadInterface' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php', '_ContaoManager\\Firebase\\JWT\\Key' => __DIR__ . '/..' . '/firebase/php-jwt/src/Key.php', '_ContaoManager\\Firebase\\JWT\\SignatureInvalidException' => __DIR__ . '/..' . '/firebase/php-jwt/src/SignatureInvalidException.php', '_ContaoManager\\JsonSchema\\Constraints\\BaseConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\CollectionConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\Constraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php', '_ContaoManager\\JsonSchema\\Constraints\\ConstraintInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php', '_ContaoManager\\JsonSchema\\Constraints\\EnumConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\Factory' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php', '_ContaoManager\\JsonSchema\\Constraints\\FormatConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\NumberConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\ObjectConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\SchemaConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\StringConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\LooseTypeCheck' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\StrictTypeCheck' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeCheck\\TypeCheckInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php', '_ContaoManager\\JsonSchema\\Constraints\\TypeConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php', '_ContaoManager\\JsonSchema\\Constraints\\UndefinedConstraint' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php', '_ContaoManager\\JsonSchema\\Entity\\JsonPointer' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php', '_ContaoManager\\JsonSchema\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidConfigException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidSchemaMediaTypeException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php', '_ContaoManager\\JsonSchema\\Exception\\InvalidSourceUriException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php', '_ContaoManager\\JsonSchema\\Exception\\JsonDecodingException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php', '_ContaoManager\\JsonSchema\\Exception\\ResourceNotFoundException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php', '_ContaoManager\\JsonSchema\\Exception\\RuntimeException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php', '_ContaoManager\\JsonSchema\\Exception\\UnresolvableJsonPointerException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php', '_ContaoManager\\JsonSchema\\Exception\\UriResolverException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php', '_ContaoManager\\JsonSchema\\Exception\\ValidationException' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.php', '_ContaoManager\\JsonSchema\\Iterator\\ObjectIterator' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php', '_ContaoManager\\JsonSchema\\Rfc3339' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php', '_ContaoManager\\JsonSchema\\SchemaStorage' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php', '_ContaoManager\\JsonSchema\\SchemaStorageInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php', '_ContaoManager\\JsonSchema\\UriResolverInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php', '_ContaoManager\\JsonSchema\\UriRetrieverInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\AbstractRetriever' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\Curl' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\FileGetContents' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\PredefinedArray' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php', '_ContaoManager\\JsonSchema\\Uri\\Retrievers\\UriRetrieverInterface' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php', '_ContaoManager\\JsonSchema\\Uri\\UriResolver' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php', '_ContaoManager\\JsonSchema\\Uri\\UriRetriever' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php', '_ContaoManager\\JsonSchema\\Validator' => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema/Validator.php', '_ContaoManager\\Lcobucci\\Clock\\Clock' => __DIR__ . '/..' . '/lcobucci/clock/src/Clock.php', '_ContaoManager\\Lcobucci\\Clock\\FrozenClock' => __DIR__ . '/..' . '/lcobucci/clock/src/FrozenClock.php', '_ContaoManager\\Lcobucci\\Clock\\SystemClock' => __DIR__ . '/..' . '/lcobucci/clock/src/SystemClock.php', '_ContaoManager\\Monolog\\Attribute\\AsMonologProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php', '_ContaoManager\\Monolog\\Attribute\\WithMonologChannel' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Attribute/WithMonologChannel.php', '_ContaoManager\\Monolog\\DateTimeImmutable' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/DateTimeImmutable.php', '_ContaoManager\\Monolog\\ErrorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/ErrorHandler.php', '_ContaoManager\\Monolog\\Formatter\\ChromePHPFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php', '_ContaoManager\\Monolog\\Formatter\\ElasticaFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php', '_ContaoManager\\Monolog\\Formatter\\ElasticsearchFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php', '_ContaoManager\\Monolog\\Formatter\\FlowdockFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php', '_ContaoManager\\Monolog\\Formatter\\FluentdFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php', '_ContaoManager\\Monolog\\Formatter\\FormatterInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php', '_ContaoManager\\Monolog\\Formatter\\GelfMessageFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php', '_ContaoManager\\Monolog\\Formatter\\GoogleCloudLoggingFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php', '_ContaoManager\\Monolog\\Formatter\\HtmlFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php', '_ContaoManager\\Monolog\\Formatter\\JsonFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LineFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LogglyFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LogmaticFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php', '_ContaoManager\\Monolog\\Formatter\\LogstashFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php', '_ContaoManager\\Monolog\\Formatter\\MongoDBFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php', '_ContaoManager\\Monolog\\Formatter\\NormalizerFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php', '_ContaoManager\\Monolog\\Formatter\\ScalarFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php', '_ContaoManager\\Monolog\\Formatter\\SyslogFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php', '_ContaoManager\\Monolog\\Formatter\\WildfireFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php', '_ContaoManager\\Monolog\\Handler\\AbstractHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php', '_ContaoManager\\Monolog\\Handler\\AbstractProcessingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php', '_ContaoManager\\Monolog\\Handler\\AbstractSyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php', '_ContaoManager\\Monolog\\Handler\\AmqpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php', '_ContaoManager\\Monolog\\Handler\\BrowserConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php', '_ContaoManager\\Monolog\\Handler\\BufferHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php', '_ContaoManager\\Monolog\\Handler\\ChromePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php', '_ContaoManager\\Monolog\\Handler\\CouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php', '_ContaoManager\\Monolog\\Handler\\CubeHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php', '_ContaoManager\\Monolog\\Handler\\Curl\\Util' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php', '_ContaoManager\\Monolog\\Handler\\DeduplicationHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php', '_ContaoManager\\Monolog\\Handler\\DoctrineCouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php', '_ContaoManager\\Monolog\\Handler\\DynamoDbHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php', '_ContaoManager\\Monolog\\Handler\\ElasticaHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php', '_ContaoManager\\Monolog\\Handler\\ElasticsearchHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php', '_ContaoManager\\Monolog\\Handler\\ErrorLogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php', '_ContaoManager\\Monolog\\Handler\\FallbackGroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php', '_ContaoManager\\Monolog\\Handler\\FilterHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossedHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php', '_ContaoManager\\Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php', '_ContaoManager\\Monolog\\Handler\\FirePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php', '_ContaoManager\\Monolog\\Handler\\FleepHookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php', '_ContaoManager\\Monolog\\Handler\\FlowdockHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php', '_ContaoManager\\Monolog\\Handler\\FormattableHandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php', '_ContaoManager\\Monolog\\Handler\\FormattableHandlerTrait' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php', '_ContaoManager\\Monolog\\Handler\\GelfHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php', '_ContaoManager\\Monolog\\Handler\\GroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php', '_ContaoManager\\Monolog\\Handler\\Handler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Handler.php', '_ContaoManager\\Monolog\\Handler\\HandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php', '_ContaoManager\\Monolog\\Handler\\HandlerWrapper' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php', '_ContaoManager\\Monolog\\Handler\\IFTTTHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php', '_ContaoManager\\Monolog\\Handler\\InsightOpsHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php', '_ContaoManager\\Monolog\\Handler\\LogEntriesHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php', '_ContaoManager\\Monolog\\Handler\\LogglyHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php', '_ContaoManager\\Monolog\\Handler\\LogmaticHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php', '_ContaoManager\\Monolog\\Handler\\MailHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MailHandler.php', '_ContaoManager\\Monolog\\Handler\\MandrillHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php', '_ContaoManager\\Monolog\\Handler\\MissingExtensionException' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php', '_ContaoManager\\Monolog\\Handler\\MongoDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php', '_ContaoManager\\Monolog\\Handler\\NativeMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php', '_ContaoManager\\Monolog\\Handler\\NewRelicHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php', '_ContaoManager\\Monolog\\Handler\\NoopHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NoopHandler.php', '_ContaoManager\\Monolog\\Handler\\NullHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NullHandler.php', '_ContaoManager\\Monolog\\Handler\\OverflowHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/OverflowHandler.php', '_ContaoManager\\Monolog\\Handler\\PHPConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php', '_ContaoManager\\Monolog\\Handler\\ProcessHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ProcessHandler.php', '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php', '_ContaoManager\\Monolog\\Handler\\ProcessableHandlerTrait' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php', '_ContaoManager\\Monolog\\Handler\\PsrHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php', '_ContaoManager\\Monolog\\Handler\\PushoverHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php', '_ContaoManager\\Monolog\\Handler\\RedisHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php', '_ContaoManager\\Monolog\\Handler\\RedisPubSubHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php', '_ContaoManager\\Monolog\\Handler\\RollbarHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php', '_ContaoManager\\Monolog\\Handler\\RotatingFileHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php', '_ContaoManager\\Monolog\\Handler\\SamplingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php', '_ContaoManager\\Monolog\\Handler\\SendGridHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SendGridHandler.php', '_ContaoManager\\Monolog\\Handler\\SlackHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php', '_ContaoManager\\Monolog\\Handler\\SlackWebhookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php', '_ContaoManager\\Monolog\\Handler\\Slack\\SlackRecord' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php', '_ContaoManager\\Monolog\\Handler\\SocketHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php', '_ContaoManager\\Monolog\\Handler\\SqsHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php', '_ContaoManager\\Monolog\\Handler\\StreamHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php', '_ContaoManager\\Monolog\\Handler\\SymfonyMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php', '_ContaoManager\\Monolog\\Handler\\SyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php', '_ContaoManager\\Monolog\\Handler\\SyslogUdpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php', '_ContaoManager\\Monolog\\Handler\\SyslogUdp\\UdpSocket' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php', '_ContaoManager\\Monolog\\Handler\\TelegramBotHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php', '_ContaoManager\\Monolog\\Handler\\TestHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/TestHandler.php', '_ContaoManager\\Monolog\\Handler\\WebRequestRecognizerTrait' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php', '_ContaoManager\\Monolog\\Handler\\WhatFailureGroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php', '_ContaoManager\\Monolog\\Handler\\ZendMonitorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php', '_ContaoManager\\Monolog\\JsonSerializableDateTimeImmutable' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/JsonSerializableDateTimeImmutable.php', '_ContaoManager\\Monolog\\Level' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Level.php', '_ContaoManager\\Monolog\\LogRecord' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/LogRecord.php', '_ContaoManager\\Monolog\\Logger' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Logger.php', '_ContaoManager\\Monolog\\Processor\\ClosureContextProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ClosureContextProcessor.php', '_ContaoManager\\Monolog\\Processor\\GitProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php', '_ContaoManager\\Monolog\\Processor\\HostnameProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php', '_ContaoManager\\Monolog\\Processor\\IntrospectionProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php', '_ContaoManager\\Monolog\\Processor\\LoadAverageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/LoadAverageProcessor.php', '_ContaoManager\\Monolog\\Processor\\MemoryPeakUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php', '_ContaoManager\\Monolog\\Processor\\MemoryProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php', '_ContaoManager\\Monolog\\Processor\\MemoryUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php', '_ContaoManager\\Monolog\\Processor\\MercurialProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php', '_ContaoManager\\Monolog\\Processor\\ProcessIdProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php', '_ContaoManager\\Monolog\\Processor\\ProcessorInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php', '_ContaoManager\\Monolog\\Processor\\PsrLogMessageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php', '_ContaoManager\\Monolog\\Processor\\TagProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php', '_ContaoManager\\Monolog\\Processor\\UidProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php', '_ContaoManager\\Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php', '_ContaoManager\\Monolog\\Registry' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Registry.php', '_ContaoManager\\Monolog\\ResettableInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/ResettableInterface.php', '_ContaoManager\\Monolog\\SignalHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/SignalHandler.php', '_ContaoManager\\Monolog\\Test\\TestCase' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Test/TestCase.php', '_ContaoManager\\Monolog\\Utils' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Utils.php', '_ContaoManager\\OTPHP\\Factory' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Factory.php', '_ContaoManager\\OTPHP\\FactoryInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/FactoryInterface.php', '_ContaoManager\\OTPHP\\HOTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/HOTP.php', '_ContaoManager\\OTPHP\\HOTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/HOTPInterface.php', '_ContaoManager\\OTPHP\\InternalClock' => __DIR__ . '/..' . '/spomky-labs/otphp/src/InternalClock.php', '_ContaoManager\\OTPHP\\OTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/OTP.php', '_ContaoManager\\OTPHP\\OTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/OTPInterface.php', '_ContaoManager\\OTPHP\\ParameterTrait' => __DIR__ . '/..' . '/spomky-labs/otphp/src/ParameterTrait.php', '_ContaoManager\\OTPHP\\TOTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/TOTP.php', '_ContaoManager\\OTPHP\\TOTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/TOTPInterface.php', '_ContaoManager\\OTPHP\\Url' => __DIR__ . '/..' . '/spomky-labs/otphp/src/Url.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\AbstractNodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Attribute' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Attribute.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Comment' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Comment.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\DoctrineConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Node' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Node.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeTraverser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamClosureThisTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamImmediatelyInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamLaterInvokedCallableTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PureUnlessCallableIsImpureTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\RequireImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\SelfOutTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypelessParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeUnsealedTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\InvalidTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ObjectShapeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\OffsetAccessTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Lexer\\Lexer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php', '_ContaoManager\\PHPStan\\PhpDocParser\\ParserConfig' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/ParserConfig.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\ParserException' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ParserException.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TokenIterator' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Parser\\TypeParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\DiffElem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/DiffElem.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Differ' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Differ.php', '_ContaoManager\\PHPStan\\PhpDocParser\\Printer\\Printer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Printer/Printer.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base32' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base32Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base32Hex.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlash' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlash.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Base64UrlSafe' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Base64UrlSafe.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Binary' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Binary.php', '_ContaoManager\\ParagonIE\\ConstantTime\\EncoderInterface' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/EncoderInterface.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Encoding' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Encoding.php', '_ContaoManager\\ParagonIE\\ConstantTime\\Hex' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/Hex.php', '_ContaoManager\\ParagonIE\\ConstantTime\\RFC4648' => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src/RFC4648.php', '_ContaoManager\\Psr\\Cache\\CacheException' => __DIR__ . '/..' . '/psr/cache/src/CacheException.php', '_ContaoManager\\Psr\\Cache\\CacheItemInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemInterface.php', '_ContaoManager\\Psr\\Cache\\CacheItemPoolInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemPoolInterface.php', '_ContaoManager\\Psr\\Cache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/cache/src/InvalidArgumentException.php', '_ContaoManager\\Psr\\Clock\\ClockInterface' => __DIR__ . '/..' . '/psr/clock/src/ClockInterface.php', '_ContaoManager\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php', '_ContaoManager\\Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php', '_ContaoManager\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php', '_ContaoManager\\Psr\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/EventDispatcherInterface.php', '_ContaoManager\\Psr\\EventDispatcher\\ListenerProviderInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/ListenerProviderInterface.php', '_ContaoManager\\Psr\\EventDispatcher\\StoppableEventInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/StoppableEventInterface.php', '_ContaoManager\\Psr\\Http\\Client\\ClientExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientExceptionInterface.php', '_ContaoManager\\Psr\\Http\\Client\\ClientInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientInterface.php', '_ContaoManager\\Psr\\Http\\Client\\NetworkExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/NetworkExceptionInterface.php', '_ContaoManager\\Psr\\Http\\Client\\RequestExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/RequestExceptionInterface.php', '_ContaoManager\\Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php', '_ContaoManager\\Psr\\Http\\Message\\RequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/RequestFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ResponseFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ResponseFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ServerRequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ServerRequestFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php', '_ContaoManager\\Psr\\Http\\Message\\StreamFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/StreamFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UploadedFileFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UploadedFileFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UriFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UriFactoryInterface.php', '_ContaoManager\\Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php', '_ContaoManager\\Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/src/AbstractLogger.php', '_ContaoManager\\Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/src/InvalidArgumentException.php', '_ContaoManager\\Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/src/LogLevel.php', '_ContaoManager\\Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareInterface.php', '_ContaoManager\\Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareTrait.php', '_ContaoManager\\Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerInterface.php', '_ContaoManager\\Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerTrait.php', '_ContaoManager\\Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/src/NullLogger.php', '_ContaoManager\\Ramsey\\Collection\\AbstractArray' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractArray.php', '_ContaoManager\\Ramsey\\Collection\\AbstractCollection' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractCollection.php', '_ContaoManager\\Ramsey\\Collection\\AbstractSet' => __DIR__ . '/..' . '/ramsey/collection/src/AbstractSet.php', '_ContaoManager\\Ramsey\\Collection\\ArrayInterface' => __DIR__ . '/..' . '/ramsey/collection/src/ArrayInterface.php', '_ContaoManager\\Ramsey\\Collection\\Collection' => __DIR__ . '/..' . '/ramsey/collection/src/Collection.php', '_ContaoManager\\Ramsey\\Collection\\CollectionInterface' => __DIR__ . '/..' . '/ramsey/collection/src/CollectionInterface.php', '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueue' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueue.php', '_ContaoManager\\Ramsey\\Collection\\DoubleEndedQueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueueInterface.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/CollectionException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\CollectionMismatchException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/CollectionMismatchException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidArgumentException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\InvalidPropertyOrMethod' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\NoSuchElementException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/NoSuchElementException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/OutOfBoundsException.php', '_ContaoManager\\Ramsey\\Collection\\Exception\\UnsupportedOperationException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/UnsupportedOperationException.php', '_ContaoManager\\Ramsey\\Collection\\GenericArray' => __DIR__ . '/..' . '/ramsey/collection/src/GenericArray.php', '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AbstractMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\AbstractTypedMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AbstractTypedMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\AssociativeArrayMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/AssociativeArrayMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\MapInterface' => __DIR__ . '/..' . '/ramsey/collection/src/Map/MapInterface.php', '_ContaoManager\\Ramsey\\Collection\\Map\\NamedParameterMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/NamedParameterMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMap' => __DIR__ . '/..' . '/ramsey/collection/src/Map/TypedMap.php', '_ContaoManager\\Ramsey\\Collection\\Map\\TypedMapInterface' => __DIR__ . '/..' . '/ramsey/collection/src/Map/TypedMapInterface.php', '_ContaoManager\\Ramsey\\Collection\\Queue' => __DIR__ . '/..' . '/ramsey/collection/src/Queue.php', '_ContaoManager\\Ramsey\\Collection\\QueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/QueueInterface.php', '_ContaoManager\\Ramsey\\Collection\\Set' => __DIR__ . '/..' . '/ramsey/collection/src/Set.php', '_ContaoManager\\Ramsey\\Collection\\Sort' => __DIR__ . '/..' . '/ramsey/collection/src/Sort.php', '_ContaoManager\\Ramsey\\Collection\\Tool\\TypeTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/TypeTrait.php', '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueExtractorTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueExtractorTrait.php', '_ContaoManager\\Ramsey\\Collection\\Tool\\ValueToStringTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueToStringTrait.php', '_ContaoManager\\Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\BuilderCollection' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/BuilderCollection.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\FallbackBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/FallbackBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Builder\\UuidBuilderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/UuidBuilderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\CodecInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/CodecInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\GuidStringCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/GuidStringCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\OrderedTimeCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/OrderedTimeCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\StringCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/StringCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampFirstCombCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Codec\\TimestampLastCombCodec' => __DIR__ . '/..' . '/ramsey/uuid/src/Codec/TimestampLastCombCodec.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\NumberConverterInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/NumberConverterInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\BigNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/BigNumberConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\DegradedNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Number\\GenericNumberConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\TimeConverterInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/TimeConverterInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\BigNumberTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\DegradedTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\GenericTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\PhpTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\Converter\\Time\\UnixTimeConverter' => __DIR__ . '/..' . '/ramsey/uuid/src/Converter/Time/UnixTimeConverter.php', '_ContaoManager\\Ramsey\\Uuid\\DegradedUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/DegradedUuid.php', '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/DeprecatedUuidInterface.php', '_ContaoManager\\Ramsey\\Uuid\\DeprecatedUuidMethodsTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\BuilderNotFoundException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/BuilderNotFoundException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\DateTimeException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/DateTimeException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\DceSecurityException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/DceSecurityException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidArgumentException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidBytesException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidBytesException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\InvalidUuidStringException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/InvalidUuidStringException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\NameException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/NameException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\NodeException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/NodeException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\RandomSourceException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/RandomSourceException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\TimeSourceException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/TimeSourceException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnableToBuildUuidException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UnableToBuildUuidException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\UnsupportedOperationException' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UnsupportedOperationException.php', '_ContaoManager\\Ramsey\\Uuid\\Exception\\UuidExceptionInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Exception/UuidExceptionInterface.php', '_ContaoManager\\Ramsey\\Uuid\\FeatureSet' => __DIR__ . '/..' . '/ramsey/uuid/src/FeatureSet.php', '_ContaoManager\\Ramsey\\Uuid\\Fields\\FieldsInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Fields/FieldsInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Fields\\SerializableFieldsTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Fields/SerializableFieldsTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\CombGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/CombGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DceSecurityGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DceSecurityGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DceSecurityGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultNameGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DefaultNameGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\DefaultTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/DefaultTimeGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/NameGeneratorFactory.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\NameGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/NameGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidNameGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidNameGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidRandomGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\PeclUuidTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomBytesGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomBytesGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomGeneratorFactory.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\RandomLibAdapter' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/RandomLibAdapter.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/TimeGeneratorFactory.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\TimeGeneratorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/TimeGeneratorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Generator\\UnixTimeGenerator' => __DIR__ . '/..' . '/ramsey/uuid/src/Generator/UnixTimeGenerator.php', '_ContaoManager\\Ramsey\\Uuid\\Guid\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/Fields.php', '_ContaoManager\\Ramsey\\Uuid\\Guid\\Guid' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/Guid.php', '_ContaoManager\\Ramsey\\Uuid\\Guid\\GuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Guid/GuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Lazy\\LazyUuidFromString' => __DIR__ . '/..' . '/ramsey/uuid/src/Lazy/LazyUuidFromString.php', '_ContaoManager\\Ramsey\\Uuid\\Math\\BrickMathCalculator' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/BrickMathCalculator.php', '_ContaoManager\\Ramsey\\Uuid\\Math\\CalculatorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/CalculatorInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Math\\RoundingMode' => __DIR__ . '/..' . '/ramsey/uuid/src/Math/RoundingMode.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/Fields.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\Uuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/Uuid.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/UuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Nonstandard\\UuidV6' => __DIR__ . '/..' . '/ramsey/uuid/src/Nonstandard/UuidV6.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\DceSecurityProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/DceSecurityProviderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Dce\\SystemDceSecurityProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Dce/SystemDceSecurityProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\NodeProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/NodeProviderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\FallbackNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\NodeProviderCollection' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/NodeProviderCollection.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\RandomNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\StaticNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/StaticNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Node\\SystemNodeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\TimeProviderInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/TimeProviderInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\FixedTimeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Provider\\Time\\SystemTimeProvider' => __DIR__ . '/..' . '/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Fields' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/Fields.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\FieldsInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/FieldsInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/MaxTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\MaxUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/MaxUuid.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/NilTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\NilUuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/NilUuid.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\TimeTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/TimeTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidBuilder.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV1' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV1.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV2' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV2.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV3' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV3.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV4' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV4.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV5' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV5.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV6' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV6.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV7' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV7.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\UuidV8' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/UuidV8.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\Validator' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/Validator.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VariantTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/VariantTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Rfc4122\\VersionTrait' => __DIR__ . '/..' . '/ramsey/uuid/src/Rfc4122/VersionTrait.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Decimal' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Decimal.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Hexadecimal' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Hexadecimal.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Integer' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Integer.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\NumberInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/NumberInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\Time' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/Time.php', '_ContaoManager\\Ramsey\\Uuid\\Type\\TypeInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Type/TypeInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Uuid' => __DIR__ . '/..' . '/ramsey/uuid/src/Uuid.php', '_ContaoManager\\Ramsey\\Uuid\\UuidFactory' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidFactory.php', '_ContaoManager\\Ramsey\\Uuid\\UuidFactoryInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidFactoryInterface.php', '_ContaoManager\\Ramsey\\Uuid\\UuidInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/UuidInterface.php', '_ContaoManager\\Ramsey\\Uuid\\Validator\\GenericValidator' => __DIR__ . '/..' . '/ramsey/uuid/src/Validator/GenericValidator.php', '_ContaoManager\\Ramsey\\Uuid\\Validator\\ValidatorInterface' => __DIR__ . '/..' . '/ramsey/uuid/src/Validator/ValidatorInterface.php', '_ContaoManager\\Seld\\JsonLint\\DuplicateKeyException' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php', '_ContaoManager\\Seld\\JsonLint\\JsonParser' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/JsonParser.php', '_ContaoManager\\Seld\\JsonLint\\Lexer' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/Lexer.php', '_ContaoManager\\Seld\\JsonLint\\ParsingException' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/ParsingException.php', '_ContaoManager\\Seld\\JsonLint\\Undefined' => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint/Undefined.php', '_ContaoManager\\Seld\\PharUtils\\Linter' => __DIR__ . '/..' . '/seld/phar-utils/src/Linter.php', '_ContaoManager\\Seld\\PharUtils\\Timestamps' => __DIR__ . '/..' . '/seld/phar-utils/src/Timestamps.php', '_ContaoManager\\Seld\\Signal\\SignalHandler' => __DIR__ . '/..' . '/seld/signal-handler/src/SignalHandler.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Identifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Component/Identifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Component\\Length' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Component/Length.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\DERData' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/DERData.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Element' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Element.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Exception\\DecodeException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Exception/DecodeException.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\ElementBase' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Feature/ElementBase.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Encodable' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Feature/Encodable.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Feature\\Stringable' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Feature/Stringable.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/BaseString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\BaseTime' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/BaseTime.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\ConstructedString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/ConstructedString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Sequence' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Sequence.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Constructed\\Set' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Constructed/Set.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\PrimitiveType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/PrimitiveType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BMPString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BMPString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\BitString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/BitString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Boolean' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Boolean.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\CharacterString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/CharacterString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\EOC' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/EOC.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Enumerated' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Enumerated.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GeneralizedTime' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GeneralizedTime.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\GraphicString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/GraphicString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\IA5String' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/IA5String.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Integer' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Integer.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NullType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NullType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Number' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Number.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\NumericString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/NumericString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectDescriptor' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectDescriptor.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\ObjectIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/ObjectIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\OctetString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/OctetString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\PrintableString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/PrintableString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\Real' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/Real.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\RelativeOID' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/RelativeOID.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\T61String' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/T61String.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTCTime' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTCTime.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UTF8String' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UTF8String.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\UniversalString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/UniversalString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VideotexString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VideotexString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Primitive\\VisibleString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Primitive/VisibleString.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\StringType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/StringType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Structure' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Structure.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/TaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ApplicationType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ApplicationType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ContextSpecificType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ContextSpecificType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\DERTaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/DERTaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitTagging' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitTagging.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ExplicitlyTaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ExplicitlyTaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitTagging' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitTagging.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\ImplicitlyTaggedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/ImplicitlyTaggedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\PrivateType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/PrivateType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\Tagged\\TaggedTypeWrap' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/Tagged/TaggedTypeWrap.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\TimeType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/TimeType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UniversalClass' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/UniversalClass.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Type\\UnspecifiedType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Type/UnspecifiedType.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\BigInt' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Util/BigInt.php', '_ContaoManager\\SpomkyLabs\\Pki\\ASN1\\Util\\Flags' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/ASN1/Util/Flags.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoBridge\\Crypto\\OpenSSLCrypto' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoBridge/Crypto/OpenSSLCrypto.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEM' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoEncoding/PEM.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoEncoding\\PEMBundle' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoEncoding/PEMBundle.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierFactory' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierFactory.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\AlgorithmIdentifierProvider' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/AlgorithmIdentifierProvider.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\ECPublicKeyAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/ECPublicKeyAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed25519AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed25519AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\Ed448AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/Ed448AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410EdAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410EdAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RFC8410XAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RFC8410XAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\RSAPSSSSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/RSAPSSSSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X25519AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X25519AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Asymmetric\\X448AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Asymmetric/X448AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES128CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES128CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES192CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES192CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AES256CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AES256CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\AESCBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/AESCBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\BlockCipherAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/BlockCipherAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\CipherAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/CipherAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESCBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESCBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\DESEDE3CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/DESEDE3CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Cipher\\RC2CBCAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Cipher/RC2CBCAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AlgorithmIdentifierType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AlgorithmIdentifierType.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\AsymmetricCryptoAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/AsymmetricCryptoAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\EncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/EncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\HashAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/HashAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\PRFAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/PRFAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Feature\\SignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Feature/SignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\GenericAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/GenericAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA1AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA1AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA224AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA224AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA256AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA256AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA384AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA384AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\HMACWithSHA512AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/HMACWithSHA512AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\MD5AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/MD5AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\RFC4231HMACAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/RFC4231HMACAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA1AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA1AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA224AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA224AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA256AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA256AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA2AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA2AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA384AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA384AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Hash\\SHA512AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Hash/SHA512AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA1AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA1AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA224AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA224AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA256AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA256AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA384AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA384AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECDSAWithSHA512AlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECDSAWithSHA512AlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\ECSignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/ECSignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD2WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD2WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD4WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD4WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\MD5WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/MD5WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC3279RSASignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC3279RSASignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RFC4055RSASignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RFC4055RSASignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\RSASignatureAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/RSASignatureAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA1WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA1WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA224WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA224WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA256WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA256WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA384WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA384WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\Signature\\SHA512WithRSAEncryptionAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/Signature/SHA512WithRSAEncryptionAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\AlgorithmIdentifier\\SpecificAlgorithmIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/AlgorithmIdentifier/SpecificAlgorithmIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\Attribute\\OneAsymmetricKeyAttributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/Attribute/OneAsymmetricKeyAttributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECConversion' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECConversion.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\EC\\ECPublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/EC/ECPublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\OneAsymmetricKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/OneAsymmetricKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PrivateKeyInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PrivateKeyInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\PublicKeyInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/PublicKeyInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Curve25519PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Curve25519PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\Ed25519PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/Ed25519PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve25519\\X25519PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve25519/X25519PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\Ed448PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/Ed448PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\Curve448\\X448PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/Curve448/X448PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RFC8410\\RFC8410PublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RFC8410/RFC8410PublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSAPublicKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSAPublicKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Asymmetric\\RSA\\RSASSAPSSPrivateKey' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Asymmetric/RSA/RSASSAPSSPrivateKey.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\ECSignature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/ECSignature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed25519Signature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed25519Signature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Ed448Signature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Ed448Signature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\GenericSignature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/GenericSignature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\RSASignature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/RSASignature.php', '_ContaoManager\\SpomkyLabs\\Pki\\CryptoTypes\\Signature\\Signature' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/CryptoTypes/Signature/Signature.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Attribute' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Attribute.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeType' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeType.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeTypeAndValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeTypeAndValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\AttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/AttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CommonNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CommonNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\CountryNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/CountryNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\DescriptionValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/DescriptionValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\DirectoryString' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/DirectoryString.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\Feature\\PrintableStringValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/Feature/PrintableStringValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\GivenNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/GivenNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\LocalityNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/LocalityNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\NameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/NameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\OrganizationalUnitNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/OrganizationalUnitNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\PseudonymValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/PseudonymValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SerialNumberValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SerialNumberValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\StateOrProvinceNameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/StateOrProvinceNameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\SurnameValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/SurnameValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\TitleValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/TitleValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\AttributeValue\\UnknownAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/AttributeValue/UnknownAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\AttributeCollection' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/AttributeCollection.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SequenceOfAttributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SequenceOfAttributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Collection\\SetOfAttributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Collection/SetOfAttributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\Name' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/Name.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\ASN1\\RDN' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/ASN1/RDN.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\DN\\DNParser' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/DN/DNParser.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\BinaryMatch' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/BinaryMatch.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseExactMatch' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseExactMatch.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\CaseIgnoreMatch' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/CaseIgnoreMatch.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\MatchingRule' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/MatchingRule.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\MatchingRule\\StringPrepMatchingRule' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/MatchingRule/StringPrepMatchingRule.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\CheckBidiStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/CheckBidiStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\InsignificantNonSubstringSpaceStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/InsignificantNonSubstringSpaceStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\MapStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/MapStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\NormalizeStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/NormalizeStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\PrepareStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/PrepareStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\ProhibitStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/ProhibitStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\StringPreparer' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/StringPreparer.php', '_ContaoManager\\SpomkyLabs\\Pki\\X501\\StringPrep\\TranscodeStep' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X501/StringPrep/TranscodeStep.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertIssuer' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertIssuer.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttCertValidityPeriod' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttCertValidityPeriod.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificate' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificate.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\AttributeCertificateInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/AttributeCertificateInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AccessIdentityAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AccessIdentityAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\AuthenticationInfoAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/AuthenticationInfoAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\ChargingIdentityAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/ChargingIdentityAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\GroupAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/GroupAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrSyntax' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrSyntax.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\IetfAttrValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/IetfAttrValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\RoleAttributeValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/RoleAttributeValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attribute\\SvceAuthInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attribute/SvceAuthInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Attributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Attributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Holder' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Holder.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\IssuerSerial' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/IssuerSerial.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\ObjectDigestInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/ObjectDigestInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\V2Form' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/V2Form.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidationConfig' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidationConfig.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\ACValidator' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/ACValidator.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\AttributeCertificate\\Validation\\Exception\\ACValidationException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/AttributeCertificate/Validation/Exception/ACValidationException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Certificate' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Certificate.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateBundle' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateBundle.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\CertificateChain' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/CertificateChain.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AAControlsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AAControlsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AccessDescription' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AccessDescription.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\AuthorityAccessDescription' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/AuthorityAccessDescription.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AccessDescription\\SubjectAccessDescription' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AccessDescription/SubjectAccessDescription.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityInformationAccessExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityInformationAccessExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\AuthorityKeyIdentifierExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/AuthorityKeyIdentifierExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\BasicConstraintsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/BasicConstraintsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CRLDistributionPointsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CRLDistributionPointsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePoliciesExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePoliciesExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\CPSQualifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/CPSQualifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\DisplayText' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/DisplayText.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\NoticeReference' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/NoticeReference.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyInformation' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyInformation.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\PolicyQualifierInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/PolicyQualifierInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\CertificatePolicy\\UserNoticeQualifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/CertificatePolicy/UserNoticeQualifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPoint' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPoint.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\DistributionPointName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/DistributionPointName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\FullName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/FullName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\ReasonFlags' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/ReasonFlags.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\DistributionPoint\\RelativeName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/DistributionPoint/RelativeName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\ExtendedKeyUsageExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/ExtendedKeyUsageExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Extension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Extension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\FreshestCRLExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/FreshestCRLExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\InhibitAnyPolicyExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/InhibitAnyPolicyExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\IssuerAlternativeNameExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/IssuerAlternativeNameExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\KeyUsageExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/KeyUsageExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraintsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraintsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtree' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtree.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NameConstraints\\GeneralSubtrees' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NameConstraints/GeneralSubtrees.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\NoRevocationAvailableExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/NoRevocationAvailableExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyConstraintsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyConstraintsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappingsExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappingsExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\PolicyMappings\\PolicyMapping' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/PolicyMappings/PolicyMapping.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectAlternativeNameExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectAlternativeNameExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectDirectoryAttributesExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectDirectoryAttributesExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectInformationAccessExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectInformationAccessExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\SubjectKeyIdentifierExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/SubjectKeyIdentifierExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\TargetInformationExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/TargetInformationExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Target' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Target.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetGroup' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetGroup.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\TargetName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/TargetName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\Target\\Targets' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/Target/Targets.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extension\\UnknownExtension' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extension/UnknownExtension.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Extensions' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Extensions.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\TBSCertificate' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/TBSCertificate.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Time' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Time.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\UniqueIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/UniqueIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Certificate\\Validity' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Certificate/Validity.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\CertificationPath' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/CertificationPath.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathBuildingException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathBuildingException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Exception\\PathValidationException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Exception/PathValidationException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathBuilding\\CertificationPathBuilder' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathBuilding/CertificationPathBuilder.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationConfig' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationConfig.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidationResult' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidationResult.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\PathValidator' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/PathValidator.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\PathValidation\\ValidatorState' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/PathValidation/ValidatorState.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyNode' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyNode.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationPath\\Policy\\PolicyTree' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationPath/Policy/PolicyTree.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attribute\\ExtensionRequestValue' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attribute/ExtensionRequestValue.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\Attributes' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/Attributes.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequest' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequest.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\CertificationRequest\\CertificationRequestInfo' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/CertificationRequest/CertificationRequestInfo.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Exception\\X509ValidationException' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Exception/X509ValidationException.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\Feature\\DateTimeHelper' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/Feature/DateTimeHelper.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DNSName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/DNSName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\DirectoryName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/DirectoryName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\EDIPartyName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/EDIPartyName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\GeneralNames' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/GeneralNames.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPAddress' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/IPAddress.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv4Address' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv4Address.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\IPv6Address' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/IPv6Address.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\OtherName' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/OtherName.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RFC822Name' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/RFC822Name.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\RegisteredID' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/RegisteredID.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\UniformResourceIdentifier' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/UniformResourceIdentifier.php', '_ContaoManager\\SpomkyLabs\\Pki\\X509\\GeneralName\\X400Address' => __DIR__ . '/..' . '/spomky-labs/pki-framework/src/X509/GeneralName/X400Address.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Command\\ServerLogCommand' => __DIR__ . '/..' . '/symfony/monolog-bridge/Command/ServerLogCommand.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\CompatibilityFormatter' => __DIR__ . '/..' . '/symfony/monolog-bridge/Formatter/CompatibilityFormatter.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\ConsoleFormatter' => __DIR__ . '/..' . '/symfony/monolog-bridge/Formatter/ConsoleFormatter.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Formatter\\VarDumperFormatter' => __DIR__ . '/..' . '/symfony/monolog-bridge/Formatter/VarDumperFormatter.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ChromePhpHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ChromePhpHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/CompatibilityHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\CompatibilityProcessingHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/CompatibilityProcessingHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ConsoleHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ElasticsearchLogstashHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ElasticsearchLogstashHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\HttpCodeActivationStrategy' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/FingersCrossed/HttpCodeActivationStrategy.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FingersCrossed\\NotFoundActivationStrategy' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/FingersCrossed/NotFoundActivationStrategy.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\FirePHPHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/FirePHPHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\MailerHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/MailerHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\NotifierHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/NotifierHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Handler\\ServerLogHandler' => __DIR__ . '/..' . '/symfony/monolog-bridge/Handler/ServerLogHandler.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Logger' => __DIR__ . '/..' . '/symfony/monolog-bridge/Logger.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\AbstractTokenProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/AbstractTokenProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\CompatibilityProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/CompatibilityProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\ConsoleCommandProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/ConsoleCommandProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\DebugProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/DebugProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\RouteProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/RouteProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\SwitchUserTokenProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/SwitchUserTokenProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\TokenProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/TokenProcessor.php', '_ContaoManager\\Symfony\\Bridge\\Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/symfony/monolog-bridge/Processor/WebProcessor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ConfigBuilderCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\RouterCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\SerializerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\TranslationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ValidatorCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AboutCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AboutCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AbstractConfigCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AbstractConfigCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\AssetsInstallCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AssetsInstallCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\BuildDebugContainerTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/BuildDebugContainerTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheClearCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CacheClearCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolClearCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolClearCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolDeleteCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolDeleteCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolInvalidateTagsCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolInvalidateTagsCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolListCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolListCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolPruneCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolPruneCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\CacheWarmupCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CacheWarmupCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ConfigDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDumpReferenceCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ContainerDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ContainerLintCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\DebugAutowiringCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/DebugAutowiringCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\EventDispatcherDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/RouterDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\RouterMatchCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/RouterMatchCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsDecryptToLocalCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsEncryptFromLocalCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsGenerateKeysCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsListCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsListCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsRemoveCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsRemoveCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsSetCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsSetCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/TranslationDebugCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationUpdateCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/TranslationUpdateCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\WorkflowDumpCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/WorkflowDumpCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\XliffLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/XliffLintCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Command\\YamlLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/YamlLintCommand.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Application' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Application.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/Descriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Helper/DescriptorHelper.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/AbstractController.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/ControllerResolver.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/RedirectController.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/TemplateController.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\AbstractDataCollector' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/AbstractDataCollector.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\RouterDataCollector' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/RouterDataCollector.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DataCollector\\TemplateAwareDataCollectorInterface' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddAnnotationsCachedReaderPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddDebugLogProcessorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AssetsContextPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ContainerBuilderDebugDumpPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\DataCollectorTranslatorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\EnableLoggerDebugModePass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/EnableLoggerDebugModePass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ErrorLoggerCompilerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ErrorLoggerCompilerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\LoggingTranslatorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ProfilerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TranslationUpdateCommandPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Configuration.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\FrameworkExtension' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\VirtualRequestStackPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/VirtualRequestStackPass.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\ConsoleProfilerListener' => __DIR__ . '/..' . '/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\EventListener\\SuggestMissingPackageSubscriber' => __DIR__ . '/..' . '/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle' => __DIR__ . '/..' . '/symfony/framework-bundle/FrameworkBundle.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache' => __DIR__ . '/..' . '/symfony/framework-bundle/HttpCache/HttpCache.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\KernelBrowser' => __DIR__ . '/..' . '/symfony/framework-bundle/KernelBrowser.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Kernel\\MicroKernelTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Kernel/MicroKernelTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AnnotatedRouteControllerLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\AttributeRouteControllerLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/AttributeRouteControllerLoader.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Attribute\\AsRoutingConditionService' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/DelegatingLoader.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\RouteLoaderInterface' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/RouteLoaderInterface.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Routing\\Router' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/Router.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\AbstractVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/AbstractVault.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\DotenvVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/DotenvVault.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Secrets\\SodiumVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/SodiumVault.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\BrowserKitAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\DomCrawlerAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\HttpClientAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/KernelTestCase.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\MailerAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/MailerAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\NotificationAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/NotificationAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestBrowserToken' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/TestBrowserToken.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\TestContainer' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/TestContainer.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestAssertionsTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/WebTestAssertionsTrait.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/WebTestCase.php', '_ContaoManager\\Symfony\\Bundle\\FrameworkBundle\\Translation\\Translator' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/Translator.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddProcessorsPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/DependencyInjection/Compiler/AddProcessorsPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\AddSwiftMailerTransportPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/DependencyInjection/Compiler/AddSwiftMailerTransportPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\DebugHandlerPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/DependencyInjection/Compiler/DebugHandlerPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\FixEmptyLoggerPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/DependencyInjection/Compiler/FixEmptyLoggerPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Compiler\\LoggerChannelPass' => __DIR__ . '/..' . '/symfony/monolog-bundle/DependencyInjection/Compiler/LoggerChannelPass.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/monolog-bundle/DependencyInjection/Configuration.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\DependencyInjection\\MonologExtension' => __DIR__ . '/..' . '/symfony/monolog-bundle/DependencyInjection/MonologExtension.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\MonologBundle' => __DIR__ . '/..' . '/symfony/monolog-bundle/MonologBundle.php', '_ContaoManager\\Symfony\\Bundle\\MonologBundle\\SwiftMailer\\MessageFactory' => __DIR__ . '/..' . '/symfony/monolog-bundle/SwiftMailer/MessageFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\CacheWarmer\\ExpressionCacheWarmer' => __DIR__ . '/..' . '/symfony/security-bundle/CacheWarmer/ExpressionCacheWarmer.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Command\\DebugFirewallCommand' => __DIR__ . '/..' . '/symfony/security-bundle/Command/DebugFirewallCommand.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DataCollector\\SecurityDataCollector' => __DIR__ . '/..' . '/symfony/security-bundle/DataCollector/SecurityDataCollector.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableFirewallListener' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/TraceableFirewallListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\TraceableListenerTrait' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/TraceableListenerTrait.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedLazyListener' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/WrappedLazyListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/security-bundle/Debug/WrappedListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSecurityVotersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\AddSessionDomainConstraintPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\CleanRememberMeVerifierPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/CleanRememberMeVerifierPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\MakeFirewallsEventDispatcherTraceablePass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/MakeFirewallsEventDispatcherTraceablePass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterCsrfFeaturesPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterEntryPointPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterEntryPointPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterGlobalSecurityEventListenersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterLdapLocatorPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterLdapLocatorPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\RegisterTokenUsageTrackingPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\ReplaceDecoratedRememberMeHandlerPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/ReplaceDecoratedRememberMeHandlerPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Compiler\\SortFirewallListenersPass' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Compiler/SortFirewallListenersPass.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\MainConfiguration' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/MainConfiguration.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\SecurityExtension' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/SecurityExtension.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcTokenHandlerFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\OidcUserInfoTokenHandlerFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/OidcUserInfoTokenHandlerFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\ServiceTokenHandlerFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/ServiceTokenHandlerFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\AccessToken\\TokenHandlerFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/AccessToken/TokenHandlerFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AbstractFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/AbstractFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AccessTokenFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/AccessTokenFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\AuthenticatorFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/AuthenticatorFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\CustomAuthenticatorFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/CustomAuthenticatorFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FirewallListenerFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/FirewallListenerFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\FormLoginLdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\HttpBasicLdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\JsonLoginLdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginLdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LdapFactoryTrait' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginLinkFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginLinkFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\LoginThrottlingFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RememberMeFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/RememberMeFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\RemoteUserFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/RemoteUserFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\SignatureAlgorithmFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/SignatureAlgorithmFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\StatelessAuthenticatorFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/StatelessAuthenticatorFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\Factory\\X509Factory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/Factory/X509Factory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\InMemoryFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\LdapFactory' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/LdapFactory.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\DependencyInjection\\Security\\UserProvider\\UserProviderFactoryInterface' => __DIR__ . '/..' . '/symfony/security-bundle/DependencyInjection/Security/UserProvider/UserProviderFactoryInterface.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\FirewallListener' => __DIR__ . '/..' . '/symfony/security-bundle/EventListener/FirewallListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\EventListener\\VoteListener' => __DIR__ . '/..' . '/symfony/security-bundle/EventListener/VoteListener.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\LoginLink\\FirewallAwareLoginLinkHandler' => __DIR__ . '/..' . '/symfony/security-bundle/LoginLink/FirewallAwareLoginLinkHandler.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\DecoratedRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-bundle/RememberMe/DecoratedRememberMeHandler.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\RememberMe\\FirewallAwareRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-bundle/RememberMe/FirewallAwareRememberMeHandler.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Routing\\LogoutRouteLoader' => __DIR__ . '/..' . '/symfony/security-bundle/Routing/LogoutRouteLoader.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security' => __DIR__ . '/..' . '/symfony/security-bundle/Security.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\SecurityBundle' => __DIR__ . '/..' . '/symfony/security-bundle/SecurityBundle.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallAwareTrait' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallAwareTrait.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallConfig' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallConfig.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallContext.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap' => __DIR__ . '/..' . '/symfony/security-bundle/Security/FirewallMap.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\LazyFirewallContext' => __DIR__ . '/..' . '/symfony/security-bundle/Security/LazyFirewallContext.php', '_ContaoManager\\Symfony\\Bundle\\SecurityBundle\\Security\\UserAuthenticator' => __DIR__ . '/..' . '/symfony/security-bundle/Security/UserAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/AdapterInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ApcuAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ArrayAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ChainAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseBucketAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/CouchbaseBucketAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\CouchbaseCollectionAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/CouchbaseCollectionAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\DoctrineDbalAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/DoctrineDbalAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/MemcachedAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\NullAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/NullAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ParameterNormalizer' => __DIR__ . '/..' . '/symfony/cache/Adapter/ParameterNormalizer.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PdoAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpArrayAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpFilesAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ProxyAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/Psr16Adapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', '_ContaoManager\\Symfony\\Component\\Cache\\CacheItem' => __DIR__ . '/..' . '/symfony/cache/CacheItem.php', '_ContaoManager\\Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => __DIR__ . '/..' . '/symfony/cache/DataCollector/CacheDataCollector.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CacheCollectorPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php', '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\CacheException' => __DIR__ . '/..' . '/symfony/cache/Exception/CacheException.php', '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/cache/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Cache\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/cache/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Cache\\LockRegistry' => __DIR__ . '/..' . '/symfony/cache/LockRegistry.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DefaultMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DeflateMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => __DIR__ . '/..' . '/symfony/cache/Marshaller/MarshallerInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\SodiumMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/SodiumMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/TagAwareMarshaller.php', '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationDispatcher' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationDispatcher.php', '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationHandler' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationHandler.php', '_ContaoManager\\Symfony\\Component\\Cache\\Messenger\\EarlyExpirationMessage' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationMessage.php', '_ContaoManager\\Symfony\\Component\\Cache\\PruneableInterface' => __DIR__ . '/..' . '/symfony/cache/PruneableInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Psr16Cache' => __DIR__ . '/..' . '/symfony/cache/Psr16Cache.php', '_ContaoManager\\Symfony\\Component\\Cache\\ResettableInterface' => __DIR__ . '/..' . '/symfony/cache/ResettableInterface.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractAdapterTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ContractsTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ContractsTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis5Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Redis6ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6ProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster5Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6Proxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisCluster6ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6ProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterNodeProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RedisTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxy.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/CopyTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GeosearchTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GetrangeTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/HsetTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/MoveTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/NullableReturnTrait.php', '_ContaoManager\\Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/PfcountTrait.php', '_ContaoManager\\Symfony\\Component\\Clock\\Clock' => __DIR__ . '/..' . '/symfony/clock/Clock.php', '_ContaoManager\\Symfony\\Component\\Clock\\ClockAwareTrait' => __DIR__ . '/..' . '/symfony/clock/ClockAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Clock\\ClockInterface' => __DIR__ . '/..' . '/symfony/clock/ClockInterface.php', '_ContaoManager\\Symfony\\Component\\Clock\\DatePoint' => __DIR__ . '/..' . '/symfony/clock/DatePoint.php', '_ContaoManager\\Symfony\\Component\\Clock\\MockClock' => __DIR__ . '/..' . '/symfony/clock/MockClock.php', '_ContaoManager\\Symfony\\Component\\Clock\\MonotonicClock' => __DIR__ . '/..' . '/symfony/clock/MonotonicClock.php', '_ContaoManager\\Symfony\\Component\\Clock\\NativeClock' => __DIR__ . '/..' . '/symfony/clock/NativeClock.php', '_ContaoManager\\Symfony\\Component\\Clock\\Test\\ClockSensitiveTrait' => __DIR__ . '/..' . '/symfony/clock/Test/ClockSensitiveTrait.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ClassBuilder' => __DIR__ . '/..' . '/symfony/config/Builder/ClassBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGenerator.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\ConfigBuilderInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Method' => __DIR__ . '/..' . '/symfony/config/Builder/Method.php', '_ContaoManager\\Symfony\\Component\\Config\\Builder\\Property' => __DIR__ . '/..' . '/symfony/config/Builder/Property.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCache' => __DIR__ . '/..' . '/symfony/config/ConfigCache.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactory' => __DIR__ . '/..' . '/symfony/config/ConfigCacheFactory.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheFactoryInterface' => __DIR__ . '/..' . '/symfony/config/ConfigCacheFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\ConfigCacheInterface' => __DIR__ . '/..' . '/symfony/config/ConfigCacheInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ArrayNode' => __DIR__ . '/..' . '/symfony/config/Definition/ArrayNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BaseNode' => __DIR__ . '/..' . '/symfony/config/Definition/BaseNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\BooleanNode' => __DIR__ . '/..' . '/symfony/config/Definition/BooleanNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ArrayNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BooleanNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/BooleanNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\BuilderAwareInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/BuilderAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\EnumNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/EnumNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ExprBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ExprBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\FloatNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/FloatNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/IntegerNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\MergeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/MergeBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeParentInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NormalizationBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NormalizationBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\NumericNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NumericNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ParentNodeDefinitionInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ScalarNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ScalarNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/TreeBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\ValidationBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ValidationBuilder.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Builder\\VariableNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/VariableNodeDefinition.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurableInterface' => __DIR__ . '/..' . '/symfony/config/Definition/ConfigurableInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configuration' => __DIR__ . '/..' . '/symfony/config/Definition/Configuration.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ConfigurationInterface' => __DIR__ . '/..' . '/symfony/config/Definition/ConfigurationInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Configurator\\DefinitionConfigurator' => __DIR__ . '/..' . '/symfony/config/Definition/Configurator/DefinitionConfigurator.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\XmlReferenceDumper' => __DIR__ . '/..' . '/symfony/config/Definition/Dumper/XmlReferenceDumper.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Dumper\\YamlReferenceDumper' => __DIR__ . '/..' . '/symfony/config/Definition/Dumper/YamlReferenceDumper.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\EnumNode' => __DIR__ . '/..' . '/symfony/config/Definition/EnumNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\DuplicateKeyException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/DuplicateKeyException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\Exception' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/Exception.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\ForbiddenOverwriteException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/ForbiddenOverwriteException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidConfigurationException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidConfigurationException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidDefinitionException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidDefinitionException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\InvalidTypeException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidTypeException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Exception\\UnsetKeyException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/UnsetKeyException.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\FloatNode' => __DIR__ . '/..' . '/symfony/config/Definition/FloatNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\IntegerNode' => __DIR__ . '/..' . '/symfony/config/Definition/IntegerNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Loader\\DefinitionFileLoader' => __DIR__ . '/..' . '/symfony/config/Definition/Loader/DefinitionFileLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NodeInterface' => __DIR__ . '/..' . '/symfony/config/Definition/NodeInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\NumericNode' => __DIR__ . '/..' . '/symfony/config/Definition/NumericNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\Processor' => __DIR__ . '/..' . '/symfony/config/Definition/Processor.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypeNodeInterface' => __DIR__ . '/..' . '/symfony/config/Definition/PrototypeNodeInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\PrototypedArrayNode' => __DIR__ . '/..' . '/symfony/config/Definition/PrototypedArrayNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\ScalarNode' => __DIR__ . '/..' . '/symfony/config/Definition/ScalarNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Definition\\VariableNode' => __DIR__ . '/..' . '/symfony/config/Definition/VariableNode.php', '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLocatorFileNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Config\\Exception\\LoaderLoadException' => __DIR__ . '/..' . '/symfony/config/Exception/LoaderLoadException.php', '_ContaoManager\\Symfony\\Component\\Config\\FileLocator' => __DIR__ . '/..' . '/symfony/config/FileLocator.php', '_ContaoManager\\Symfony\\Component\\Config\\FileLocatorInterface' => __DIR__ . '/..' . '/symfony/config/FileLocatorInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DelegatingLoader' => __DIR__ . '/..' . '/symfony/config/Loader/DelegatingLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\DirectoryAwareLoaderInterface' => __DIR__ . '/..' . '/symfony/config/Loader/DirectoryAwareLoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/config/Loader/FileLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/config/Loader/GlobFileLoader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\Loader' => __DIR__ . '/..' . '/symfony/config/Loader/Loader.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolver' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderResolver.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\LoaderResolverInterface' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderResolverInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Loader\\ParamConfigurator' => __DIR__ . '/..' . '/symfony/config/Loader/ParamConfigurator.php', '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCache' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerConfigCache.php', '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerConfigCacheFactory' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerConfigCacheFactory.php', '_ContaoManager\\Symfony\\Component\\Config\\ResourceCheckerInterface' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ClassExistenceResource' => __DIR__ . '/..' . '/symfony/config/Resource/ClassExistenceResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ComposerResource' => __DIR__ . '/..' . '/symfony/config/Resource/ComposerResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\DirectoryResource' => __DIR__ . '/..' . '/symfony/config/Resource/DirectoryResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileExistenceResource' => __DIR__ . '/..' . '/symfony/config/Resource/FileExistenceResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\FileResource' => __DIR__ . '/..' . '/symfony/config/Resource/FileResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\GlobResource' => __DIR__ . '/..' . '/symfony/config/Resource/GlobResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ReflectionClassResource' => __DIR__ . '/..' . '/symfony/config/Resource/ReflectionClassResource.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\ResourceInterface' => __DIR__ . '/..' . '/symfony/config/Resource/ResourceInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceChecker' => __DIR__ . '/..' . '/symfony/config/Resource/SelfCheckingResourceChecker.php', '_ContaoManager\\Symfony\\Component\\Config\\Resource\\SelfCheckingResourceInterface' => __DIR__ . '/..' . '/symfony/config/Resource/SelfCheckingResourceInterface.php', '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\InvalidXmlException' => __DIR__ . '/..' . '/symfony/config/Util/Exception/InvalidXmlException.php', '_ContaoManager\\Symfony\\Component\\Config\\Util\\Exception\\XmlParsingException' => __DIR__ . '/..' . '/symfony/config/Util/Exception/XmlParsingException.php', '_ContaoManager\\Symfony\\Component\\Config\\Util\\XmlUtils' => __DIR__ . '/..' . '/symfony/config/Util/XmlUtils.php', '_ContaoManager\\Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php', '_ContaoManager\\Symfony\\Component\\Console\\Attribute\\AsCommand' => __DIR__ . '/..' . '/symfony/console/Attribute/AsCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => __DIR__ . '/..' . '/symfony/console/CI/GithubActionReporter.php', '_ContaoManager\\Symfony\\Component\\Console\\Color' => __DIR__ . '/..' . '/symfony/console/Color.php', '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php', '_ContaoManager\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\CompleteCommand' => __DIR__ . '/..' . '/symfony/console/Command/CompleteCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => __DIR__ . '/..' . '/symfony/console/Command/DumpCompletionCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\LazyCommand' => __DIR__ . '/..' . '/symfony/console/Command/LazyCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => __DIR__ . '/..' . '/symfony/console/Command/SignalableCommandInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Command\\TraceableCommand' => __DIR__ . '/..' . '/symfony/console/Command/TraceableCommand.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionInput' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionSuggestions.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/BashCompletionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => __DIR__ . '/..' . '/symfony/console/Completion/Output/CompletionOutputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\FishCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/FishCompletionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Output\\ZshCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/ZshCompletionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Completion\\Suggestion' => __DIR__ . '/..' . '/symfony/console/Completion/Suggestion.php', '_ContaoManager\\Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php', '_ContaoManager\\Symfony\\Component\\Console\\Cursor' => __DIR__ . '/..' . '/symfony/console/Cursor.php', '_ContaoManager\\Symfony\\Component\\Console\\DataCollector\\CommandDataCollector' => __DIR__ . '/..' . '/symfony/console/DataCollector/CommandDataCollector.php', '_ContaoManager\\Symfony\\Component\\Console\\Debug\\CliRequest' => __DIR__ . '/..' . '/symfony/console/Debug/CliRequest.php', '_ContaoManager\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\ReStructuredTextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/ReStructuredTextDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php', '_ContaoManager\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleSignalEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/symfony/console/Exception/MissingInputException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/NamespaceNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RunCommandFailedException' => __DIR__ . '/..' . '/symfony/console/Exception/RunCommandFailedException.php', '_ContaoManager\\Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatter.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatterStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php', '_ContaoManager\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/symfony/console/Helper/Dumper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\OutputWrapper' => __DIR__ . '/..' . '/symfony/console/Helper/OutputWrapper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableCellStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php', '_ContaoManager\\Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php', '_ContaoManager\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php', '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandContext' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandContext.php', '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessage' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandMessage.php', '_ContaoManager\\Symfony\\Component\\Console\\Messenger\\RunCommandMessageHandler' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandMessageHandler.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\AnsiColorMode' => __DIR__ . '/..' . '/symfony/console/Output/AnsiColorMode.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleSectionOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => __DIR__ . '/..' . '/symfony/console/Output/TrimmedBufferOutput.php', '_ContaoManager\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php', '_ContaoManager\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php', '_ContaoManager\\Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php', '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalMap' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalMap.php', '_ContaoManager\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalRegistry.php', '_ContaoManager\\Symfony\\Component\\Console\\SingleCommandApplication' => __DIR__ . '/..' . '/symfony/console/SingleCommandApplication.php', '_ContaoManager\\Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php', '_ContaoManager\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php', '_ContaoManager\\Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandCompletionTester.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => __DIR__ . '/..' . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php', '_ContaoManager\\Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/symfony/console/Tester/TesterTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Alias' => __DIR__ . '/..' . '/symfony/dependency-injection/Alias.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\AbstractArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/AbstractArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ArgumentInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ArgumentInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\BoundArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/BoundArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\IteratorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/IteratorArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\LazyClosure' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/LazyClosure.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ReferenceSetArgumentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/RewindableGenerator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceClosureArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceClosureArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocatorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceLocatorArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Argument\\TaggedIteratorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/TaggedIteratorArgument.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsAlias' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AsAlias.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsDecorator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AsDecorator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AsTaggedItem' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AsTaggedItem.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autoconfigure' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Autoconfigure.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutoconfigureTag' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutoconfigureTag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Autowire' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Autowire.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireCallable' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireCallable.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireDecorated' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireDecorated.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireIterator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireIterator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\AutowireServiceClosure' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireServiceClosure.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Exclude' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Exclude.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/MapDecorated.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedIterator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\Target' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Target.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Attribute\\When' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/When.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ChildDefinition' => __DIR__ . '/..' . '/symfony/dependency-injection/ChildDefinition.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AbstractRecursivePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AliasDeprecatedPublicServicesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AnalyzeServiceReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AttributeAutoconfigurationPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutoAliasServicePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutoAliasServicePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireAsDecoratorPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireAsDecoratorPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowirePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckReferenceValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CheckTypeDeclarationsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\Compiler' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/Compiler.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CompilerPassInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DecoratorServicePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/DecoratorServicePass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\DefinitionErrorExceptionPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ExtensionCompilerPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\InlineServiceDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\MergeExtensionConfigurationPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PassConfig' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/PassConfig.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\PriorityTaggedServiceTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterAutoconfigureAttributesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterEnvVarProcessorsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterReverseContainerPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RegisterServiceSubscribersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveAbstractDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveBuildParametersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveBuildParametersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveClassPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveDecoratorStackPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveEnvPlaceholdersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveFactoryClassPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveHotPathPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveHotPathPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInstanceofConditionalsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInvalidReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNamedArgumentsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNoPreloadPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveReferencesToAliasesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveServiceSubscribersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ResolveTaggedIteratorArgumentPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceLocatorTagPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraph' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphEdge' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphNode' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Compiler\\ValidateEnvPlaceholdersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResource' => __DIR__ . '/..' . '/symfony/dependency-injection/Config/ContainerParametersResource.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResourceChecker' => __DIR__ . '/..' . '/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Container' => __DIR__ . '/..' . '/symfony/dependency-injection/Container.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerAwareTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerBuilder' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerBuilder.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Definition' => __DIR__ . '/..' . '/symfony/dependency-injection/Definition.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Dumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/Dumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\DumperInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/DumperInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\GraphvizDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/GraphvizDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\PhpDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/PhpDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\Preloader' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/Preloader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\XmlDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/XmlDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Dumper\\YamlDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/YamlDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarLoaderInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessor.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessorInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/AutowiringFailedException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/BadMethodCallException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/EnvNotFoundException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\EnvParameterException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/EnvParameterException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidParameterTypeException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/InvalidParameterTypeException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/OutOfBoundsException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ParameterNotFoundException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ServiceNotFoundException.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguage' => __DIR__ . '/..' . '/symfony/dependency-injection/ExpressionLanguage.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/dependency-injection/ExpressionLanguageProvider.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\AbstractExtension' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/AbstractExtension.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurableExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ConfigurableExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ConfigurationExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\Extension' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/Extension.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\ExtensionTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ExtensionTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/PrependExtensionInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\InstantiatorInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\LazyServiceInstantiator' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/LazyServiceInstantiator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\RealServiceInstantiator' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\DumperInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\LazyServiceDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\NullDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\LazyProxy\\ProxyHelper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/ProxyHelper.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\ClosureLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/ClosureLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AliasConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ClosureReferenceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ContainerConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\DefaultsConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\EnvConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\FromCallableConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/FromCallableConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InlineServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InstanceofConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ParametersConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\PrototypeConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ReferenceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServicesConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AbstractTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ArgumentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutoconfigureTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutowireTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\BindTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\CallTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ClassTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConfiguratorTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConstructorTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ConstructorTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DecorateTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DeprecateTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FactoryTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FileTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FromCallableTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FromCallableTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\LazyTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ParentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PropertyTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PublicTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ShareTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\SyntheticTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\TagTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\DirectoryLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/DirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/FileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/GlobFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/IniFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/PhpFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/XmlFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/YamlFileLoader.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Parameter' => __DIR__ . '/..' . '/symfony/dependency-injection/Parameter.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ContainerBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBagInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ParameterBag.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Reference' => __DIR__ . '/..' . '/symfony/dependency-injection/Reference.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ReverseContainer' => __DIR__ . '/..' . '/symfony/dependency-injection/ReverseContainer.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\ServiceLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/ServiceLocator.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/TaggedContainerInterface.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\TypedReference' => __DIR__ . '/..' . '/symfony/dependency-injection/TypedReference.php', '_ContaoManager\\Symfony\\Component\\DependencyInjection\\Variable' => __DIR__ . '/..' . '/symfony/dependency-injection/Variable.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\BufferingLogger' => __DIR__ . '/..' . '/symfony/error-handler/BufferingLogger.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Debug' => __DIR__ . '/..' . '/symfony/error-handler/Debug.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\DebugClassLoader' => __DIR__ . '/..' . '/symfony/error-handler/DebugClassLoader.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ClassNotFoundErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ErrorEnhancerInterface' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedFunctionErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedMethodErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorHandler' => __DIR__ . '/..' . '/symfony/error-handler/ErrorHandler.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\CliErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\FileLinkFormatter' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\HtmlErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ErrorRenderer\\SerializerErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\ClassNotFoundError' => __DIR__ . '/..' . '/symfony/error-handler/Error/ClassNotFoundError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\FatalError' => __DIR__ . '/..' . '/symfony/error-handler/Error/FatalError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\OutOfMemoryError' => __DIR__ . '/..' . '/symfony/error-handler/Error/OutOfMemoryError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedFunctionError' => __DIR__ . '/..' . '/symfony/error-handler/Error/UndefinedFunctionError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Error\\UndefinedMethodError' => __DIR__ . '/..' . '/symfony/error-handler/Error/UndefinedMethodError.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\FlattenException' => __DIR__ . '/..' . '/symfony/error-handler/Exception/FlattenException.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => __DIR__ . '/..' . '/symfony/error-handler/Exception/SilencedErrorContext.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\Internal\\TentativeTypes' => __DIR__ . '/..' . '/symfony/error-handler/Internal/TentativeTypes.php', '_ContaoManager\\Symfony\\Component\\ErrorHandler\\ThrowableUtils' => __DIR__ . '/..' . '/symfony/error-handler/ThrowableUtils.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Attribute\\AsEventListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Attribute/AsEventListener.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/WrappedListener.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcher.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcherInterface.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventSubscriberInterface.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\GenericEvent' => __DIR__ . '/..' . '/symfony/event-dispatcher/GenericEvent.php', '_ContaoManager\\Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ImmutableEventDispatcher.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/filesystem/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/FileNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/IOException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface' => __DIR__ . '/..' . '/symfony/filesystem/Exception/IOExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Filesystem' => __DIR__ . '/..' . '/symfony/filesystem/Filesystem.php', '_ContaoManager\\Symfony\\Component\\Filesystem\\Path' => __DIR__ . '/..' . '/symfony/filesystem/Path.php', '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/finder/Exception/AccessDeniedException.php', '_ContaoManager\\Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => __DIR__ . '/..' . '/symfony/finder/Exception/DirectoryNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Finder\\Finder' => __DIR__ . '/..' . '/symfony/finder/Finder.php', '_ContaoManager\\Symfony\\Component\\Finder\\Gitignore' => __DIR__ . '/..' . '/symfony/finder/Gitignore.php', '_ContaoManager\\Symfony\\Component\\Finder\\Glob' => __DIR__ . '/..' . '/symfony/finder/Glob.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/CustomFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DateRangeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DepthRangeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\LazyIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/LazyIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', '_ContaoManager\\Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeader' => __DIR__ . '/..' . '/symfony/http-foundation/AcceptHeader.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\AcceptHeaderItem' => __DIR__ . '/..' . '/symfony/http-foundation/AcceptHeaderItem.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\BinaryFileResponse' => __DIR__ . '/..' . '/symfony/http-foundation/BinaryFileResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ChainRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/ChainRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Cookie' => __DIR__ . '/..' . '/symfony/http-foundation/Cookie.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/BadRequestException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\ConflictingHeadersException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/ConflictingHeadersException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\JsonException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/JsonException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\RequestExceptionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/RequestExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SessionNotFoundException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/SessionNotFoundException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\SuspiciousOperationException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/SuspiciousOperationException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Exception\\UnexpectedValueException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/UnexpectedValueException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ExpressionRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/ExpressionRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\FileBag' => __DIR__ . '/..' . '/symfony/http-foundation/FileBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/AccessDeniedException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\CannotWriteFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/CannotWriteFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\ExtensionFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/ExtensionFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FileNotFoundException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\FormSizeFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FormSizeFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\IniSizeFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/IniSizeFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/NoFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\NoTmpDirFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/NoTmpDirFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\PartialFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/PartialFileException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/UnexpectedTypeException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Exception\\UploadException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/UploadException.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\File' => __DIR__ . '/..' . '/symfony/http-foundation/File/File.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\Stream' => __DIR__ . '/..' . '/symfony/http-foundation/File/Stream.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile' => __DIR__ . '/..' . '/symfony/http-foundation/File/UploadedFile.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderBag' => __DIR__ . '/..' . '/symfony/http-foundation/HeaderBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\HeaderUtils' => __DIR__ . '/..' . '/symfony/http-foundation/HeaderUtils.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\InputBag' => __DIR__ . '/..' . '/symfony/http-foundation/InputBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\IpUtils' => __DIR__ . '/..' . '/symfony/http-foundation/IpUtils.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\JsonResponse' => __DIR__ . '/..' . '/symfony/http-foundation/JsonResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ParameterBag' => __DIR__ . '/..' . '/symfony/http-foundation/ParameterBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\AbstractRequestRateLimiter' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\PeekableRequestRateLimiterInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RateLimiter\\RequestRateLimiterInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RedirectResponse' => __DIR__ . '/..' . '/symfony/http-foundation/RedirectResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Request' => __DIR__ . '/..' . '/symfony/http-foundation/Request.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcherInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\AttributesRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\ExpressionRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\HostRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IpsRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\IsJsonRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\MethodRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PathRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\PortRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestMatcher\\SchemeRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\RequestStack' => __DIR__ . '/..' . '/symfony/http-foundation/RequestStack.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Response' => __DIR__ . '/..' . '/symfony/http-foundation/Response.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ResponseHeaderBag' => __DIR__ . '/..' . '/symfony/http-foundation/ResponseHeaderBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\ServerBag' => __DIR__ . '/..' . '/symfony/http-foundation/ServerBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Attribute/AttributeBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\FlashBagAwareSessionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\AutoExpireFlashBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/FlashBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/FlashBagInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Session' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Session.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionBagInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionBagProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionBagProxy.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionFactoryInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\SessionUtils' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionUtils.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\AbstractSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\IdentityMarshaller' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MarshallingSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcachedSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MigratingSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MongoDbSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NullSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\RedisSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\SessionHandlerFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\StrictSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MetadataBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MetadataBag.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/NativeSessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageFactoryInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/SessionStorageInterface.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedJsonResponse' => __DIR__ . '/..' . '/symfony/http-foundation/StreamedJsonResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\StreamedResponse' => __DIR__ . '/..' . '/symfony/http-foundation/StreamedResponse.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\RequestAttributeValueSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseCookieValueSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseFormatSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasCookie' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHasHeader' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderLocationSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseHeaderSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsRedirected' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsSuccessful' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseIsUnprocessable' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\Test\\Constraint\\ResponseStatusCodeSame' => __DIR__ . '/..' . '/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UriSigner' => __DIR__ . '/..' . '/symfony/http-foundation/UriSigner.php', '_ContaoManager\\Symfony\\Component\\HttpFoundation\\UrlHelper' => __DIR__ . '/..' . '/symfony/http-foundation/UrlHelper.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsController' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/AsController.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\AsTargetedValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/AsTargetedValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\Cache' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/Cache.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapDateTime' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapDateTime.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryParameter' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapQueryParameter.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapQueryString' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapQueryString.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\MapRequestPayload' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/MapRequestPayload.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\ValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/ValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithHttpStatus' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/WithHttpStatus.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Attribute\\WithLogLevel' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/WithLogLevel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/AbstractBundle.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\Bundle' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/Bundle.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleExtension' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/BundleExtension.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/BundleInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\CacheClearerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/CacheClearerInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\ChainCacheClearer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/ChainCacheClearer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheClearer\\Psr6CacheClearer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerAggregate' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\CacheWarmer\\WarmableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/WarmableInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Config\\FileLocator' => __DIR__ . '/..' . '/symfony/http-kernel/Config/FileLocator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactoryInterface' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\BackedEnumValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DateTimeValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\QueryParameterValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestPayloadValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\UidValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ContainerControllerResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerReference' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerReference.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ErrorController' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ErrorController.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/TraceableArgumentResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/TraceableControllerResolver.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Controller\\ValueResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ValueResolverInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\AjaxDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/AjaxDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ConfigDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/ConfigDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DataCollectorInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\DumpDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DumpDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\EventDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/EventDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\ExceptionDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/ExceptionDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LateDataCollectorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\LoggerDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/LoggerDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\MemoryDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/MemoryDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RequestDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/RequestDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\RouterDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/RouterDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DataCollector\\TimeDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/TimeDataCollector.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\ErrorHandlerConfigurator' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/FileLinkFormatter.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/TraceableEventDispatcher.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Debug\\VirtualRequestStack' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/VirtualRequestStack.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\AddAnnotatedClassesToCachePass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ConfigurableExtension' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ControllerArgumentValueResolverPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\Extension' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/Extension.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\FragmentRendererPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LazyLoadingFragmentHandler' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\LoggerPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/LoggerPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\MergeExtensionConfigurationPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterControllerArgumentLocatorsPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterLocaleAwareServicesPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\RemoveEmptyControllerArgumentLocatorsPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ResettableServicePass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ResettableServicePass.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ServicesResetter.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/AbstractSessionListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\AddRequestFormatsListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/AddRequestFormatsListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\CacheAttributeListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/CacheAttributeListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DebugHandlersListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DisallowRobotsIndexingListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\DumpListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DumpListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ErrorListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\FragmentListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/FragmentListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleAwareListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/LocaleAwareListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\LocaleListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/LocaleListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ProfilerListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ProfilerListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ResponseListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/RouterListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/SessionListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\StreamedResponseListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/StreamedResponseListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\SurrogateListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/SurrogateListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ValidateRequestListener.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerArgumentsEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ControllerArgumentsEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ControllerEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ControllerEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ExceptionEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ExceptionEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/FinishRequestEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\KernelEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/KernelEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\RequestEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/RequestEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ResponseEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ResponseEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\TerminateEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/TerminateEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Event\\ViewEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ViewEvent.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/AccessDeniedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/BadRequestHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ConflictHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ControllerDoesNotReturnResponseException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/GoneHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/HttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/HttpExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\InvalidMetadataException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/InvalidMetadataException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/LengthRequiredHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\LockedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/LockedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/NotAcceptableHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/NotFoundHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/PreconditionFailedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ResolverNotFoundException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ResolverNotFoundException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/TooManyRequestsHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnauthorizedHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnexpectedSessionUsageException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\AbstractSurrogateFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\EsiFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/EsiFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentHandler' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentHandler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentRendererInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGenerator' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentUriGenerator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGeneratorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\HIncludeFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\InlineFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/InlineFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Esi.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/HttpCache.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategyInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Ssi' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Ssi.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\Store' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Store.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/StoreInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SubRequestHandler' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/SubRequestHandler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpCache\\SurrogateInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/SurrogateInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpClientKernel' => __DIR__ . '/..' . '/symfony/http-kernel/HttpClientKernel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernel' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelBrowser' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernelBrowser.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\HttpKernelInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernelInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Kernel' => __DIR__ . '/..' . '/symfony/http-kernel/Kernel.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelEvents' => __DIR__ . '/..' . '/symfony/http-kernel/KernelEvents.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\KernelInterface' => __DIR__ . '/..' . '/symfony/http-kernel/KernelInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerConfigurator' => __DIR__ . '/..' . '/symfony/http-kernel/Log/DebugLoggerConfigurator.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Log/DebugLoggerInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Log\\Logger' => __DIR__ . '/..' . '/symfony/http-kernel/Log/Logger.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\FileProfilerStorage' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/FileProfilerStorage.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profile' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/Profile.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\Profiler' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/Profiler.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/ProfilerStorageInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\RebootableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/RebootableInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\TerminableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/TerminableInterface.php', '_ContaoManager\\Symfony\\Component\\HttpKernel\\UriSigner' => __DIR__ . '/..' . '/symfony/http-kernel/UriSigner.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Command\\UserPasswordHashCommand' => __DIR__ . '/..' . '/symfony/password-hasher/Command/UserPasswordHashCommand.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\InvalidPasswordException' => __DIR__ . '/..' . '/symfony/password-hasher/Exception/InvalidPasswordException.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/password-hasher/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\CheckPasswordLengthTrait' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/CheckPasswordLengthTrait.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MessageDigestPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/MessageDigestPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\MigratingPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/MigratingPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\NativePasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/NativePasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherAwareInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PasswordHasherAwareInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactory' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PasswordHasherFactory.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PasswordHasherFactoryInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PasswordHasherFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\Pbkdf2PasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/Pbkdf2PasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\PlaintextPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/PlaintextPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\SodiumPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/SodiumPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasher' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/UserPasswordHasher.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\Hasher\\UserPasswordHasherInterface' => __DIR__ . '/..' . '/symfony/password-hasher/Hasher/UserPasswordHasherInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\LegacyPasswordHasherInterface' => __DIR__ . '/..' . '/symfony/password-hasher/LegacyPasswordHasherInterface.php', '_ContaoManager\\Symfony\\Component\\PasswordHasher\\PasswordHasherInterface' => __DIR__ . '/..' . '/symfony/password-hasher/PasswordHasherInterface.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/process/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/process/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/process/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessFailedException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessSignaledException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessTimedOutException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/RunProcessFailedException.php', '_ContaoManager\\Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/process/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Process\\ExecutableFinder' => __DIR__ . '/..' . '/symfony/process/ExecutableFinder.php', '_ContaoManager\\Symfony\\Component\\Process\\InputStream' => __DIR__ . '/..' . '/symfony/process/InputStream.php', '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessContext' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessContext.php', '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessage' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessMessage.php', '_ContaoManager\\Symfony\\Component\\Process\\Messenger\\RunProcessMessageHandler' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessMessageHandler.php', '_ContaoManager\\Symfony\\Component\\Process\\PhpExecutableFinder' => __DIR__ . '/..' . '/symfony/process/PhpExecutableFinder.php', '_ContaoManager\\Symfony\\Component\\Process\\PhpProcess' => __DIR__ . '/..' . '/symfony/process/PhpProcess.php', '_ContaoManager\\Symfony\\Component\\Process\\PhpSubprocess' => __DIR__ . '/..' . '/symfony/process/PhpSubprocess.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/AbstractPipes.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => __DIR__ . '/..' . '/symfony/process/Pipes/PipesInterface.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/UnixPipes.php', '_ContaoManager\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/WindowsPipes.php', '_ContaoManager\\Symfony\\Component\\Process\\Process' => __DIR__ . '/..' . '/symfony/process/Process.php', '_ContaoManager\\Symfony\\Component\\Process\\ProcessUtils' => __DIR__ . '/..' . '/symfony/process/ProcessUtils.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/property-access/Exception/AccessException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/property-access/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidPropertyPathException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchIndexException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchPropertyException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/property-access/Exception/OutOfBoundsException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UnexpectedTypeException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UninitializedPropertyException.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccess' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccess.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessor' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessor.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorBuilder.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPath' => __DIR__ . '/..' . '/symfony/property-access/PropertyPath.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathBuilder.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIterator.php', '_ContaoManager\\Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIteratorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpDocExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpStanExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ReflectionExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/SerializerExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScope' => __DIR__ . '/..' . '/symfony/property-info/PhpStan/NameScope.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PhpStan\\NameScopeFactory' => __DIR__ . '/..' . '/symfony/property-info/PhpStan/NameScopeFactory.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyAccessExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyDescriptionExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoCacheExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractor.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInitializableExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyListExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfo.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfoExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyTypeExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfo.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Type' => __DIR__ . '/..' . '/symfony/property-info/Type.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpDocTypeHelper.php', '_ContaoManager\\Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpStanTypeHelper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Alias' => __DIR__ . '/..' . '/symfony/routing/Alias.php', '_ContaoManager\\Symfony\\Component\\Routing\\Annotation\\Route' => __DIR__ . '/..' . '/symfony/routing/Annotation/Route.php', '_ContaoManager\\Symfony\\Component\\Routing\\Attribute\\Route' => __DIR__ . '/..' . '/symfony/routing/Attribute/Route.php', '_ContaoManager\\Symfony\\Component\\Routing\\CompiledRoute' => __DIR__ . '/..' . '/symfony/routing/CompiledRoute.php', '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\AddExpressionLanguageProvidersPass' => __DIR__ . '/..' . '/symfony/routing/DependencyInjection/AddExpressionLanguageProvidersPass.php', '_ContaoManager\\Symfony\\Component\\Routing\\DependencyInjection\\RoutingResolverPass' => __DIR__ . '/..' . '/symfony/routing/DependencyInjection/RoutingResolverPass.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/routing/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidParameterException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => __DIR__ . '/..' . '/symfony/routing/Exception/MethodNotAllowedException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => __DIR__ . '/..' . '/symfony/routing/Exception/MissingMandatoryParametersException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => __DIR__ . '/..' . '/symfony/routing/Exception/NoConfigurationException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException' => __DIR__ . '/..' . '/symfony/routing/Exception/ResourceNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteCircularReferenceException' => __DIR__ . '/..' . '/symfony/routing/Exception/RouteCircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RouteNotFoundException' => __DIR__ . '/..' . '/symfony/routing/Exception/RouteNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/routing/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator' => __DIR__ . '/..' . '/symfony/routing/Generator/CompiledUrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\ConfigurableRequirementsInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/ConfigurableRequirementsInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumper' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/GeneratorDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumperInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGenerator' => __DIR__ . '/..' . '/symfony/routing/Generator/UrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/UrlGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationClassLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationClassLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationDirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationDirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AnnotationFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeClassLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AttributeClassLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeDirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AttributeDirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\AttributeFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AttributeFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ClosureLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ClosureLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\AliasConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/AliasConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\CollectionConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/CollectionConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/ImportConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RouteConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/RouteConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/RoutingConfigurator.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\AddTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/AddTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\HostTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/HostTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\LocalizedRouteTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\PrefixTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\RouteTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/RouteTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ContainerLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ContainerLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\DirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/DirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/GlobFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\ObjectLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ObjectLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/PhpFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\Psr4DirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/Psr4DirectoryLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/XmlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/YamlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\CompiledUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/CompiledUrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherTrait' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumper' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/MatcherDumper.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumperInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\Dumper\\StaticPrefixCollection' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/routing/Matcher/ExpressionLanguageProvider.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/RedirectableUrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\RequestMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/RequestMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\TraceableUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/TraceableUrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/UrlMatcher.php', '_ContaoManager\\Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/UrlMatcherInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\RequestContext' => __DIR__ . '/..' . '/symfony/routing/RequestContext.php', '_ContaoManager\\Symfony\\Component\\Routing\\RequestContextAwareInterface' => __DIR__ . '/..' . '/symfony/routing/RequestContextAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\EnumRequirement' => __DIR__ . '/..' . '/symfony/routing/Requirement/EnumRequirement.php', '_ContaoManager\\Symfony\\Component\\Routing\\Requirement\\Requirement' => __DIR__ . '/..' . '/symfony/routing/Requirement/Requirement.php', '_ContaoManager\\Symfony\\Component\\Routing\\Route' => __DIR__ . '/..' . '/symfony/routing/Route.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouteCollection' => __DIR__ . '/..' . '/symfony/routing/RouteCollection.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompiler' => __DIR__ . '/..' . '/symfony/routing/RouteCompiler.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouteCompilerInterface' => __DIR__ . '/..' . '/symfony/routing/RouteCompilerInterface.php', '_ContaoManager\\Symfony\\Component\\Routing\\Router' => __DIR__ . '/..' . '/symfony/routing/Router.php', '_ContaoManager\\Symfony\\Component\\Routing\\RouterInterface' => __DIR__ . '/..' . '/symfony/routing/RouterInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\AuthenticationEvents' => __DIR__ . '/..' . '/symfony/security-core/AuthenticationEvents.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolver' => __DIR__ . '/..' . '/symfony/security-core/Authentication/AuthenticationTrustResolver.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\CacheTokenVerifier' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/CacheTokenVerifier.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\InMemoryTokenProvider' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/InMemoryTokenProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/PersistentToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\PersistentTokenInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/PersistentTokenInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenProviderInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/TokenProviderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\RememberMe\\TokenVerifierInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/RememberMe/TokenVerifierInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\AbstractToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/AbstractToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\NullToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/NullToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\PreAuthenticatedToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/PreAuthenticatedToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/RememberMeToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorage' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/Storage/TokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/Storage/TokenStorageInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\UsageTrackingTokenStorage' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/Storage/UsageTrackingTokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\SwitchUserToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/SwitchUserToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/TokenInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken' => __DIR__ . '/..' . '/symfony/security-core/Authentication/Token/UsernamePasswordToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AccessDecisionManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AccessDecisionManagerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AuthorizationChecker.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationCheckerInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/AuthorizationCheckerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguage' => __DIR__ . '/..' . '/symfony/security-core/Authorization/ExpressionLanguage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/security-core/Authorization/ExpressionLanguageProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AccessDecisionStrategyInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/AccessDecisionStrategyInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AffirmativeStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/AffirmativeStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\ConsensusStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/ConsensusStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\PriorityStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/PriorityStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\UnanimousStrategy' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Strategy/UnanimousStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\TraceableAccessDecisionManager' => __DIR__ . '/..' . '/symfony/security-core/Authorization/TraceableAccessDecisionManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AuthenticatedVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/AuthenticatedVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/CacheableVoterInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\ExpressionVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/ExpressionVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleHierarchyVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/RoleHierarchyVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\RoleVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/RoleVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\TraceableVoter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/TraceableVoter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\Voter' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/Voter.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface' => __DIR__ . '/..' . '/symfony/security-core/Authorization/Voter/VoterInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationEvent' => __DIR__ . '/..' . '/symfony/security-core/Event/AuthenticationEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\AuthenticationSuccessEvent' => __DIR__ . '/..' . '/symfony/security-core/Event/AuthenticationSuccessEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Event\\VoteEvent' => __DIR__ . '/..' . '/symfony/security-core/Event/VoteEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AccessDeniedException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountExpiredException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AccountExpiredException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AccountStatusException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AccountStatusException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationCredentialsNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationExpiredException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\AuthenticationServiceException' => __DIR__ . '/..' . '/symfony/security-core/Exception/AuthenticationServiceException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException' => __DIR__ . '/..' . '/symfony/security-core/Exception/BadCredentialsException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CookieTheftException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CookieTheftException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CredentialsExpiredException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CredentialsExpiredException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAccountStatusException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CustomUserMessageAccountStatusException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\CustomUserMessageAuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/CustomUserMessageAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\DisabledException' => __DIR__ . '/..' . '/symfony/security-core/Exception/DisabledException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/security-core/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InsufficientAuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/InsufficientAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/security-core/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\InvalidCsrfTokenException' => __DIR__ . '/..' . '/symfony/security-core/Exception/InvalidCsrfTokenException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LazyResponseException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LazyResponseException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LockedException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LockedException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\LogoutException' => __DIR__ . '/..' . '/symfony/security-core/Exception/LogoutException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\ProviderNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/ProviderNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/security-core/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\SessionUnavailableException' => __DIR__ . '/..' . '/symfony/security-core/Exception/SessionUnavailableException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TokenNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/TokenNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\TooManyLoginAttemptsAuthenticationException' => __DIR__ . '/..' . '/symfony/security-core/Exception/TooManyLoginAttemptsAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UnsupportedUserException' => __DIR__ . '/..' . '/symfony/security-core/Exception/UnsupportedUserException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Exception\\UserNotFoundException' => __DIR__ . '/..' . '/symfony/security-core/Exception/UserNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\Role' => __DIR__ . '/..' . '/symfony/security-core/Role/Role.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchy' => __DIR__ . '/..' . '/symfony/security-core/Role/RoleHierarchy.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\RoleHierarchyInterface' => __DIR__ . '/..' . '/symfony/security-core/Role/RoleHierarchyInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Role\\SwitchUserRole' => __DIR__ . '/..' . '/symfony/security-core/Role/SwitchUserRole.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Security' => __DIR__ . '/..' . '/symfony/security-core/Security.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\ExpiredSignatureException' => __DIR__ . '/..' . '/symfony/security-core/Signature/Exception/ExpiredSignatureException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\Exception\\InvalidSignatureException' => __DIR__ . '/..' . '/symfony/security-core/Signature/Exception/InvalidSignatureException.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\ExpiredSignatureStorage' => __DIR__ . '/..' . '/symfony/security-core/Signature/ExpiredSignatureStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Signature\\SignatureHasher' => __DIR__ . '/..' . '/symfony/security-core/Signature/SignatureHasher.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Test\\AccessDecisionStrategyTestCase' => __DIR__ . '/..' . '/symfony/security-core/Test/AccessDecisionStrategyTestCase.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\AttributesBasedUserProviderInterface' => __DIR__ . '/..' . '/symfony/security-core/User/AttributesBasedUserProviderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserChecker' => __DIR__ . '/..' . '/symfony/security-core/User/ChainUserChecker.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\ChainUserProvider' => __DIR__ . '/..' . '/symfony/security-core/User/ChainUserProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\EquatableInterface' => __DIR__ . '/..' . '/symfony/security-core/User/EquatableInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUser' => __DIR__ . '/..' . '/symfony/security-core/User/InMemoryUser.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserChecker' => __DIR__ . '/..' . '/symfony/security-core/User/InMemoryUserChecker.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\InMemoryUserProvider' => __DIR__ . '/..' . '/symfony/security-core/User/InMemoryUserProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\LegacyPasswordAuthenticatedUserInterface' => __DIR__ . '/..' . '/symfony/security-core/User/LegacyPasswordAuthenticatedUserInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\MissingUserProvider' => __DIR__ . '/..' . '/symfony/security-core/User/MissingUserProvider.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\OidcUser' => __DIR__ . '/..' . '/symfony/security-core/User/OidcUser.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordAuthenticatedUserInterface' => __DIR__ . '/..' . '/symfony/security-core/User/PasswordAuthenticatedUserInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\PasswordUpgraderInterface' => __DIR__ . '/..' . '/symfony/security-core/User/PasswordUpgraderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface' => __DIR__ . '/..' . '/symfony/security-core/User/UserCheckerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserInterface' => __DIR__ . '/..' . '/symfony/security-core/User/UserInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\User\\UserProviderInterface' => __DIR__ . '/..' . '/symfony/security-core/User/UserProviderInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPassword' => __DIR__ . '/..' . '/symfony/security-core/Validator/Constraints/UserPassword.php', '_ContaoManager\\Symfony\\Component\\Security\\Core\\Validator\\Constraints\\UserPasswordValidator' => __DIR__ . '/..' . '/symfony/security-core/Validator/Constraints/UserPasswordValidator.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfToken' => __DIR__ . '/..' . '/symfony/security-csrf/CsrfToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManager' => __DIR__ . '/..' . '/symfony/security-csrf/CsrfTokenManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\CsrfTokenManagerInterface' => __DIR__ . '/..' . '/symfony/security-csrf/CsrfTokenManagerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\Exception\\TokenNotFoundException' => __DIR__ . '/..' . '/symfony/security-csrf/Exception/TokenNotFoundException.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\TokenGeneratorInterface' => __DIR__ . '/..' . '/symfony/security-csrf/TokenGenerator/TokenGeneratorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenGenerator\\UriSafeTokenGenerator' => __DIR__ . '/..' . '/symfony/security-csrf/TokenGenerator/UriSafeTokenGenerator.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\ClearableTokenStorageInterface' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/ClearableTokenStorageInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\NativeSessionTokenStorage' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/NativeSessionTokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\SessionTokenStorage' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/SessionTokenStorage.php', '_ContaoManager\\Symfony\\Component\\Security\\Csrf\\TokenStorage\\TokenStorageInterface' => __DIR__ . '/..' . '/symfony/security-csrf/TokenStorage/TokenStorageInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMap' => __DIR__ . '/..' . '/symfony/security-http/AccessMap.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessMapInterface' => __DIR__ . '/..' . '/symfony/security-http/AccessMapInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenExtractorInterface' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/AccessTokenExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/AccessTokenHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\ChainAccessTokenExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/ChainAccessTokenExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\FormEncodedBodyExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/FormEncodedBodyExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\HeaderAccessTokenExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/HeaderAccessTokenExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\InvalidSignatureException' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/Exception/InvalidSignatureException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\Exception\\MissingClaimException' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/Exception/MissingClaimException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTokenHandler' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/OidcTokenHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcTrait' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/OidcTrait.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\Oidc\\OidcUserInfoTokenHandler' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/Oidc/OidcUserInfoTokenHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\AccessToken\\QueryAccessTokenExtractor' => __DIR__ . '/..' . '/symfony/security-http/AccessToken/QueryAccessTokenExtractor.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\CurrentUser' => __DIR__ . '/..' . '/symfony/security-http/Attribute/CurrentUser.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Attribute\\IsGranted' => __DIR__ . '/..' . '/symfony/security-http/Attribute/IsGranted.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticationFailureHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationSuccessHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticationSuccessHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationUtils' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticationUtils.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManager' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticatorManager.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\AuthenticatorManagerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/AuthenticatorManagerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationFailureHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/CustomAuthenticationFailureHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\CustomAuthenticationSuccessHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/CustomAuthenticationSuccessHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationFailureHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/DefaultAuthenticationFailureHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\DefaultAuthenticationSuccessHandler' => __DIR__ . '/..' . '/symfony/security-http/Authentication/DefaultAuthenticationSuccessHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authentication\\UserAuthenticatorInterface' => __DIR__ . '/..' . '/symfony/security-http/Authentication/UserAuthenticatorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AbstractAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractLoginFormAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AbstractLoginFormAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AbstractPreAuthenticatedAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AbstractPreAuthenticatedAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AccessTokenAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AccessTokenAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\AuthenticatorInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/AuthenticatorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticatorManagerListener' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Debug/TraceableAuthenticatorManagerListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FallbackUserLoader' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/FallbackUserLoader.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\FormLoginAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/FormLoginAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\HttpBasicAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/HttpBasicAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\InteractiveAuthenticatorInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/InteractiveAuthenticatorInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\JsonLoginAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/JsonLoginAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\LoginLinkAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/LoginLinkAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\BadgeInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/BadgeInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\CsrfTokenBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/CsrfTokenBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PasswordUpgradeBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\PreAuthenticatedUserBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/PreAuthenticatedUserBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\RememberMeBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/RememberMeBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Badge\\UserBadge' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Badge/UserBadge.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CredentialsInterface' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Credentials/CredentialsInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\CustomCredentials' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Credentials/CustomCredentials.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Credentials\\PasswordCredentials' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Credentials/PasswordCredentials.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\Passport' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/Passport.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Passport\\SelfValidatingPassport' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Passport/SelfValidatingPassport.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RememberMeAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/RememberMeAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\RemoteUserAuthenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/RemoteUserAuthenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\Token\\PostAuthenticationToken' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/Token/PostAuthenticationToken.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authenticator\\X509Authenticator' => __DIR__ . '/..' . '/symfony/security-http/Authenticator/X509Authenticator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Authorization\\AccessDeniedHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/Authorization/AccessDeniedHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\SecurityTokenValueResolver' => __DIR__ . '/..' . '/symfony/security-http/Controller/SecurityTokenValueResolver.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Controller\\UserValueResolver' => __DIR__ . '/..' . '/symfony/security-http/Controller/UserValueResolver.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface' => __DIR__ . '/..' . '/symfony/security-http/EntryPoint/AuthenticationEntryPointInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EntryPoint\\Exception\\NotAnEntryPointException' => __DIR__ . '/..' . '/symfony/security-http/EntryPoint/Exception/NotAnEntryPointException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckCredentialsListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CheckCredentialsListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CheckRememberMeConditionsListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CheckRememberMeConditionsListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\ClearSiteDataLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/ClearSiteDataLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CookieClearingLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CookieClearingLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfProtectionListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CsrfProtectionListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\CsrfTokenClearingLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/CsrfTokenClearingLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\DefaultLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/DefaultLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\IsGrantedAttributeListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/IsGrantedAttributeListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\LoginThrottlingListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/LoginThrottlingListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\PasswordMigratingListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/PasswordMigratingListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\RememberMeListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/RememberMeListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionLogoutListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/SessionLogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\SessionStrategyListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/SessionStrategyListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserCheckerListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/UserCheckerListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\EventListener\\UserProviderListener' => __DIR__ . '/..' . '/symfony/security-http/EventListener/UserProviderListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\AuthenticationTokenCreatedEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/AuthenticationTokenCreatedEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\CheckPassportEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/CheckPassportEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\InteractiveLoginEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/InteractiveLoginEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LazyResponseEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LazyResponseEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginFailureEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LoginFailureEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LoginSuccessEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LoginSuccessEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\LogoutEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/LogoutEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\SwitchUserEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/SwitchUserEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Event\\TokenDeauthenticatedEvent' => __DIR__ . '/..' . '/symfony/security-http/Event/TokenDeauthenticatedEvent.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall' => __DIR__ . '/..' . '/symfony/security-http/Firewall.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMap' => __DIR__ . '/..' . '/symfony/security-http/FirewallMap.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\FirewallMapInterface' => __DIR__ . '/..' . '/symfony/security-http/FirewallMapInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AbstractListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/AbstractListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AccessListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/AccessListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\AuthenticatorManagerListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/AuthenticatorManagerListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ChannelListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/ChannelListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ContextListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/ContextListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\ExceptionListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/ExceptionListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\FirewallListenerInterface' => __DIR__ . '/..' . '/symfony/security-http/Firewall/FirewallListenerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\LogoutListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/LogoutListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Firewall\\SwitchUserListener' => __DIR__ . '/..' . '/symfony/security-http/Firewall/SwitchUserListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\HttpUtils' => __DIR__ . '/..' . '/symfony/security-http/HttpUtils.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Impersonate\\ImpersonateUrlGenerator' => __DIR__ . '/..' . '/symfony/security-http/Impersonate/ImpersonateUrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\ExpiredLoginLinkException' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/ExpiredLoginLinkException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkAuthenticationException' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkAuthenticationException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkException' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkException.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\Exception\\InvalidLoginLinkExceptionInterface' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/Exception/InvalidLoginLinkExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkDetails' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkDetails.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandler' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\LoginLink\\LoginLinkNotification' => __DIR__ . '/..' . '/symfony/security-http/LoginLink/LoginLinkNotification.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Logout\\LogoutUrlGenerator' => __DIR__ . '/..' . '/symfony/security-http/Logout/LogoutUrlGenerator.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\ParameterBagUtils' => __DIR__ . '/..' . '/symfony/security-http/ParameterBagUtils.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RateLimiter\\DefaultLoginRateLimiter' => __DIR__ . '/..' . '/symfony/security-http/RateLimiter/DefaultLoginRateLimiter.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\AbstractRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/AbstractRememberMeHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\PersistentRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/PersistentRememberMeHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeDetails' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/RememberMeDetails.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\RememberMeHandlerInterface' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/RememberMeHandlerInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\ResponseListener' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/ResponseListener.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\RememberMe\\SignatureRememberMeHandler' => __DIR__ . '/..' . '/symfony/security-http/RememberMe/SignatureRememberMeHandler.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityEvents' => __DIR__ . '/..' . '/symfony/security-http/SecurityEvents.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\SecurityRequestAttributes' => __DIR__ . '/..' . '/symfony/security-http/SecurityRequestAttributes.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategy' => __DIR__ . '/..' . '/symfony/security-http/Session/SessionAuthenticationStrategy.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Session\\SessionAuthenticationStrategyInterface' => __DIR__ . '/..' . '/symfony/security-http/Session/SessionAuthenticationStrategyInterface.php', '_ContaoManager\\Symfony\\Component\\Security\\Http\\Util\\TargetPathTrait' => __DIR__ . '/..' . '/symfony/security-http/Util/TargetPathTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Context' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Context.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\DiscriminatorMap' => __DIR__ . '/..' . '/symfony/serializer/Annotation/DiscriminatorMap.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Groups' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Groups.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\Ignore' => __DIR__ . '/..' . '/symfony/serializer/Annotation/Ignore.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\MaxDepth' => __DIR__ . '/..' . '/symfony/serializer/Annotation/MaxDepth.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedName' => __DIR__ . '/..' . '/symfony/serializer/Annotation/SerializedName.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Annotation\\SerializedPath' => __DIR__ . '/..' . '/symfony/serializer/Annotation/SerializedPath.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Context' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Context.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\DiscriminatorMap' => __DIR__ . '/..' . '/symfony/serializer/Attribute/DiscriminatorMap.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Groups' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Groups.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\Ignore' => __DIR__ . '/..' . '/symfony/serializer/Attribute/Ignore.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\MaxDepth' => __DIR__ . '/..' . '/symfony/serializer/Attribute/MaxDepth.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedName' => __DIR__ . '/..' . '/symfony/serializer/Attribute/SerializedName.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Attribute\\SerializedPath' => __DIR__ . '/..' . '/symfony/serializer/Attribute/SerializedPath.php', '_ContaoManager\\Symfony\\Component\\Serializer\\CacheWarmer\\CompiledClassMetadataCacheWarmer' => __DIR__ . '/..' . '/symfony/serializer/CacheWarmer/CompiledClassMetadataCacheWarmer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/serializer/Command/DebugCommand.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderInterface' => __DIR__ . '/..' . '/symfony/serializer/Context/ContextBuilderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\ContextBuilderTrait' => __DIR__ . '/..' . '/symfony/serializer/Context/ContextBuilderTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\CsvEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/CsvEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\JsonEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/JsonEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\XmlEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/XmlEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Encoder\\YamlEncoderContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Encoder/YamlEncoderContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/AbstractNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\AbstractObjectNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\BackedEnumNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/BackedEnumNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ConstraintViolationListNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ConstraintViolationListNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateIntervalNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/DateIntervalNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\DateTimeNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\FormErrorNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/FormErrorNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\GetSetMethodNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/GetSetMethodNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\JsonSerializableNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/JsonSerializableNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ObjectNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ObjectNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\ProblemNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/ProblemNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\PropertyNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/PropertyNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UidNormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/UidNormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\Normalizer\\UnwrappingDenormalizerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/Normalizer/UnwrappingDenormalizerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Context\\SerializerContextBuilder' => __DIR__ . '/..' . '/symfony/serializer/Context/SerializerContextBuilder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\DataCollector\\SerializerDataCollector' => __DIR__ . '/..' . '/symfony/serializer/DataCollector/SerializerDataCollector.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableEncoder' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Debug\\TraceableSerializer' => __DIR__ . '/..' . '/symfony/serializer/Debug/TraceableSerializer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\DependencyInjection\\SerializerPass' => __DIR__ . '/..' . '/symfony/serializer/DependencyInjection/SerializerPass.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainDecoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ChainDecoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ChainEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ChainEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareDecoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ContextAwareDecoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\ContextAwareEncoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/ContextAwareEncoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\CsvEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/CsvEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\DecoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/DecoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\EncoderInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/EncoderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonDecode' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonDecode.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncode' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonEncode.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\JsonEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/JsonEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\NormalizationAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Encoder/NormalizationAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\XmlEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/XmlEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Encoder\\YamlEncoder' => __DIR__ . '/..' . '/symfony/serializer/Encoder/YamlEncoder.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/serializer/Exception/BadMethodCallException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\CircularReferenceException' => __DIR__ . '/..' . '/symfony/serializer/Exception/CircularReferenceException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/serializer/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\ExtraAttributesException' => __DIR__ . '/..' . '/symfony/serializer/Exception/ExtraAttributesException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/serializer/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/serializer/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MappingException' => __DIR__ . '/..' . '/symfony/serializer/Exception/MappingException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\MissingConstructorArgumentsException' => __DIR__ . '/..' . '/symfony/serializer/Exception/MissingConstructorArgumentsException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotEncodableValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/NotEncodableValueException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\NotNormalizableValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/NotNormalizableValueException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\PartialDenormalizationException' => __DIR__ . '/..' . '/symfony/serializer/Exception/PartialDenormalizationException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/serializer/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnexpectedValueException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnexpectedValueException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnsupportedException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Exception\\UnsupportedFormatException' => __DIR__ . '/..' . '/symfony/serializer/Exception/UnsupportedFormatException.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractor' => __DIR__ . '/..' . '/symfony/serializer/Extractor/ObjectPropertyListExtractor.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Extractor\\ObjectPropertyListExtractorInterface' => __DIR__ . '/..' . '/symfony/serializer/Extractor/ObjectPropertyListExtractorInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/AttributeMetadata.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\AttributeMetadataInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/AttributeMetadataInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorFromClassMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorMapping' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorMapping.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassDiscriminatorResolverInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassDiscriminatorResolverInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadata' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassMetadata.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\ClassMetadataInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/ClassMetadataInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CacheClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryCompiler' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactoryInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassMetadataFactoryInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassResolverTrait' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/ClassResolverTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Factory\\CompiledClassMetadataFactory' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Factory/CompiledClassMetadataFactory.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AnnotationLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/AnnotationLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\AttributeLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/AttributeLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/FileLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderChain' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/LoaderChain.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/LoaderInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/XmlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Mapping\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/serializer/Mapping/Loader/YamlFileLoader.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\AdvancedNameConverterInterface' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/AdvancedNameConverterInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\CamelCaseToSnakeCaseNameConverter' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\MetadataAwareNameConverter' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/MetadataAwareNameConverter.php', '_ContaoManager\\Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface' => __DIR__ . '/..' . '/symfony/serializer/NameConverter/NameConverterInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/AbstractNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/AbstractObjectNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ArrayDenormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\BackedEnumNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/BackedEnumNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CacheableSupportsMethodInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/CacheableSupportsMethodInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ConstraintViolationListNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ConstraintViolationListNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareDenormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ContextAwareDenormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ContextAwareNormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ContextAwareNormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\CustomNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/CustomNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DataUriNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DataUriNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateIntervalNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateIntervalNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateTimeNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DateTimeZoneNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DateTimeZoneNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizableInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizableInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/DenormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\FormErrorNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/FormErrorNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/GetSetMethodNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\JsonSerializableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/JsonSerializableNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\MimeMessageNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/MimeMessageNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizableInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizableInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/NormalizerInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ObjectNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ObjectToPopulateTrait' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ObjectToPopulateTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\ProblemNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/ProblemNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/PropertyNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\TranslatableNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/TranslatableNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UidNormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/UidNormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Normalizer\\UnwrappingDenormalizer' => __DIR__ . '/..' . '/symfony/serializer/Normalizer/UnwrappingDenormalizer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\Serializer' => __DIR__ . '/..' . '/symfony/serializer/Serializer.php', '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareInterface' => __DIR__ . '/..' . '/symfony/serializer/SerializerAwareInterface.php', '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerAwareTrait' => __DIR__ . '/..' . '/symfony/serializer/SerializerAwareTrait.php', '_ContaoManager\\Symfony\\Component\\Serializer\\SerializerInterface' => __DIR__ . '/..' . '/symfony/serializer/SerializerInterface.php', '_ContaoManager\\Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/symfony/string/AbstractString.php', '_ContaoManager\\Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/symfony/string/AbstractUnicodeString.php', '_ContaoManager\\Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/symfony/string/ByteString.php', '_ContaoManager\\Symfony\\Component\\String\\CodePointString' => __DIR__ . '/..' . '/symfony/string/CodePointString.php', '_ContaoManager\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/string/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/string/Exception/InvalidArgumentException.php', '_ContaoManager\\Symfony\\Component\\String\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/string/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/EnglishInflector.php', '_ContaoManager\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/FrenchInflector.php', '_ContaoManager\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => __DIR__ . '/..' . '/symfony/string/Inflector/InflectorInterface.php', '_ContaoManager\\Symfony\\Component\\String\\LazyString' => __DIR__ . '/..' . '/symfony/string/LazyString.php', '_ContaoManager\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => __DIR__ . '/..' . '/symfony/string/Slugger/AsciiSlugger.php', '_ContaoManager\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => __DIR__ . '/..' . '/symfony/string/Slugger/SluggerInterface.php', '_ContaoManager\\Symfony\\Component\\String\\UnicodeString' => __DIR__ . '/..' . '/symfony/string/UnicodeString.php', '_ContaoManager\\Symfony\\Component\\Uid\\AbstractUid' => __DIR__ . '/..' . '/symfony/uid/AbstractUid.php', '_ContaoManager\\Symfony\\Component\\Uid\\BinaryUtil' => __DIR__ . '/..' . '/symfony/uid/BinaryUtil.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUlidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/GenerateUlidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\GenerateUuidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/GenerateUuidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUlidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/InspectUlidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Command\\InspectUuidCommand' => __DIR__ . '/..' . '/symfony/uid/Command/InspectUuidCommand.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\NameBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/NameBasedUuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\RandomBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/RandomBasedUuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\TimeBasedUuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/TimeBasedUuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UlidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/UlidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\Factory\\UuidFactory' => __DIR__ . '/..' . '/symfony/uid/Factory/UuidFactory.php', '_ContaoManager\\Symfony\\Component\\Uid\\MaxUlid' => __DIR__ . '/..' . '/symfony/uid/MaxUlid.php', '_ContaoManager\\Symfony\\Component\\Uid\\MaxUuid' => __DIR__ . '/..' . '/symfony/uid/MaxUuid.php', '_ContaoManager\\Symfony\\Component\\Uid\\NilUlid' => __DIR__ . '/..' . '/symfony/uid/NilUlid.php', '_ContaoManager\\Symfony\\Component\\Uid\\NilUuid' => __DIR__ . '/..' . '/symfony/uid/NilUuid.php', '_ContaoManager\\Symfony\\Component\\Uid\\TimeBasedUidInterface' => __DIR__ . '/..' . '/symfony/uid/TimeBasedUidInterface.php', '_ContaoManager\\Symfony\\Component\\Uid\\Ulid' => __DIR__ . '/..' . '/symfony/uid/Ulid.php', '_ContaoManager\\Symfony\\Component\\Uid\\Uuid' => __DIR__ . '/..' . '/symfony/uid/Uuid.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV1' => __DIR__ . '/..' . '/symfony/uid/UuidV1.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV3' => __DIR__ . '/..' . '/symfony/uid/UuidV3.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV4' => __DIR__ . '/..' . '/symfony/uid/UuidV4.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV5' => __DIR__ . '/..' . '/symfony/uid/UuidV5.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV6' => __DIR__ . '/..' . '/symfony/uid/UuidV6.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV7' => __DIR__ . '/..' . '/symfony/uid/UuidV7.php', '_ContaoManager\\Symfony\\Component\\Uid\\UuidV8' => __DIR__ . '/..' . '/symfony/uid/UuidV8.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\AmqpCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/AmqpCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ArgsStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ArgsStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\Caster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/Caster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ClassStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ClassStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ConstStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ConstStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/CutArrayStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\CutStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/CutStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DOMCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DOMCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DateCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DateCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DoctrineCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DsCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DsPairStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\EnumStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/EnumStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ExceptionCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FFICaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FFICaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FiberCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FiberCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\FrameStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FrameStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\GmpCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/GmpCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImagineCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ImagineCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ImgStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ImgStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\IntlCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/IntlCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\LinkStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/LinkStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/MemcachedCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\MysqliCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/MysqliCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PdoCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/PdoCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/PgSqlCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ProxyManagerCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/RdKafkaCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\RedisCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/RedisCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ReflectionCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ResourceCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ResourceCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\ScalarStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ScalarStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SplCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/SplCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\StubCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/StubCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/SymfonyCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\TraceStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/TraceStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UninitializedStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/UninitializedStub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\UuidCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/UuidCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/XmlReaderCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/XmlResourceCaster.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/AbstractCloner.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\ClonerInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/ClonerInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Cursor' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Cursor.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Data' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Data.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/DumperInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Internal/NoDefault.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\Stub' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Stub.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/VarCloner.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand' => __DIR__ . '/..' . '/symfony/var-dumper/Command/ServerDumpCommand.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/AbstractDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\CliDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/CliDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextualizedDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/DataDumperInterface.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/HtmlDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Dumper\\ServerDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ServerDumper.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => __DIR__ . '/..' . '/symfony/var-dumper/Exception/ThrowingCasterException.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\Connection' => __DIR__ . '/..' . '/symfony/var-dumper/Server/Connection.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Server\\DumpServer' => __DIR__ . '/..' . '/symfony/var-dumper/Server/DumpServer.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => __DIR__ . '/..' . '/symfony/var-dumper/Test/VarDumperTestTrait.php', '_ContaoManager\\Symfony\\Component\\VarDumper\\VarDumper' => __DIR__ . '/..' . '/symfony/var-dumper/VarDumper.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ClassNotFoundException.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/LogicException.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Hydrator' => __DIR__ . '/..' . '/symfony/var-exporter/Hydrator.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Instantiator' => __DIR__ . '/..' . '/symfony/var-exporter/Instantiator.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Exporter' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Exporter.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Hydrator' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Hydrator.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectRegistry' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/LazyObjectRegistry.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectState' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/LazyObjectState.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\LazyObjectTrait' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/LazyObjectTrait.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Reference' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Reference.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Registry' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Registry.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\Internal\\Values' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Values.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyGhostTrait' => __DIR__ . '/..' . '/symfony/var-exporter/LazyGhostTrait.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyObjectInterface' => __DIR__ . '/..' . '/symfony/var-exporter/LazyObjectInterface.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\LazyProxyTrait' => __DIR__ . '/..' . '/symfony/var-exporter/LazyProxyTrait.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\ProxyHelper' => __DIR__ . '/..' . '/symfony/var-exporter/ProxyHelper.php', '_ContaoManager\\Symfony\\Component\\VarExporter\\VarExporter' => __DIR__ . '/..' . '/symfony/var-exporter/VarExporter.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/yaml/Command/LintCommand.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Dumper' => __DIR__ . '/..' . '/symfony/yaml/Dumper.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Escaper' => __DIR__ . '/..' . '/symfony/yaml/Escaper.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\DumpException' => __DIR__ . '/..' . '/symfony/yaml/Exception/DumpException.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/yaml/Exception/ExceptionInterface.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\ParseException' => __DIR__ . '/..' . '/symfony/yaml/Exception/ParseException.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/yaml/Exception/RuntimeException.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Inline' => __DIR__ . '/..' . '/symfony/yaml/Inline.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Parser' => __DIR__ . '/..' . '/symfony/yaml/Parser.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Tag\\TaggedValue' => __DIR__ . '/..' . '/symfony/yaml/Tag/TaggedValue.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Unescaper' => __DIR__ . '/..' . '/symfony/yaml/Unescaper.php', '_ContaoManager\\Symfony\\Component\\Yaml\\Yaml' => __DIR__ . '/..' . '/symfony/yaml/Yaml.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheInterface.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\CacheTrait' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheTrait.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\CallbackInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CallbackInterface.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\ItemInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/ItemInterface.php', '_ContaoManager\\Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/TagAwareCacheInterface.php', '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/Event.php', '_ContaoManager\\Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', '_ContaoManager\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceCollectionInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceCollectionInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', '_ContaoManager\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidKeyAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidKeyAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AndroidSafetyNetAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AndroidSafetyNetAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AppleAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AppleAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObject' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObject.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationObjectLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationObjectLoader.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatement.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\AttestationStatementSupportManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/AttestationStatementSupportManager.php', '_ContaoManager\\Webauthn\\AttestationStatement\\FidoU2FAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/FidoU2FAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\NoneAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/NoneAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\PackedAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/PackedAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestationStatement\\TPMAttestationStatementSupport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestationStatement/TPMAttestationStatementSupport.php', '_ContaoManager\\Webauthn\\AttestedCredentialData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AttestedCredentialData.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtension' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtension.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensions.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientInputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientInputs.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputs' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputs.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\AuthenticationExtensionsClientOutputsLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/AuthenticationExtensionsClientOutputsLoader.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputChecker.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputCheckerHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputCheckerHandler.php', '_ContaoManager\\Webauthn\\AuthenticationExtensions\\ExtensionOutputError' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticationExtensions/ExtensionOutputError.php', '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponse.php', '_ContaoManager\\Webauthn\\AuthenticatorAssertionResponseValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php', '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponse.php', '_ContaoManager\\Webauthn\\AuthenticatorAttestationResponseValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php', '_ContaoManager\\Webauthn\\AuthenticatorData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorData.php', '_ContaoManager\\Webauthn\\AuthenticatorDataLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorDataLoader.php', '_ContaoManager\\Webauthn\\AuthenticatorResponse' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorResponse.php', '_ContaoManager\\Webauthn\\AuthenticatorSelectionCriteria' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/AuthenticatorSelectionCriteria.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStep' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStep.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManager.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CeremonyStepManagerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CeremonyStepManagerFactory.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAlgorithm' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAlgorithm.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAllowedCredentialList' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAllowedCredentialList.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckAttestationFormatIsKnownAndValid' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckAttestationFormatIsKnownAndValid.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckBackupBitsAreConsistent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckBackupBitsAreConsistent.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckChallenge' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckChallenge.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckClientDataCollectorType' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckClientDataCollectorType.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCounter' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCounter.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckCredentialId' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckCredentialId.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckExtensions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckExtensions.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckHasAttestedCredentialData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckHasAttestedCredentialData.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckMetadataStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckMetadataStatement.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckOrigin' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckOrigin.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckRelyingPartyIdIdHash' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckRelyingPartyIdIdHash.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckSignature' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckSignature.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckTopOrigin' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckTopOrigin.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserHandle' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserHandle.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserVerification' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserVerification.php', '_ContaoManager\\Webauthn\\CeremonyStep\\CheckUserWasPresent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/CheckUserWasPresent.php', '_ContaoManager\\Webauthn\\CeremonyStep\\HostTopOriginValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/HostTopOriginValidator.php', '_ContaoManager\\Webauthn\\CeremonyStep\\TopOriginValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CeremonyStep/TopOriginValidator.php', '_ContaoManager\\Webauthn\\CertificateChainChecker\\CertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/CertificateChainChecker.php', '_ContaoManager\\Webauthn\\CertificateChainChecker\\PhpCertificateChainChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateChainChecker/PhpCertificateChainChecker.php', '_ContaoManager\\Webauthn\\CertificateToolbox' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CertificateToolbox.php', '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollector' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollector.php', '_ContaoManager\\Webauthn\\ClientDataCollector\\ClientDataCollectorManager' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/ClientDataCollectorManager.php', '_ContaoManager\\Webauthn\\ClientDataCollector\\WebauthnAuthenticationCollector' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/ClientDataCollector/WebauthnAuthenticationCollector.php', '_ContaoManager\\Webauthn\\CollectedClientData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/CollectedClientData.php', '_ContaoManager\\Webauthn\\Counter\\CounterChecker' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/CounterChecker.php', '_ContaoManager\\Webauthn\\Counter\\ThrowExceptionIfInvalid' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Counter/ThrowExceptionIfInvalid.php', '_ContaoManager\\Webauthn\\Credential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Credential.php', '_ContaoManager\\Webauthn\\Denormalizer\\AttestationObjectDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestationObjectDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AttestationStatementDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestationStatementDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AttestedCredentialDataNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AttestedCredentialDataNormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionNormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticationExtensionsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticationExtensionsDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAssertionResponseDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorAttestationResponseDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorAttestationResponseDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorDataDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorDataDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\AuthenticatorResponseDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/AuthenticatorResponseDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\CollectedClientDataDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/CollectedClientDataDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\ExtensionDescriptorDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/ExtensionDescriptorDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialDescriptorNormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialOptionsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialOptionsDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialParametersDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialParametersDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialSourceDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\PublicKeyCredentialUserEntityDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/PublicKeyCredentialUserEntityDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\TrustPathDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/TrustPathDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\VerificationMethodANDCombinationsDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/VerificationMethodANDCombinationsDenormalizer.php', '_ContaoManager\\Webauthn\\Denormalizer\\WebauthnSerializerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Denormalizer/WebauthnSerializerFactory.php', '_ContaoManager\\Webauthn\\Event\\AttestationObjectLoaded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AttestationObjectLoaded.php', '_ContaoManager\\Webauthn\\Event\\AttestationStatementLoaded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AttestationStatementLoaded.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationFailedEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationFailedEvent.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAssertionResponseValidationSucceededEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationFailedEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationFailedEvent.php', '_ContaoManager\\Webauthn\\Event\\AuthenticatorAttestationResponseValidationSucceededEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/AuthenticatorAttestationResponseValidationSucceededEvent.php', '_ContaoManager\\Webauthn\\Event\\BeforeCertificateChainValidation' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/BeforeCertificateChainValidation.php', '_ContaoManager\\Webauthn\\Event\\CanDispatchEvents' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CanDispatchEvents.php', '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationFailed' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationFailed.php', '_ContaoManager\\Webauthn\\Event\\CertificateChainValidationSucceeded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/CertificateChainValidationSucceeded.php', '_ContaoManager\\Webauthn\\Event\\MetadataStatementFound' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/MetadataStatementFound.php', '_ContaoManager\\Webauthn\\Event\\NullEventDispatcher' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/NullEventDispatcher.php', '_ContaoManager\\Webauthn\\Event\\WebauthnEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Event/WebauthnEvent.php', '_ContaoManager\\Webauthn\\Exception\\AttestationStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AttestationStatementException.php', '_ContaoManager\\Webauthn\\Exception\\AttestationStatementLoadingException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AttestationStatementLoadingException.php', '_ContaoManager\\Webauthn\\Exception\\AttestationStatementVerificationException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AttestationStatementVerificationException.php', '_ContaoManager\\Webauthn\\Exception\\AuthenticationExtensionException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AuthenticationExtensionException.php', '_ContaoManager\\Webauthn\\Exception\\AuthenticatorResponseVerificationException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/AuthenticatorResponseVerificationException.php', '_ContaoManager\\Webauthn\\Exception\\CertificateChainException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CertificateChainException.php', '_ContaoManager\\Webauthn\\Exception\\CertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CertificateException.php', '_ContaoManager\\Webauthn\\Exception\\CertificateRevocationListException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CertificateRevocationListException.php', '_ContaoManager\\Webauthn\\Exception\\CounterException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/CounterException.php', '_ContaoManager\\Webauthn\\Exception\\ExpiredCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/ExpiredCertificateException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidAttestationStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidAttestationStatementException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidCertificateException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidDataException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidDataException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidTrustPathException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidTrustPathException.php', '_ContaoManager\\Webauthn\\Exception\\InvalidUserHandleException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/InvalidUserHandleException.php', '_ContaoManager\\Webauthn\\Exception\\MetadataServiceException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MetadataServiceException.php', '_ContaoManager\\Webauthn\\Exception\\MetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MetadataStatementException.php', '_ContaoManager\\Webauthn\\Exception\\MetadataStatementLoadingException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MetadataStatementLoadingException.php', '_ContaoManager\\Webauthn\\Exception\\MissingMetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/MissingMetadataStatementException.php', '_ContaoManager\\Webauthn\\Exception\\RevokedCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/RevokedCertificateException.php', '_ContaoManager\\Webauthn\\Exception\\UnsupportedFeatureException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/UnsupportedFeatureException.php', '_ContaoManager\\Webauthn\\Exception\\WebauthnException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Exception/WebauthnException.php', '_ContaoManager\\Webauthn\\FakeCredentialGenerator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/FakeCredentialGenerator.php', '_ContaoManager\\Webauthn\\MetadataService\\CanLogData' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CanLogData.php', '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateChainValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateChainValidator.php', '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\CertificateToolbox' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/CertificateToolbox.php', '_ContaoManager\\Webauthn\\MetadataService\\CertificateChain\\PhpCertificateChainValidator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/CertificateChain/PhpCertificateChainValidator.php', '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\ExtensionDescriptorDenormalizer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/ExtensionDescriptorDenormalizer.php', '_ContaoManager\\Webauthn\\MetadataService\\Denormalizer\\MetadataStatementSerializerFactory' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Denormalizer/MetadataStatementSerializerFactory.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\BeforeCertificateChainValidation' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/BeforeCertificateChainValidation.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\CanDispatchEvents' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CanDispatchEvents.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationFailed' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationFailed.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\CertificateChainValidationSucceeded' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/CertificateChainValidationSucceeded.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\MetadataStatementFound' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/MetadataStatementFound.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\NullEventDispatcher' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/NullEventDispatcher.php', '_ContaoManager\\Webauthn\\MetadataService\\Event\\WebauthnEvent' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Event/WebauthnEvent.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateChainException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateChainException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\CertificateRevocationListException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/CertificateRevocationListException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\ExpiredCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/ExpiredCertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\InvalidCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/InvalidCertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataServiceException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataServiceException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MetadataStatementLoadingException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MetadataStatementLoadingException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\MissingMetadataStatementException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/MissingMetadataStatementException.php', '_ContaoManager\\Webauthn\\MetadataService\\Exception\\RevokedCertificateException' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Exception/RevokedCertificateException.php', '_ContaoManager\\Webauthn\\MetadataService\\MetadataStatementRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/MetadataStatementRepository.php', '_ContaoManager\\Webauthn\\MetadataService\\Psr18HttpClient' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Psr18HttpClient.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\ChainedMetadataServices' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/ChainedMetadataServices.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\DistantResourceMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/DistantResourceMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\FidoAllianceCompliantMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/FidoAllianceCompliantMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\FolderResourceMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/FolderResourceMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\InMemoryMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/InMemoryMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\JsonMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/JsonMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\LocalResourceMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/LocalResourceMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayload' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayload.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataBLOBPayloadEntry' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataBLOBPayloadEntry.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\MetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/MetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Service\\StringMetadataService' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Service/StringMetadataService.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AbstractDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AbstractDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AlternativeDescriptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AlternativeDescriptions.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorGetInfo' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorGetInfo.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\AuthenticatorStatus' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/AuthenticatorStatus.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricAccuracyDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\BiometricStatusReport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/BiometricStatusReport.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\CodeAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/CodeAccuracyDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\DisplayPNGCharacteristicsDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/DisplayPNGCharacteristicsDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\EcdaaTrustAnchor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/EcdaaTrustAnchor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\ExtensionDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/ExtensionDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\MetadataStatement' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/MetadataStatement.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\PatternAccuracyDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/PatternAccuracyDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RgbPaletteEntry' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/RgbPaletteEntry.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\RogueListEntry' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/RogueListEntry.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\StatusReport' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/StatusReport.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodANDCombinations' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodANDCombinations.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\VerificationMethodDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/VerificationMethodDescriptor.php', '_ContaoManager\\Webauthn\\MetadataService\\Statement\\Version' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/Statement/Version.php', '_ContaoManager\\Webauthn\\MetadataService\\StatusReportRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/StatusReportRepository.php', '_ContaoManager\\Webauthn\\MetadataService\\ValueFilter' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/MetadataService/ValueFilter.php', '_ContaoManager\\Webauthn\\PublicKeyCredential' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredential.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialCreationOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialCreationOptions.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptor' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptor.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialDescriptorCollection' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialDescriptorCollection.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialEntity.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialLoader.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialOptions.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialParameters' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialParameters.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialRequestOptions' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRequestOptions.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialRpEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialRpEntity.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialSource' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSource.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialSourceRepository' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialSourceRepository.php', '_ContaoManager\\Webauthn\\PublicKeyCredentialUserEntity' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/PublicKeyCredentialUserEntity.php', '_ContaoManager\\Webauthn\\SimpleFakeCredentialGenerator' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/SimpleFakeCredentialGenerator.php', '_ContaoManager\\Webauthn\\StringStream' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/StringStream.php', '_ContaoManager\\Webauthn\\TokenBinding\\IgnoreTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/IgnoreTokenBindingHandler.php', '_ContaoManager\\Webauthn\\TokenBinding\\SecTokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/SecTokenBindingHandler.php', '_ContaoManager\\Webauthn\\TokenBinding\\TokenBinding' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBinding.php', '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingHandler.php', '_ContaoManager\\Webauthn\\TokenBinding\\TokenBindingNotSupportedHandler' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TokenBinding/TokenBindingNotSupportedHandler.php', '_ContaoManager\\Webauthn\\TrustPath\\CertificateTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/CertificateTrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\EcdaaKeyIdTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EcdaaKeyIdTrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\EmptyTrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/EmptyTrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\TrustPath' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPath.php', '_ContaoManager\\Webauthn\\TrustPath\\TrustPathLoader' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/TrustPath/TrustPathLoader.php', '_ContaoManager\\Webauthn\\U2FPublicKey' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/U2FPublicKey.php', '_ContaoManager\\Webauthn\\Util\\Base64' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/Base64.php', '_ContaoManager\\Webauthn\\Util\\CoseSignatureFixer' => __DIR__ . '/..' . '/web-auth/webauthn-lib/src/Util/CoseSignatureFixer.php', '_ContaoManager\\Webmozart\\Assert\\Assert' => __DIR__ . '/..' . '/webmozart/assert/src/Assert.php', '_ContaoManager\\Webmozart\\Assert\\InvalidArgumentException' => __DIR__ . '/..' . '/webmozart/assert/src/InvalidArgumentException.php', '_ContaoManager\\Webmozart\\Assert\\Mixin' => __DIR__ . '/..' . '/webmozart/assert/src/Mixin.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlockFactoryInterface' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Description' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Serializer' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\TagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Extends_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\AbstractPHPStanFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ExtendsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\Factory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ImplementsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ImplementsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\MethodParameterFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PHPStanFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ParamFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ParamFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyReadFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\PropertyWriteFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\ReturnFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\StaticMethod' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateExtendsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateExtendsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\TemplateImplementsFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\VarFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Implements_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\MethodParameter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Mixin' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Template' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateCovariant' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateExtends' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TemplateImplements' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php', '_ContaoManager\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php', '_ContaoManager\\phpDocumentor\\Reflection\\Element' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Element.php', '_ContaoManager\\phpDocumentor\\Reflection\\Exception\\PcreException' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php', '_ContaoManager\\phpDocumentor\\Reflection\\File' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/File.php', '_ContaoManager\\phpDocumentor\\Reflection\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Fqsen.php', '_ContaoManager\\phpDocumentor\\Reflection\\FqsenResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/FqsenResolver.php', '_ContaoManager\\phpDocumentor\\Reflection\\Location' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Location.php', '_ContaoManager\\phpDocumentor\\Reflection\\Project' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Project.php', '_ContaoManager\\phpDocumentor\\Reflection\\ProjectFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/ProjectFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoType.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShape.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ArrayShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ArrayShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\CallableString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ConstExpression' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ConstExpression.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\False_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\FloatValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/FloatValue.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\HtmlEscapedString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerRange' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\IntegerValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/IntegerValue.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShape.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ListShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ListShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\List_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/List_.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LiteralString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\LowercaseString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NegativeInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyArray' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyArray.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyList' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyList.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyLowercaseString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NonEmptyString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\NumericString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\Numeric_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShape' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShape.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ObjectShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ObjectShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\PositiveInteger' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\ShapeItem' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/ShapeItem.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\StringValue' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\TraitString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php', '_ContaoManager\\phpDocumentor\\Reflection\\PseudoTypes\\True_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Type' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Type.php', '_ContaoManager\\phpDocumentor\\Reflection\\TypeResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/TypeResolver.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AbstractList' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AbstractList.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\AggregatedType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ArrayKey' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ArrayKey.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Array_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Array_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Boolean' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Boolean.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\CallableParameter' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/CallableParameter.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Callable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Callable_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ClassString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ClassString.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Collection' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Collection.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Compound' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Compound.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Context' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Context.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\ContextFactory' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Expression' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Expression.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Float_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Float_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Integer' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Integer.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\InterfaceString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/InterfaceString.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Intersection' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Intersection.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Iterable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Iterable_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Mixed_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Mixed_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Never_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Never_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Null_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Null_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Nullable' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Nullable.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Object_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Object_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Parent_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Parent_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Resource_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Resource_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Scalar' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Scalar.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Self_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Self_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Static_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Static_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\String_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/String_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\This' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/This.php', '_ContaoManager\\phpDocumentor\\Reflection\\Types\\Void_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Void_.php', '_ContaoManager\\phpDocumentor\\Reflection\\Utils' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Utils.php', '_ContaoManager\\studio24\\Rotate\\Delete' => __DIR__ . '/..' . '/studio24/rotate/src/Delete.php', '_ContaoManager\\studio24\\Rotate\\DirectoryIterator' => __DIR__ . '/..' . '/studio24/rotate/src/DirectoryIterator.php', '_ContaoManager\\studio24\\Rotate\\FilenameFormat' => __DIR__ . '/..' . '/studio24/rotate/src/FilenameFormat.php', '_ContaoManager\\studio24\\Rotate\\FilenameFormatException' => __DIR__ . '/..' . '/studio24/rotate/src/FilenameFormatException.php', '_ContaoManager\\studio24\\Rotate\\Rotate' => __DIR__ . '/..' . '/studio24/rotate/src/Rotate.php', '_ContaoManager\\studio24\\Rotate\\RotateAbstract' => __DIR__ . '/..' . '/studio24/rotate/src/RotateAbstract.php', '_ContaoManager\\studio24\\Rotate\\RotateException' => __DIR__ . '/..' . '/studio24/rotate/src/RotateException.php', '_ContaoManager\\' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInit53b6ad81fd066558f6a8010b29d2c105::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit53b6ad81fd066558f6a8010b29d2c105::$prefixDirsPsr4; $loader->classMap = ComposerStaticInit53b6ad81fd066558f6a8010b29d2c105::$classMap; }, null, ClassLoader::class); } } setClassMapAuthoritative(true); $loader->register(true); $filesToLoad = \Composer\Autoload\ComposerStaticInit53b6ad81fd066558f6a8010b29d2c105::$files; $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; require $file; } }, null, null); foreach ($filesToLoad as $fileIdentifier => $file) { $requireFile($fileIdentifier, $file); } return $loader; } } Copyright (C) 2015 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. # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ### [3.4.3] 2024-09-19 * Fixed some type annotations ### [3.4.2] 2024-07-12 * Fixed PHP 5.3 syntax error ### [3.4.1] 2024-07-12 * Fixed normalizeStability's return type to enforce valid stabilities ### [3.4.0] 2023-08-31 * Support larger major version numbers (#149) ### [3.3.2] 2022-04-01 * Fixed handling of non-string values (#134) ### [3.3.1] 2022-03-16 * Fixed possible cache key clash in the CompilingMatcher memoization (#132) ### [3.3.0] 2022-03-15 * Improved performance of CompilingMatcher by memoizing more (#131) * Added CompilingMatcher::clear to clear all memoization caches ### [3.2.9] 2022-02-04 * Revert #129 (Fixed MultiConstraint with MatchAllConstraint) which caused regressions ### [3.2.8] 2022-02-04 * Updates to latest phpstan / CI by @Seldaek in https://github.com/composer/semver/pull/130 * Fixed MultiConstraint with MatchAllConstraint by @Toflar in https://github.com/composer/semver/pull/129 ### [3.2.7] 2022-01-04 * Fixed: typo in type definition of Intervals class causing issues with Psalm scanning vendors ### [3.2.6] 2021-10-25 * Fixed: type improvements to parseStability ### [3.2.5] 2021-05-24 * Fixed: issue comparing disjunctive MultiConstraints to conjunctive ones (#127) * Fixed: added complete type information using phpstan annotations ### [3.2.4] 2020-11-13 * Fixed: code clean-up ### [3.2.3] 2020-11-12 * Fixed: constraints in the form of `X || Y, >=Y.1` and other such complex constructs were in some cases being optimized into a more restrictive constraint ### [3.2.2] 2020-10-14 * Fixed: internal code cleanups ### [3.2.1] 2020-09-27 * Fixed: accidental validation of broken constraints combining ^/~ and wildcards, and -dev suffix allowing weird cases * Fixed: normalization of beta0 and such which was dropping the 0 ### [3.2.0] 2020-09-09 * Added: support for `x || @dev`, not very useful but seen in the wild and failed to validate with 1.5.2/1.6.0 * Added: support for `foobar-dev` being equal to `dev-foobar`, dev-foobar is the official way to write it but we need to support the other for BC and convenience ### [3.1.0] 2020-09-08 * Added: support for constraints like `^2.x-dev` and `~2.x-dev`, not very useful but seen in the wild and failed to validate with 3.0.1 * Fixed: invalid aliases will no longer throw, unless explicitly validated by Composer in the root package ### [3.0.1] 2020-09-08 * Fixed: handling of some invalid -dev versions which were seen as valid ### [3.0.0] 2020-05-26 * Break: Renamed `EmptyConstraint`, replace it with `MatchAllConstraint` * Break: Unlikely to affect anyone but strictly speaking a breaking change, `*.*` and such variants will not match all `dev-*` versions anymore, only `*` does * Break: ConstraintInterface is now considered internal/private and not meant to be implemented by third parties anymore * Added `Intervals` class to check if a constraint is a subsets of another one, and allow compacting complex MultiConstraints into simpler ones * Added `CompilingMatcher` class to speed up constraint matching against simple Constraint instances * Added `MatchAllConstraint` and `MatchNoneConstraint` which match everything and nothing * Added more advanced optimization of contiguous constraints inside MultiConstraint * Added tentative support for PHP 8 * Fixed ConstraintInterface::matches to be commutative in all cases ### [2.0.0] 2020-04-21 * Break: `dev-master`, `dev-trunk` and `dev-default` now normalize to `dev-master`, `dev-trunk` and `dev-default` instead of `9999999-dev` in 1.x * Break: Removed the deprecated `AbstractConstraint` * Added `getUpperBound` and `getLowerBound` to ConstraintInterface. They return `Composer\Semver\Constraint\Bound` instances * Added `MultiConstraint::create` to create the most-optimal form of ConstraintInterface from an array of constraint strings ### [1.7.2] 2020-12-03 * Fixed: Allow installing on php 8 ### [1.7.1] 2020-09-27 * Fixed: accidental validation of broken constraints combining ^/~ and wildcards, and -dev suffix allowing weird cases * Fixed: normalization of beta0 and such which was dropping the 0 ### [1.7.0] 2020-09-09 * Added: support for `x || @dev`, not very useful but seen in the wild and failed to validate with 1.5.2/1.6.0 * Added: support for `foobar-dev` being equal to `dev-foobar`, dev-foobar is the official way to write it but we need to support the other for BC and convenience ### [1.6.0] 2020-09-08 * Added: support for constraints like `^2.x-dev` and `~2.x-dev`, not very useful but seen in the wild and failed to validate with 1.5.2 * Fixed: invalid aliases will no longer throw, unless explicitly validated by Composer in the root package ### [1.5.2] 2020-09-08 * Fixed: handling of some invalid -dev versions which were seen as valid * Fixed: some doctypes ### [1.5.1] 2020-01-13 * Fixed: Parsing of aliased version was not validating the alias to be a valid version ### [1.5.0] 2019-03-19 * Added: some support for date versions (e.g. 201903) in `~` operator * Fixed: support for stabilities in `~` operator was inconsistent ### [1.4.2] 2016-08-30 * Fixed: collapsing of complex constraints lead to buggy constraints ### [1.4.1] 2016-06-02 * Changed: branch-like requirements no longer strip build metadata - [composer/semver#38](https://github.com/composer/semver/pull/38). ### [1.4.0] 2016-03-30 * Added: getters on MultiConstraint - [composer/semver#35](https://github.com/composer/semver/pull/35). ### [1.3.0] 2016-02-25 * Fixed: stability parsing - [composer/composer#1234](https://github.com/composer/composer/issues/4889). * Changed: collapse contiguous constraints when possible. ### [1.2.0] 2015-11-10 * Changed: allow multiple numerical identifiers in 'pre-release' version part. * Changed: add more 'v' prefix support. ### [1.1.0] 2015-11-03 * Changed: dropped redundant `test` namespace. * Changed: minor adjustment in datetime parsing normalization. * Changed: `ConstraintInterface` relaxed, setPrettyString is not required anymore. * Changed: `AbstractConstraint` marked deprecated, will be removed in 2.0. * Changed: `Constraint` is now extensible. ### [1.0.0] 2015-09-21 * Break: `VersionConstraint` renamed to `Constraint`. * Break: `SpecificConstraint` renamed to `AbstractConstraint`. * Break: `LinkConstraintInterface` renamed to `ConstraintInterface`. * Break: `VersionParser::parseNameVersionPairs` was removed. * Changed: `VersionParser::parseConstraints` allows (but ignores) build metadata now. * Changed: `VersionParser::parseConstraints` allows (but ignores) prefixing numeric versions with a 'v' now. * Changed: Fixed namespace(s) of test files. * Changed: `Comparator::compare` no longer throws `InvalidArgumentException`. * Changed: `Constraint` now throws `InvalidArgumentException`. ### [0.1.0] 2015-07-23 * Added: `Composer\Semver\Comparator`, various methods to compare versions. * Added: various documents such as README.md, LICENSE, etc. * Added: configuration files for Git, Travis, php-cs-fixer, phpunit. * Break: the following namespaces were renamed: - Namespace: `Composer\Package\Version` -> `Composer\Semver` - Namespace: `Composer\Package\LinkConstraint` -> `Composer\Semver\Constraint` - Namespace: `Composer\Test\Package\Version` -> `Composer\Test\Semver` - Namespace: `Composer\Test\Package\LinkConstraint` -> `Composer\Test\Semver\Constraint` * Changed: code style using php-cs-fixer. [3.4.3]: https://github.com/composer/semver/compare/3.4.2...3.4.3 [3.4.2]: https://github.com/composer/semver/compare/3.4.1...3.4.2 [3.4.1]: https://github.com/composer/semver/compare/3.4.0...3.4.1 [3.4.0]: https://github.com/composer/semver/compare/3.3.2...3.4.0 [3.3.2]: https://github.com/composer/semver/compare/3.3.1...3.3.2 [3.3.1]: https://github.com/composer/semver/compare/3.3.0...3.3.1 [3.3.0]: https://github.com/composer/semver/compare/3.2.9...3.3.0 [3.2.9]: https://github.com/composer/semver/compare/3.2.8...3.2.9 [3.2.8]: https://github.com/composer/semver/compare/3.2.7...3.2.8 [3.2.7]: https://github.com/composer/semver/compare/3.2.6...3.2.7 [3.2.6]: https://github.com/composer/semver/compare/3.2.5...3.2.6 [3.2.5]: https://github.com/composer/semver/compare/3.2.4...3.2.5 [3.2.4]: https://github.com/composer/semver/compare/3.2.3...3.2.4 [3.2.3]: https://github.com/composer/semver/compare/3.2.2...3.2.3 [3.2.2]: https://github.com/composer/semver/compare/3.2.1...3.2.2 [3.2.1]: https://github.com/composer/semver/compare/3.2.0...3.2.1 [3.2.0]: https://github.com/composer/semver/compare/3.1.0...3.2.0 [3.1.0]: https://github.com/composer/semver/compare/3.0.1...3.1.0 [3.0.1]: https://github.com/composer/semver/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/composer/semver/compare/2.0.0...3.0.0 [2.0.0]: https://github.com/composer/semver/compare/1.5.1...2.0.0 [1.7.2]: https://github.com/composer/semver/compare/1.7.1...1.7.2 [1.7.1]: https://github.com/composer/semver/compare/1.7.0...1.7.1 [1.7.0]: https://github.com/composer/semver/compare/1.6.0...1.7.0 [1.6.0]: https://github.com/composer/semver/compare/1.5.2...1.6.0 [1.5.2]: https://github.com/composer/semver/compare/1.5.1...1.5.2 [1.5.1]: https://github.com/composer/semver/compare/1.5.0...1.5.1 [1.5.0]: https://github.com/composer/semver/compare/1.4.2...1.5.0 [1.4.2]: https://github.com/composer/semver/compare/1.4.1...1.4.2 [1.4.1]: https://github.com/composer/semver/compare/1.4.0...1.4.1 [1.4.0]: https://github.com/composer/semver/compare/1.3.0...1.4.0 [1.3.0]: https://github.com/composer/semver/compare/1.2.0...1.3.0 [1.2.0]: https://github.com/composer/semver/compare/1.1.0...1.2.0 [1.1.0]: https://github.com/composer/semver/compare/1.0.0...1.1.0 [1.0.0]: https://github.com/composer/semver/compare/0.1.0...1.0.0 [0.1.0]: https://github.com/composer/semver/compare/5e0b9a4da...0.1.0 composer/semver =============== Semver (Semantic Versioning) library that offers utilities, version constraint parsing and validation. Originally written as part of [composer/composer](https://github.com/composer/composer), now extracted and made available as a stand-alone library. [![Continuous Integration](https://github.com/composer/semver/actions/workflows/continuous-integration.yml/badge.svg?branch=main)](https://github.com/composer/semver/actions/workflows/continuous-integration.yml) [![PHP Lint](https://github.com/composer/semver/actions/workflows/lint.yml/badge.svg?branch=main)](https://github.com/composer/semver/actions/workflows/lint.yml) [![PHPStan](https://github.com/composer/semver/actions/workflows/phpstan.yml/badge.svg?branch=main)](https://github.com/composer/semver/actions/workflows/phpstan.yml) Installation ------------ Install the latest version with: ```bash composer require composer/semver ``` Requirements ------------ * PHP 5.3.2 is required but using the latest version of PHP is highly recommended. Version Comparison ------------------ For details on how versions are compared, refer to the [Versions](https://getcomposer.org/doc/articles/versions.md) article in the documentation section of the [getcomposer.org](https://getcomposer.org) website. Basic usage ----------- ### Comparator The [`Composer\Semver\Comparator`](https://github.com/composer/semver/blob/main/src/Comparator.php) class provides the following methods for comparing versions: * greaterThan($v1, $v2) * greaterThanOrEqualTo($v1, $v2) * lessThan($v1, $v2) * lessThanOrEqualTo($v1, $v2) * equalTo($v1, $v2) * notEqualTo($v1, $v2) Each function takes two version strings as arguments and returns a boolean. For example: ```php use Composer\Semver\Comparator; Comparator::greaterThan('1.25.0', '1.24.0'); // 1.25.0 > 1.24.0 ``` ### Semver The [`Composer\Semver\Semver`](https://github.com/composer/semver/blob/main/src/Semver.php) class provides the following methods: * satisfies($version, $constraints) * satisfiedBy(array $versions, $constraint) * sort($versions) * rsort($versions) ### Intervals The [`Composer\Semver\Intervals`](https://github.com/composer/semver/blob/main/src/Intervals.php) static class provides a few utilities to work with complex constraints or read version intervals from a constraint: ```php use Composer\Semver\Intervals; // Checks whether $candidate is a subset of $constraint Intervals::isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint); // Checks whether $a and $b have any intersection, equivalent to $a->matches($b) Intervals::haveIntersections(ConstraintInterface $a, ConstraintInterface $b); // Optimizes a complex multi constraint by merging all intervals down to the smallest // possible multi constraint. The drawbacks are this is not very fast, and the resulting // multi constraint will have no human readable prettyConstraint configured on it Intervals::compactConstraint(ConstraintInterface $constraint); // Creates an array of numeric intervals and branch constraints representing a given constraint Intervals::get(ConstraintInterface $constraint); // Clears the memoization cache when you are done processing constraints Intervals::clear() ``` See the class docblocks for more details. License ------- composer/semver is licensed under the MIT License, see the LICENSE file for details. { "name": "composer\/semver", "description": "Semver library that offers utilities, version constraint parsing and validation.", "type": "library", "license": "MIT", "keywords": [ "semver", "semantic", "versioning", "validation" ], "authors": [ { "name": "Nils Adermann", "email": "naderman@naderman.de", "homepage": "http:\/\/www.naderman.de" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http:\/\/seld.be" }, { "name": "Rob Bast", "email": "rob.bast@gmail.com", "homepage": "http:\/\/robbast.nl" } ], "support": { "irc": "ircs:\/\/irc.libera.chat:6697\/composer", "issues": "https:\/\/github.com\/composer\/semver\/issues" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { "symfony\/phpunit-bridge": "^3 || ^7", "phpstan\/phpstan": "^1.11" }, "autoload": { "psr-4": { "Composer\\Semver\\": "src" } }, "autoload-dev": { "psr-4": { "Composer\\Semver\\": "tests" } }, "extra": { "branch-alias": { "dev-main": "3.x-dev" } }, "scripts": { "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor\/bin\/simple-phpunit", "phpstan": "@php vendor\/bin\/phpstan analyse" } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; /** * Helper class to evaluate constraint by compiling and reusing the code to evaluate */ class CompilingMatcher { /** * @var array * @phpstan-var array */ private static $compiledCheckerCache = array(); /** * @var array * @phpstan-var array */ private static $resultCache = array(); /** @var bool */ private static $enabled; /** * @phpstan-var array */ private static $transOpInt = array(Constraint::OP_EQ => Constraint::STR_OP_EQ, Constraint::OP_LT => Constraint::STR_OP_LT, Constraint::OP_LE => Constraint::STR_OP_LE, Constraint::OP_GT => Constraint::STR_OP_GT, Constraint::OP_GE => Constraint::STR_OP_GE, Constraint::OP_NE => Constraint::STR_OP_NE); /** * Clears the memoization cache once you are done * * @return void */ public static function clear() { self::$resultCache = array(); self::$compiledCheckerCache = array(); } /** * Evaluates the expression: $constraint match $operator $version * * @param ConstraintInterface $constraint * @param int $operator * @phpstan-param Constraint::OP_* $operator * @param string $version * * @return bool */ public static function match(ConstraintInterface $constraint, $operator, $version) { $resultCacheKey = $operator . $constraint . ';' . $version; if (isset(self::$resultCache[$resultCacheKey])) { return self::$resultCache[$resultCacheKey]; } if (self::$enabled === null) { self::$enabled = !\in_array('eval', \explode(',', (string) \ini_get('disable_functions')), \true); } if (!self::$enabled) { return self::$resultCache[$resultCacheKey] = $constraint->matches(new Constraint(self::$transOpInt[$operator], $version)); } $cacheKey = $operator . $constraint; if (!isset(self::$compiledCheckerCache[$cacheKey])) { $code = $constraint->compile($operator); self::$compiledCheckerCache[$cacheKey] = $function = eval('return function($v, $b){return ' . $code . ';};'); } else { $function = self::$compiledCheckerCache[$cacheKey]; } return self::$resultCache[$resultCacheKey] = $function($version, \strpos($version, 'dev-') === 0); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver; use Composer\Semver\Constraint\Constraint; class Interval { /** @var Constraint */ private $start; /** @var Constraint */ private $end; public function __construct(Constraint $start, Constraint $end) { $this->start = $start; $this->end = $end; } /** * @return Constraint */ public function getStart() { return $this->start; } /** * @return Constraint */ public function getEnd() { return $this->end; } /** * @return Constraint */ public static function fromZero() { static $zero; if (null === $zero) { $zero = new Constraint('>=', '0.0.0.0-dev'); } return $zero; } /** * @return Constraint */ public static function untilPositiveInfinity() { static $positiveInfinity; if (null === $positiveInfinity) { $positiveInfinity = new Constraint('<', \PHP_INT_MAX . '.0.0.0'); } return $positiveInfinity; } /** * @return self */ public static function any() { return new self(self::fromZero(), self::untilPositiveInfinity()); } /** * @return array{'names': string[], 'exclude': bool} */ public static function anyDev() { // any == exclude nothing return array('names' => array(), 'exclude' => \true); } /** * @return array{'names': string[], 'exclude': bool} */ public static function noDev() { // nothing == no names included return array('names' => array(), 'exclude' => \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver; use Composer\Semver\Constraint\Constraint; class Comparator { /** * Evaluates the expression: $version1 > $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function greaterThan($version1, $version2) { return self::compare($version1, '>', $version2); } /** * Evaluates the expression: $version1 >= $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function greaterThanOrEqualTo($version1, $version2) { return self::compare($version1, '>=', $version2); } /** * Evaluates the expression: $version1 < $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function lessThan($version1, $version2) { return self::compare($version1, '<', $version2); } /** * Evaluates the expression: $version1 <= $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function lessThanOrEqualTo($version1, $version2) { return self::compare($version1, '<=', $version2); } /** * Evaluates the expression: $version1 == $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function equalTo($version1, $version2) { return self::compare($version1, '==', $version2); } /** * Evaluates the expression: $version1 != $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function notEqualTo($version1, $version2) { return self::compare($version1, '!=', $version2); } /** * Evaluates the expression: $version1 $operator $version2. * * @param string $version1 * @param string $operator * @param string $version2 * * @return bool * * @phpstan-param Constraint::STR_OP_* $operator */ public static function compare($version1, $operator, $version2) { $constraint = new Constraint($operator, $version2); return $constraint->matchSpecific(new Constraint('==', $version1), \true); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Semver\Constraint\MatchNoneConstraint; use Composer\Semver\Constraint\MultiConstraint; /** * Helper class generating intervals from constraints * * This contains utilities for: * * - compacting an existing constraint which can be used to combine several into one * by creating a MultiConstraint out of the many constraints you have. * * - checking whether one subset is a subset of another. * * Note: You should call clear to free memoization memory usage when you are done using this class */ class Intervals { /** * @phpstan-var array */ private static $intervalsCache = array(); /** * @phpstan-var array */ private static $opSortOrder = array('>=' => -3, '<' => -2, '>' => 2, '<=' => 3); /** * Clears the memoization cache once you are done * * @return void */ public static function clear() { self::$intervalsCache = array(); } /** * Checks whether $candidate is a subset of $constraint * * @return bool */ public static function isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint) { if ($constraint instanceof MatchAllConstraint) { return \true; } if ($candidate instanceof MatchNoneConstraint || $constraint instanceof MatchNoneConstraint) { return \false; } $intersectionIntervals = self::get(new MultiConstraint(array($candidate, $constraint), \true)); $candidateIntervals = self::get($candidate); if (\count($intersectionIntervals['numeric']) !== \count($candidateIntervals['numeric'])) { return \false; } foreach ($intersectionIntervals['numeric'] as $index => $interval) { if (!isset($candidateIntervals['numeric'][$index])) { return \false; } if ((string) $candidateIntervals['numeric'][$index]->getStart() !== (string) $interval->getStart()) { return \false; } if ((string) $candidateIntervals['numeric'][$index]->getEnd() !== (string) $interval->getEnd()) { return \false; } } if ($intersectionIntervals['branches']['exclude'] !== $candidateIntervals['branches']['exclude']) { return \false; } if (\count($intersectionIntervals['branches']['names']) !== \count($candidateIntervals['branches']['names'])) { return \false; } foreach ($intersectionIntervals['branches']['names'] as $index => $name) { if ($name !== $candidateIntervals['branches']['names'][$index]) { return \false; } } return \true; } /** * Checks whether $a and $b have any intersection, equivalent to $a->matches($b) * * @return bool */ public static function haveIntersections(ConstraintInterface $a, ConstraintInterface $b) { if ($a instanceof MatchAllConstraint || $b instanceof MatchAllConstraint) { return \true; } if ($a instanceof MatchNoneConstraint || $b instanceof MatchNoneConstraint) { return \false; } $intersectionIntervals = self::generateIntervals(new MultiConstraint(array($a, $b), \true), \true); return \count($intersectionIntervals['numeric']) > 0 || $intersectionIntervals['branches']['exclude'] || \count($intersectionIntervals['branches']['names']) > 0; } /** * Attempts to optimize a MultiConstraint * * When merging MultiConstraints together they can get very large, this will * compact it by looking at the real intervals covered by all the constraints * and then creates a new constraint containing only the smallest amount of rules * to match the same intervals. * * @return ConstraintInterface */ public static function compactConstraint(ConstraintInterface $constraint) { if (!$constraint instanceof MultiConstraint) { return $constraint; } $intervals = self::generateIntervals($constraint); $constraints = array(); $hasNumericMatchAll = \false; if (\count($intervals['numeric']) === 1 && (string) $intervals['numeric'][0]->getStart() === (string) \Composer\Semver\Interval::fromZero() && (string) $intervals['numeric'][0]->getEnd() === (string) \Composer\Semver\Interval::untilPositiveInfinity()) { $constraints[] = $intervals['numeric'][0]->getStart(); $hasNumericMatchAll = \true; } else { $unEqualConstraints = array(); for ($i = 0, $count = \count($intervals['numeric']); $i < $count; $i++) { $interval = $intervals['numeric'][$i]; // if current interval ends with < N and next interval begins with > N we can swap this out for != N // but this needs to happen as a conjunctive expression together with the start of the current interval // and end of next interval, so [>=M, N, [>=M, !=N, getEnd()->getOperator() === '<' && $i + 1 < $count) { $nextInterval = $intervals['numeric'][$i + 1]; if ($interval->getEnd()->getVersion() === $nextInterval->getStart()->getVersion() && $nextInterval->getStart()->getOperator() === '>') { // only add a start if we didn't already do so, can be skipped if we're looking at second // interval in [>=M, N, P, =M, !=N] already and we only want to add !=P right now if (\count($unEqualConstraints) === 0 && (string) $interval->getStart() !== (string) \Composer\Semver\Interval::fromZero()) { $unEqualConstraints[] = $interval->getStart(); } $unEqualConstraints[] = new Constraint('!=', $interval->getEnd()->getVersion()); continue; } } if (\count($unEqualConstraints) > 0) { // this is where the end of the following interval of a != constraint is added as explained above if ((string) $interval->getEnd() !== (string) \Composer\Semver\Interval::untilPositiveInfinity()) { $unEqualConstraints[] = $interval->getEnd(); } // count is 1 if entire constraint is just one != expression if (\count($unEqualConstraints) > 1) { $constraints[] = new MultiConstraint($unEqualConstraints, \true); } else { $constraints[] = $unEqualConstraints[0]; } $unEqualConstraints = array(); continue; } // convert back >= x - <= x intervals to == x if ($interval->getStart()->getVersion() === $interval->getEnd()->getVersion() && $interval->getStart()->getOperator() === '>=' && $interval->getEnd()->getOperator() === '<=') { $constraints[] = new Constraint('==', $interval->getStart()->getVersion()); continue; } if ((string) $interval->getStart() === (string) \Composer\Semver\Interval::fromZero()) { $constraints[] = $interval->getEnd(); } elseif ((string) $interval->getEnd() === (string) \Composer\Semver\Interval::untilPositiveInfinity()) { $constraints[] = $interval->getStart(); } else { $constraints[] = new MultiConstraint(array($interval->getStart(), $interval->getEnd()), \true); } } } $devConstraints = array(); if (0 === \count($intervals['branches']['names'])) { if ($intervals['branches']['exclude']) { if ($hasNumericMatchAll) { return new MatchAllConstraint(); } // otherwise constraint should contain a != operator and already cover this } } else { foreach ($intervals['branches']['names'] as $branchName) { if ($intervals['branches']['exclude']) { $devConstraints[] = new Constraint('!=', $branchName); } else { $devConstraints[] = new Constraint('==', $branchName); } } // excluded branches, e.g. != dev-foo are conjunctive with the interval, so // > 2.0 != dev-foo must return a conjunctive constraint if ($intervals['branches']['exclude']) { if (\count($constraints) > 1) { return new MultiConstraint(\array_merge(array(new MultiConstraint($constraints, \false)), $devConstraints), \true); } if (\count($constraints) === 1 && (string) $constraints[0] === (string) \Composer\Semver\Interval::fromZero()) { if (\count($devConstraints) > 1) { return new MultiConstraint($devConstraints, \true); } return $devConstraints[0]; } return new MultiConstraint(\array_merge($constraints, $devConstraints), \true); } // otherwise devConstraints contains a list of == operators for branches which are disjunctive with the // rest of the constraint $constraints = \array_merge($constraints, $devConstraints); } if (\count($constraints) > 1) { return new MultiConstraint($constraints, \false); } if (\count($constraints) === 1) { return $constraints[0]; } return new MatchNoneConstraint(); } /** * Creates an array of numeric intervals and branch constraints representing a given constraint * * if the returned numeric array is empty it means the constraint matches nothing in the numeric range (0 - +inf) * if the returned branches array is empty it means no dev-* versions are matched * if a constraint matches all possible dev-* versions, branches will contain Interval::anyDev() * * @return array * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ public static function get(ConstraintInterface $constraint) { $key = (string) $constraint; if (!isset(self::$intervalsCache[$key])) { self::$intervalsCache[$key] = self::generateIntervals($constraint); } return self::$intervalsCache[$key]; } /** * @param bool $stopOnFirstValidInterval * * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ private static function generateIntervals(ConstraintInterface $constraint, $stopOnFirstValidInterval = \false) { if ($constraint instanceof MatchAllConstraint) { return array('numeric' => array(new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), \Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \Composer\Semver\Interval::anyDev()); } if ($constraint instanceof MatchNoneConstraint) { return array('numeric' => array(), 'branches' => array('names' => array(), 'exclude' => \false)); } if ($constraint instanceof Constraint) { return self::generateSingleConstraintIntervals($constraint); } if (!$constraint instanceof MultiConstraint) { throw new \UnexpectedValueException('The constraint passed in should be an MatchAllConstraint, Constraint or MultiConstraint instance, got ' . \get_class($constraint) . '.'); } $constraints = $constraint->getConstraints(); $numericGroups = array(); $constraintBranches = array(); foreach ($constraints as $c) { $res = self::get($c); $numericGroups[] = $res['numeric']; $constraintBranches[] = $res['branches']; } if ($constraint->isDisjunctive()) { $branches = \Composer\Semver\Interval::noDev(); foreach ($constraintBranches as $b) { if ($b['exclude']) { if ($branches['exclude']) { // disjunctive constraint, so only exclude what's excluded in all constraints // !=a,!=b || !=b,!=c => !=b $branches['names'] = \array_intersect($branches['names'], $b['names']); } else { // disjunctive constraint so exclude all names which are not explicitly included in the alternative // (==b || ==c) || !=a,!=b => !=a $branches['exclude'] = \true; $branches['names'] = \array_diff($b['names'], $branches['names']); } } else { if ($branches['exclude']) { // disjunctive constraint so exclude all names which are not explicitly included in the alternative // !=a,!=b || (==b || ==c) => !=a $branches['names'] = \array_diff($branches['names'], $b['names']); } else { // disjunctive constraint, so just add all the other branches // (==a || ==b) || ==c => ==a || ==b || ==c $branches['names'] = \array_merge($branches['names'], $b['names']); } } } } else { $branches = \Composer\Semver\Interval::anyDev(); foreach ($constraintBranches as $b) { if ($b['exclude']) { if ($branches['exclude']) { // conjunctive, so just add all branch names to be excluded // !=a && !=b => !=a,!=b $branches['names'] = \array_merge($branches['names'], $b['names']); } else { // conjunctive, so only keep included names which are not excluded // (==a||==c) && !=a,!=b => ==c $branches['names'] = \array_diff($branches['names'], $b['names']); } } else { if ($branches['exclude']) { // conjunctive, so only keep included names which are not excluded // !=a,!=b && (==a||==c) => ==c $branches['names'] = \array_diff($b['names'], $branches['names']); $branches['exclude'] = \false; } else { // conjunctive, so only keep names that are included in both // (==a||==b) && (==a||==c) => ==a $branches['names'] = \array_intersect($branches['names'], $b['names']); } } } } $branches['names'] = \array_unique($branches['names']); if (\count($numericGroups) === 1) { return array('numeric' => $numericGroups[0], 'branches' => $branches); } $borders = array(); foreach ($numericGroups as $group) { foreach ($group as $interval) { $borders[] = array('version' => $interval->getStart()->getVersion(), 'operator' => $interval->getStart()->getOperator(), 'side' => 'start'); $borders[] = array('version' => $interval->getEnd()->getVersion(), 'operator' => $interval->getEnd()->getOperator(), 'side' => 'end'); } } $opSortOrder = self::$opSortOrder; \usort($borders, function ($a, $b) use($opSortOrder) { $order = \version_compare($a['version'], $b['version']); if ($order === 0) { return $opSortOrder[$a['operator']] - $opSortOrder[$b['operator']]; } return $order; }); $activeIntervals = 0; $intervals = array(); $index = 0; $activationThreshold = $constraint->isConjunctive() ? \count($numericGroups) : 1; $start = null; foreach ($borders as $border) { if ($border['side'] === 'start') { $activeIntervals++; } else { $activeIntervals--; } if (!$start && $activeIntervals >= $activationThreshold) { $start = new Constraint($border['operator'], $border['version']); } elseif ($start && $activeIntervals < $activationThreshold) { // filter out invalid intervals like > x - <= x, or >= x - < x if (\version_compare($start->getVersion(), $border['version'], '=') && ($start->getOperator() === '>' && $border['operator'] === '<=' || $start->getOperator() === '>=' && $border['operator'] === '<')) { unset($intervals[$index]); } else { $intervals[$index] = new \Composer\Semver\Interval($start, new Constraint($border['operator'], $border['version'])); $index++; if ($stopOnFirstValidInterval) { break; } } $start = null; } } return array('numeric' => $intervals, 'branches' => $branches); } /** * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ private static function generateSingleConstraintIntervals(Constraint $constraint) { $op = $constraint->getOperator(); // handle branch constraints first if (\strpos($constraint->getVersion(), 'dev-') === 0) { $intervals = array(); $branches = array('names' => array(), 'exclude' => \false); // != dev-foo means any numeric version may match, we treat >/< like != they are not really defined for branches if ($op === '!=') { $intervals[] = new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), \Composer\Semver\Interval::untilPositiveInfinity()); $branches = array('names' => array($constraint->getVersion()), 'exclude' => \true); } elseif ($op === '==') { $branches['names'][] = $constraint->getVersion(); } return array('numeric' => $intervals, 'branches' => $branches); } if ($op[0] === '>') { // > & >= return array('numeric' => array(new \Composer\Semver\Interval($constraint, \Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \Composer\Semver\Interval::noDev()); } if ($op[0] === '<') { // < & <= return array('numeric' => array(new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), $constraint)), 'branches' => \Composer\Semver\Interval::noDev()); } if ($op === '!=') { // convert !=x to intervals of 0 - x - +inf + dev* return array('numeric' => array(new \Composer\Semver\Interval(\Composer\Semver\Interval::fromZero(), new Constraint('<', $constraint->getVersion())), new \Composer\Semver\Interval(new Constraint('>', $constraint->getVersion()), \Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \Composer\Semver\Interval::anyDev()); } // convert ==x to an interval of >=x - <=x return array('numeric' => array(new \Composer\Semver\Interval(new Constraint('>=', $constraint->getVersion()), new Constraint('<=', $constraint->getVersion()))), 'branches' => \Composer\Semver\Interval::noDev()); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver; use Composer\Semver\Constraint\Constraint; class Semver { const SORT_ASC = 1; const SORT_DESC = -1; /** @var VersionParser */ private static $versionParser; /** * Determine if given version satisfies given constraints. * * @param string $version * @param string $constraints * * @return bool */ public static function satisfies($version, $constraints) { if (null === self::$versionParser) { self::$versionParser = new \Composer\Semver\VersionParser(); } $versionParser = self::$versionParser; $provider = new Constraint('==', $versionParser->normalize($version)); $parsedConstraints = $versionParser->parseConstraints($constraints); return $parsedConstraints->matches($provider); } /** * Return all versions that satisfy given constraints. * * @param string[] $versions * @param string $constraints * * @return string[] */ public static function satisfiedBy(array $versions, $constraints) { $versions = \array_filter($versions, function ($version) use($constraints) { return \Composer\Semver\Semver::satisfies($version, $constraints); }); return \array_values($versions); } /** * Sort given array of versions. * * @param string[] $versions * * @return string[] */ public static function sort(array $versions) { return self::usort($versions, self::SORT_ASC); } /** * Sort given array of versions in reverse. * * @param string[] $versions * * @return string[] */ public static function rsort(array $versions) { return self::usort($versions, self::SORT_DESC); } /** * @param string[] $versions * @param int $direction * * @return string[] */ private static function usort(array $versions, $direction) { if (null === self::$versionParser) { self::$versionParser = new \Composer\Semver\VersionParser(); } $versionParser = self::$versionParser; $normalized = array(); // Normalize outside of usort() scope for minor performance increase. // Creates an array of arrays: [[normalized, key], ...] foreach ($versions as $key => $version) { $normalizedVersion = $versionParser->normalize($version); $normalizedVersion = $versionParser->normalizeDefaultBranch($normalizedVersion); $normalized[] = array($normalizedVersion, $key); } \usort($normalized, function (array $left, array $right) use($direction) { if ($left[0] === $right[0]) { return 0; } if (\Composer\Semver\Comparator::lessThan($left[0], $right[0])) { return -$direction; } return $direction; }); // Recreate input array, using the original indexes which are now in sorted order. $sorted = array(); foreach ($normalized as $item) { $sorted[] = $versions[$item[1]]; } return $sorted; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Semver\Constraint\MultiConstraint; use Composer\Semver\Constraint\Constraint; /** * Version parser. * * @author Jordi Boggiano */ class VersionParser { /** * Regex to match pre-release data (sort of). * * Due to backwards compatibility: * - Instead of enforcing hyphen, an underscore, dot or nothing at all are also accepted. * - Only stabilities as recognized by Composer are allowed to precede a numerical identifier. * - Numerical-only pre-release identifiers are not supported, see tests. * * |--------------| * [major].[minor].[patch] -[pre-release] +[build-metadata] * * @var string */ private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\\d+)*+)?)?([.-]?dev)?'; /** @var string */ private static $stabilitiesRegex = 'stable|RC|beta|alpha|dev'; /** * Returns the stability of a version. * * @param string $version * * @return string * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev' */ public static function parseStability($version) { $version = (string) \preg_replace('{#.+$}', '', (string) $version); if (\strpos($version, 'dev-') === 0 || '-dev' === \substr($version, -4)) { return 'dev'; } \preg_match('{' . self::$modifierRegex . '(?:\\+.*)?$}i', \strtolower($version), $match); if (!empty($match[3])) { return 'dev'; } if (!empty($match[1])) { if ('beta' === $match[1] || 'b' === $match[1]) { return 'beta'; } if ('alpha' === $match[1] || 'a' === $match[1]) { return 'alpha'; } if ('rc' === $match[1]) { return 'RC'; } } return 'stable'; } /** * @param string $stability * * @return string * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev' */ public static function normalizeStability($stability) { $stability = \strtolower((string) $stability); if (!\in_array($stability, array('stable', 'rc', 'beta', 'alpha', 'dev'), \true)) { throw new \InvalidArgumentException('Invalid stability string "' . $stability . '", expected one of stable, RC, beta, alpha or dev'); } return $stability === 'rc' ? 'RC' : $stability; } /** * Normalizes a version string to be able to perform comparisons on it. * * @param string $version * @param ?string $fullVersion optional complete version string to give more context * * @throws \UnexpectedValueException * * @return string */ public function normalize($version, $fullVersion = null) { $version = \trim((string) $version); $origVersion = $version; if (null === $fullVersion) { $fullVersion = $version; } // strip off aliasing if (\preg_match('{^([^,\\s]++) ++as ++([^,\\s]++)$}', $version, $match)) { $version = $match[1]; } // strip off stability flag if (\preg_match('{@(?:' . self::$stabilitiesRegex . ')$}i', $version, $match)) { $version = \substr($version, 0, \strlen($version) - \strlen($match[0])); } // normalize master/trunk/default branches to dev-name for BC with 1.x as these used to be valid constraints if (\in_array($version, array('master', 'trunk', 'default'), \true)) { $version = 'dev-' . $version; } // if requirement is branch-like, use full name if (\stripos($version, 'dev-') === 0) { return 'dev-' . \substr($version, 4); } // strip off build metadata if (\preg_match('{^([^,\\s+]++)\\+[^\\s]++$}', $version, $match)) { $version = $match[1]; } // match classical versioning if (\preg_match('{^v?(\\d{1,5}+)(\\.\\d++)?(\\.\\d++)?(\\.\\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) { $version = $matches[1] . (!empty($matches[2]) ? $matches[2] : '.0') . (!empty($matches[3]) ? $matches[3] : '.0') . (!empty($matches[4]) ? $matches[4] : '.0'); $index = 5; // match date(time) based versioning } elseif (\preg_match('{^v?(\\d{4}(?:[.:-]?\\d{2}){1,6}(?:[.:-]?\\d{1,3}){0,2})' . self::$modifierRegex . '$}i', $version, $matches)) { $version = (string) \preg_replace('{\\D}', '.', $matches[1]); $index = 2; } // add version modifiers if a version was matched if (isset($index)) { if (!empty($matches[$index])) { if ('stable' === $matches[$index]) { return $version; } $version .= '-' . $this->expandStability($matches[$index]) . (isset($matches[$index + 1]) && '' !== $matches[$index + 1] ? \ltrim($matches[$index + 1], '.-') : ''); } if (!empty($matches[$index + 2])) { $version .= '-dev'; } return $version; } // match dev branches if (\preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { try { $normalized = $this->normalizeBranch($match[1]); // a branch ending with -dev is only valid if it is numeric // if it gets prefixed with dev- it means the branch name should // have had a dev- prefix already when passed to normalize if (\strpos($normalized, 'dev-') === \false) { return $normalized; } } catch (\Exception $e) { } } $extraMessage = ''; if (\preg_match('{ +as +' . \preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))?$}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version'; } elseif (\preg_match('{^' . \preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))? +as +}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; } throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage); } /** * Extract numeric prefix from alias, if it is in numeric format, suitable for version comparison. * * @param string $branch Branch name (e.g. 2.1.x-dev) * * @return string|false Numeric prefix if present (e.g. 2.1.) or false */ public function parseNumericAliasPrefix($branch) { if (\preg_match('{^(?P(\\d++\\.)*\\d++)(?:\\.x)?-dev$}i', (string) $branch, $matches)) { return $matches['version'] . '.'; } return \false; } /** * Normalizes a branch name to be able to perform comparisons on it. * * @param string $name * * @return string */ public function normalizeBranch($name) { $name = \trim((string) $name); if (\preg_match('{^v?(\\d++)(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?$}i', $name, $matches)) { $version = ''; for ($i = 1; $i < 5; ++$i) { $version .= isset($matches[$i]) ? \str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; } return \str_replace('x', '9999999', $version) . '-dev'; } return 'dev-' . $name; } /** * Normalizes a default branch name (i.e. master on git) to 9999999-dev. * * @param string $name * * @return string * * @deprecated No need to use this anymore in theory, Composer 2 does not normalize any branch names to 9999999-dev anymore */ public function normalizeDefaultBranch($name) { if ($name === 'dev-master' || $name === 'dev-default' || $name === 'dev-trunk') { return '9999999-dev'; } return (string) $name; } /** * Parses a constraint string into MultiConstraint and/or Constraint objects. * * @param string $constraints * * @return ConstraintInterface */ public function parseConstraints($constraints) { $prettyConstraint = (string) $constraints; $orConstraints = \preg_split('{\\s*\\|\\|?\\s*}', \trim((string) $constraints)); if (\false === $orConstraints) { throw new \RuntimeException('Failed to preg_split string: ' . $constraints); } $orGroups = array(); foreach ($orConstraints as $orConstraint) { $andConstraints = \preg_split('{(?< ,]) *(? 1) { $constraintObjects = array(); foreach ($andConstraints as $andConstraint) { foreach ($this->parseConstraint($andConstraint) as $parsedAndConstraint) { $constraintObjects[] = $parsedAndConstraint; } } } else { $constraintObjects = $this->parseConstraint($andConstraints[0]); } if (1 === \count($constraintObjects)) { $constraint = $constraintObjects[0]; } else { $constraint = new MultiConstraint($constraintObjects); } $orGroups[] = $constraint; } $parsedConstraint = MultiConstraint::create($orGroups, \false); $parsedConstraint->setPrettyString($prettyConstraint); return $parsedConstraint; } /** * @param string $constraint * * @throws \UnexpectedValueException * * @return array * * @phpstan-return non-empty-array */ private function parseConstraint($constraint) { // strip off aliasing if (\preg_match('{^([^,\\s]++) ++as ++([^,\\s]++)$}', $constraint, $match)) { $constraint = $match[1]; } // strip @stability flags, and keep it for later use if (\preg_match('{^([^,\\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) { $constraint = '' !== $match[1] ? $match[1] : '*'; if ($match[2] !== 'stable') { $stabilityModifier = $match[2]; } } // get rid of #refs as those are used by composer only if (\preg_match('{^(dev-[^,\\s@]+?|[^,\\s@]+?\\.x-dev)#.+$}i', $constraint, $match)) { $constraint = $match[1]; } if (\preg_match('{^(v)?[xX*](\\.[xX*])*$}i', $constraint, $match)) { if (!empty($match[1]) || !empty($match[2])) { return array(new Constraint('>=', '0.0.0.0-dev')); } return array(new MatchAllConstraint()); } $versionRegex = 'v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.(\\d++))?(?:' . self::$modifierRegex . '|\\.([xX*][.-]?dev))(?:\\+[^\\s]+)?'; // Tilde Range // // Like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous // version, to ensure that unstable instances of the current version are allowed. However, if a stability // suffix is added to the constraint, then a >= match on the current version is used instead. if (\preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) { if (\strpos($constraint, '~>') === 0) { throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator'); } // Work out which position in the version we are operating at if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) { $position = 4; } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } // when matching 2.x-dev or 3.0.x-dev we have to shift the second or third number, despite no second/third number matching above if (!empty($matches[8])) { $position++; } // Calculate the stability suffix $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new Constraint('>=', $lowVersion); // For upper bound, we increment the position of one more significance, // but highPosition = 0 would be illegal $highPosition = \max(1, $position - 1); $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); return array($lowerBound, $upperBound); } // Caret Range // // Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple. // In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for // versions 0.X >=0.1.0, and no updates for versions 0.0.X if (\preg_match('{^\\^' . $versionRegex . '($)}i', $constraint, $matches)) { // Work out which position in the version we are operating at if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) { $position = 1; } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) { $position = 2; } else { $position = 3; } // Calculate the stability suffix $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new Constraint('>=', $lowVersion); // For upper bound, we increment the position of one more significance, // but highPosition = 0 would be illegal $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); return array($lowerBound, $upperBound); } // X Range // // Any of X, x, or * may be used to "stand in" for one of the numeric values in the [major, minor, patch] tuple. // A partial version range is treated as an X-Range, so the special character is in fact optional. if (\preg_match('{^v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.[xX*])++$}', $constraint, $matches)) { if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev'; $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; if ($lowVersion === '0.0.0.0-dev') { return array(new Constraint('<', $highVersion)); } return array(new Constraint('>=', $lowVersion), new Constraint('<', $highVersion)); } // Hyphen Range // // Specifies an inclusive set. If a partial version is provided as the first version in the inclusive range, // then the missing pieces are replaced with zeroes. If a partial version is provided as the second version in // the inclusive range, then all versions that start with the supplied parts of the tuple are accepted, but // nothing that would be greater than the provided tuple parts. if (\preg_match('{^(?P' . $versionRegex . ') +- +(?P' . $versionRegex . ')($)}i', $constraint, $matches)) { // Calculate the stability suffix $lowStabilitySuffix = ''; if (empty($matches[6]) && empty($matches[8]) && empty($matches[9])) { $lowStabilitySuffix = '-dev'; } $lowVersion = $this->normalize($matches['from']); $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix); $empty = function ($x) { return $x === 0 || $x === '0' ? \false : empty($x); }; if (!$empty($matches[12]) && !$empty($matches[13]) || !empty($matches[15]) || !empty($matches[17]) || !empty($matches[18])) { $highVersion = $this->normalize($matches['to']); $upperBound = new Constraint('<=', $highVersion); } else { $highMatch = array('', $matches[11], $matches[12], $matches[13], $matches[14]); // validate to version $this->normalize($matches['to']); $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[12]) ? 1 : 2, 1) . '-dev'; $upperBound = new Constraint('<', $highVersion); } return array($lowerBound, $upperBound); } // Basic Comparators if (\preg_match('{^(<>|!=|>=?|<=?|==?)?\\s*(.*)}', $constraint, $matches)) { try { try { $version = $this->normalize($matches[2]); } catch (\UnexpectedValueException $e) { // recover from an invalid constraint like foobar-dev which should be dev-foobar // except if the constraint uses a known operator, in which case it must be a parse error if (\substr($matches[2], -4) === '-dev' && \preg_match('{^[0-9a-zA-Z-./]+$}', $matches[2])) { $version = $this->normalize('dev-' . \substr($matches[2], 0, -4)); } else { throw $e; } } $op = $matches[1] ?: '='; if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') { $version .= '-' . $stabilityModifier; } elseif ('<' === $op || '>=' === $op) { if (!\preg_match('/-' . self::$modifierRegex . '$/', \strtolower($matches[2]))) { if (\strpos($matches[2], 'dev-') !== 0) { $version .= '-dev'; } } } return array(new Constraint($matches[1] ?: '=', $version)); } catch (\Exception $e) { } } $message = 'Could not parse version constraint ' . $constraint; if (isset($e)) { $message .= ': ' . $e->getMessage(); } throw new \UnexpectedValueException($message); } /** * Increment, decrement, or simply pad a version number. * * Support function for {@link parseConstraint()} * * @param array $matches Array with version parts in array indexes 1,2,3,4 * @param int $position 1,2,3,4 - which segment of the version to increment/decrement * @param int $increment * @param string $pad The string to pad version parts after $position * * @return string|null The new version * * @phpstan-param string[] $matches */ private function manipulateVersionString(array $matches, $position, $increment = 0, $pad = '0') { for ($i = 4; $i > 0; --$i) { if ($i > $position) { $matches[$i] = $pad; } elseif ($i === $position && $increment) { $matches[$i] += $increment; // If $matches[$i] was 0, carry the decrement if ($matches[$i] < 0) { $matches[$i] = $pad; --$position; // Return null on a carry overflow if ($i === 1) { return null; } } } } return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; } /** * Expand shorthand stability string to long version. * * @param string $stability * * @return string */ private function expandStability($stability) { $stability = \strtolower($stability); switch ($stability) { case 'a': return 'alpha'; case 'b': return 'beta'; case 'p': case 'pl': return 'patch'; case 'rc': return 'RC'; default: return $stability; } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver\Constraint; /** * DO NOT IMPLEMENT this interface. It is only meant for usage as a type hint * in libraries relying on composer/semver but creating your own constraint class * that implements this interface is not a supported use case and will cause the * composer/semver components to return unexpected results. */ interface ConstraintInterface { /** * Checks whether the given constraint intersects in any way with this constraint * * @param ConstraintInterface $provider * * @return bool */ public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider); /** * Provides a compiled version of the constraint for the given operator * The compiled version must be a PHP expression. * Executor of compile version must provide 2 variables: * - $v = the string version to compare with * - $b = whether or not the version is a non-comparable branch (starts with "dev-") * * @see Constraint::OP_* for the list of available operators. * @example return '!$b && version_compare($v, '1.0', '>')'; * * @param int $otherOperator one Constraint::OP_* * * @return string * * @phpstan-param Constraint::OP_* $otherOperator */ public function compile($otherOperator); /** * @return Bound */ public function getUpperBound(); /** * @return Bound */ public function getLowerBound(); /** * @return string */ public function getPrettyString(); /** * @param string|null $prettyString * * @return void */ public function setPrettyString($prettyString); /** * @return string */ public function __toString(); } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver\Constraint; /** * Defines a conjunctive or disjunctive set of constraints. */ class MultiConstraint implements \Composer\Semver\Constraint\ConstraintInterface { /** * @var ConstraintInterface[] * @phpstan-var non-empty-array */ protected $constraints; /** @var string|null */ protected $prettyString; /** @var string|null */ protected $string; /** @var bool */ protected $conjunctive; /** @var Bound|null */ protected $lowerBound; /** @var Bound|null */ protected $upperBound; /** * @param ConstraintInterface[] $constraints A set of constraints * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive * * @throws \InvalidArgumentException If less than 2 constraints are passed */ public function __construct(array $constraints, $conjunctive = \true) { if (\count($constraints) < 2) { throw new \InvalidArgumentException('Must provide at least two constraints for a MultiConstraint. Use ' . 'the regular Constraint class for one constraint only or MatchAllConstraint for none. You may use ' . 'MultiConstraint::create() which optimizes and handles those cases automatically.'); } $this->constraints = $constraints; $this->conjunctive = $conjunctive; } /** * @return ConstraintInterface[] */ public function getConstraints() { return $this->constraints; } /** * @return bool */ public function isConjunctive() { return $this->conjunctive; } /** * @return bool */ public function isDisjunctive() { return !$this->conjunctive; } /** * {@inheritDoc} */ public function compile($otherOperator) { $parts = array(); foreach ($this->constraints as $constraint) { $code = $constraint->compile($otherOperator); if ($code === 'true') { if (!$this->conjunctive) { return 'true'; } } elseif ($code === 'false') { if ($this->conjunctive) { return 'false'; } } else { $parts[] = '(' . $code . ')'; } } if (!$parts) { return $this->conjunctive ? 'true' : 'false'; } return $this->conjunctive ? \implode('&&', $parts) : \implode('||', $parts); } /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider) { if (\false === $this->conjunctive) { foreach ($this->constraints as $constraint) { if ($provider->matches($constraint)) { return \true; } } return \false; } // when matching a conjunctive and a disjunctive multi constraint we have to iterate over the disjunctive one // otherwise we'd return true if different parts of the disjunctive constraint match the conjunctive one // which would lead to incorrect results, e.g. [>1 and <2] would match [<1 or >2] although they do not intersect if ($provider instanceof \Composer\Semver\Constraint\MultiConstraint && $provider->isDisjunctive()) { return $provider->matches($this); } foreach ($this->constraints as $constraint) { if (!$provider->matches($constraint)) { return \false; } } return \true; } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * {@inheritDoc} */ public function __toString() { if ($this->string !== null) { return $this->string; } $constraints = array(); foreach ($this->constraints as $constraint) { $constraints[] = (string) $constraint; } return $this->string = '[' . \implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']'; } /** * {@inheritDoc} */ public function getLowerBound() { $this->extractBounds(); if (null === $this->lowerBound) { throw new \LogicException('extractBounds should have populated the lowerBound property'); } return $this->lowerBound; } /** * {@inheritDoc} */ public function getUpperBound() { $this->extractBounds(); if (null === $this->upperBound) { throw new \LogicException('extractBounds should have populated the upperBound property'); } return $this->upperBound; } /** * Tries to optimize the constraints as much as possible, meaning * reducing/collapsing congruent constraints etc. * Does not necessarily return a MultiConstraint instance if * things can be reduced to a simple constraint * * @param ConstraintInterface[] $constraints A set of constraints * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive * * @return ConstraintInterface */ public static function create(array $constraints, $conjunctive = \true) { if (0 === \count($constraints)) { return new \Composer\Semver\Constraint\MatchAllConstraint(); } if (1 === \count($constraints)) { return $constraints[0]; } $optimized = self::optimizeConstraints($constraints, $conjunctive); if ($optimized !== null) { list($constraints, $conjunctive) = $optimized; if (\count($constraints) === 1) { return $constraints[0]; } } return new self($constraints, $conjunctive); } /** * @param ConstraintInterface[] $constraints * @param bool $conjunctive * @return ?array * * @phpstan-return array{0: list, 1: bool}|null */ private static function optimizeConstraints(array $constraints, $conjunctive) { // parse the two OR groups and if they are contiguous we collapse // them into one constraint // [>= 1 < 2] || [>= 2 < 3] || [>= 3 < 4] => [>= 1 < 4] if (!$conjunctive) { $left = $constraints[0]; $mergedConstraints = array(); $optimized = \false; for ($i = 1, $l = \count($constraints); $i < $l; $i++) { $right = $constraints[$i]; if ($left instanceof self && $left->conjunctive && $right instanceof self && $right->conjunctive && \count($left->constraints) === 2 && \count($right->constraints) === 2 && ($left0 = (string) $left->constraints[0]) && $left0[0] === '>' && $left0[1] === '=' && ($left1 = (string) $left->constraints[1]) && $left1[0] === '<' && ($right0 = (string) $right->constraints[0]) && $right0[0] === '>' && $right0[1] === '=' && ($right1 = (string) $right->constraints[1]) && $right1[0] === '<' && \substr($left1, 2) === \substr($right0, 3)) { $optimized = \true; $left = new \Composer\Semver\Constraint\MultiConstraint(array($left->constraints[0], $right->constraints[1]), \true); } else { $mergedConstraints[] = $left; $left = $right; } } if ($optimized) { $mergedConstraints[] = $left; return array($mergedConstraints, \false); } } // TODO: Here's the place to put more optimizations return null; } /** * @return void */ private function extractBounds() { if (null !== $this->lowerBound) { return; } foreach ($this->constraints as $constraint) { if (null === $this->lowerBound || null === $this->upperBound) { $this->lowerBound = $constraint->getLowerBound(); $this->upperBound = $constraint->getUpperBound(); continue; } if ($constraint->getLowerBound()->compareTo($this->lowerBound, $this->isConjunctive() ? '>' : '<')) { $this->lowerBound = $constraint->getLowerBound(); } if ($constraint->getUpperBound()->compareTo($this->upperBound, $this->isConjunctive() ? '<' : '>')) { $this->upperBound = $constraint->getUpperBound(); } } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver\Constraint; /** * Defines a constraint. */ class Constraint implements \Composer\Semver\Constraint\ConstraintInterface { /* operator integer values */ const OP_EQ = 0; const OP_LT = 1; const OP_LE = 2; const OP_GT = 3; const OP_GE = 4; const OP_NE = 5; /* operator string values */ const STR_OP_EQ = '=='; const STR_OP_EQ_ALT = '='; const STR_OP_LT = '<'; const STR_OP_LE = '<='; const STR_OP_GT = '>'; const STR_OP_GE = '>='; const STR_OP_NE = '!='; const STR_OP_NE_ALT = '<>'; /** * Operator to integer translation table. * * @var array * @phpstan-var array */ private static $transOpStr = array('=' => self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, '<=' => self::OP_LE, '>' => self::OP_GT, '>=' => self::OP_GE, '<>' => self::OP_NE, '!=' => self::OP_NE); /** * Integer to operator translation table. * * @var array * @phpstan-var array */ private static $transOpInt = array(self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', self::OP_GT => '>', self::OP_GE => '>=', self::OP_NE => '!='); /** * @var int * @phpstan-var self::OP_* */ protected $operator; /** @var string */ protected $version; /** @var string|null */ protected $prettyString; /** @var Bound */ protected $lowerBound; /** @var Bound */ protected $upperBound; /** * Sets operator and version to compare with. * * @param string $operator * @param string $version * * @throws \InvalidArgumentException if invalid operator is given. * * @phpstan-param self::STR_OP_* $operator */ public function __construct($operator, $version) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $this->operator = self::$transOpStr[$operator]; $this->version = $version; } /** * @return string */ public function getVersion() { return $this->version; } /** * @return string * * @phpstan-return self::STR_OP_* */ public function getOperator() { return self::$transOpInt[$this->operator]; } /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider) { if ($provider instanceof self) { return $this->matchSpecific($provider); } // turn matching around to find a match return $provider->matches($this); } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } /** * Get all supported comparison operators. * * @return array * * @phpstan-return list */ public static function getSupportedOperators() { return \array_keys(self::$transOpStr); } /** * @param string $operator * @return int * * @phpstan-param self::STR_OP_* $operator * @phpstan-return self::OP_* */ public static function getOperatorConstant($operator) { return self::$transOpStr[$operator]; } /** * @param string $a * @param string $b * @param string $operator * @param bool $compareBranches * * @throws \InvalidArgumentException if invalid operator is given. * * @return bool * * @phpstan-param self::STR_OP_* $operator */ public function versionCompare($a, $b, $operator, $compareBranches = \false) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $aIsBranch = \strpos($a, 'dev-') === 0; $bIsBranch = \strpos($b, 'dev-') === 0; if ($operator === '!=' && ($aIsBranch || $bIsBranch)) { return $a !== $b; } if ($aIsBranch && $bIsBranch) { return $operator === '==' && $a === $b; } // when branches are not comparable, we make sure dev branches never match anything if (!$compareBranches && ($aIsBranch || $bIsBranch)) { return \false; } return \version_compare($a, $b, $operator); } /** * {@inheritDoc} */ public function compile($otherOperator) { if (\strpos($this->version, 'dev-') === 0) { if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('$b && $v === %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return \sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } return 'false'; } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } return 'false'; } if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('\\version_compare($v, %s, \'==\')', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return \sprintf('$b || \\version_compare($v, %s, \'!=\')', \var_export($this->version, \true)); } return \sprintf('!$b && \\version_compare(%s, $v, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$otherOperator]); } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('$b || (!$b && \\version_compare($v, %s, \'!=\'))', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) { if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) { return '!$b'; } } else { // $this->operator must be self::OP_GT || self::OP_GE here if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) { return '!$b'; } } if (self::OP_NE === $otherOperator) { return 'true'; } $codeComparison = \sprintf('\\version_compare($v, %s, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$this->operator]); if ($this->operator === self::OP_LE) { if ($otherOperator === self::OP_GT) { return \sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } elseif ($this->operator === self::OP_GE) { if ($otherOperator === self::OP_LT) { return \sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } return \sprintf('!$b && %s', $codeComparison); } /** * @param Constraint $provider * @param bool $compareBranches * * @return bool */ public function matchSpecific(\Composer\Semver\Constraint\Constraint $provider, $compareBranches = \false) { $noEqualOp = \str_replace('=', '', self::$transOpInt[$this->operator]); $providerNoEqualOp = \str_replace('=', '', self::$transOpInt[$provider->operator]); $isEqualOp = self::OP_EQ === $this->operator; $isNonEqualOp = self::OP_NE === $this->operator; $isProviderEqualOp = self::OP_EQ === $provider->operator; $isProviderNonEqualOp = self::OP_NE === $provider->operator; // '!=' operator is match when other operator is not '==' operator or version is not match // these kinds of comparisons always have a solution if ($isNonEqualOp || $isProviderNonEqualOp) { if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && \strpos($provider->version, 'dev-') === 0) { return \false; } if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && \strpos($this->version, 'dev-') === 0) { return \false; } if (!$isEqualOp && !$isProviderEqualOp) { return \true; } return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); } // an example for the condition is <= 2.0 & < 1.0 // these kinds of comparisons always have a solution if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) { return !(\strpos($this->version, 'dev-') === 0 || \strpos($provider->version, 'dev-') === 0); } $version1 = $isEqualOp ? $this->version : $provider->version; $version2 = $isEqualOp ? $provider->version : $this->version; $operator = $isEqualOp ? $provider->operator : $this->operator; if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) { // special case, e.g. require >= 1.0 and provide < 1.0 // 1.0 >= 1.0 but 1.0 is outside of the provided interval return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp && \version_compare($provider->version, $this->version, '==')); } return \false; } /** * @return string */ public function __toString() { return self::$transOpInt[$this->operator] . ' ' . $this->version; } /** * {@inheritDoc} */ public function getLowerBound() { $this->extractBounds(); return $this->lowerBound; } /** * {@inheritDoc} */ public function getUpperBound() { $this->extractBounds(); return $this->upperBound; } /** * @return void */ private function extractBounds() { if (null !== $this->lowerBound) { return; } // Branches if (\strpos($this->version, 'dev-') === 0) { $this->lowerBound = \Composer\Semver\Constraint\Bound::zero(); $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity(); return; } switch ($this->operator) { case self::OP_EQ: $this->lowerBound = new \Composer\Semver\Constraint\Bound($this->version, \true); $this->upperBound = new \Composer\Semver\Constraint\Bound($this->version, \true); break; case self::OP_LT: $this->lowerBound = \Composer\Semver\Constraint\Bound::zero(); $this->upperBound = new \Composer\Semver\Constraint\Bound($this->version, \false); break; case self::OP_LE: $this->lowerBound = \Composer\Semver\Constraint\Bound::zero(); $this->upperBound = new \Composer\Semver\Constraint\Bound($this->version, \true); break; case self::OP_GT: $this->lowerBound = new \Composer\Semver\Constraint\Bound($this->version, \false); $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity(); break; case self::OP_GE: $this->lowerBound = new \Composer\Semver\Constraint\Bound($this->version, \true); $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity(); break; case self::OP_NE: $this->lowerBound = \Composer\Semver\Constraint\Bound::zero(); $this->upperBound = \Composer\Semver\Constraint\Bound::positiveInfinity(); break; } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver\Constraint; /** * Defines the absence of a constraint. * * This constraint matches everything. */ class MatchAllConstraint implements \Composer\Semver\Constraint\ConstraintInterface { /** @var string|null */ protected $prettyString; /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider) { return \true; } /** * {@inheritDoc} */ public function compile($otherOperator) { return 'true'; } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * {@inheritDoc} */ public function __toString() { return '*'; } /** * {@inheritDoc} */ public function getUpperBound() { return \Composer\Semver\Constraint\Bound::positiveInfinity(); } /** * {@inheritDoc} */ public function getLowerBound() { return \Composer\Semver\Constraint\Bound::zero(); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver\Constraint; /** * Blackhole of constraints, nothing escapes it */ class MatchNoneConstraint implements \Composer\Semver\Constraint\ConstraintInterface { /** @var string|null */ protected $prettyString; /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\Composer\Semver\Constraint\ConstraintInterface $provider) { return \false; } /** * {@inheritDoc} */ public function compile($otherOperator) { return 'false'; } /** * {@inheritDoc} */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * {@inheritDoc} */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * {@inheritDoc} */ public function __toString() { return '[]'; } /** * {@inheritDoc} */ public function getUpperBound() { return new \Composer\Semver\Constraint\Bound('0.0.0.0-dev', \false); } /** * {@inheritDoc} */ public function getLowerBound() { return new \Composer\Semver\Constraint\Bound('0.0.0.0-dev', \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Semver\Constraint; class Bound { /** * @var string */ private $version; /** * @var bool */ private $isInclusive; /** * @param string $version * @param bool $isInclusive */ public function __construct($version, $isInclusive) { $this->version = $version; $this->isInclusive = $isInclusive; } /** * @return string */ public function getVersion() { return $this->version; } /** * @return bool */ public function isInclusive() { return $this->isInclusive; } /** * @return bool */ public function isZero() { return $this->getVersion() === '0.0.0.0-dev' && $this->isInclusive(); } /** * @return bool */ public function isPositiveInfinity() { return $this->getVersion() === \PHP_INT_MAX . '.0.0.0' && !$this->isInclusive(); } /** * Compares a bound to another with a given operator. * * @param Bound $other * @param string $operator * * @return bool */ public function compareTo(\Composer\Semver\Constraint\Bound $other, $operator) { if (!\in_array($operator, array('<', '>'), \true)) { throw new \InvalidArgumentException('Does not support any other operator other than > or <.'); } // If they are the same it doesn't matter if ($this == $other) { return \false; } $compareResult = \version_compare($this->getVersion(), $other->getVersion()); // Not the same version means we don't need to check if the bounds are inclusive or not if (0 !== $compareResult) { return ('>' === $operator ? 1 : -1) === $compareResult; } // Question we're answering here is "am I higher than $other?" return '>' === $operator ? $other->isInclusive() : !$other->isInclusive(); } public function __toString() { return \sprintf('%s [%s]', $this->getVersion(), $this->isInclusive() ? 'inclusive' : 'exclusive'); } /** * @return self */ public static function zero() { return new \Composer\Semver\Constraint\Bound('0.0.0.0-dev', \true); } /** * @return self */ public static function positiveInfinity() { return new \Composer\Semver\Constraint\Bound(\PHP_INT_MAX . '.0.0.0', \false); } } $vendorDir . '/symfony/deprecation-contracts/function.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '09f6b20656683369174dd6fa83b7e5fb' => $vendorDir . '/symfony/polyfill-uuid/bootstrap.php', 'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php', '2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', 'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php', ); * 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 */ private static $installedIsLocalDir; /** * @var bool|null */ private static $canGetVendors; /** * @var array[] * @psalm-var array}> */ private static $installedByVendor = array(); /** * Returns a list of all package names which are present, either by being installed, replaced or provided * * @return string[] * @psalm-return list */ public static function getInstalledPackages() { $packages = array(); foreach (self::getInstalled() as $installed) { $packages[] = \array_keys($installed['versions']); } if (1 === \count($packages)) { return $packages[0]; } return \array_keys(\array_flip(\call_user_func_array('array_merge', $packages))); } /** * Returns a list of all package names with a specific type e.g. 'library' * * @param string $type * @return string[] * @psalm-return list */ public static function getInstalledPackagesByType($type) { $packagesByType = array(); foreach (self::getInstalled() as $installed) { foreach ($installed['versions'] as $name => $package) { if (isset($package['type']) && $package['type'] === $type) { $packagesByType[] = $name; } } } return $packagesByType; } /** * Checks whether the given package is installed * * This also returns true if the package name is provided or replaced by another package * * @param string $packageName * @param bool $includeDevRequirements * @return bool */ public static function isInstalled($packageName, $includeDevRequirements = \true) { foreach (self::getInstalled() as $installed) { if (isset($installed['versions'][$packageName])) { return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === \false; } } return \false; } /** * Checks whether the given package satisfies a version constraint * * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: * * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') * * @param VersionParser $parser Install composer/semver to have access to this class and functionality * @param string $packageName * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package * @return bool */ public static function satisfies(VersionParser $parser, $packageName, $constraint) { $constraint = $parser->parseConstraints((string) $constraint); $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); return $provided->matches($constraint); } /** * Returns a version constraint representing all the range(s) which are installed for a given package * * It is easier to use this via isInstalled() with the $constraint argument if you need to check * whether a given version of a package is installed, and not just whether it exists * * @param string $packageName * @return string Version constraint usable with composer/semver */ public static function getVersionRanges($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } $ranges = array(); if (isset($installed['versions'][$packageName]['pretty_version'])) { $ranges[] = $installed['versions'][$packageName]['pretty_version']; } if (\array_key_exists('aliases', $installed['versions'][$packageName])) { $ranges = \array_merge($ranges, $installed['versions'][$packageName]['aliases']); } if (\array_key_exists('replaced', $installed['versions'][$packageName])) { $ranges = \array_merge($ranges, $installed['versions'][$packageName]['replaced']); } if (\array_key_exists('provided', $installed['versions'][$packageName])) { $ranges = \array_merge($ranges, $installed['versions'][$packageName]['provided']); } return \implode(' || ', $ranges); } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present */ public static function getVersion($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } if (!isset($installed['versions'][$packageName]['version'])) { return null; } return $installed['versions'][$packageName]['version']; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present */ public static function getPrettyVersion($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } if (!isset($installed['versions'][$packageName]['pretty_version'])) { return null; } return $installed['versions'][$packageName]['pretty_version']; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference */ public static function getReference($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } if (!isset($installed['versions'][$packageName]['reference'])) { return null; } return $installed['versions'][$packageName]['reference']; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @param string $packageName * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. */ public static function getInstallPath($packageName) { foreach (self::getInstalled() as $installed) { if (!isset($installed['versions'][$packageName])) { continue; } return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; } throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); } /** * @return array * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} */ public static function getRootPackage() { $installed = self::getInstalled(); return $installed[0]['root']; } /** * Returns the raw installed.php data for custom implementations * * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. * @return array[] * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} */ public static function getRawData() { @\trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', \E_USER_DEPRECATED); if (null === self::$installed) { // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 if (\substr(__DIR__, -8, 1) !== 'C') { self::$installed = (include __DIR__ . '/installed.php'); } else { self::$installed = array(); } } return self::$installed; } /** * Returns the raw data of all installed.php which are currently loaded for custom implementations * * @return array[] * @psalm-return list}> */ public static function getAllRawData() { return self::getInstalled(); } /** * Lets you reload the static array from another file * * This is only useful for complex integrations in which a project needs to use * this class but then also needs to execute another project's autoloader in process, * and wants to ensure both projects have access to their version of installed.php. * * A typical case would be PHPUnit, where it would need to make sure it reads all * the data it needs from this class, then call reload() with * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure * the project in which it runs can then also use this class safely, without * interference between PHPUnit's dependencies and the project's dependencies. * * @param array[] $data A vendor/composer/installed.php data set * @return void * * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data */ public static function reload($data) { self::$installed = $data; self::$installedByVendor = array(); // when using reload, we disable the duplicate protection to ensure that self::$installed data is // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, // so we have to assume it does not, and that may result in duplicate data being returned when listing // all installed packages for example self::$installedIsLocalDir = \false; } /** * @return array[] * @psalm-return list}> */ private static function getInstalled() { if (null === self::$canGetVendors) { self::$canGetVendors = \method_exists('Composer\\Autoload\\ClassLoader', 'getRegisteredLoaders'); } $installed = array(); $copiedLocalDir = \false; if (self::$canGetVendors) { $selfDir = \strtr(__DIR__, '\\', '/'); foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { $vendorDir = \strtr($vendorDir, '\\', '/'); if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (\is_file($vendorDir . '/composer/installed.php')) { /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ $required = (require $vendorDir . '/composer/installed.php'); self::$installedByVendor[$vendorDir] = $required; $installed[] = $required; if (self::$installed === null && $vendorDir . '/composer' === $selfDir) { self::$installed = $required; self::$installedIsLocalDir = \true; } } if (self::$installedIsLocalDir && $vendorDir . '/composer' === $selfDir) { $copiedLocalDir = \true; } } } if (null === self::$installed) { // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 if (\substr(__DIR__, -8, 1) !== 'C') { /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ $required = (require __DIR__ . '/installed.php'); self::$installed = $required; } else { self::$installed = array(); } } if (self::$installed !== array() && !$copiedLocalDir) { $installed[] = self::$installed; } return $installed; } } array('name' => 'contao/contao-manager', 'pretty_version' => '1.9.1', 'version' => '1.9.1.0', 'reference' => 'f021425fd7445d3daafb6f65260fa1b716d605c1', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \false), 'versions' => array('brick/math' => array('pretty_version' => '0.12.1', 'version' => '0.12.1.0', 'reference' => 'f510c0a40911935b77b86859eb5223d58d660df1', 'type' => 'library', 'install_path' => __DIR__ . '/../brick/math', 'aliases' => array(), 'dev_requirement' => \false), 'composer/ca-bundle' => array('pretty_version' => '1.5.5', 'version' => '1.5.5.0', 'reference' => '08c50d5ec4c6ced7d0271d2862dec8c1033283e6', 'type' => 'library', 'install_path' => __DIR__ . '/./ca-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'composer/class-map-generator' => array('pretty_version' => '1.6.0', 'version' => '1.6.0.0', 'reference' => 'ffe442c5974c44a9343e37a0abcb1cc37319f5b9', 'type' => 'library', 'install_path' => __DIR__ . '/./class-map-generator', 'aliases' => array(), 'dev_requirement' => \false), 'composer/composer' => array('pretty_version' => '2.8.5', 'version' => '2.8.5.0', 'reference' => 'ae208dc1e182bd45d99fcecb956501da212454a1', 'type' => 'library', 'install_path' => __DIR__ . '/./composer', 'aliases' => array(), 'dev_requirement' => \false), 'composer/metadata-minifier' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'c549d23829536f0d0e984aaabbf02af91f443207', 'type' => 'library', 'install_path' => __DIR__ . '/./metadata-minifier', 'aliases' => array(), 'dev_requirement' => \false), 'composer/pcre' => array('pretty_version' => '3.3.2', 'version' => '3.3.2.0', 'reference' => 'b2bed4734f0cc156ee1fe9c0da2550420d99a21e', 'type' => 'library', 'install_path' => __DIR__ . '/./pcre', 'aliases' => array(), 'dev_requirement' => \false), 'composer/semver' => array('pretty_version' => '3.4.3', 'version' => '3.4.3.0', 'reference' => '4313d26ada5e0c4edfbd1dc481a92ff7bff91f12', 'type' => 'library', 'install_path' => __DIR__ . '/./semver', 'aliases' => array(), 'dev_requirement' => \false), 'composer/spdx-licenses' => array('pretty_version' => '1.5.8', 'version' => '1.5.8.0', 'reference' => '560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a', 'type' => 'library', 'install_path' => __DIR__ . '/./spdx-licenses', 'aliases' => array(), 'dev_requirement' => \false), 'composer/xdebug-handler' => array('pretty_version' => '3.0.5', 'version' => '3.0.5.0', 'reference' => '6c1925561632e83d60a44492e0b344cf48ab85ef', 'type' => 'library', 'install_path' => __DIR__ . '/./xdebug-handler', 'aliases' => array(), 'dev_requirement' => \false), 'contao/contao-manager' => array('pretty_version' => '1.9.1', 'version' => '1.9.1.0', 'reference' => 'f021425fd7445d3daafb6f65260fa1b716d605c1', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'crell/api-problem' => array('pretty_version' => '3.7.0', 'version' => '3.7.0.0', 'reference' => 'b41d66dc1d403b2d406699e2e05bb2b48efe3b7f', 'type' => 'library', 'install_path' => __DIR__ . '/../crell/api-problem', 'aliases' => array(), 'dev_requirement' => \false), 'doctrine/deprecations' => array('pretty_version' => '1.1.4', 'version' => '1.1.4.0', 'reference' => '31610dbb31faa98e6b5447b62340826f54fbc4e9', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/deprecations', 'aliases' => array(), 'dev_requirement' => \false), 'firebase/php-jwt' => array('pretty_version' => 'v6.11.0', 'version' => '6.11.0.0', 'reference' => '8f718f4dfc9c5d5f0c994cdfd103921b43592712', 'type' => 'library', 'install_path' => __DIR__ . '/../firebase/php-jwt', 'aliases' => array(), 'dev_requirement' => \false), 'justinrainbow/json-schema' => array('pretty_version' => '5.3.0', 'version' => '5.3.0.0', 'reference' => 'feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8', 'type' => 'library', 'install_path' => __DIR__ . '/../justinrainbow/json-schema', 'aliases' => array(), 'dev_requirement' => \false), 'lcobucci/clock' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => '039ef98c6b57b101d10bd11d8fdfda12cbd996dc', 'type' => 'library', 'install_path' => __DIR__ . '/../lcobucci/clock', 'aliases' => array(), 'dev_requirement' => \false), 'monolog/monolog' => array('pretty_version' => '3.8.1', 'version' => '3.8.1.0', 'reference' => 'aef6ee73a77a66e404dd6540934a9ef1b3c855b4', 'type' => 'library', 'install_path' => __DIR__ . '/../monolog/monolog', 'aliases' => array(), 'dev_requirement' => \false), 'paragonie/constant_time_encoding' => array('pretty_version' => 'v3.0.0', 'version' => '3.0.0.0', 'reference' => 'df1e7fde177501eee2037dd159cf04f5f301a512', 'type' => 'library', 'install_path' => __DIR__ . '/../paragonie/constant_time_encoding', 'aliases' => array(), 'dev_requirement' => \false), 'phpdocumentor/reflection-common' => array('pretty_version' => '2.2.0', 'version' => '2.2.0.0', 'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b', 'type' => 'library', 'install_path' => __DIR__ . '/../phpdocumentor/reflection-common', 'aliases' => array(), 'dev_requirement' => \false), 'phpdocumentor/reflection-docblock' => array('pretty_version' => '5.6.1', 'version' => '5.6.1.0', 'reference' => 'e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8', 'type' => 'library', 'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock', 'aliases' => array(), 'dev_requirement' => \false), 'phpdocumentor/type-resolver' => array('pretty_version' => '1.10.0', 'version' => '1.10.0.0', 'reference' => '679e3ce485b99e84c775d28e2e96fade9a7fb50a', 'type' => 'library', 'install_path' => __DIR__ . '/../phpdocumentor/type-resolver', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpdoc-parser' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '9b30d6fd026b2c132b3985ce6b23bec09ab3aa68', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', 'aliases' => array(), 'dev_requirement' => \false), 'psr/cache' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/cache', 'aliases' => array(), 'dev_requirement' => \false), 'psr/cache-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '2.0|3.0')), 'psr/clock' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/clock', 'aliases' => array(), 'dev_requirement' => \false), 'psr/clock-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0')), 'psr/container' => array('pretty_version' => '2.0.2', 'version' => '2.0.2.0', 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0')), 'psr/event-dispatcher' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/event-dispatcher', 'aliases' => array(), 'dev_requirement' => \false), 'psr/event-dispatcher-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0')), 'psr/http-client' => array('pretty_version' => '1.0.3', 'version' => '1.0.3.0', 'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-client', 'aliases' => array(), 'dev_requirement' => \false), 'psr/http-factory' => array('pretty_version' => '1.1.0', 'version' => '1.1.0.0', 'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-factory', 'aliases' => array(), 'dev_requirement' => \false), 'psr/http-message' => array('pretty_version' => '2.0', 'version' => '2.0.0.0', 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-message', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log' => array('pretty_version' => '3.0.2', 'version' => '3.0.2.0', 'reference' => 'f16e1d5863e37f8d8c2a01719f5b34baa2b714d3', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/log', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0|2.0|3.0', 1 => '3.0.0')), 'psr/simple-cache-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0|2.0|3.0')), 'ramsey/collection' => array('pretty_version' => '2.0.0', 'version' => '2.0.0.0', 'reference' => 'a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/collection', 'aliases' => array(), 'dev_requirement' => \false), 'ramsey/uuid' => array('pretty_version' => '4.7.6', 'version' => '4.7.6.0', 'reference' => '91039bc1faa45ba123c4328958e620d382ec7088', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/uuid', 'aliases' => array(), 'dev_requirement' => \false), 'react/promise' => array('pretty_version' => 'v3.2.0', 'version' => '3.2.0.0', 'reference' => '8a164643313c71354582dc850b42b33fa12a4b63', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise', 'aliases' => array(), 'dev_requirement' => \false), 'rhumsaa/uuid' => array('dev_requirement' => \false, 'replaced' => array(0 => '4.7.6')), 'seld/jsonlint' => array('pretty_version' => '1.11.0', 'version' => '1.11.0.0', 'reference' => '1748aaf847fc731cfad7725aec413ee46f0cc3a2', 'type' => 'library', 'install_path' => __DIR__ . '/../seld/jsonlint', 'aliases' => array(), 'dev_requirement' => \false), 'seld/phar-utils' => array('pretty_version' => '1.2.1', 'version' => '1.2.1.0', 'reference' => 'ea2f4014f163c1be4c601b9b7bd6af81ba8d701c', 'type' => 'library', 'install_path' => __DIR__ . '/../seld/phar-utils', 'aliases' => array(), 'dev_requirement' => \false), 'seld/signal-handler' => array('pretty_version' => '2.0.2', 'version' => '2.0.2.0', 'reference' => '04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98', 'type' => 'library', 'install_path' => __DIR__ . '/../seld/signal-handler', 'aliases' => array(), 'dev_requirement' => \false), 'spomky-labs/cbor-php' => array('pretty_version' => '3.1.0', 'version' => '3.1.0.0', 'reference' => '499d9bff0a6d59c4f1b813cc617fc3fd56d6dca4', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/cbor-php', 'aliases' => array(), 'dev_requirement' => \false), 'spomky-labs/otphp' => array('pretty_version' => '11.3.0', 'version' => '11.3.0.0', 'reference' => '2d8ccb5fc992b9cc65ef321fa4f00fefdb3f4b33', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/otphp', 'aliases' => array(), 'dev_requirement' => \false), 'spomky-labs/pki-framework' => array('pretty_version' => '1.2.2', 'version' => '1.2.2.0', 'reference' => '5ac374c3e295c8b917208ff41b4d30f76668478c', 'type' => 'library', 'install_path' => __DIR__ . '/../spomky-labs/pki-framework', 'aliases' => array(), 'dev_requirement' => \false), 'studio24/rotate' => array('pretty_version' => 'v1.0.1', 'version' => '1.0.1.0', 'reference' => '9d99d364bcf619bd9dd48f09ccf292f077c492e8', 'type' => 'library', 'install_path' => __DIR__ . '/../studio24/rotate', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => 'b209751ed25f735ea90ca4c9c969d9413a17dfee', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache-contracts' => array('pretty_version' => 'v3.5.1', 'version' => '3.5.1.0', 'reference' => '15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0|3.0')), 'symfony/clock' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => 'b2bf55c4dd115003309eafa87ee7df9ed3dde81b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/clock', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/config' => array('pretty_version' => 'v6.4.14', 'version' => '6.4.14.0', 'reference' => '4e55e7e4ffddd343671ea972216d4509f46c22ef', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/config', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/console' => array('pretty_version' => 'v6.4.17', 'version' => '6.4.17.0', 'reference' => '799445db3f15768ecc382ac5699e6da0520a0a04', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/dependency-injection' => array('pretty_version' => 'v6.4.16', 'version' => '6.4.16.0', 'reference' => '7a379d8871f6a36f01559c14e11141cc02eb8dc8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v3.5.1', 'version' => '3.5.1.0', 'reference' => '74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/error-handler' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => 'e8d3b5b1975e67812a54388b1ba8e9ec28eb770e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/error-handler', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/event-dispatcher' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => '0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/event-dispatcher-contracts' => array('pretty_version' => 'v3.5.1', 'version' => '3.5.1.0', 'reference' => '7642f5e970b672283b7823222ae8ef8bbc160b9f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/event-dispatcher-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '2.0|3.0')), 'symfony/filesystem' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => '4856c9cf585d5a0313d8d35afd681a526f038dd3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/filesystem', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/finder' => array('pretty_version' => 'v6.4.17', 'version' => '6.4.17.0', 'reference' => '1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/framework-bundle' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => '91df8ee37543ebc01756c9e5eaf94d1878ff1ccd', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/framework-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/http-foundation' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => 'd0492d6217e5ab48f51fca76f64cf8e78919d0db', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/http-kernel' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => 'fca7197bfe9e99dfae7fb1ad3f7f5bd9ef80e1b7', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/monolog-bridge' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => '9d14621e59f22c2b6d030d92d37ffe5ae1e60452', 'type' => 'symfony-bridge', 'install_path' => __DIR__ . '/../symfony/monolog-bridge', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/monolog-bundle' => array('pretty_version' => 'v3.10.0', 'version' => '3.10.0.0', 'reference' => '414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/monolog-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/password-hasher' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => 'e97a1b31f60b8bdfc1fdedab4398538da9441d47', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/password-hasher', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-intl-grapheme' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => 'b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-intl-normalizer' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => '3833d7255cc303546435cb650316bff708a1c75c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php73' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php73', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php81' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => '4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php81', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-php83' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => '2fb86d65e2d424369ad2905e83b236a8805ba491', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php83', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-uuid' => array('pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', 'reference' => '21533be36c24be3f4b1669c4725c7d1d2bab4ae2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-uuid', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/process' => array('pretty_version' => 'v6.4.15', 'version' => '6.4.15.0', 'reference' => '3cb242f059c14ae08591c5c4087d1fe443564392', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/process', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/property-access' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => '80e0378f2f058b60d87dedc3c760caec882e992c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/property-access', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/property-info' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => '94d18e5cc11a37fd92856d38b61d9cdf72536a1e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/property-info', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/routing' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => 'e9bfc94953019089acdfb9be51c1b9142c4afa68', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/routing', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-bundle' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => '181d1fcf5f88ef8212ed7f6434e5ff51c9d7dff3', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/security-bundle', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-core' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => '0ae7ae716968e00287ab9b7768405e0dc9cad109', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/security-core', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-csrf' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => 'c34421b7d34efbaef5d611ab2e646a0ec464ffe3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/security-csrf', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/security-http' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => '54f2ccce1f3822eee3fb3a85debd9a67d12762b8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/security-http', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/serializer' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => '6ad986f62276da4c8c69754decfaa445a89cb6e3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/serializer', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/service-contracts' => array('pretty_version' => 'v3.5.1', 'version' => '3.5.1.0', 'reference' => 'e53260aabf78fb3d63f8d79d69ece59f80d5eda0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/service-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0|3.0')), 'symfony/string' => array('pretty_version' => 'v6.4.15', 'version' => '6.4.15.0', 'reference' => '73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/uid' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => '18eb207f0436a993fffbdd811b5b8fa35fa5e007', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/uid', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/var-dumper' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => '4ad10cf8b020e77ba665305bb7804389884b4837', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/var-exporter' => array('pretty_version' => 'v6.4.13', 'version' => '6.4.13.0', 'reference' => '0f605f72a363f8743001038a176eeb2a11223b51', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-exporter', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/yaml' => array('pretty_version' => 'v6.4.18', 'version' => '6.4.18.0', 'reference' => 'bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/yaml', 'aliases' => array(), 'dev_requirement' => \false), 'web-auth/cose-lib' => array('pretty_version' => '4.4.0', 'version' => '4.4.0.0', 'reference' => '2166016e48e0214f4f63320a7758a9386d14c92a', 'type' => 'library', 'install_path' => __DIR__ . '/../web-auth/cose-lib', 'aliases' => array(), 'dev_requirement' => \false), 'web-auth/webauthn-lib' => array('pretty_version' => '4.9.2', 'version' => '4.9.2.0', 'reference' => '008b25171c27cf4813420d0de31cc059bcc71f1a', 'type' => 'library', 'install_path' => __DIR__ . '/../web-auth/webauthn-lib', 'aliases' => array(), 'dev_requirement' => \false), 'webmozart/assert' => array('pretty_version' => '1.11.0', 'version' => '1.11.0.0', 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991', 'type' => 'library', 'install_path' => __DIR__ . '/../webmozart/assert', 'aliases' => array(), 'dev_requirement' => \false))); Copyright (C) 2021 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. composer/pcre ============= PCRE wrapping library that offers type-safe `preg_*` replacements. This library gives you a way to ensure `preg_*` functions do not fail silently, returning unexpected `null`s that may not be handled. As of 3.0 this library enforces [`PREG_UNMATCHED_AS_NULL`](#preg_unmatched_as_null) usage for all matching and replaceCallback functions, [read more below](#preg_unmatched_as_null) to understand the implications. It thus makes it easier to work with static analysis tools like PHPStan or Psalm as it simplifies and reduces the possible return values from all the `preg_*` functions which are quite packed with edge cases. As of v2.2.0 / v3.2.0 the library also comes with a [PHPStan extension](#phpstan-extension) for parsing regular expressions and giving you even better output types. This library is a thin wrapper around `preg_*` functions with [some limitations](#restrictions--limitations). If you are looking for a richer API to handle regular expressions have a look at [rawr/t-regx](https://packagist.org/packages/rawr/t-regx) instead. [![Continuous Integration](https://github.com/composer/pcre/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/composer/pcre/actions) Installation ------------ Install the latest version with: ```bash $ composer require composer/pcre ``` Requirements ------------ * PHP 7.4.0 is required for 3.x versions * PHP 7.2.0 is required for 2.x versions * PHP 5.3.2 is required for 1.x versions Basic usage ----------- Instead of: ```php if (preg_match('{fo+}', $string, $matches)) { ... } if (preg_match('{fo+}', $string, $matches, PREG_OFFSET_CAPTURE)) { ... } if (preg_match_all('{fo+}', $string, $matches)) { ... } $newString = preg_replace('{fo+}', 'bar', $string); $newString = preg_replace_callback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string); $newString = preg_replace_callback_array(['{fo+}' => fn ($match) => strtoupper($match[0])], $string); $filtered = preg_grep('{[a-z]}', $elements); $array = preg_split('{[a-z]+}', $string); ``` You can now call these on the `Preg` class: ```php use Composer\Pcre\Preg; if (Preg::match('{fo+}', $string, $matches)) { ... } if (Preg::matchWithOffsets('{fo+}', $string, $matches)) { ... } if (Preg::matchAll('{fo+}', $string, $matches)) { ... } $newString = Preg::replace('{fo+}', 'bar', $string); $newString = Preg::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string); $newString = Preg::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string); $filtered = Preg::grep('{[a-z]}', $elements); $array = Preg::split('{[a-z]+}', $string); ``` The main difference is if anything fails to match/replace/.., it will throw a `Composer\Pcre\PcreException` instead of returning `null` (or false in some cases), so you can now use the return values safely relying on the fact that they can only be strings (for replace), ints (for match) or arrays (for grep/split). Additionally the `Preg` class provides match methods that return `bool` rather than `int`, for stricter type safety when the number of pattern matches is not useful: ```php use Composer\Pcre\Preg; if (Preg::isMatch('{fo+}', $string, $matches)) // bool if (Preg::isMatchAll('{fo+}', $string, $matches)) // bool ``` Finally the `Preg` class provides a few `*StrictGroups` method variants that ensure match groups are always present and thus non-nullable, making it easier to write type-safe code: ```php use Composer\Pcre\Preg; // $matches is guaranteed to be an array of strings, if a subpattern does not match and produces a null it will throw if (Preg::matchStrictGroups('{fo+}', $string, $matches)) if (Preg::matchAllStrictGroups('{fo+}', $string, $matches)) ``` **Note:** This is generally safe to use as long as you do not have optional subpatterns (i.e. `(something)?` or `(something)*` or branches with a `|` that result in some groups not being matched at all). A subpattern that can match an empty string like `(.*)` is **not** optional, it will be present as an empty string in the matches. A non-matching subpattern, even if optional like `(?:foo)?` will anyway not be present in matches so it is also not a problem to use these with `*StrictGroups` methods. If you would prefer a slightly more verbose usage, replacing by-ref arguments by result objects, you can use the `Regex` class: ```php use Composer\Pcre\Regex; // this is useful when you are just interested in knowing if something matched // as it returns a bool instead of int(1/0) for match $bool = Regex::isMatch('{fo+}', $string); $result = Regex::match('{fo+}', $string); if ($result->matched) { something($result->matches); } $result = Regex::matchWithOffsets('{fo+}', $string); if ($result->matched) { something($result->matches); } $result = Regex::matchAll('{fo+}', $string); if ($result->matched && $result->count > 3) { something($result->matches); } $newString = Regex::replace('{fo+}', 'bar', $string)->result; $newString = Regex::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string)->result; $newString = Regex::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string)->result; ``` Note that `preg_grep` and `preg_split` are only callable via the `Preg` class as they do not have complex return types warranting a specific result object. See the [MatchResult](src/MatchResult.php), [MatchWithOffsetsResult](src/MatchWithOffsetsResult.php), [MatchAllResult](src/MatchAllResult.php), [MatchAllWithOffsetsResult](src/MatchAllWithOffsetsResult.php), and [ReplaceResult](src/ReplaceResult.php) class sources for more details. Restrictions / Limitations -------------------------- Due to type safety requirements a few restrictions are in place. - matching using `PREG_OFFSET_CAPTURE` is made available via `matchWithOffsets` and `matchAllWithOffsets`. You cannot pass the flag to `match`/`matchAll`. - `Preg::split` will also reject `PREG_SPLIT_OFFSET_CAPTURE` and you should use `splitWithOffsets` instead. - `matchAll` rejects `PREG_SET_ORDER` as it also changes the shape of the returned matches. There is no alternative provided as you can fairly easily code around it. - `preg_filter` is not supported as it has a rather crazy API, most likely you should rather use `Preg::grep` in combination with some loop and `Preg::replace`. - `replace`, `replaceCallback` and `replaceCallbackArray` do not support an array `$subject`, only simple strings. - As of 2.0, the library always uses `PREG_UNMATCHED_AS_NULL` for matching, which offers [much saner/more predictable results](#preg_unmatched_as_null). As of 3.0 the flag is also set for `replaceCallback` and `replaceCallbackArray`. #### PREG_UNMATCHED_AS_NULL As of 2.0, this library always uses PREG_UNMATCHED_AS_NULL for all `match*` and `isMatch*` functions. As of 3.0 it is also done for `replaceCallback` and `replaceCallbackArray`. This means your matches will always contain all matching groups, either as null if unmatched or as string if it matched. The advantages in clarity and predictability are clearer if you compare the two outputs of running this with and without PREG_UNMATCHED_AS_NULL in $flags: ```php preg_match('/(a)(b)*(c)(d)*/', 'ac', $matches, $flags); ``` | no flag | PREG_UNMATCHED_AS_NULL | | --- | --- | | array (size=4) | array (size=5) | | 0 => string 'ac' (length=2) | 0 => string 'ac' (length=2) | | 1 => string 'a' (length=1) | 1 => string 'a' (length=1) | | 2 => string '' (length=0) | 2 => null | | 3 => string 'c' (length=1) | 3 => string 'c' (length=1) | | | 4 => null | | group 2 (any unmatched group preceding one that matched) is set to `''`. You cannot tell if it matched an empty string or did not match at all | group 2 is `null` when unmatched and a string if it matched, easy to check for | | group 4 (any optional group without a matching one following) is missing altogether. So you have to check with `isset()`, but really you want `isset($m[4]) && $m[4] !== ''` for safety unless you are very careful to check that a non-optional group follows it | group 4 is always set, and null in this case as there was no match, easy to check for with `$m[4] !== null` | PHPStan Extension ----------------- To use the PHPStan extension if you do not use `phpstan/extension-installer` you can include `vendor/composer/pcre/extension.neon` in your PHPStan config. The extension provides much better type information for $matches as well as regex validation where possible. License ------- composer/pcre is licensed under the MIT License, see the LICENSE file for details. # composer/pcre PHPStan extensions # # These can be reused by third party packages by including 'vendor/composer/pcre/extension.neon' # in your phpstan config services: - class: Composer\Pcre\PHPStan\PregMatchParameterOutTypeExtension tags: - phpstan.staticMethodParameterOutTypeExtension - class: Composer\Pcre\PHPStan\PregMatchTypeSpecifyingExtension tags: - phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension - class: Composer\Pcre\PHPStan\PregReplaceCallbackClosureTypeExtension tags: - phpstan.staticMethodParameterClosureTypeExtension rules: - Composer\Pcre\PHPStan\UnsafeStrictGroupsCallRule - Composer\Pcre\PHPStan\InvalidRegexPatternRule { "name": "composer\/pcre", "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "type": "library", "license": "MIT", "keywords": [ "pcre", "regex", "preg", "regular expression" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http:\/\/seld.be" } ], "require": { "php": "^7.4 || ^8.0" }, "require-dev": { "phpunit\/phpunit": "^8 || ^9", "phpstan\/phpstan": "^1.12 || ^2", "phpstan\/phpstan-strict-rules": "^1 || ^2" }, "conflict": { "phpstan\/phpstan": "<1.11.10" }, "autoload": { "psr-4": { "Composer\\Pcre\\": "src" } }, "autoload-dev": { "psr-4": { "Composer\\Pcre\\": "tests" } }, "extra": { "branch-alias": { "dev-main": "3.x-dev" }, "phpstan": { "includes": [ "extension.neon" ] } }, "scripts": { "test": "@php vendor\/bin\/phpunit", "phpstan": "@php phpstan analyse" } }regexShapeMatcher = $regexShapeMatcher; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } public function getClass() : string { return Preg::class; } public function isStaticMethodSupported(MethodReflection $methodReflection, StaticCall $node, TypeSpecifierContext $context) : bool { return \in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups', 'matchAll', 'isMatchAll', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true) && !$context->null(); } public function specifyTypes(MethodReflection $methodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $args = $node->getArgs(); $patternArg = $args[0] ?? null; $matchesArg = $args[2] ?? null; $flagsArg = $args[3] ?? null; if ($patternArg === null || $matchesArg === null) { return new SpecifiedTypes(); } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); if ($flagsType === null) { return new SpecifiedTypes(); } if (\stripos($methodReflection->getName(), 'matchAll') !== \false) { $matchedType = $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope); } else { $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope); } if ($matchedType === null) { return new SpecifiedTypes(); } if (\in_array($methodReflection->getName(), ['matchStrictGroups', 'isMatchStrictGroups', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true)) { $matchedType = \Composer\Pcre\PHPStan\PregMatchFlags::removeNullFromMatches($matchedType); } $overwrite = \false; if ($context->false()) { $overwrite = \true; $context = $context->negate(); } // @phpstan-ignore function.alreadyNarrowedType if (\method_exists('_ContaoManager\\PHPStan\\Analyser\\SpecifiedTypes', 'setRootExpr')) { $typeSpecifier = $this->typeSpecifier->create($matchesArg->value, $matchedType, $context, $scope)->setRootExpr($node); return $overwrite ? $typeSpecifier->setAlwaysOverwriteTypes() : $typeSpecifier; } // @phpstan-ignore arguments.count return $this->typeSpecifier->create( $matchesArg->value, $matchedType, $context, // @phpstan-ignore argument.type $overwrite, $scope, $node ); } } regexShapeMatcher = $regexShapeMatcher; } public function isStaticMethodSupported(MethodReflection $methodReflection, ParameterReflection $parameter) : bool { return \in_array($methodReflection->getDeclaringClass()->getName(), [Preg::class, Regex::class], \true) && \in_array($methodReflection->getName(), ['replaceCallback', 'replaceCallbackStrictGroups'], \true) && $parameter->getName() === 'replacement'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, ParameterReflection $parameter, Scope $scope) : ?Type { $args = $methodCall->getArgs(); $patternArg = $args[0] ?? null; $flagsArg = $args[5] ?? null; if ($patternArg === null) { return null; } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); $matchesType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope); if ($matchesType === null) { return null; } if ($methodReflection->getName() === 'replaceCallbackStrictGroups' && \count($matchesType->getConstantArrays()) === 1) { $matchesType = $matchesType->getConstantArrays()[0]; $matchesType = new ConstantArrayType($matchesType->getKeyTypes(), \array_map(static function (Type $valueType) : Type { if (\count($valueType->getConstantArrays()) === 1) { $valueTypeArray = $valueType->getConstantArrays()[0]; return new ConstantArrayType($valueTypeArray->getKeyTypes(), \array_map(static function (Type $valueType) : Type { return TypeCombinator::removeNull($valueType); }, $valueTypeArray->getValueTypes()), $valueTypeArray->getNextAutoIndexes(), [], $valueTypeArray->isList()); } return TypeCombinator::removeNull($valueType); }, $matchesType->getValueTypes()), $matchesType->getNextAutoIndexes(), [], $matchesType->isList()); } return new ClosureType([new NativeParameterReflection($parameter->getName(), $parameter->isOptional(), $matchesType, $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue())], new StringType()); } } regexShapeMatcher = $regexShapeMatcher; } public function isStaticMethodSupported(MethodReflection $methodReflection, ParameterReflection $parameter) : bool { return $methodReflection->getDeclaringClass()->getName() === Preg::class && \in_array($methodReflection->getName(), ['match', 'isMatch', 'matchStrictGroups', 'isMatchStrictGroups', 'matchAll', 'isMatchAll', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true) && $parameter->getName() === 'matches'; } public function getParameterOutTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, ParameterReflection $parameter, Scope $scope) : ?Type { $args = $methodCall->getArgs(); $patternArg = $args[0] ?? null; $matchesArg = $args[2] ?? null; $flagsArg = $args[3] ?? null; if ($patternArg === null || $matchesArg === null) { return null; } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); if ($flagsType === null) { return null; } if (\stripos($methodReflection->getName(), 'matchAll') !== \false) { return $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope); } return $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope); } } */ class InvalidRegexPatternRule implements Rule { public function getNodeType() : string { return StaticCall::class; } public function processNode(Node $node, Scope $scope) : array { $patterns = $this->extractPatterns($node, $scope); $errors = []; foreach ($patterns as $pattern) { $errorMessage = $this->validatePattern($pattern); if ($errorMessage === null) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Regex pattern is invalid: %s', $errorMessage))->identifier('regexp.pattern')->build(); } return $errors; } /** * @return string[] */ private function extractPatterns(StaticCall $node, Scope $scope) : array { if (!$node->class instanceof FullyQualified) { return []; } $isRegex = $node->class->toString() === Regex::class; $isPreg = $node->class->toString() === Preg::class; if (!$isRegex && !$isPreg) { return []; } if (!$node->name instanceof Node\Identifier || !Preg::isMatch('{^(match|isMatch|grep|replace|split)}', $node->name->name)) { return []; } $functionName = $node->name->name; if (!isset($node->getArgs()[0])) { return []; } $patternNode = $node->getArgs()[0]->value; $patternType = $scope->getType($patternNode); $patternStrings = []; foreach ($patternType->getConstantStrings() as $constantStringType) { if ($functionName === 'replaceCallbackArray') { continue; } $patternStrings[] = $constantStringType->getValue(); } foreach ($patternType->getConstantArrays() as $constantArrayType) { if (in_array($functionName, ['replace', 'replaceCallback'], \true)) { foreach ($constantArrayType->getValueTypes() as $arrayKeyType) { foreach ($arrayKeyType->getConstantStrings() as $constantString) { $patternStrings[] = $constantString->getValue(); } } } if ($functionName !== 'replaceCallbackArray') { continue; } foreach ($constantArrayType->getKeyTypes() as $arrayKeyType) { foreach ($arrayKeyType->getConstantStrings() as $constantString) { $patternStrings[] = $constantString->getValue(); } } } return $patternStrings; } private function validatePattern(string $pattern) : ?string { try { $msg = null; $prev = \set_error_handler(function (int $severity, string $message, string $file) use(&$msg) : bool { $msg = \preg_replace("#^preg_match(_all)?\\(.*?\\): #", '', $message); return \true; }); if ($pattern === '') { return 'Empty string is not a valid regular expression'; } Preg::match($pattern, ''); if ($msg !== null) { return $msg; } } catch (PcreException $e) { if ($e->getCode() === \PREG_INTERNAL_ERROR && $msg !== null) { return $msg; } return \preg_replace('{.*? failed executing ".*": }', '', $e->getMessage()); } finally { \restore_error_handler(); } return null; } } getType($flagsArg->value); $constantScalars = $flagsType->getConstantScalarValues(); if ($constantScalars === []) { return null; } $internalFlagsTypes = []; foreach ($flagsType->getConstantScalarValues() as $constantScalarValue) { if (!\is_int($constantScalarValue)) { return null; } $internalFlagsTypes[] = new ConstantIntegerType($constantScalarValue | \PREG_UNMATCHED_AS_NULL); } return TypeCombinator::union(...$internalFlagsTypes); } public static function removeNullFromMatches(Type $matchesType) : Type { return TypeTraverser::map($matchesType, static function (Type $type, callable $traverse) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof ConstantArrayType) { return new ConstantArrayType($type->getKeyTypes(), \array_map(static function (Type $valueType) use($traverse) : Type { return $traverse($valueType); }, $type->getValueTypes()), $type->getNextAutoIndexes(), [], $type->isList()); } if ($type instanceof ArrayType) { return new ArrayType($type->getKeyType(), $traverse($type->getItemType())); } return TypeCombinator::removeNull($type); }); } } */ final class UnsafeStrictGroupsCallRule implements Rule { /** * @var RegexArrayShapeMatcher */ private $regexShapeMatcher; public function __construct(RegexArrayShapeMatcher $regexShapeMatcher) { $this->regexShapeMatcher = $regexShapeMatcher; } public function getNodeType() : string { return StaticCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->class instanceof FullyQualified) { return []; } $isRegex = $node->class->toString() === Regex::class; $isPreg = $node->class->toString() === Preg::class; if (!$isRegex && !$isPreg) { return []; } if (!$node->name instanceof Node\Identifier || !\in_array($node->name->name, ['matchStrictGroups', 'isMatchStrictGroups', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], \true)) { return []; } $args = $node->getArgs(); if (!isset($args[0])) { return []; } $patternArg = $args[0] ?? null; if ($isPreg) { if (!isset($args[2])) { // no matches set, skip as the matches won't be used anyway return []; } $flagsArg = $args[3] ?? null; } else { $flagsArg = $args[2] ?? null; } if ($patternArg === null) { return []; } $flagsType = \Composer\Pcre\PHPStan\PregMatchFlags::getType($flagsArg, $scope); if ($flagsType === null) { return []; } $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope); if ($matchedType === null) { return [RuleErrorBuilder::message(sprintf('The %s call is potentially unsafe as $matches\' type could not be inferred.', $node->name->name))->identifier('composerPcre.maybeUnsafeStrictGroups')->build()]; } if (\count($matchedType->getConstantArrays()) === 1) { $matchedType = $matchedType->getConstantArrays()[0]; $nullableGroups = []; foreach ($matchedType->getValueTypes() as $index => $type) { if (TypeCombinator::containsNull($type)) { $nullableGroups[] = $matchedType->getKeyTypes()[$index]->getValue(); } } if (\count($nullableGroups) > 0) { return [RuleErrorBuilder::message(sprintf('The %s call is unsafe as match group%s "%s" %s optional and may be null.', $node->name->name, \count($nullableGroups) > 1 ? 's' : '', \implode('", "', $nullableGroups), \count($nullableGroups) > 1 ? 'are' : 'is'))->identifier('composerPcre.unsafeStrictGroups')->build()]; } } return []; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; final class MatchResult { /** * An array of match group => string matched * * @readonly * @var array */ public $matches; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; class Regex { /** * @param non-empty-string $pattern */ public static function isMatch(string $pattern, string $subject, int $offset = 0) : bool { return (bool) \Composer\Pcre\Preg::match($pattern, $subject, $matches, 0, $offset); } /** * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported */ public static function match(string $pattern, string $subject, int $flags = 0, int $offset = 0) : \Composer\Pcre\MatchResult { self::checkOffsetCapture($flags, 'matchWithOffsets'); $count = \Composer\Pcre\Preg::match($pattern, $subject, $matches, $flags, $offset); return new \Composer\Pcre\MatchResult($count, $matches); } /** * Variant of `match()` which returns non-null matches (or throws) * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @throws UnexpectedNullMatchException */ public static function matchStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0) : \Composer\Pcre\MatchStrictGroupsResult { // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups $count = \Composer\Pcre\Preg::matchStrictGroups($pattern, $subject, $matches, $flags, $offset); return new \Composer\Pcre\MatchStrictGroupsResult($count, $matches); } /** * Runs preg_match with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported */ public static function matchWithOffsets(string $pattern, string $subject, int $flags = 0, int $offset = 0) : \Composer\Pcre\MatchWithOffsetsResult { $count = \Composer\Pcre\Preg::matchWithOffsets($pattern, $subject, $matches, $flags, $offset); return new \Composer\Pcre\MatchWithOffsetsResult($count, $matches); } /** * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported */ public static function matchAll(string $pattern, string $subject, int $flags = 0, int $offset = 0) : \Composer\Pcre\MatchAllResult { self::checkOffsetCapture($flags, 'matchAllWithOffsets'); self::checkSetOrder($flags); $count = \Composer\Pcre\Preg::matchAll($pattern, $subject, $matches, $flags, $offset); return new \Composer\Pcre\MatchAllResult($count, $matches); } /** * Variant of `matchAll()` which returns non-null matches (or throws) * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @throws UnexpectedNullMatchException */ public static function matchAllStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0) : \Composer\Pcre\MatchAllStrictGroupsResult { self::checkOffsetCapture($flags, 'matchAllWithOffsets'); self::checkSetOrder($flags); // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups $count = \Composer\Pcre\Preg::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset); return new \Composer\Pcre\MatchAllStrictGroupsResult($count, $matches); } /** * Runs preg_match_all with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported */ public static function matchAllWithOffsets(string $pattern, string $subject, int $flags = 0, int $offset = 0) : \Composer\Pcre\MatchAllWithOffsetsResult { self::checkSetOrder($flags); $count = \Composer\Pcre\Preg::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset); return new \Composer\Pcre\MatchAllWithOffsetsResult($count, $matches); } /** * @param string|string[] $pattern * @param string|string[] $replacement * @param string $subject */ public static function replace($pattern, $replacement, $subject, int $limit = -1) : \Composer\Pcre\ReplaceResult { $result = \Composer\Pcre\Preg::replace($pattern, $replacement, $subject, $limit, $count); return new \Composer\Pcre\ReplaceResult($count, $result); } /** * @param string|string[] $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set */ public static function replaceCallback($pattern, callable $replacement, $subject, int $limit = -1, int $flags = 0) : \Composer\Pcre\ReplaceResult { $result = \Composer\Pcre\Preg::replaceCallback($pattern, $replacement, $subject, $limit, $count, $flags); return new \Composer\Pcre\ReplaceResult($count, $result); } /** * Variant of `replaceCallback()` which outputs non-null matches (or throws) * * @param string $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set */ public static function replaceCallbackStrictGroups($pattern, callable $replacement, $subject, int $limit = -1, int $flags = 0) : \Composer\Pcre\ReplaceResult { $result = \Composer\Pcre\Preg::replaceCallbackStrictGroups($pattern, $replacement, $subject, $limit, $count, $flags); return new \Composer\Pcre\ReplaceResult($count, $result); } /** * @param ($flags is PREG_OFFSET_CAPTURE ? (array}>): string>) : array): string>) $pattern * @param string $subject * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set */ public static function replaceCallbackArray(array $pattern, $subject, int $limit = -1, int $flags = 0) : \Composer\Pcre\ReplaceResult { $result = \Composer\Pcre\Preg::replaceCallbackArray($pattern, $subject, $limit, $count, $flags); return new \Composer\Pcre\ReplaceResult($count, $result); } private static function checkOffsetCapture(int $flags, string $useFunctionName) : void { if (($flags & \PREG_OFFSET_CAPTURE) !== 0) { throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the return type, use ' . $useFunctionName . '() instead'); } } private static function checkSetOrder(int $flags) : void { if (($flags & \PREG_SET_ORDER) !== 0) { throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the return type'); } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; final class MatchAllWithOffsetsResult { /** * An array of match group => list of matches, every match being a pair of string matched + offset in bytes (or -1 if no match) * * @readonly * @var array> * @phpstan-var array}>> */ public $matches; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array> $matches * @phpstan-param array}>> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; $this->count = $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; final class MatchWithOffsetsResult { /** * An array of match group => pair of string matched + offset in bytes (or -1 if no match) * * @readonly * @var array * @phpstan-var array}> */ public $matches; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array $matches * @phpstan-param array}> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; final class MatchAllStrictGroupsResult { /** * An array of match group => list of matched strings * * @readonly * @var array> */ public $matches; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; $this->count = $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; class UnexpectedNullMatchException extends \Composer\Pcre\PcreException { public static function fromFunction($function, $pattern) { throw new \LogicException('fromFunction should not be called on ' . self::class . ', use ' . \Composer\Pcre\PcreException::class); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; final class MatchStrictGroupsResult { /** * An array of match group => string matched * * @readonly * @var array */ public $matches; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; final class MatchAllResult { /** * An array of match group => list of matched strings * * @readonly * @var array> */ public $matches; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count * @param array> $matches */ public function __construct(int $count, array $matches) { $this->matches = $matches; $this->matched = (bool) $count; $this->count = $count; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; final class ReplaceResult { /** * @readonly * @var string */ public $result; /** * @readonly * @var 0|positive-int */ public $count; /** * @readonly * @var bool */ public $matched; /** * @param 0|positive-int $count */ public function __construct(int $count, string $result) { $this->count = $count; $this->matched = (bool) $count; $this->result = $result; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; class Preg { /** @internal */ public const ARRAY_MSG = '$subject as an array is not supported. You can use \'foreach\' instead.'; /** @internal */ public const INVALID_TYPE_MSG = '$subject must be a string, %s given.'; /** * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|1 * * @param-out array $matches */ public static function match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : int { self::checkOffsetCapture($flags, 'matchWithOffsets'); $result = \preg_match($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset); if ($result === \false) { throw \Composer\Pcre\PcreException::fromFunction('preg_match', $pattern); } return $result; } /** * Variant of `match()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|1 * @throws UnexpectedNullMatchException * * @param-out array $matches */ public static function matchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : int { $result = self::match($pattern, $subject, $matchesInternal, $flags, $offset); $matches = self::enforceNonNullMatches($pattern, $matchesInternal, 'match'); return $result; } /** * Runs preg_match with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_OFFSET_CAPTURE are always set, no other flags are supported * @return 0|1 * * @param-out array}> $matches */ public static function matchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0) : int { $result = \preg_match($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL | \PREG_OFFSET_CAPTURE, $offset); if ($result === \false) { throw \Composer\Pcre\PcreException::fromFunction('preg_match', $pattern); } return $result; } /** * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|positive-int * * @param-out array> $matches */ public static function matchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : int { self::checkOffsetCapture($flags, 'matchAllWithOffsets'); self::checkSetOrder($flags); $result = \preg_match_all($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset); if (!\is_int($result)) { // PHP < 8 may return null, 8+ returns int|false throw \Composer\Pcre\PcreException::fromFunction('preg_match_all', $pattern); } return $result; } /** * Variant of `match()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @return 0|positive-int * @throws UnexpectedNullMatchException * * @param-out array> $matches */ public static function matchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : int { $result = self::matchAll($pattern, $subject, $matchesInternal, $flags, $offset); $matches = self::enforceNonNullMatchAll($pattern, $matchesInternal, 'matchAll'); return $result; } /** * Runs preg_match_all with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL and PREG_MATCH_OFFSET are always set, no other flags are supported * @return 0|positive-int * * @param-out array}>> $matches */ public static function matchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0) : int { self::checkSetOrder($flags); $result = \preg_match_all($pattern, $subject, $matches, $flags | \PREG_UNMATCHED_AS_NULL | \PREG_OFFSET_CAPTURE, $offset); if (!\is_int($result)) { // PHP < 8 may return null, 8+ returns int|false throw \Composer\Pcre\PcreException::fromFunction('preg_match_all', $pattern); } return $result; } /** * @param string|string[] $pattern * @param string|string[] $replacement * @param string $subject * @param int $count Set by method * * @param-out int<0, max> $count */ public static function replace($pattern, $replacement, $subject, int $limit = -1, ?int &$count = null) : string { if (!\is_scalar($subject)) { if (\is_array($subject)) { throw new \InvalidArgumentException(static::ARRAY_MSG); } throw new \TypeError(\sprintf(static::INVALID_TYPE_MSG, \gettype($subject))); } $result = \preg_replace($pattern, $replacement, $subject, $limit, $count); if ($result === null) { throw \Composer\Pcre\PcreException::fromFunction('preg_replace', $pattern); } return $result; } /** * @param string|string[] $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int $count Set by method * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set * * @param-out int<0, max> $count */ public static function replaceCallback($pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0) : string { if (!\is_scalar($subject)) { if (\is_array($subject)) { throw new \InvalidArgumentException(static::ARRAY_MSG); } throw new \TypeError(\sprintf(static::INVALID_TYPE_MSG, \gettype($subject))); } $result = \preg_replace_callback($pattern, $replacement, $subject, $limit, $count, $flags | \PREG_UNMATCHED_AS_NULL); if ($result === null) { throw \Composer\Pcre\PcreException::fromFunction('preg_replace_callback', $pattern); } return $result; } /** * Variant of `replaceCallback()` which outputs non-null matches (or throws) * * @param string $pattern * @param ($flags is PREG_OFFSET_CAPTURE ? (callable(array}>): string) : callable(array): string) $replacement * @param string $subject * @param int $count Set by method * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set * * @param-out int<0, max> $count */ public static function replaceCallbackStrictGroups(string $pattern, callable $replacement, $subject, int $limit = -1, ?int &$count = null, int $flags = 0) : string { return self::replaceCallback($pattern, function (array $matches) use($pattern, $replacement) { return $replacement(self::enforceNonNullMatches($pattern, $matches, 'replaceCallback')); }, $subject, $limit, $count, $flags); } /** * @param ($flags is PREG_OFFSET_CAPTURE ? (array}>): string>) : array): string>) $pattern * @param string $subject * @param int $count Set by method * @param int-mask $flags PREG_OFFSET_CAPTURE is supported, PREG_UNMATCHED_AS_NULL is always set * * @param-out int<0, max> $count */ public static function replaceCallbackArray(array $pattern, $subject, int $limit = -1, ?int &$count = null, int $flags = 0) : string { if (!\is_scalar($subject)) { if (\is_array($subject)) { throw new \InvalidArgumentException(static::ARRAY_MSG); } throw new \TypeError(\sprintf(static::INVALID_TYPE_MSG, \gettype($subject))); } $result = \preg_replace_callback_array($pattern, $subject, $limit, $count, $flags | \PREG_UNMATCHED_AS_NULL); if ($result === null) { $pattern = \array_keys($pattern); throw \Composer\Pcre\PcreException::fromFunction('preg_replace_callback_array', $pattern); } return $result; } /** * @param int-mask $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE * @return list */ public static function split(string $pattern, string $subject, int $limit = -1, int $flags = 0) : array { if (($flags & \PREG_SPLIT_OFFSET_CAPTURE) !== 0) { throw new \InvalidArgumentException('PREG_SPLIT_OFFSET_CAPTURE is not supported as it changes the type of $matches, use splitWithOffsets() instead'); } $result = \preg_split($pattern, $subject, $limit, $flags); if ($result === \false) { throw \Composer\Pcre\PcreException::fromFunction('preg_split', $pattern); } return $result; } /** * @param int-mask $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE, PREG_SPLIT_OFFSET_CAPTURE is always set * @return list * @phpstan-return list}> */ public static function splitWithOffsets(string $pattern, string $subject, int $limit = -1, int $flags = 0) : array { $result = \preg_split($pattern, $subject, $limit, $flags | \PREG_SPLIT_OFFSET_CAPTURE); if ($result === \false) { throw \Composer\Pcre\PcreException::fromFunction('preg_split', $pattern); } return $result; } /** * @template T of string|\Stringable * @param string $pattern * @param array $array * @param int-mask $flags PREG_GREP_INVERT * @return array */ public static function grep(string $pattern, array $array, int $flags = 0) : array { $result = \preg_grep($pattern, $array, $flags); if ($result === \false) { throw \Composer\Pcre\PcreException::fromFunction('preg_grep', $pattern); } return $result; } /** * Variant of match() which returns a bool instead of int * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array $matches */ public static function isMatch(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : bool { return (bool) static::match($pattern, $subject, $matches, $flags, $offset); } /** * Variant of `isMatch()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * @throws UnexpectedNullMatchException * * @param-out array $matches */ public static function isMatchStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : bool { return (bool) self::matchStrictGroups($pattern, $subject, $matches, $flags, $offset); } /** * Variant of matchAll() which returns a bool instead of int * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array> $matches */ public static function isMatchAll(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : bool { return (bool) static::matchAll($pattern, $subject, $matches, $flags, $offset); } /** * Variant of `isMatchAll()` which outputs non-null matches (or throws) * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array> $matches */ public static function isMatchAllStrictGroups(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : bool { return (bool) self::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset); } /** * Variant of matchWithOffsets() which returns a bool instead of int * * Runs preg_match with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array}> $matches */ public static function isMatchWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0) : bool { return (bool) static::matchWithOffsets($pattern, $subject, $matches, $flags, $offset); } /** * Variant of matchAllWithOffsets() which returns a bool instead of int * * Runs preg_match_all with PREG_OFFSET_CAPTURE * * @param non-empty-string $pattern * @param array $matches Set by method * @param int-mask $flags PREG_UNMATCHED_AS_NULL is always set, no other flags are supported * * @param-out array}>> $matches */ public static function isMatchAllWithOffsets(string $pattern, string $subject, ?array &$matches, int $flags = 0, int $offset = 0) : bool { return (bool) static::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset); } private static function checkOffsetCapture(int $flags, string $useFunctionName) : void { if (($flags & \PREG_OFFSET_CAPTURE) !== 0) { throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the type of $matches, use ' . $useFunctionName . '() instead'); } } private static function checkSetOrder(int $flags) : void { if (($flags & \PREG_SET_ORDER) !== 0) { throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the type of $matches'); } } /** * @param array $matches * @return array * @throws UnexpectedNullMatchException */ private static function enforceNonNullMatches(string $pattern, array $matches, string $variantMethod) { foreach ($matches as $group => $match) { if (\is_string($match) || \is_array($match) && \is_string($match[0])) { continue; } throw new \Composer\Pcre\UnexpectedNullMatchException('Pattern "' . $pattern . '" had an unexpected unmatched group "' . $group . '", make sure the pattern always matches or use ' . $variantMethod . '() instead.'); } /** @var array */ return $matches; } /** * @param array> $matches * @return array> * @throws UnexpectedNullMatchException */ private static function enforceNonNullMatchAll(string $pattern, array $matches, string $variantMethod) { foreach ($matches as $group => $groupMatches) { foreach ($groupMatches as $match) { if (null === $match) { throw new \Composer\Pcre\UnexpectedNullMatchException('Pattern "' . $pattern . '" had an unexpected unmatched group "' . $group . '", make sure the pattern always matches or use ' . $variantMethod . '() instead.'); } } } /** @var array> */ return $matches; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Pcre; class PcreException extends \RuntimeException { /** * @param string $function * @param string|string[] $pattern * @return self */ public static function fromFunction($function, $pattern) { $code = \preg_last_error(); if (\is_array($pattern)) { $pattern = \implode(', ', $pattern); } return new \Composer\Pcre\PcreException($function . '(): failed executing "' . $pattern . '": ' . self::pcreLastErrorMessage($code), $code); } /** * @param int $code * @return string */ private static function pcreLastErrorMessage($code) { if (\function_exists('preg_last_error_msg')) { return \preg_last_error_msg(); } $constants = \get_defined_constants(\true); if (!isset($constants['pcre']) || !\is_array($constants['pcre'])) { return 'UNDEFINED_ERROR'; } foreach ($constants['pcre'] as $const => $val) { if ($val === $code && \substr($const, -6) === '_ERROR') { return $const; } } return 'UNDEFINED_ERROR'; } } Copyright (C) 2021 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. composer/metadata-minifier ========================== Small utility library that handles metadata minification and expansion. This is used by [Composer](https://github.com/composer/composer)'s 2.x repository metadata protocol. Installation ------------ Install the latest version with: ```bash $ composer require composer/metadata-minifier ``` Requirements ------------ * PHP 5.3.2 is required but using the latest version of PHP is highly recommended. Basic usage ----------- ### `Composer\MetadataMinifier\MetadataMinifier` - `MetadataMinifier::expand()`: Expands an array of minified versions back to their original format - `MetadataMinifier::minify()`: Minifies an array of versions into a set of version diffs License ------- composer/metadata-minifier is licensed under the MIT License, see the LICENSE file for details. parameters: level: 8 paths: - src - tests { "name": "composer\/metadata-minifier", "description": "Small utility library that handles metadata minification and expansion.", "type": "library", "license": "MIT", "keywords": [ "compression", "composer" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http:\/\/seld.be" } ], "support": { "issues": "https:\/\/github.com\/composer\/metadata-minifier\/issues" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { "symfony\/phpunit-bridge": "^4.2 || ^5", "phpstan\/phpstan": "^0.12.55", "composer\/composer": "^2" }, "autoload": { "psr-4": { "Composer\\MetadataMinifier\\": "src" } }, "autoload-dev": { "psr-4": { "Composer\\Test\\MetadataMinifier\\": "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" } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\MetadataMinifier; class MetadataMinifier { /** * Expands an array of minified versions back to their original format * * @param array[] $versions A list of minified version arrays * @return array[] A list of version arrays */ public static function expand(array $versions) { $expanded = array(); $expandedVersion = null; foreach ($versions as $versionData) { if (!$expandedVersion) { $expandedVersion = $versionData; $expanded[] = $expandedVersion; continue; } // add any changes from the previous version to the expanded one foreach ($versionData as $key => $val) { if ($val === '__unset') { unset($expandedVersion[$key]); } else { $expandedVersion[$key] = $val; } } $expanded[] = $expandedVersion; } return $expanded; } /** * Minifies an array of versions into a set of version diffs * * @param array[] $versions A list of version arrays * @return array[] A list of versions minified with each array only containing the differences to the previous one */ public static function minify(array $versions) { $minifiedVersions = array(); $lastKnownVersionData = null; foreach ($versions as $version) { if (!$lastKnownVersionData) { $lastKnownVersionData = $version; $minifiedVersions[] = $version; continue; } $minifiedVersion = array(); // add any changes from the previous version foreach ($version as $key => $val) { if (!isset($lastKnownVersionData[$key]) || $lastKnownVersionData[$key] !== $val) { $minifiedVersion[$key] = $val; $lastKnownVersionData[$key] = $val; } } // store any deletions from the previous version for keys missing in current one foreach ($lastKnownVersionData as $key => $val) { if (!isset($version[$key])) { $minifiedVersion[$key] = "__unset"; unset($lastKnownVersionData[$key]); } } $minifiedVersions[] = $minifiedVersion; } return $minifiedVersions; } } { "389-exception": [ "389 Directory Server Exception" ], "Asterisk-exception": [ "Asterisk exception" ], "Autoconf-exception-2.0": [ "Autoconf exception 2.0" ], "Autoconf-exception-3.0": [ "Autoconf exception 3.0" ], "Autoconf-exception-generic": [ "Autoconf generic exception" ], "Autoconf-exception-generic-3.0": [ "Autoconf generic exception for GPL-3.0" ], "Autoconf-exception-macro": [ "Autoconf macro exception" ], "Bison-exception-2.2": [ "Bison exception 2.2" ], "Bootloader-exception": [ "Bootloader Distribution Exception" ], "Classpath-exception-2.0": [ "Classpath exception 2.0" ], "CLISP-exception-2.0": [ "CLISP exception 2.0" ], "cryptsetup-OpenSSL-exception": [ "cryptsetup OpenSSL exception" ], "DigiRule-FOSS-exception": [ "DigiRule FOSS License Exception" ], "eCos-exception-2.0": [ "eCos exception 2.0" ], "Fawkes-Runtime-exception": [ "Fawkes Runtime Exception" ], "FLTK-exception": [ "FLTK exception" ], "Font-exception-2.0": [ "Font exception 2.0" ], "freertos-exception-2.0": [ "FreeRTOS Exception 2.0" ], "GCC-exception-2.0": [ "GCC Runtime Library exception 2.0" ], "GCC-exception-2.0-note": [ "GCC Runtime Library exception 2.0 - note variant" ], "GCC-exception-3.1": [ "GCC Runtime Library exception 3.1" ], "GNAT-exception": [ "GNAT exception" ], "GNU-compiler-exception": [ "GNU Compiler Exception" ], "gnu-javamail-exception": [ "GNU JavaMail exception" ], "GPL-3.0-interface-exception": [ "GPL-3.0 Interface Exception" ], "GPL-3.0-linking-exception": [ "GPL-3.0 Linking Exception" ], "GPL-3.0-linking-source-exception": [ "GPL-3.0 Linking Exception (with Corresponding Source)" ], "GPL-CC-1.0": [ "GPL Cooperation Commitment 1.0" ], "GStreamer-exception-2005": [ "GStreamer Exception (2005)" ], "GStreamer-exception-2008": [ "GStreamer Exception (2008)" ], "i2p-gpl-java-exception": [ "i2p GPL+Java Exception" ], "KiCad-libraries-exception": [ "KiCad Libraries Exception" ], "LGPL-3.0-linking-exception": [ "LGPL-3.0 Linking Exception" ], "libpri-OpenH323-exception": [ "libpri OpenH323 exception" ], "Libtool-exception": [ "Libtool Exception" ], "Linux-syscall-note": [ "Linux Syscall Note" ], "LLGPL": [ "LLGPL Preamble" ], "LLVM-exception": [ "LLVM Exception" ], "LZMA-exception": [ "LZMA exception" ], "mif-exception": [ "Macros and Inline Functions Exception" ], "Nokia-Qt-exception-1.1": [ "Nokia Qt LGPL exception 1.1" ], "OCaml-LGPL-linking-exception": [ "OCaml LGPL Linking Exception" ], "OCCT-exception-1.0": [ "Open CASCADE Exception 1.0" ], "OpenJDK-assembly-exception-1.0": [ "OpenJDK Assembly exception 1.0" ], "openvpn-openssl-exception": [ "OpenVPN OpenSSL Exception" ], "PS-or-PDF-font-exception-20170817": [ "PS/PDF font exception (2017-08-17)" ], "QPL-1.0-INRIA-2004-exception": [ "INRIA QPL 1.0 2004 variant exception" ], "Qt-GPL-exception-1.0": [ "Qt GPL exception 1.0" ], "Qt-LGPL-exception-1.1": [ "Qt LGPL exception 1.1" ], "Qwt-exception-1.0": [ "Qwt exception 1.0" ], "SANE-exception": [ "SANE Exception" ], "SHL-2.0": [ "Solderpad Hardware License v2.0" ], "SHL-2.1": [ "Solderpad Hardware License v2.1" ], "stunnel-exception": [ "stunnel Exception" ], "SWI-exception": [ "SWI exception" ], "Swift-exception": [ "Swift Exception" ], "Texinfo-exception": [ "Texinfo exception" ], "u-boot-exception-2.0": [ "U-Boot exception 2.0" ], "UBDL-exception": [ "Unmodified Binary Distribution exception" ], "Universal-FOSS-exception-1.0": [ "Universal FOSS Exception, Version 1.0" ], "vsftpd-openssl-exception": [ "vsftpd OpenSSL exception" ], "WxWindows-exception-3.1": [ "WxWindows Library Exception 3.1" ], "x11vnc-openssl-exception": [ "x11vnc OpenSSL Exception" ] }{ "0BSD": [ "BSD Zero Clause License", true, false ], "AAL": [ "Attribution Assurance License", true, false ], "Abstyles": [ "Abstyles License", false, false ], "AdaCore-doc": [ "AdaCore Doc License", false, false ], "Adobe-2006": [ "Adobe Systems Incorporated Source Code License Agreement", false, false ], "Adobe-Display-PostScript": [ "Adobe Display PostScript License", false, false ], "Adobe-Glyph": [ "Adobe Glyph List License", false, false ], "Adobe-Utopia": [ "Adobe Utopia Font License", false, false ], "ADSL": [ "Amazon Digital Services License", false, false ], "AFL-1.1": [ "Academic Free License v1.1", true, false ], "AFL-1.2": [ "Academic Free License v1.2", true, false ], "AFL-2.0": [ "Academic Free License v2.0", true, false ], "AFL-2.1": [ "Academic Free License v2.1", true, false ], "AFL-3.0": [ "Academic Free License v3.0", true, false ], "Afmparse": [ "Afmparse License", false, false ], "AGPL-1.0": [ "Affero General Public License v1.0", false, true ], "AGPL-1.0-only": [ "Affero General Public License v1.0 only", false, false ], "AGPL-1.0-or-later": [ "Affero General Public License v1.0 or later", false, false ], "AGPL-3.0": [ "GNU Affero General Public License v3.0", true, true ], "AGPL-3.0-only": [ "GNU Affero General Public License v3.0 only", true, false ], "AGPL-3.0-or-later": [ "GNU Affero General Public License v3.0 or later", true, false ], "Aladdin": [ "Aladdin Free Public License", false, false ], "AMDPLPA": [ "AMD's plpa_map.c License", false, false ], "AML": [ "Apple MIT License", false, false ], "AML-glslang": [ "AML glslang variant License", false, false ], "AMPAS": [ "Academy of Motion Picture Arts and Sciences BSD", false, false ], "ANTLR-PD": [ "ANTLR Software Rights Notice", false, false ], "ANTLR-PD-fallback": [ "ANTLR Software Rights Notice with license fallback", false, false ], "Apache-1.0": [ "Apache License 1.0", false, false ], "Apache-1.1": [ "Apache License 1.1", true, false ], "Apache-2.0": [ "Apache License 2.0", true, false ], "APAFML": [ "Adobe Postscript AFM License", false, false ], "APL-1.0": [ "Adaptive Public License 1.0", true, false ], "App-s2p": [ "App::s2p License", false, false ], "APSL-1.0": [ "Apple Public Source License 1.0", true, false ], "APSL-1.1": [ "Apple Public Source License 1.1", true, false ], "APSL-1.2": [ "Apple Public Source License 1.2", true, false ], "APSL-2.0": [ "Apple Public Source License 2.0", true, false ], "Arphic-1999": [ "Arphic Public License", false, false ], "Artistic-1.0": [ "Artistic License 1.0", true, false ], "Artistic-1.0-cl8": [ "Artistic License 1.0 w/clause 8", true, false ], "Artistic-1.0-Perl": [ "Artistic License 1.0 (Perl)", true, false ], "Artistic-2.0": [ "Artistic License 2.0", true, false ], "ASWF-Digital-Assets-1.0": [ "ASWF Digital Assets License version 1.0", false, false ], "ASWF-Digital-Assets-1.1": [ "ASWF Digital Assets License 1.1", false, false ], "Baekmuk": [ "Baekmuk License", false, false ], "Bahyph": [ "Bahyph License", false, false ], "Barr": [ "Barr License", false, false ], "Beerware": [ "Beerware License", false, false ], "Bitstream-Charter": [ "Bitstream Charter Font License", false, false ], "Bitstream-Vera": [ "Bitstream Vera Font License", false, false ], "BitTorrent-1.0": [ "BitTorrent Open Source License v1.0", false, false ], "BitTorrent-1.1": [ "BitTorrent Open Source License v1.1", false, false ], "blessing": [ "SQLite Blessing", false, false ], "BlueOak-1.0.0": [ "Blue Oak Model License 1.0.0", false, false ], "Boehm-GC": [ "Boehm-Demers-Weiser GC License", false, false ], "Borceux": [ "Borceux license", false, false ], "Brian-Gladman-3-Clause": [ "Brian Gladman 3-Clause License", false, false ], "BSD-1-Clause": [ "BSD 1-Clause License", true, false ], "BSD-2-Clause": [ "BSD 2-Clause \"Simplified\" License", true, false ], "BSD-2-Clause-FreeBSD": [ "BSD 2-Clause FreeBSD License", false, true ], "BSD-2-Clause-NetBSD": [ "BSD 2-Clause NetBSD License", false, true ], "BSD-2-Clause-Patent": [ "BSD-2-Clause Plus Patent License", true, false ], "BSD-2-Clause-Views": [ "BSD 2-Clause with views sentence", false, false ], "BSD-3-Clause": [ "BSD 3-Clause \"New\" or \"Revised\" License", true, false ], "BSD-3-Clause-Attribution": [ "BSD with attribution", false, false ], "BSD-3-Clause-Clear": [ "BSD 3-Clause Clear License", false, false ], "BSD-3-Clause-flex": [ "BSD 3-Clause Flex variant", false, false ], "BSD-3-Clause-HP": [ "Hewlett-Packard BSD variant license", false, false ], "BSD-3-Clause-LBNL": [ "Lawrence Berkeley National Labs BSD variant license", true, false ], "BSD-3-Clause-Modification": [ "BSD 3-Clause Modification", false, false ], "BSD-3-Clause-No-Military-License": [ "BSD 3-Clause No Military License", false, false ], "BSD-3-Clause-No-Nuclear-License": [ "BSD 3-Clause No Nuclear License", false, false ], "BSD-3-Clause-No-Nuclear-License-2014": [ "BSD 3-Clause No Nuclear License 2014", false, false ], "BSD-3-Clause-No-Nuclear-Warranty": [ "BSD 3-Clause No Nuclear Warranty", false, false ], "BSD-3-Clause-Open-MPI": [ "BSD 3-Clause Open MPI variant", false, false ], "BSD-3-Clause-Sun": [ "BSD 3-Clause Sun Microsystems", false, false ], "BSD-4-Clause": [ "BSD 4-Clause \"Original\" or \"Old\" License", false, false ], "BSD-4-Clause-Shortened": [ "BSD 4 Clause Shortened", false, false ], "BSD-4-Clause-UC": [ "BSD-4-Clause (University of California-Specific)", false, false ], "BSD-4.3RENO": [ "BSD 4.3 RENO License", false, false ], "BSD-4.3TAHOE": [ "BSD 4.3 TAHOE License", false, false ], "BSD-Advertising-Acknowledgement": [ "BSD Advertising Acknowledgement License", false, false ], "BSD-Attribution-HPND-disclaimer": [ "BSD with Attribution and HPND disclaimer", false, false ], "BSD-Inferno-Nettverk": [ "BSD-Inferno-Nettverk", false, false ], "BSD-Protection": [ "BSD Protection License", false, false ], "BSD-Source-Code": [ "BSD Source Code Attribution", false, false ], "BSD-Systemics": [ "Systemics BSD variant license", false, false ], "BSL-1.0": [ "Boost Software License 1.0", true, false ], "BUSL-1.1": [ "Business Source License 1.1", false, false ], "bzip2-1.0.5": [ "bzip2 and libbzip2 License v1.0.5", false, true ], "bzip2-1.0.6": [ "bzip2 and libbzip2 License v1.0.6", false, false ], "C-UDA-1.0": [ "Computational Use of Data Agreement v1.0", false, false ], "CAL-1.0": [ "Cryptographic Autonomy License 1.0", true, false ], "CAL-1.0-Combined-Work-Exception": [ "Cryptographic Autonomy License 1.0 (Combined Work Exception)", true, false ], "Caldera": [ "Caldera License", false, false ], "CATOSL-1.1": [ "Computer Associates Trusted Open Source License 1.1", true, false ], "CC-BY-1.0": [ "Creative Commons Attribution 1.0 Generic", false, false ], "CC-BY-2.0": [ "Creative Commons Attribution 2.0 Generic", false, false ], "CC-BY-2.5": [ "Creative Commons Attribution 2.5 Generic", false, false ], "CC-BY-2.5-AU": [ "Creative Commons Attribution 2.5 Australia", false, false ], "CC-BY-3.0": [ "Creative Commons Attribution 3.0 Unported", false, false ], "CC-BY-3.0-AT": [ "Creative Commons Attribution 3.0 Austria", false, false ], "CC-BY-3.0-DE": [ "Creative Commons Attribution 3.0 Germany", false, false ], "CC-BY-3.0-IGO": [ "Creative Commons Attribution 3.0 IGO", false, false ], "CC-BY-3.0-NL": [ "Creative Commons Attribution 3.0 Netherlands", false, false ], "CC-BY-3.0-US": [ "Creative Commons Attribution 3.0 United States", false, false ], "CC-BY-4.0": [ "Creative Commons Attribution 4.0 International", false, false ], "CC-BY-NC-1.0": [ "Creative Commons Attribution Non Commercial 1.0 Generic", false, false ], "CC-BY-NC-2.0": [ "Creative Commons Attribution Non Commercial 2.0 Generic", false, false ], "CC-BY-NC-2.5": [ "Creative Commons Attribution Non Commercial 2.5 Generic", false, false ], "CC-BY-NC-3.0": [ "Creative Commons Attribution Non Commercial 3.0 Unported", false, false ], "CC-BY-NC-3.0-DE": [ "Creative Commons Attribution Non Commercial 3.0 Germany", false, false ], "CC-BY-NC-4.0": [ "Creative Commons Attribution Non Commercial 4.0 International", false, false ], "CC-BY-NC-ND-1.0": [ "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic", false, false ], "CC-BY-NC-ND-2.0": [ "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic", false, false ], "CC-BY-NC-ND-2.5": [ "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic", false, false ], "CC-BY-NC-ND-3.0": [ "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported", false, false ], "CC-BY-NC-ND-3.0-DE": [ "Creative Commons Attribution Non Commercial No Derivatives 3.0 Germany", false, false ], "CC-BY-NC-ND-3.0-IGO": [ "Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO", false, false ], "CC-BY-NC-ND-4.0": [ "Creative Commons Attribution Non Commercial No Derivatives 4.0 International", false, false ], "CC-BY-NC-SA-1.0": [ "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic", false, false ], "CC-BY-NC-SA-2.0": [ "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic", false, false ], "CC-BY-NC-SA-2.0-DE": [ "Creative Commons Attribution Non Commercial Share Alike 2.0 Germany", false, false ], "CC-BY-NC-SA-2.0-FR": [ "Creative Commons Attribution-NonCommercial-ShareAlike 2.0 France", false, false ], "CC-BY-NC-SA-2.0-UK": [ "Creative Commons Attribution Non Commercial Share Alike 2.0 England and Wales", false, false ], "CC-BY-NC-SA-2.5": [ "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic", false, false ], "CC-BY-NC-SA-3.0": [ "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported", false, false ], "CC-BY-NC-SA-3.0-DE": [ "Creative Commons Attribution Non Commercial Share Alike 3.0 Germany", false, false ], "CC-BY-NC-SA-3.0-IGO": [ "Creative Commons Attribution Non Commercial Share Alike 3.0 IGO", false, false ], "CC-BY-NC-SA-4.0": [ "Creative Commons Attribution Non Commercial Share Alike 4.0 International", false, false ], "CC-BY-ND-1.0": [ "Creative Commons Attribution No Derivatives 1.0 Generic", false, false ], "CC-BY-ND-2.0": [ "Creative Commons Attribution No Derivatives 2.0 Generic", false, false ], "CC-BY-ND-2.5": [ "Creative Commons Attribution No Derivatives 2.5 Generic", false, false ], "CC-BY-ND-3.0": [ "Creative Commons Attribution No Derivatives 3.0 Unported", false, false ], "CC-BY-ND-3.0-DE": [ "Creative Commons Attribution No Derivatives 3.0 Germany", false, false ], "CC-BY-ND-4.0": [ "Creative Commons Attribution No Derivatives 4.0 International", false, false ], "CC-BY-SA-1.0": [ "Creative Commons Attribution Share Alike 1.0 Generic", false, false ], "CC-BY-SA-2.0": [ "Creative Commons Attribution Share Alike 2.0 Generic", false, false ], "CC-BY-SA-2.0-UK": [ "Creative Commons Attribution Share Alike 2.0 England and Wales", false, false ], "CC-BY-SA-2.1-JP": [ "Creative Commons Attribution Share Alike 2.1 Japan", false, false ], "CC-BY-SA-2.5": [ "Creative Commons Attribution Share Alike 2.5 Generic", false, false ], "CC-BY-SA-3.0": [ "Creative Commons Attribution Share Alike 3.0 Unported", false, false ], "CC-BY-SA-3.0-AT": [ "Creative Commons Attribution Share Alike 3.0 Austria", false, false ], "CC-BY-SA-3.0-DE": [ "Creative Commons Attribution Share Alike 3.0 Germany", false, false ], "CC-BY-SA-3.0-IGO": [ "Creative Commons Attribution-ShareAlike 3.0 IGO", false, false ], "CC-BY-SA-4.0": [ "Creative Commons Attribution Share Alike 4.0 International", false, false ], "CC-PDDC": [ "Creative Commons Public Domain Dedication and Certification", false, false ], "CC0-1.0": [ "Creative Commons Zero v1.0 Universal", false, false ], "CDDL-1.0": [ "Common Development and Distribution License 1.0", true, false ], "CDDL-1.1": [ "Common Development and Distribution License 1.1", false, false ], "CDL-1.0": [ "Common Documentation License 1.0", false, false ], "CDLA-Permissive-1.0": [ "Community Data License Agreement Permissive 1.0", false, false ], "CDLA-Permissive-2.0": [ "Community Data License Agreement Permissive 2.0", false, false ], "CDLA-Sharing-1.0": [ "Community Data License Agreement Sharing 1.0", false, false ], "CECILL-1.0": [ "CeCILL Free Software License Agreement v1.0", false, false ], "CECILL-1.1": [ "CeCILL Free Software License Agreement v1.1", false, false ], "CECILL-2.0": [ "CeCILL Free Software License Agreement v2.0", false, false ], "CECILL-2.1": [ "CeCILL Free Software License Agreement v2.1", true, false ], "CECILL-B": [ "CeCILL-B Free Software License Agreement", false, false ], "CECILL-C": [ "CeCILL-C Free Software License Agreement", false, false ], "CERN-OHL-1.1": [ "CERN Open Hardware Licence v1.1", false, false ], "CERN-OHL-1.2": [ "CERN Open Hardware Licence v1.2", false, false ], "CERN-OHL-P-2.0": [ "CERN Open Hardware Licence Version 2 - Permissive", true, false ], "CERN-OHL-S-2.0": [ "CERN Open Hardware Licence Version 2 - Strongly Reciprocal", true, false ], "CERN-OHL-W-2.0": [ "CERN Open Hardware Licence Version 2 - Weakly Reciprocal", true, false ], "CFITSIO": [ "CFITSIO License", false, false ], "check-cvs": [ "check-cvs License", false, false ], "checkmk": [ "Checkmk License", false, false ], "ClArtistic": [ "Clarified Artistic License", false, false ], "Clips": [ "Clips License", false, false ], "CMU-Mach": [ "CMU Mach License", false, false ], "CNRI-Jython": [ "CNRI Jython License", false, false ], "CNRI-Python": [ "CNRI Python License", true, false ], "CNRI-Python-GPL-Compatible": [ "CNRI Python Open Source GPL Compatible License Agreement", false, false ], "COIL-1.0": [ "Copyfree Open Innovation License", false, false ], "Community-Spec-1.0": [ "Community Specification License 1.0", false, false ], "Condor-1.1": [ "Condor Public License v1.1", false, false ], "copyleft-next-0.3.0": [ "copyleft-next 0.3.0", false, false ], "copyleft-next-0.3.1": [ "copyleft-next 0.3.1", false, false ], "Cornell-Lossless-JPEG": [ "Cornell Lossless JPEG License", false, false ], "CPAL-1.0": [ "Common Public Attribution License 1.0", true, false ], "CPL-1.0": [ "Common Public License 1.0", true, false ], "CPOL-1.02": [ "Code Project Open License 1.02", false, false ], "Cronyx": [ "Cronyx License", false, false ], "Crossword": [ "Crossword License", false, false ], "CrystalStacker": [ "CrystalStacker License", false, false ], "CUA-OPL-1.0": [ "CUA Office Public License v1.0", true, false ], "Cube": [ "Cube License", false, false ], "curl": [ "curl License", false, false ], "D-FSL-1.0": [ "Deutsche Freie Software Lizenz", false, false ], "DEC-3-Clause": [ "DEC 3-Clause License", false, false ], "diffmark": [ "diffmark license", false, false ], "DL-DE-BY-2.0": [ "Data licence Germany \u2013 attribution \u2013 version 2.0", false, false ], "DL-DE-ZERO-2.0": [ "Data licence Germany \u2013 zero \u2013 version 2.0", false, false ], "DOC": [ "DOC License", false, false ], "Dotseqn": [ "Dotseqn License", false, false ], "DRL-1.0": [ "Detection Rule License 1.0", false, false ], "DRL-1.1": [ "Detection Rule License 1.1", false, false ], "DSDP": [ "DSDP License", false, false ], "dtoa": [ "David M. Gay dtoa License", false, false ], "dvipdfm": [ "dvipdfm License", false, false ], "ECL-1.0": [ "Educational Community License v1.0", true, false ], "ECL-2.0": [ "Educational Community License v2.0", true, false ], "eCos-2.0": [ "eCos license version 2.0", false, true ], "EFL-1.0": [ "Eiffel Forum License v1.0", true, false ], "EFL-2.0": [ "Eiffel Forum License v2.0", true, false ], "eGenix": [ "eGenix.com Public License 1.1.0", false, false ], "Elastic-2.0": [ "Elastic License 2.0", false, false ], "Entessa": [ "Entessa Public License v1.0", true, false ], "EPICS": [ "EPICS Open License", false, false ], "EPL-1.0": [ "Eclipse Public License 1.0", true, false ], "EPL-2.0": [ "Eclipse Public License 2.0", true, false ], "ErlPL-1.1": [ "Erlang Public License v1.1", false, false ], "etalab-2.0": [ "Etalab Open License 2.0", false, false ], "EUDatagrid": [ "EU DataGrid Software License", true, false ], "EUPL-1.0": [ "European Union Public License 1.0", false, false ], "EUPL-1.1": [ "European Union Public License 1.1", true, false ], "EUPL-1.2": [ "European Union Public License 1.2", true, false ], "Eurosym": [ "Eurosym License", false, false ], "Fair": [ "Fair License", true, false ], "FBM": [ "Fuzzy Bitmap License", false, false ], "FDK-AAC": [ "Fraunhofer FDK AAC Codec Library", false, false ], "Ferguson-Twofish": [ "Ferguson Twofish License", false, false ], "Frameworx-1.0": [ "Frameworx Open License 1.0", true, false ], "FreeBSD-DOC": [ "FreeBSD Documentation License", false, false ], "FreeImage": [ "FreeImage Public License v1.0", false, false ], "FSFAP": [ "FSF All Permissive License", false, false ], "FSFUL": [ "FSF Unlimited License", false, false ], "FSFULLR": [ "FSF Unlimited License (with License Retention)", false, false ], "FSFULLRWD": [ "FSF Unlimited License (With License Retention and Warranty Disclaimer)", false, false ], "FTL": [ "Freetype Project License", false, false ], "Furuseth": [ "Furuseth License", false, false ], "fwlw": [ "fwlw License", false, false ], "GCR-docs": [ "Gnome GCR Documentation License", false, false ], "GD": [ "GD License", false, false ], "GFDL-1.1": [ "GNU Free Documentation License v1.1", false, true ], "GFDL-1.1-invariants-only": [ "GNU Free Documentation License v1.1 only - invariants", false, false ], "GFDL-1.1-invariants-or-later": [ "GNU Free Documentation License v1.1 or later - invariants", false, false ], "GFDL-1.1-no-invariants-only": [ "GNU Free Documentation License v1.1 only - no invariants", false, false ], "GFDL-1.1-no-invariants-or-later": [ "GNU Free Documentation License v1.1 or later - no invariants", false, false ], "GFDL-1.1-only": [ "GNU Free Documentation License v1.1 only", false, false ], "GFDL-1.1-or-later": [ "GNU Free Documentation License v1.1 or later", false, false ], "GFDL-1.2": [ "GNU Free Documentation License v1.2", false, true ], "GFDL-1.2-invariants-only": [ "GNU Free Documentation License v1.2 only - invariants", false, false ], "GFDL-1.2-invariants-or-later": [ "GNU Free Documentation License v1.2 or later - invariants", false, false ], "GFDL-1.2-no-invariants-only": [ "GNU Free Documentation License v1.2 only - no invariants", false, false ], "GFDL-1.2-no-invariants-or-later": [ "GNU Free Documentation License v1.2 or later - no invariants", false, false ], "GFDL-1.2-only": [ "GNU Free Documentation License v1.2 only", false, false ], "GFDL-1.2-or-later": [ "GNU Free Documentation License v1.2 or later", false, false ], "GFDL-1.3": [ "GNU Free Documentation License v1.3", false, true ], "GFDL-1.3-invariants-only": [ "GNU Free Documentation License v1.3 only - invariants", false, false ], "GFDL-1.3-invariants-or-later": [ "GNU Free Documentation License v1.3 or later - invariants", false, false ], "GFDL-1.3-no-invariants-only": [ "GNU Free Documentation License v1.3 only - no invariants", false, false ], "GFDL-1.3-no-invariants-or-later": [ "GNU Free Documentation License v1.3 or later - no invariants", false, false ], "GFDL-1.3-only": [ "GNU Free Documentation License v1.3 only", false, false ], "GFDL-1.3-or-later": [ "GNU Free Documentation License v1.3 or later", false, false ], "Giftware": [ "Giftware License", false, false ], "GL2PS": [ "GL2PS License", false, false ], "Glide": [ "3dfx Glide License", false, false ], "Glulxe": [ "Glulxe License", false, false ], "GLWTPL": [ "Good Luck With That Public License", false, false ], "gnuplot": [ "gnuplot License", false, false ], "GPL-1.0": [ "GNU General Public License v1.0 only", false, true ], "GPL-1.0+": [ "GNU General Public License v1.0 or later", false, true ], "GPL-1.0-only": [ "GNU General Public License v1.0 only", false, false ], "GPL-1.0-or-later": [ "GNU General Public License v1.0 or later", false, false ], "GPL-2.0": [ "GNU General Public License v2.0 only", true, true ], "GPL-2.0+": [ "GNU General Public License v2.0 or later", true, true ], "GPL-2.0-only": [ "GNU General Public License v2.0 only", true, false ], "GPL-2.0-or-later": [ "GNU General Public License v2.0 or later", true, false ], "GPL-2.0-with-autoconf-exception": [ "GNU General Public License v2.0 w/Autoconf exception", false, true ], "GPL-2.0-with-bison-exception": [ "GNU General Public License v2.0 w/Bison exception", false, true ], "GPL-2.0-with-classpath-exception": [ "GNU General Public License v2.0 w/Classpath exception", false, true ], "GPL-2.0-with-font-exception": [ "GNU General Public License v2.0 w/Font exception", false, true ], "GPL-2.0-with-GCC-exception": [ "GNU General Public License v2.0 w/GCC Runtime Library exception", false, true ], "GPL-3.0": [ "GNU General Public License v3.0 only", true, true ], "GPL-3.0+": [ "GNU General Public License v3.0 or later", true, true ], "GPL-3.0-only": [ "GNU General Public License v3.0 only", true, false ], "GPL-3.0-or-later": [ "GNU General Public License v3.0 or later", true, false ], "GPL-3.0-with-autoconf-exception": [ "GNU General Public License v3.0 w/Autoconf exception", false, true ], "GPL-3.0-with-GCC-exception": [ "GNU General Public License v3.0 w/GCC Runtime Library exception", true, true ], "Graphics-Gems": [ "Graphics Gems License", false, false ], "gSOAP-1.3b": [ "gSOAP Public License v1.3b", false, false ], "HaskellReport": [ "Haskell Language Report License", false, false ], "hdparm": [ "hdparm License", false, false ], "Hippocratic-2.1": [ "Hippocratic License 2.1", false, false ], "HP-1986": [ "Hewlett-Packard 1986 License", false, false ], "HP-1989": [ "Hewlett-Packard 1989 License", false, false ], "HPND": [ "Historical Permission Notice and Disclaimer", true, false ], "HPND-DEC": [ "Historical Permission Notice and Disclaimer - DEC variant", false, false ], "HPND-doc": [ "Historical Permission Notice and Disclaimer - documentation variant", false, false ], "HPND-doc-sell": [ "Historical Permission Notice and Disclaimer - documentation sell variant", false, false ], "HPND-export-US": [ "HPND with US Government export control warning", false, false ], "HPND-export-US-modify": [ "HPND with US Government export control warning and modification rqmt", false, false ], "HPND-Markus-Kuhn": [ "Historical Permission Notice and Disclaimer - Markus Kuhn variant", false, false ], "HPND-Pbmplus": [ "Historical Permission Notice and Disclaimer - Pbmplus variant", false, false ], "HPND-sell-MIT-disclaimer-xserver": [ "Historical Permission Notice and Disclaimer - sell xserver variant with MIT disclaimer", false, false ], "HPND-sell-regexpr": [ "Historical Permission Notice and Disclaimer - sell regexpr variant", false, false ], "HPND-sell-variant": [ "Historical Permission Notice and Disclaimer - sell variant", false, false ], "HPND-sell-variant-MIT-disclaimer": [ "HPND sell variant with MIT disclaimer", false, false ], "HPND-UC": [ "Historical Permission Notice and Disclaimer - University of California variant", false, false ], "HTMLTIDY": [ "HTML Tidy License", false, false ], "IBM-pibs": [ "IBM PowerPC Initialization and Boot Software", false, false ], "ICU": [ "ICU License", true, false ], "IEC-Code-Components-EULA": [ "IEC Code Components End-user licence agreement", false, false ], "IJG": [ "Independent JPEG Group License", false, false ], "IJG-short": [ "Independent JPEG Group License - short", false, false ], "ImageMagick": [ "ImageMagick License", false, false ], "iMatix": [ "iMatix Standard Function Library Agreement", false, false ], "Imlib2": [ "Imlib2 License", false, false ], "Info-ZIP": [ "Info-ZIP License", false, false ], "Inner-Net-2.0": [ "Inner Net License v2.0", false, false ], "Intel": [ "Intel Open Source License", true, false ], "Intel-ACPI": [ "Intel ACPI Software License Agreement", false, false ], "Interbase-1.0": [ "Interbase Public License v1.0", false, false ], "IPA": [ "IPA Font License", true, false ], "IPL-1.0": [ "IBM Public License v1.0", true, false ], "ISC": [ "ISC License", true, false ], "Jam": [ "Jam License", true, false ], "JasPer-2.0": [ "JasPer License", false, false ], "JPL-image": [ "JPL Image Use Policy", false, false ], "JPNIC": [ "Japan Network Information Center License", false, false ], "JSON": [ "JSON License", false, false ], "Kastrup": [ "Kastrup License", false, false ], "Kazlib": [ "Kazlib License", false, false ], "Knuth-CTAN": [ "Knuth CTAN License", false, false ], "LAL-1.2": [ "Licence Art Libre 1.2", false, false ], "LAL-1.3": [ "Licence Art Libre 1.3", false, false ], "Latex2e": [ "Latex2e License", false, false ], "Latex2e-translated-notice": [ "Latex2e with translated notice permission", false, false ], "Leptonica": [ "Leptonica License", false, false ], "LGPL-2.0": [ "GNU Library General Public License v2 only", true, true ], "LGPL-2.0+": [ "GNU Library General Public License v2 or later", true, true ], "LGPL-2.0-only": [ "GNU Library General Public License v2 only", true, false ], "LGPL-2.0-or-later": [ "GNU Library General Public License v2 or later", true, false ], "LGPL-2.1": [ "GNU Lesser General Public License v2.1 only", true, true ], "LGPL-2.1+": [ "GNU Lesser General Public License v2.1 or later", true, true ], "LGPL-2.1-only": [ "GNU Lesser General Public License v2.1 only", true, false ], "LGPL-2.1-or-later": [ "GNU Lesser General Public License v2.1 or later", true, false ], "LGPL-3.0": [ "GNU Lesser General Public License v3.0 only", true, true ], "LGPL-3.0+": [ "GNU Lesser General Public License v3.0 or later", true, true ], "LGPL-3.0-only": [ "GNU Lesser General Public License v3.0 only", true, false ], "LGPL-3.0-or-later": [ "GNU Lesser General Public License v3.0 or later", true, false ], "LGPLLR": [ "Lesser General Public License For Linguistic Resources", false, false ], "Libpng": [ "libpng License", false, false ], "libpng-2.0": [ "PNG Reference Library version 2", false, false ], "libselinux-1.0": [ "libselinux public domain notice", false, false ], "libtiff": [ "libtiff License", false, false ], "libutil-David-Nugent": [ "libutil David Nugent License", false, false ], "LiLiQ-P-1.1": [ "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1", true, false ], "LiLiQ-R-1.1": [ "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1", true, false ], "LiLiQ-Rplus-1.1": [ "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1", true, false ], "Linux-man-pages-1-para": [ "Linux man-pages - 1 paragraph", false, false ], "Linux-man-pages-copyleft": [ "Linux man-pages Copyleft", false, false ], "Linux-man-pages-copyleft-2-para": [ "Linux man-pages Copyleft - 2 paragraphs", false, false ], "Linux-man-pages-copyleft-var": [ "Linux man-pages Copyleft Variant", false, false ], "Linux-OpenIB": [ "Linux Kernel Variant of OpenIB.org license", false, false ], "LOOP": [ "Common Lisp LOOP License", false, false ], "LPL-1.0": [ "Lucent Public License Version 1.0", true, false ], "LPL-1.02": [ "Lucent Public License v1.02", true, false ], "LPPL-1.0": [ "LaTeX Project Public License v1.0", false, false ], "LPPL-1.1": [ "LaTeX Project Public License v1.1", false, false ], "LPPL-1.2": [ "LaTeX Project Public License v1.2", false, false ], "LPPL-1.3a": [ "LaTeX Project Public License v1.3a", false, false ], "LPPL-1.3c": [ "LaTeX Project Public License v1.3c", true, false ], "lsof": [ "lsof License", false, false ], "Lucida-Bitmap-Fonts": [ "Lucida Bitmap Fonts License", false, false ], "LZMA-SDK-9.11-to-9.20": [ "LZMA SDK License (versions 9.11 to 9.20)", false, false ], "LZMA-SDK-9.22": [ "LZMA SDK License (versions 9.22 and beyond)", false, false ], "magaz": [ "magaz License", false, false ], "MakeIndex": [ "MakeIndex License", false, false ], "Martin-Birgmeier": [ "Martin Birgmeier License", false, false ], "McPhee-slideshow": [ "McPhee Slideshow License", false, false ], "metamail": [ "metamail License", false, false ], "Minpack": [ "Minpack License", false, false ], "MirOS": [ "The MirOS Licence", true, false ], "MIT": [ "MIT License", true, false ], "MIT-0": [ "MIT No Attribution", true, false ], "MIT-advertising": [ "Enlightenment License (e16)", false, false ], "MIT-CMU": [ "CMU License", false, false ], "MIT-enna": [ "enna License", false, false ], "MIT-feh": [ "feh License", false, false ], "MIT-Festival": [ "MIT Festival Variant", false, false ], "MIT-Modern-Variant": [ "MIT License Modern Variant", true, false ], "MIT-open-group": [ "MIT Open Group variant", false, false ], "MIT-testregex": [ "MIT testregex Variant", false, false ], "MIT-Wu": [ "MIT Tom Wu Variant", false, false ], "MITNFA": [ "MIT +no-false-attribs license", false, false ], "MMIXware": [ "MMIXware License", false, false ], "Motosoto": [ "Motosoto License", true, false ], "MPEG-SSG": [ "MPEG Software Simulation", false, false ], "mpi-permissive": [ "mpi Permissive License", false, false ], "mpich2": [ "mpich2 License", false, false ], "MPL-1.0": [ "Mozilla Public License 1.0", true, false ], "MPL-1.1": [ "Mozilla Public License 1.1", true, false ], "MPL-2.0": [ "Mozilla Public License 2.0", true, false ], "MPL-2.0-no-copyleft-exception": [ "Mozilla Public License 2.0 (no copyleft exception)", true, false ], "mplus": [ "mplus Font License", false, false ], "MS-LPL": [ "Microsoft Limited Public License", false, false ], "MS-PL": [ "Microsoft Public License", true, false ], "MS-RL": [ "Microsoft Reciprocal License", true, false ], "MTLL": [ "Matrix Template Library License", false, false ], "MulanPSL-1.0": [ "Mulan Permissive Software License, Version 1", false, false ], "MulanPSL-2.0": [ "Mulan Permissive Software License, Version 2", true, false ], "Multics": [ "Multics License", true, false ], "Mup": [ "Mup License", false, false ], "NAIST-2003": [ "Nara Institute of Science and Technology License (2003)", false, false ], "NASA-1.3": [ "NASA Open Source Agreement 1.3", true, false ], "Naumen": [ "Naumen Public License", true, false ], "NBPL-1.0": [ "Net Boolean Public License v1", false, false ], "NCGL-UK-2.0": [ "Non-Commercial Government Licence", false, false ], "NCSA": [ "University of Illinois/NCSA Open Source License", true, false ], "Net-SNMP": [ "Net-SNMP License", false, false ], "NetCDF": [ "NetCDF license", false, false ], "Newsletr": [ "Newsletr License", false, false ], "NGPL": [ "Nethack General Public License", true, false ], "NICTA-1.0": [ "NICTA Public Software License, Version 1.0", false, false ], "NIST-PD": [ "NIST Public Domain Notice", false, false ], "NIST-PD-fallback": [ "NIST Public Domain Notice with license fallback", false, false ], "NIST-Software": [ "NIST Software License", false, false ], "NLOD-1.0": [ "Norwegian Licence for Open Government Data (NLOD) 1.0", false, false ], "NLOD-2.0": [ "Norwegian Licence for Open Government Data (NLOD) 2.0", false, false ], "NLPL": [ "No Limit Public License", false, false ], "Nokia": [ "Nokia Open Source License", true, false ], "NOSL": [ "Netizen Open Source License", false, false ], "Noweb": [ "Noweb License", false, false ], "NPL-1.0": [ "Netscape Public License v1.0", false, false ], "NPL-1.1": [ "Netscape Public License v1.1", false, false ], "NPOSL-3.0": [ "Non-Profit Open Software License 3.0", true, false ], "NRL": [ "NRL License", false, false ], "NTP": [ "NTP License", true, false ], "NTP-0": [ "NTP No Attribution", false, false ], "Nunit": [ "Nunit License", false, true ], "O-UDA-1.0": [ "Open Use of Data Agreement v1.0", false, false ], "OCCT-PL": [ "Open CASCADE Technology Public License", false, false ], "OCLC-2.0": [ "OCLC Research Public License 2.0", true, false ], "ODbL-1.0": [ "Open Data Commons Open Database License v1.0", false, false ], "ODC-By-1.0": [ "Open Data Commons Attribution License v1.0", false, false ], "OFFIS": [ "OFFIS License", false, false ], "OFL-1.0": [ "SIL Open Font License 1.0", false, false ], "OFL-1.0-no-RFN": [ "SIL Open Font License 1.0 with no Reserved Font Name", false, false ], "OFL-1.0-RFN": [ "SIL Open Font License 1.0 with Reserved Font Name", false, false ], "OFL-1.1": [ "SIL Open Font License 1.1", true, false ], "OFL-1.1-no-RFN": [ "SIL Open Font License 1.1 with no Reserved Font Name", true, false ], "OFL-1.1-RFN": [ "SIL Open Font License 1.1 with Reserved Font Name", true, false ], "OGC-1.0": [ "OGC Software License, Version 1.0", false, false ], "OGDL-Taiwan-1.0": [ "Taiwan Open Government Data License, version 1.0", false, false ], "OGL-Canada-2.0": [ "Open Government Licence - Canada", false, false ], "OGL-UK-1.0": [ "Open Government Licence v1.0", false, false ], "OGL-UK-2.0": [ "Open Government Licence v2.0", false, false ], "OGL-UK-3.0": [ "Open Government Licence v3.0", false, false ], "OGTSL": [ "Open Group Test Suite License", true, false ], "OLDAP-1.1": [ "Open LDAP Public License v1.1", false, false ], "OLDAP-1.2": [ "Open LDAP Public License v1.2", false, false ], "OLDAP-1.3": [ "Open LDAP Public License v1.3", false, false ], "OLDAP-1.4": [ "Open LDAP Public License v1.4", false, false ], "OLDAP-2.0": [ "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", false, false ], "OLDAP-2.0.1": [ "Open LDAP Public License v2.0.1", false, false ], "OLDAP-2.1": [ "Open LDAP Public License v2.1", false, false ], "OLDAP-2.2": [ "Open LDAP Public License v2.2", false, false ], "OLDAP-2.2.1": [ "Open LDAP Public License v2.2.1", false, false ], "OLDAP-2.2.2": [ "Open LDAP Public License 2.2.2", false, false ], "OLDAP-2.3": [ "Open LDAP Public License v2.3", false, false ], "OLDAP-2.4": [ "Open LDAP Public License v2.4", false, false ], "OLDAP-2.5": [ "Open LDAP Public License v2.5", false, false ], "OLDAP-2.6": [ "Open LDAP Public License v2.6", false, false ], "OLDAP-2.7": [ "Open LDAP Public License v2.7", false, false ], "OLDAP-2.8": [ "Open LDAP Public License v2.8", true, false ], "OLFL-1.3": [ "Open Logistics Foundation License Version 1.3", true, false ], "OML": [ "Open Market License", false, false ], "OpenPBS-2.3": [ "OpenPBS v2.3 Software License", false, false ], "OpenSSL": [ "OpenSSL License", false, false ], "OPL-1.0": [ "Open Public License v1.0", false, false ], "OPL-UK-3.0": [ "United Kingdom Open Parliament Licence v3.0", false, false ], "OPUBL-1.0": [ "Open Publication License v1.0", false, false ], "OSET-PL-2.1": [ "OSET Public License version 2.1", true, false ], "OSL-1.0": [ "Open Software License 1.0", true, false ], "OSL-1.1": [ "Open Software License 1.1", false, false ], "OSL-2.0": [ "Open Software License 2.0", true, false ], "OSL-2.1": [ "Open Software License 2.1", true, false ], "OSL-3.0": [ "Open Software License 3.0", true, false ], "PADL": [ "PADL License", false, false ], "Parity-6.0.0": [ "The Parity Public License 6.0.0", false, false ], "Parity-7.0.0": [ "The Parity Public License 7.0.0", false, false ], "PDDL-1.0": [ "Open Data Commons Public Domain Dedication & License 1.0", false, false ], "PHP-3.0": [ "PHP License v3.0", true, false ], "PHP-3.01": [ "PHP License v3.01", true, false ], "Pixar": [ "Pixar License", false, false ], "Plexus": [ "Plexus Classworlds License", false, false ], "pnmstitch": [ "pnmstitch License", false, false ], "PolyForm-Noncommercial-1.0.0": [ "PolyForm Noncommercial License 1.0.0", false, false ], "PolyForm-Small-Business-1.0.0": [ "PolyForm Small Business License 1.0.0", false, false ], "PostgreSQL": [ "PostgreSQL License", true, false ], "PSF-2.0": [ "Python Software Foundation License 2.0", false, false ], "psfrag": [ "psfrag License", false, false ], "psutils": [ "psutils License", false, false ], "Python-2.0": [ "Python License 2.0", true, false ], "Python-2.0.1": [ "Python License 2.0.1", false, false ], "python-ldap": [ "Python ldap License", false, false ], "Qhull": [ "Qhull License", false, false ], "QPL-1.0": [ "Q Public License 1.0", true, false ], "QPL-1.0-INRIA-2004": [ "Q Public License 1.0 - INRIA 2004 variant", false, false ], "Rdisc": [ "Rdisc License", false, false ], "RHeCos-1.1": [ "Red Hat eCos Public License v1.1", false, false ], "RPL-1.1": [ "Reciprocal Public License 1.1", true, false ], "RPL-1.5": [ "Reciprocal Public License 1.5", true, false ], "RPSL-1.0": [ "RealNetworks Public Source License v1.0", true, false ], "RSA-MD": [ "RSA Message-Digest License", false, false ], "RSCPL": [ "Ricoh Source Code Public License", true, false ], "Ruby": [ "Ruby License", false, false ], "SAX-PD": [ "Sax Public Domain Notice", false, false ], "Saxpath": [ "Saxpath License", false, false ], "SCEA": [ "SCEA Shared Source License", false, false ], "SchemeReport": [ "Scheme Language Report License", false, false ], "Sendmail": [ "Sendmail License", false, false ], "Sendmail-8.23": [ "Sendmail License 8.23", false, false ], "SGI-B-1.0": [ "SGI Free Software License B v1.0", false, false ], "SGI-B-1.1": [ "SGI Free Software License B v1.1", false, false ], "SGI-B-2.0": [ "SGI Free Software License B v2.0", false, false ], "SGI-OpenGL": [ "SGI OpenGL License", false, false ], "SGP4": [ "SGP4 Permission Notice", false, false ], "SHL-0.5": [ "Solderpad Hardware License v0.5", false, false ], "SHL-0.51": [ "Solderpad Hardware License, Version 0.51", false, false ], "SimPL-2.0": [ "Simple Public License 2.0", true, false ], "SISSL": [ "Sun Industry Standards Source License v1.1", true, false ], "SISSL-1.2": [ "Sun Industry Standards Source License v1.2", false, false ], "SL": [ "SL License", false, false ], "Sleepycat": [ "Sleepycat License", true, false ], "SMLNJ": [ "Standard ML of New Jersey License", false, false ], "SMPPL": [ "Secure Messaging Protocol Public License", false, false ], "SNIA": [ "SNIA Public License 1.1", false, false ], "snprintf": [ "snprintf License", false, false ], "Soundex": [ "Soundex License", false, false ], "Spencer-86": [ "Spencer License 86", false, false ], "Spencer-94": [ "Spencer License 94", false, false ], "Spencer-99": [ "Spencer License 99", false, false ], "SPL-1.0": [ "Sun Public License v1.0", true, false ], "ssh-keyscan": [ "ssh-keyscan License", false, false ], "SSH-OpenSSH": [ "SSH OpenSSH license", false, false ], "SSH-short": [ "SSH short notice", false, false ], "SSPL-1.0": [ "Server Side Public License, v 1", false, false ], "StandardML-NJ": [ "Standard ML of New Jersey License", false, true ], "SugarCRM-1.1.3": [ "SugarCRM Public License v1.1.3", false, false ], "SunPro": [ "SunPro License", false, false ], "SWL": [ "Scheme Widget Library (SWL) Software License Agreement", false, false ], "swrule": [ "swrule License", false, false ], "Symlinks": [ "Symlinks License", false, false ], "TAPR-OHL-1.0": [ "TAPR Open Hardware License v1.0", false, false ], "TCL": [ "TCL/TK License", false, false ], "TCP-wrappers": [ "TCP Wrappers License", false, false ], "TermReadKey": [ "TermReadKey License", false, false ], "TMate": [ "TMate Open Source License", false, false ], "TORQUE-1.1": [ "TORQUE v2.5+ Software License v1.1", false, false ], "TOSL": [ "Trusster Open Source License", false, false ], "TPDL": [ "Time::ParseDate License", false, false ], "TPL-1.0": [ "THOR Public License 1.0", false, false ], "TTWL": [ "Text-Tabs+Wrap License", false, false ], "TTYP0": [ "TTYP0 License", false, false ], "TU-Berlin-1.0": [ "Technische Universitaet Berlin License 1.0", false, false ], "TU-Berlin-2.0": [ "Technische Universitaet Berlin License 2.0", false, false ], "UCAR": [ "UCAR License", false, false ], "UCL-1.0": [ "Upstream Compatibility License v1.0", true, false ], "ulem": [ "ulem License", false, false ], "Unicode-DFS-2015": [ "Unicode License Agreement - Data Files and Software (2015)", false, false ], "Unicode-DFS-2016": [ "Unicode License Agreement - Data Files and Software (2016)", true, false ], "Unicode-TOU": [ "Unicode Terms of Use", false, false ], "UnixCrypt": [ "UnixCrypt License", false, false ], "Unlicense": [ "The Unlicense", true, false ], "UPL-1.0": [ "Universal Permissive License v1.0", true, false ], "URT-RLE": [ "Utah Raster Toolkit Run Length Encoded License", false, false ], "Vim": [ "Vim License", false, false ], "VOSTROM": [ "VOSTROM Public License for Open Source", false, false ], "VSL-1.0": [ "Vovida Software License v1.0", true, false ], "W3C": [ "W3C Software Notice and License (2002-12-31)", true, false ], "W3C-19980720": [ "W3C Software Notice and License (1998-07-20)", false, false ], "W3C-20150513": [ "W3C Software Notice and Document License (2015-05-13)", false, false ], "w3m": [ "w3m License", false, false ], "Watcom-1.0": [ "Sybase Open Watcom Public License 1.0", true, false ], "Widget-Workshop": [ "Widget Workshop License", false, false ], "Wsuipa": [ "Wsuipa License", false, false ], "WTFPL": [ "Do What The F*ck You Want To Public License", false, false ], "wxWindows": [ "wxWindows Library License", true, true ], "X11": [ "X11 License", false, false ], "X11-distribute-modifications-variant": [ "X11 License Distribution Modification Variant", false, false ], "Xdebug-1.03": [ "Xdebug License v 1.03", false, false ], "Xerox": [ "Xerox License", false, false ], "Xfig": [ "Xfig License", false, false ], "XFree86-1.1": [ "XFree86 License 1.1", false, false ], "xinetd": [ "xinetd License", false, false ], "xlock": [ "xlock License", false, false ], "Xnet": [ "X.Net License", true, false ], "xpp": [ "XPP License", false, false ], "XSkat": [ "XSkat License", false, false ], "YPL-1.0": [ "Yahoo! Public License v1.0", false, false ], "YPL-1.1": [ "Yahoo! Public License v1.1", false, false ], "Zed": [ "Zed License", false, false ], "Zeeff": [ "Zeeff License", false, false ], "Zend-2.0": [ "Zend License v2.0", false, false ], "Zimbra-1.3": [ "Zimbra Public License v1.3", false, false ], "Zimbra-1.4": [ "Zimbra Public License v1.4", false, false ], "Zlib": [ "zlib License", true, false ], "zlib-acknowledgement": [ "zlib/libpng License with Acknowledgement", false, false ], "ZPL-1.1": [ "Zope Public License 1.1", false, false ], "ZPL-2.0": [ "Zope Public License 2.0", true, false ], "ZPL-2.1": [ "Zope Public License 2.1", true, false ] }Copyright (C) 2015 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. # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [main] * ... ## [.1.5.6] 2022-05-23 * Changed: updated licenses list to SPDX 3.17 * Changed: `${var}` PHP 8.2 deprecations resolved ## [1.5.6] 2021-11-18 * Changed: updated licenses list to SPDX 3.15 ## [1.5.5] 2020-12-03 * Changed: updated licenses list to SPDX 3.11 ## [1.5.4] 2020-07-15 * Changed: updated licenses list to SPDX 3.9 ## [1.5.3] 2020-02-14 * Changed: updated licenses list to SPDX 3.8 ## [1.5.2] 2019-07-29 * Changed: updated licenses list to SPDX 3.6 ## [1.5.1] 2019-03-26 * Changed: updated licenses list to SPDX 3.4 ## [1.5.0] 2018-11-01 * Changed: updated licenses list to SPDX 3.3 ## [1.4.0] 2018-05-04 * Changed: updated licenses list to SPDX 3.1 ## [1.3.0] 2018-01-31 * Added: `SpdxLicenses::getLicenses` to get the whole list of methods. * Changed: license identifiers are now case insensitive. ## [1.2.0] 2018-01-03 * Added: deprecation status for all licenses and a `SpdxLicenses::isDeprecatedByIdentifier` method. * Changed: updated licenses list to SPDX 3.0. ## [1.1.6] 2017-04-03 * Changed: updated licenses list. ## [1.1.5] 2016-09-28 * Changed: updated licenses list. ## [1.1.4] 2016-05-04 * Changed: updated licenses list. ## [1.1.3] 2016-03-25 * Changed: updated licenses list. * Changed: dropped `test` namespace. * Changed: tedious small things. ## [1.1.2] 2015-10-05 * Changed: updated licenses list. ## [1.1.1] 2015-09-07 * Changed: improved performance when looking up just one license. * Changed: updated licenses list. ## [1.1.0] 2015-07-17 * Changed: updater now sorts licenses and exceptions by key. * Changed: filenames now class constants of SpdxLicenses (`LICENSES_FILE` and `EXCEPTIONS_FILE`). * Changed: resources directory now available via static method `SpdxLicenses::getResourcesDir()`. * Changed: updated licenses list. * Changed: removed json-schema requirement. ## [1.0.0] 2015-07-15 * Break: the following classes and namespaces were renamed: - Namespace: `Composer\Util` -> `Composer\Spdx` - Classname: `SpdxLicense` -> `SpdxLicenses` - Classname: `SpdxLicenseTest` -> `SpdxLicensesTest` - Classname: `Updater` -> `SpdxLicensesUpdater` * Changed: validation via regex implementation instead of lexer. [main]: https://github.com/composer/spdx-licenses/compare/1.5.7...main [1.5.7]: https://github.com/composer/spdx-licenses/compare/1.5.6...1.5.7 [1.5.6]: https://github.com/composer/spdx-licenses/compare/1.5.5...1.5.6 [1.5.5]: https://github.com/composer/spdx-licenses/compare/1.5.4...1.5.5 [1.5.4]: https://github.com/composer/spdx-licenses/compare/1.5.3...1.5.4 [1.5.3]: https://github.com/composer/spdx-licenses/compare/1.5.2...1.5.3 [1.5.2]: https://github.com/composer/spdx-licenses/compare/1.5.1...1.5.2 [1.5.1]: https://github.com/composer/spdx-licenses/compare/1.5.0...1.5.1 [1.5.0]: https://github.com/composer/spdx-licenses/compare/1.4.0...1.5.0 [1.4.0]: https://github.com/composer/spdx-licenses/compare/1.3.0...1.4.0 [1.3.0]: https://github.com/composer/spdx-licenses/compare/1.2.0...1.3.0 [1.2.0]: https://github.com/composer/spdx-licenses/compare/1.1.6...1.2.0 [1.1.6]: https://github.com/composer/spdx-licenses/compare/1.1.5...1.1.6 [1.1.5]: https://github.com/composer/spdx-licenses/compare/1.1.4...1.1.5 [1.1.4]: https://github.com/composer/spdx-licenses/compare/1.1.3...1.1.4 [1.1.3]: https://github.com/composer/spdx-licenses/compare/1.1.2...1.1.3 [1.1.2]: https://github.com/composer/spdx-licenses/compare/1.1.1...1.1.2 [1.1.1]: https://github.com/composer/spdx-licenses/compare/1.1.0...1.1.1 [1.1.0]: https://github.com/composer/spdx-licenses/compare/1.0.0...1.1.0 [1.0.0]: https://github.com/composer/spdx-licenses/compare/0281a7fe7820c990db3058844e7d448d7b70e3ac...1.0.0 composer/spdx-licenses ====================== SPDX (Software Package Data Exchange) licenses list and validation library. Originally written as part of [composer/composer](https://github.com/composer/composer), now extracted and made available as a stand-alone library. [![Continuous Integration](https://github.com/composer/spdx-licenses/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/composer/spdx-licenses/actions) Installation ------------ Install the latest version with: ```bash $ composer require composer/spdx-licenses ``` Basic Usage ----------- ```php getLicenseByIdentifier('MIT'); // get a license exception by identifier $licenses->getExceptionByIdentifier('Autoconf-exception-3.0'); // get a license identifier by name $licenses->getIdentifierByName('MIT License'); // check if a license is OSI approved by identifier $licenses->isOsiApprovedByIdentifier('MIT'); // check if a license identifier is deprecated $licenses->isDeprecatedByIdentifier('MIT'); // check if input is a valid SPDX license expression $licenses->validate($input); ``` > Read the [specifications](https://spdx.org/specifications) > to find out more about valid license expressions. Requirements ------------ * PHP 5.3.2 is required but using the latest version of PHP is highly recommended. License ------- composer/spdx-licenses is licensed under the MIT License, see the LICENSE file for details. Source ------ License information is curated by [SPDX](https://spdx.org/). The data is pulled from the [License List Data](https://github.com/spdx/license-list-data) repository. * [Licenses](https://spdx.org/licenses/index.html) * [License Exceptions](https://spdx.org/licenses/exceptions-index.html) parameters: level: 8 paths: - src - tests typeAliases: SPDXLicense: 'array{0: string, 1: bool, 2: string, 3: bool}' SPDXLicenseException: 'array{0: string, 1: string}' { "name": "composer\/spdx-licenses", "description": "SPDX licenses list and validation library.", "type": "library", "license": "MIT", "keywords": [ "spdx", "license", "validator" ], "authors": [ { "name": "Nils Adermann", "email": "naderman@naderman.de", "homepage": "http:\/\/www.naderman.de" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http:\/\/seld.be" }, { "name": "Rob Bast", "email": "rob.bast@gmail.com", "homepage": "http:\/\/robbast.nl" } ], "support": { "irc": "ircs:\/\/irc.libera.chat:6697\/composer", "issues": "https:\/\/github.com\/composer\/spdx-licenses\/issues" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { "symfony\/phpunit-bridge": "^4.2 || ^5", "phpstan\/phpstan": "^0.12.55" }, "autoload": { "psr-4": { "Composer\\Spdx\\": "src" } }, "autoload-dev": { "psr-4": { "Composer\\Spdx\\": "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", "sync-licenses": "bin\/update-spdx-licenses" } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Composer\Spdx; class SpdxLicenses { /** @var string */ const LICENSES_FILE = 'spdx-licenses.json'; /** @var string */ const EXCEPTIONS_FILE = 'spdx-exceptions.json'; /** * Contains all the licenses. * * The array is indexed by license identifiers, which contain * a numerically indexed array with license details. * * [ lowercased license identifier => * [ 0 => identifier (string), 1 => full name (string), 2 => osi certified (bool), 3 => deprecated (bool) ] * , ... * ] * * @var array */ private $licenses; /** * @var string */ private $licensesExpression; /** * Contains all the license exceptions. * * The array is indexed by license exception identifiers, which contain * a numerically indexed array with license exception details. * * [ lowercased exception identifier => * [ 0 => exception identifier (string), 1 => full name (string) ] * , ... * ] * * @var array */ private $exceptions; /** * @var string */ private $exceptionsExpression; public function __construct() { $this->loadLicenses(); $this->loadExceptions(); } /** * Returns license metadata by license identifier. * * This function adds a link to the full license text to the license metadata. * The array returned is in the form of: * * [ 0 => full name (string), 1 => osi certified, 2 => link to license text (string), 3 => deprecation status (bool) ] * * @param string $identifier * * @return array{0: string, 1: bool, 2: string, 3: bool}|null */ public function getLicenseByIdentifier($identifier) { $key = \strtolower($identifier); if (!isset($this->licenses[$key])) { return null; } list($identifier, $name, $isOsiApproved, $isDeprecatedLicenseId) = $this->licenses[$key]; return array($name, $isOsiApproved, 'https://spdx.org/licenses/' . $identifier . '.html#licenseText', $isDeprecatedLicenseId); } /** * Returns all licenses information, keyed by the lowercased license identifier. * * @return array{0: string, 1: string, 2: bool, 3: bool}[] Each item is [ 0 => identifier (string), 1 => full name (string), 2 => osi certified (bool), 3 => deprecated (bool) ] */ public function getLicenses() { return $this->licenses; } /** * Returns license exception metadata by license exception identifier. * * This function adds a link to the full license exception text to the license exception metadata. * The array returned is in the form of: * * [ 0 => full name (string), 1 => link to license text (string) ] * * @param string $identifier * * @return array{0: string, 1: string}|null */ public function getExceptionByIdentifier($identifier) { $key = \strtolower($identifier); if (!isset($this->exceptions[$key])) { return null; } list($identifier, $name) = $this->exceptions[$key]; return array($name, 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText'); } /** * Returns the short identifier of a license (or license exception) by full name. * * @param string $name * * @return string|null */ public function getIdentifierByName($name) { foreach ($this->licenses as $licenseData) { if ($licenseData[1] === $name) { return $licenseData[0]; } } foreach ($this->exceptions as $licenseData) { if ($licenseData[1] === $name) { return $licenseData[0]; } } return null; } /** * Returns the OSI Approved status for a license by identifier. * * @param string $identifier * * @return bool */ public function isOsiApprovedByIdentifier($identifier) { return $this->licenses[\strtolower($identifier)][2]; } /** * Returns the deprecation status for a license by identifier. * * @param string $identifier * * @return bool */ public function isDeprecatedByIdentifier($identifier) { return $this->licenses[\strtolower($identifier)][3]; } /** * @param string[]|string $license * * @throws \InvalidArgumentException * * @return bool */ public function validate($license) { if (\is_array($license)) { $count = \count($license); if ($count !== \count(\array_filter($license, 'is_string'))) { throw new \InvalidArgumentException('Array of strings expected.'); } $license = $count > 1 ? '(' . \implode(' OR ', $license) . ')' : (string) \reset($license); } if (!\is_string($license)) { throw new \InvalidArgumentException(\sprintf('Array or String expected, %s given.', \gettype($license))); } return $this->isValidLicenseString($license); } /** * @return string */ public static function getResourcesDir() { return \dirname(__DIR__) . '/res'; } /** * @return void */ private function loadLicenses() { if (null !== $this->licenses) { return; } $json = \file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE); if (\false === $json) { throw new \RuntimeException('Missing license file in ' . self::getResourcesDir() . '/' . self::LICENSES_FILE); } $this->licenses = array(); foreach (\json_decode($json, \true) as $identifier => $license) { $this->licenses[\strtolower($identifier)] = array($identifier, $license[0], $license[1], $license[2]); } } /** * @return void */ private function loadExceptions() { if (null !== $this->exceptions) { return; } $json = \file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE); if (\false === $json) { throw new \RuntimeException('Missing exceptions file in ' . self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE); } $this->exceptions = array(); foreach (\json_decode($json, \true) as $identifier => $exception) { $this->exceptions[\strtolower($identifier)] = array($identifier, $exception[0]); } } /** * @return string */ private function getLicensesExpression() { if (null === $this->licensesExpression) { $licenses = \array_map('preg_quote', \array_keys($this->licenses)); \rsort($licenses); $licenses = \implode('|', $licenses); $this->licensesExpression = $licenses; } return $this->licensesExpression; } /** * @return string */ private function getExceptionsExpression() { if (null === $this->exceptionsExpression) { $exceptions = \array_map('preg_quote', \array_keys($this->exceptions)); \rsort($exceptions); $exceptions = \implode('|', $exceptions); $this->exceptionsExpression = $exceptions; } return $this->exceptionsExpression; } /** * @param string $license * * @throws \RuntimeException * * @return bool */ private function isValidLicenseString($license) { if (isset($this->licenses[\strtolower($license)])) { return \true; } $licenses = $this->getLicensesExpression(); $exceptions = $this->getExceptionsExpression(); $regex = <<[\\pL\\pN.-]{1,}) # license-id: taken from list (?{$licenses}) # license-exception-id: taken from list (?{$exceptions}) # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring) (?(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring)) # simple-expresssion: license-id / license-id+ / license-ref (?(?&licenseid)\\+? | (?&licenseid) | (?&licenseref)) # compound-expression: 1*( # simple-expression / # simple-expression WITH license-exception-id / # compound-expression AND compound-expression / # compound-expression OR compound-expression # ) / ( compound-expression ) ) (? (?&simple_expression) ( \\s+ WITH \\s+ (?&licenseexceptionid))? | \\( \\s* (?&compound_expression) \\s* \\) ) (? (?&compound_head) (?: \\s+ (?:AND|OR) \\s+ (?&compound_expression))? ) # license-expression: 1*1(simple-expression / compound-expression) (?(?&compound_expression) | (?&simple_expression)) ) # end of define ^(NONE | NOASSERTION | (?&license_expression))\$ }xi REGEX; $match = \preg_match($regex, $license); if (0 === $match) { return \false; } if (\false === $match) { throw new \RuntimeException('Regex failed to compile/run.'); } return \true; } } The MIT License (MIT) Copyright (c) 2015 phpDocumentor 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. [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![Qa workflow](https://github.com/phpDocumentor/ReflectionCommon/workflows/Qa%20workflow/badge.svg) [![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionCommon.svg)](https://coveralls.io/github/phpDocumentor/ReflectionCommon?branch=master) [![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master) [![Stable Version](https://img.shields.io/packagist/v/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common) [![Unstable Version](https://img.shields.io/packagist/vpre/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common) ReflectionCommon ================ { "name": "phpdocumentor\/reflection-common", "keywords": [ "phpdoc", "phpDocumentor", "reflection", "static analysis", "FQSEN" ], "homepage": "http:\/\/www.phpdoc.org", "description": "Common reflection classes used by phpdocumentor to reflect the code structure", "license": "MIT", "authors": [ { "name": "Jaap van Otterdijk", "email": "opensource@ijaap.nl" } ], "require": { "php": "^7.2 || ^8.0" }, "autoload": { "psr-4": { "_ContaoManager\\phpDocumentor\\Reflection\\": "src\/" } }, "require-dev": {}, "extra": { "branch-alias": { "dev-2.x": "2.x-dev" } } }fqsen = $fqsen; if (isset($matches[2])) { $this->name = $matches[2]; } else { $matches = explode('\\', $fqsen); $name = end($matches); assert(is_string($name)); $this->name = trim($name, '()'); } } /** * converts this class to string. */ public function __toString() : string { return $this->fqsen; } /** * Returns the name of the element without path. */ public function getName() : string { return $this->name; } } lineNumber = $lineNumber; $this->columnNumber = $columnNumber; } /** * Returns the line number that is covered by this location. */ public function getLineNumber() : int { return $this->lineNumber; } /** * Returns the column number (character position on a line) for this location object. */ public function getColumnNumber() : int { return $this->columnNumber; } } The MIT License (MIT) Copyright (c) 2010 Mike van Riel 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. Type Resolver build/docs latest src/ api php template template-extends template-implements extends implements phpDocumentor docs guides

Build Status Latest Stable Version License PHPStan Enabled